Browse Source

Fix enum type comparison; Start demo 003 code

Ginger Bill 9 years ago
parent
commit
664c2cd7a5
11 changed files with 356 additions and 43 deletions
  1. 7 0
      README.md
  2. 279 19
      code/demo.odin
  3. 1 1
      code/game.odin
  4. 4 4
      code/math.odin
  5. 34 1
      code/test.odin
  6. 1 1
      core/win32.odin
  7. 1 1
      src/checker/checker.cpp
  8. 2 6
      src/checker/type.cpp
  9. 1 2
      src/codegen/ssa.cpp
  10. 1 1
      src/main.cpp
  11. 25 7
      src/parser.cpp

+ 7 - 0
README.md

@@ -2,6 +2,13 @@
 
 
 Odin in an open source programming language that is simple to read, comprehend and reason with.
 Odin in an open source programming language that is simple to read, comprehend and reason with.
 
 
+## Requirements
+
+* x86-64
+* Windows
+* MSVC installed
+* call `vcvarsall.bat` to setup the path
+
 ## Warnings
 ## Warnings
 
 
 * This is still highly in development and the language's design is quite volatile.
 * This is still highly in development and the language's design is quite volatile.

+ 279 - 19
code/demo.odin

@@ -2,34 +2,294 @@
 #import "os.odin"
 #import "os.odin"
 
 
 
 
+
 main :: proc() {
 main :: proc() {
-	Fruit :: enum {
-		APPLE,
-		BANANA,
-		GRAPE,
-		MELON,
-		PEACH,
-		TOMATO,
+	// struct_padding()
+	// bounds_checking()
+	// type_introspection()
+	// any_type()
+	crazy_introspection()
+	// namespaces_and_files()
+	// miscellany()
+}
+
+struct_padding :: proc() {
+	{
+		A :: struct {
+			a: u8
+			b: u32
+			c: u16
+		}
+
+		B :: struct {
+			a: [7]u8
+			b: [3]u16
+			c: u8
+			d: u16
+		}
+
+		fmt.println("size_of(A):", size_of(A))
+		fmt.println("size_of(B):", size_of(B))
+
+		// n.b. http://cbloomrants.blogspot.co.uk/2012/07/07-23-12-structs-are-not-what-you-want.html
+	}
+	{
+		A :: struct #ordered {
+			a: u8
+			b: u32
+			c: u16
+		}
+
+		B :: struct #ordered {
+			a: [7]u8
+			b: [3]u16
+			c: u8
+			d: u16
+		}
+
+		fmt.println("size_of(A):", size_of(A))
+		fmt.println("size_of(B):", size_of(B))
+
+		// C-style structure layout
+	}
+	{
+		A :: struct #packed {
+			a: u8
+			b: u32
+			c: u16
+		}
+
+		B :: struct #packed {
+			a: [7]u8
+			b: [3]u16
+			c: u8
+			d: u16
+		}
+
+		fmt.println("size_of(A):", size_of(A))
+		fmt.println("size_of(B):", size_of(B))
+
+		// Useful for explicit layout
+	}
+
+	// Member sorting by priority
+	// Alignment desc.
+	// Size desc.
+	// source order asc.
+
+	/*
+		A :: struct {
+			a: u8
+			b: u32
+			c: u16
+		}
+
+		B :: struct {
+			a: [7]u8
+			b: [3]u16
+			c: u8
+			d: u16
+		}
+
+		Equivalent too
+
+		A :: struct #ordered {
+			b: u32
+			c: u16
+			a: u8
+		}
+
+		B :: struct #ordered {
+			b: [3]u16
+			d: u16
+			a: [7]u8
+			c: u8
+		}
+	*/
+}
+
+bounds_checking :: proc() {
+	x: [4]int
+	// x[-1] = 0; // Compile Time
+	// x[4]  = 0; // Compile Time
+
+	/*{
+		a, b := -1, 4;
+		x[a] = 0; // Runtime Time
+		x[b] = 0; // Runtime Time
+	}*/
+
+	// Works for arrays, strings, slices, and related procedures & operations
+
+	{
+		base: [10]int
+		s := base[2:6]
+		a, b := -1, 6
+
+		#no_bounds_check {
+			s[a] = 0;
+			// #bounds_check s[b] = 0;
+		}
+
+	#no_bounds_check
+		if s[a] == 0 {
+			// Do whatever
+		}
+
+		// Bounds checking can be toggled explicit
+		// on a per statement basis.
+		// _any statement_
+	}
+}
+
+type_introspection :: proc() {
+
+	info: ^Type_Info
+	x: int
+
+	info = type_info(int) // by type
+	info = type_info(x) // by value
+	// See: runtime.odin
+
+	match type i : info {
+	case Type_Info.Integer:
+		fmt.println("integer!")
+	case Type_Info.Float:
+		fmt.println("float!")
+	default:
+		fmt.println("potato!")
+	}
+
+	// Unsafe cast
+	integer_info := info as ^Type_Info.Integer
+}
+
+any_type :: proc() {
+	a: any
+
+	x := 123
+	y := 6.28
+	z := "Yo-Yo Ma"
+	// All types can be implicit cast to `any`
+	a = x
+	a = y
+	a = z
+	a = a
+
+	// any has two members
+	// data      - rawptr to the data
+	// type_info - pointer to the type info
+
+	fmt.println(x, y, z)
+	// See: Implementation
+}
+
+crazy_introspection :: proc() {
+	{
+		Fruit :: enum {
+			APPLE,
+			BANANA,
+			GRAPE,
+			MELON,
+			PEACH,
+			TOMATO,
+		}
+
+		s: string
+		s = enum_to_string(Fruit.PEACH)
+		fmt.println(s)
+
+		f := Fruit.GRAPE
+		s = enum_to_string(f)
+		fmt.println(s)
+
+		fmt.println(f)
 	}
 	}
 
 
-	fruit_ti := type_info(Fruit)
-	name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
-	info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
 
 
-	fmt.printf("% :: enum ", name);
-	fmt.fprint_type(os.stdout, info.base)
-	fmt.printf(" {\n")
-	for i := 0; i < info.values.count; i++ {
-		fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
+	{
+		// NOTE(bill): This is not safe code and I would not recommend this at all
+		// I'd recommend you use `match type` to get the subtype rather than
+		// casting pointers
+
+		Fruit :: enum {
+			APPLE,
+			BANANA,
+			GRAPE,
+			MELON,
+			PEACH,
+			TOMATO,
+		}
+
+		fruit_ti := type_info(Fruit)
+		name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
+		info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
+
+		fmt.printf("% :: enum ", name);
+		fmt.fprint_type(os.stdout, info.base)
+		fmt.printf(" {\n")
+		for i := 0; i < info.values.count; i++ {
+			fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
+		}
+		fmt.printf("}\n")
 	}
 	}
-	fmt.printf("}\n")
 
 
-	Vector3 :: struct {x, y, z: f32}
-	v := Vector3{x = 1, y = 4, z = 9}
-	fmt.println(v)
+	{
+		Vector3 :: struct {x, y, z: f32}
+
+		a := Vector3{x = 1, y = 4, z = 9}
+		fmt.println(a)
+		b := Vector3{x = 9, y = 3, z = 1}
+		fmt.println(b)
+
+		// NOTE(bill): See fmt.odin
+	}
+
+	// n.b. This pretty much "solves" serialization (to strings)
 }
 }
 
 
 
 
+namespaces_and_files :: proc() {
+	/*
+		// Non-exporting import
+		#import "file.odin"
+		#import "file.odin" as file
+		#import "file.odin" as .
+		#import "file.odin" as _
+
+		// Exporting import
+		#load "file.odin"
+	*/
+
+	// Talk about scope rules and diagram
+}
+
+miscellany :: proc() {
+	/*
+		win32 `__imp__` prefix
+		#dll_import
+		#dll_export
+
+		Change exported name/symbol for linking
+		#link_name
+
+		Custom calling conventions
+		#stdcall
+		#fastcall
+
+		Runtime stuff
+		#shared_global_scope
+	*/
+
+	// assert(false)
+	// compile_assert(false)
+	// panic("Panic message goes here")
+}
+
+
+
+
+
 // #import "fmt.odin" as fmt
 // #import "fmt.odin" as fmt
 
 
 // #foreign_system_library "Ws2_32"
 // #foreign_system_library "Ws2_32"

+ 1 - 1
code/game.odin

@@ -206,7 +206,7 @@ run :: proc() {
 		display_window(^window)
 		display_window(^window)
 		ms_to_sleep := (16 - 1000*dt) as i32
 		ms_to_sleep := (16 - 1000*dt) as i32
 		if ms_to_sleep > 0 {
 		if ms_to_sleep > 0 {
-			sleep_ms(ms_to_sleep)
+			win32.Sleep(ms_to_sleep)
 		}
 		}
 	}
 	}
 }
 }

+ 4 - 4
code/math.odin

@@ -96,7 +96,7 @@ remainder :: proc(x, y: f32) -> f32 {
 fmod :: proc(x, y: f32) -> f32 {
 fmod :: proc(x, y: f32) -> f32 {
 	y = abs(y)
 	y = abs(y)
 	result := remainder(abs(x), y)
 	result := remainder(abs(x), y)
-	if fsign(result) < 0 {
+	if sign32(result) < 0 {
 		result += y
 		result += y
 	}
 	}
 	return copy_sign(result, x)
 	return copy_sign(result, x)
@@ -120,9 +120,9 @@ cross :: proc(x, y: Vec3) -> Vec3 {
 }
 }
 
 
 
 
-vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(dot2(v, v)) }
-vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(dot3(v, v)) }
-vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(dot4(v, v)) }
+vec2_mag :: proc(v: Vec2) -> f32 { return sqrt32(dot2(v, v)) }
+vec3_mag :: proc(v: Vec3) -> f32 { return sqrt32(dot3(v, v)) }
+vec4_mag :: proc(v: Vec4) -> f32 { return sqrt32(dot4(v, v)) }
 
 
 vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)} }
 vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)} }
 vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }
 vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }

+ 34 - 1
code/test.odin

@@ -1,5 +1,38 @@
 #import "fmt.odin"
 #import "fmt.odin"
 
 
-thing :: proc() #link_name "frankerooney" {
+thing :: proc() {
 	fmt.println("Hello!")
 	fmt.println("Hello!")
 }
 }
+
+/*
+#import "fmt.odin" as fmt
+
+thing :: proc() {
+	fmt.println("Hello!")
+}
+*/
+
+/*
+#import "fmt.odin" as .
+
+thing :: proc() {
+	println("Hello!")
+}
+*/
+
+/*
+#import "fmt.odin" as _
+
+thing :: proc() {
+	// println("Hello!")
+}
+*/
+
+
+/*
+#load "fmt.odin"
+
+thing :: proc() {
+	println("Hello!")
+}
+*/

+ 1 - 1
core/win32.odin

@@ -22,7 +22,7 @@ INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE
 CS_VREDRAW    :: 0x0001
 CS_VREDRAW    :: 0x0001
 CS_HREDRAW    :: 0x0002
 CS_HREDRAW    :: 0x0002
 CS_OWNDC      :: 0x0020
 CS_OWNDC      :: 0x0020
-CW_USEDEFAULT :: 0x80000000
+CW_USEDEFAULT :: -0x80000000
 
 
 WS_OVERLAPPED       :: 0
 WS_OVERLAPPED       :: 0
 WS_MAXIMIZEBOX      :: 0x00010000
 WS_MAXIMIZEBOX      :: 0x00010000

+ 1 - 1
src/checker/checker.cpp

@@ -418,7 +418,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
 
 
 void check_scope_usage(Checker *c, Scope *scope) {
 void check_scope_usage(Checker *c, Scope *scope) {
 	// TODO(bill): Use this?
 	// TODO(bill): Use this?
-#if 1
+#if 0
 	gb_for_array(i, scope->elements.entries) {
 	gb_for_array(i, scope->elements.entries) {
 		auto *entry = scope->elements.entries + i;
 		auto *entry = scope->elements.entries + i;
 		Entity *e = entry->value;
 		Entity *e = entry->value;

+ 2 - 6
src/checker/type.cpp

@@ -599,12 +599,8 @@ b32 are_types_identical(Type *x, Type *y) {
 					break;
 					break;
 
 
 				case TypeRecord_Enum:
 				case TypeRecord_Enum:
-					if (are_types_identical(x->Record.enum_base, y->Record.enum_base)) {
-						if (x->Record.field_count == y->Record.field_count) {
-							return x->Record.fields == y->Record.fields;
-						}
-					}
-					return false;
+					// NOTE(bill): Each enum is unique
+					return x == y;
 				}
 				}
 			}
 			}
 		}
 		}

+ 1 - 2
src/codegen/ssa.cpp

@@ -1348,9 +1348,8 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
 		}
 		}
 	}
 	}
 	if (entry_index < 0) {
 	if (entry_index < 0) {
-		gb_printf_err("%s\n", type_to_string(type));
+		compiler_error("Type_Info for `%s` could not be found", type_to_string(type));
 	}
 	}
-	GB_ASSERT(entry_index >= 0);
 	return entry_index;
 	return entry_index;
 }
 }
 
 

+ 1 - 1
src/main.cpp

@@ -22,7 +22,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
 	va_end(va);
 	va_end(va);
 
 
 	if (CreateProcessA(NULL, cmd_line,
 	if (CreateProcessA(NULL, cmd_line,
-	                   NULL, NULL, true, 0, NULL, NULL,
+                   NULL, NULL, true, 0, NULL, NULL,
 	                   &start_info, &pi)) {
 	                   &start_info, &pi)) {
 		WaitForSingleObject(pi.hProcess, INFINITE);
 		WaitForSingleObject(pi.hProcess, INFINITE);
 
 

+ 25 - 7
src/parser.cpp

@@ -1499,7 +1499,14 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
 
 
 		case Token_OpenBrace: {
 		case Token_OpenBrace: {
 			if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
 			if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
-				operand = parse_literal_value(f, operand);
+				if (f->cursor[0].pos.line == f->cursor[-1].pos.line) {
+					// TODO(bill): This is a hack due to optional semicolons
+					// TODO(bill): It's probably much better to solve this by changing
+					// the syntax for struct literals and array literals
+					operand = parse_literal_value(f, operand);
+				} else {
+					loop = false;
+				}
 			} else {
 			} else {
 				loop = false;
 				loop = false;
 			}
 			}
@@ -1553,13 +1560,24 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
 
 
 			switch (op.kind) {
 			switch (op.kind) {
 			case Token_DoublePrime: {
 			case Token_DoublePrime: {
+				// TODO(bill): Properly define semantic for in-fix and post-fix calls
 				AstNode *proc = parse_identifier(f);
 				AstNode *proc = parse_identifier(f);
-				AstNode *right = parse_binary_expr(f, false, prec+1);
-				gbArray(AstNode *) args;
-				gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
-				gb_array_append(args, expression);
-				gb_array_append(args, right);
-				expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
+				/* if (f->cursor[0].kind == Token_OpenParen) {
+					AstNode *call = parse_call_expr(f, proc);
+					gb_array_append(call->CallExpr.args, expression);
+					for (isize i = gb_array_count(call->CallExpr.args)-1; i > 0; i--) {
+						gb_swap(AstNode *, call->CallExpr.args[i], call->CallExpr.args[i-1]);
+					}
+
+					expression = call;
+				} else  */{
+					AstNode *right = parse_binary_expr(f, false, prec+1);
+					gbArray(AstNode *) args;
+					gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
+					gb_array_append(args, expression);
+					gb_array_append(args, right);
+					expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
+				}
 				continue;
 				continue;
 			} break;
 			} break;