Browse Source

Use comma for struct field separators (disallow nesting)

Ginger Bill 8 years ago
parent
commit
c43d66c286
20 changed files with 716 additions and 661 deletions
  1. 149 145
      core/_preload.odin
  2. 10 9
      core/_soft_numbers.odin
  3. 4 4
      core/decimal.odin
  4. 62 66
      core/fmt.odin
  5. 43 47
      core/mem.odin
  6. 21 21
      core/os_linux.odin
  7. 22 22
      core/os_x.odin
  8. 18 18
      core/raw.odin
  9. 7 7
      core/strconv.odin
  10. 5 5
      core/sync_linux.odin
  11. 6 6
      core/sync_windows.odin
  12. 29 29
      core/sys/wgl.odin
  13. 82 82
      core/sys/windows.odin
  14. 15 14
      core/thread.odin
  15. 21 21
      core/types.odin
  16. 45 71
      examples/demo.odin
  17. 142 45
      src/check_expr.cpp
  18. 2 19
      src/check_stmt.cpp
  19. 26 30
      src/checker.cpp
  20. 7 0
      src/parser.cpp

+ 149 - 145
core/_preload.odin

@@ -35,102 +35,103 @@ Calling_Convention :: enum {
 }
 // IMPORTANT NOTE(bill): Do not change the order of any of this data
 // The compiler relies upon this _exact_ order
-Type_Info :: struct #ordered {
-// Core Types
-	Enum_Value :: union {
-		rune,
-		i8, i16, i32, i64, i128, int,
-		u8, u16, u32, u64, u128, uint,
-		f32, f64,
-	};
+
+Type_Info_Enum_Value :: union {
+	rune,
+	i8, i16, i32, i64, i128, int,
+	u8, u16, u32, u64, u128, uint,
+	f32, f64,
+};
+
 
 // Variant Types
-	Named   :: struct #ordered {name: string; base: ^Type_Info};
-	Integer :: struct #ordered {signed: bool};
-	Rune    :: struct{};
-	Float   :: struct{};
-	Complex :: struct{};
-	String  :: struct{};
-	Boolean :: struct{};
-	Any     :: struct{};
-	Pointer :: struct #ordered {
-		elem: ^Type_Info; // nil -> rawptr
-	};
-	Procedure :: struct #ordered {
-		params:     ^Type_Info; // Type_Info.Tuple
-		results:    ^Type_Info; // Type_Info.Tuple
-		variadic:   bool;
-		convention: Calling_Convention;
-	};
-	Array :: struct #ordered {
-		elem:      ^Type_Info;
-		elem_size: int;
-		count:     int;
-	};
-	Dynamic_Array :: struct #ordered {elem: ^Type_Info; elem_size: int};
-	Slice         :: struct #ordered {elem: ^Type_Info; elem_size: int};
-	Vector        :: struct #ordered {elem: ^Type_Info; elem_size, count: int};
-	Tuple :: struct #ordered { // Only really used for procedures
-		types:        []^Type_Info;
-		names:        []string;
-	};
-	Struct :: struct #ordered {
-		types:        []^Type_Info;
-		names:        []string;
-		offsets:      []int;  // offsets may not be used in tuples
-		usings:       []bool; // usings may not be used in tuples
-		is_packed:    bool;
-		is_ordered:   bool;
-		is_raw_union: bool;
-		custom_align: bool;
-	};
-	Union :: struct #ordered {
-		variants:   []^Type_Info;
-		tag_offset: int;
-	};
-	Enum :: struct #ordered {
-		base:   ^Type_Info;
-		names:  []string;
-		values: []Enum_Value;
-	};
-	Map :: struct #ordered {
-		key:              ^Type_Info;
-		value:            ^Type_Info;
-		generated_struct: ^Type_Info;
-	};
-	Bit_Field :: struct #ordered {
-		names:   []string;
-		bits:    []i32;
-		offsets: []i32;
-	};
+Type_Info_Named   :: struct #ordered {name: string, base: ^Type_Info};
+Type_Info_Integer :: struct #ordered {signed: bool};
+Type_Info_Rune    :: struct{};
+Type_Info_Float   :: struct{};
+Type_Info_Complex :: struct{};
+Type_Info_String  :: struct{};
+Type_Info_Boolean :: struct{};
+Type_Info_Any     :: struct{};
+Type_Info_Pointer :: struct #ordered {
+	elem: ^Type_Info // nil -> rawptr
+};
+Type_Info_Procedure :: struct #ordered {
+	params:     ^Type_Info, // Type_Info_Tuple
+	results:    ^Type_Info, // Type_Info_Tuple
+	variadic:   bool,
+	convention: Calling_Convention,
+};
+Type_Info_Array :: struct #ordered {
+	elem:      ^Type_Info,
+	elem_size: int,
+	count:     int,
+};
+Type_Info_Dynamic_Array :: struct #ordered {elem: ^Type_Info, elem_size: int};
+Type_Info_Slice         :: struct #ordered {elem: ^Type_Info, elem_size: int};
+Type_Info_Vector        :: struct #ordered {elem: ^Type_Info, elem_size, count: int};
+Type_Info_Tuple :: struct #ordered { // Only really used for procedures
+	types:        []^Type_Info,
+	names:        []string,
+};
+Type_Info_Struct :: struct #ordered {
+	types:        []^Type_Info,
+	names:        []string,
+	offsets:      []int,  // offsets may not be used in tuples
+	usings:       []bool, // usings may not be used in tuples
+	is_packed:    bool,
+	is_ordered:   bool,
+	is_raw_union: bool,
+	custom_align: bool,
+};
+Type_Info_Union :: struct #ordered {
+	variants:   []^Type_Info,
+	tag_offset: int,
+};
+Type_Info_Enum :: struct #ordered {
+	base:   ^Type_Info,
+	names:  []string,
+	values: []Type_Info_Enum_Value,
+};
+Type_Info_Map :: struct #ordered {
+	key:              ^Type_Info,
+	value:            ^Type_Info,
+	generated_struct: ^Type_Info,
+};
+Type_Info_Bit_Field :: struct #ordered {
+	names:   []string,
+	bits:    []i32,
+	offsets: []i32,
+};
 
 
+Type_Info :: struct #ordered {
 // Fields
-	size:  int;
-	align: int;
+	size:  int,
+	align: int,
 
 	variant: union {
-		Named,
-		Integer,
-		Rune,
-		Float,
-		Complex,
-		String,
-		Boolean,
-		Any,
-		Pointer,
-		Procedure,
-		Array,
-		Dynamic_Array,
-		Slice,
-		Vector,
-		Tuple,
-		Struct,
-		Union,
-		Enum,
-		Map,
-		Bit_Field,
-	};
+		Type_Info_Named,
+		Type_Info_Integer,
+		Type_Info_Rune,
+		Type_Info_Float,
+		Type_Info_Complex,
+		Type_Info_String,
+		Type_Info_Boolean,
+		Type_Info_Any,
+		Type_Info_Pointer,
+		Type_Info_Procedure,
+		Type_Info_Array,
+		Type_Info_Dynamic_Array,
+		Type_Info_Slice,
+		Type_Info_Vector,
+		Type_Info_Tuple,
+		Type_Info_Struct,
+		Type_Info_Union,
+		Type_Info_Enum,
+		Type_Info_Map,
+		Type_Info_Bit_Field,
+	},
 }
 
 // NOTE(bill): only the ones that are needed (not all types)
@@ -142,69 +143,72 @@ __argc__: i32;
 
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
 
-Allocator :: struct #ordered {
-	Mode :: enum u8 {
-		Alloc,
-		Free,
-		FreeAll,
-		Resize,
-	}
-	Proc :: #type proc(allocator_data: rawptr, mode: Mode,
-	                   size, alignment: int,
-	                   old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr;
+Allocator_Mode :: enum u8 {
+	Alloc,
+	Free,
+	FreeAll,
+	Resize,
+}
+
+
+Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
+	                         size, alignment: int,
+	                         old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr;
 
-	procedure: Proc;
-	data:      rawptr;
+
+Allocator :: struct #ordered {
+	procedure: Allocator_Proc,
+	data:      rawptr,
 }
 
 
 Context :: struct #ordered {
-	allocator:  Allocator;
-	thread_id:  int;
+	allocator:  Allocator,
+	thread_id:  int,
 
-	user_data:  any;
-	user_index: int;
+	user_data:  any,
+	user_index: int,
 
-	derived:    any; // May be used for derived data types
+	derived:    any, // May be used for derived data types
 }
 
 DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
 
 Source_Code_Location :: struct #ordered {
-	file_path:    string;
-	line, column: i64;
-	procedure:    string;
+	file_path:    string,
+	line, column: i64,
+	procedure:    string,
 }
 
 
 __INITIAL_MAP_CAP :: 16;
 
 __Map_Key :: struct #ordered {
-	hash: u128;
-	str:  string;
+	hash: u128,
+	str:  string,
 }
 
 __Map_Find_Result :: struct #ordered {
-	hash_index:  int;
-	entry_prev:  int;
-	entry_index: int;
+	hash_index:  int,
+	entry_prev:  int,
+	entry_index: int,
 }
 
 __Map_Entry_Header :: struct #ordered {
-	key:  __Map_Key;
-	next: int;
+	key:  __Map_Key,
+	next: int,
 /*
-	value: Value_Type;
+	value: Value_Type,
 */
 }
 
 __Map_Header :: struct #ordered {
-	m:             ^raw.Map;
-	is_key_string: bool;
-	entry_size:    int;
-	entry_align:   int;
-	value_offset:  int;
-	value_size:    int;
+	m:             ^raw.Map,
+	is_key_string: bool,
+	entry_size:    int,
+	entry_align:   int,
+	value_offset:  int,
+	value_size:    int,
 }
 
 
@@ -214,7 +218,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
 
 	base := info;
 	match i in base.variant {
-	case Type_Info.Named: base = i.base;
+	case Type_Info_Named: base = i.base;
 	}
 	return base;
 }
@@ -225,8 +229,8 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
 
 	base := info;
 	match i in base.variant {
-	case Type_Info.Named: base = i.base;
-	case Type_Info.Enum:  base = i.base;
+	case Type_Info_Named: base = i.base;
+	case Type_Info_Enum:  base = i.base;
 	}
 	return base;
 }
@@ -281,26 +285,26 @@ __check_context :: proc() {
 
 alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
 	a := context.allocator;
-	return a.procedure(a.data, Allocator.Mode.Alloc, size, alignment, nil, 0, 0);
+	return a.procedure(a.data, Allocator_Mode.Alloc, size, alignment, nil, 0, 0);
 }
 
 free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
 	if ptr == nil do return;
 	if a.procedure == nil do return;
-	a.procedure(a.data, Allocator.Mode.Free, 0, 0, ptr, 0, 0);
+	a.procedure(a.data, Allocator_Mode.Free, 0, 0, ptr, 0, 0);
 }
 
 free_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr);
 
 free_all :: proc() #inline {
 	a := context.allocator;
-	a.procedure(a.data, Allocator.Mode.FreeAll, 0, 0, nil, 0, 0);
+	a.procedure(a.data, Allocator_Mode.FreeAll, 0, 0, nil, 0, 0);
 }
 
 
 resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
 	a := context.allocator;
-	return a.procedure(a.data, Allocator.Mode.Resize, new_size, alignment, ptr, old_size, 0);
+	return a.procedure(a.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, 0);
 }
 
 
@@ -411,7 +415,7 @@ reserve :: proc(array: ^$T/[dynamic]$E, capacity: int) -> bool {
 	new_size  := capacity * size_of(E);
 	allocator := a.allocator;
 
-	new_data := allocator.procedure(allocator.data, Allocator.Mode.Resize, new_size, align_of(E), a.data, old_size, 0);
+	new_data := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, align_of(E), a.data, old_size, 0);
 	if new_data == nil do return false;
 
 	a.data = new_data;
@@ -423,12 +427,12 @@ reserve :: proc(array: ^$T/[dynamic]$E, capacity: int) -> bool {
 __get_map_header :: proc(m: ^$T/map[$K]$V) -> __Map_Header #cc_contextless {
 	header := __Map_Header{m = cast(^raw.Map)m};
 	Entry :: struct {
-		key:   __Map_Key;
-		next:  int;
-		value: V;
+		key:   __Map_Key,
+		next:  int,
+		value: V,
 	}
 
-	_, is_string := type_info_base(type_info_of(K)).variant.(Type_Info.String);
+	_, is_string := type_info_base(type_info_of(K)).variant.(Type_Info_String);
 	header.is_key_string = is_string;
 	header.entry_size    = size_of(Entry);
 	header.entry_align   = align_of(Entry);
@@ -441,7 +445,7 @@ __get_map_key :: proc(key: $K) -> __Map_Key #cc_contextless {
 	map_key: __Map_Key;
 	ti := type_info_base_without_enum(type_info_of(K));
 	match _ in ti.variant {
-	case Type_Info.Integer:
+	case Type_Info_Integer:
 		match 8*size_of(key) {
 		case   8: map_key.hash = u128((  ^u8)(&key)^);
 		case  16: map_key.hash = u128(( ^u16)(&key)^);
@@ -450,17 +454,17 @@ __get_map_key :: proc(key: $K) -> __Map_Key #cc_contextless {
 		case 128: map_key.hash = u128((^u128)(&key)^);
 		case: panic("Unhandled integer size");
 		}
-	case Type_Info.Rune:
+	case Type_Info_Rune:
 		map_key.hash = u128((cast(^rune)&key)^);
-	case Type_Info.Pointer:
+	case Type_Info_Pointer:
 		map_key.hash = u128(uint((^rawptr)(&key)^));
-	case Type_Info.Float:
+	case Type_Info_Float:
 		match 8*size_of(key) {
 		case 32: map_key.hash = u128((^u32)(&key)^);
 		case 64: map_key.hash = u128((^u64)(&key)^);
 		case: panic("Unhandled float size");
 		}
-	case Type_Info.String:
+	case Type_Info_String:
 		str := (^string)(&key)^;
 		map_key.hash = __default_hash_string(str);
 		map_key.str  = str;
@@ -566,10 +570,10 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
 }
 
 
-default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
-                            size, alignment: int,
-                            old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
-	using Allocator.Mode;
+default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
+                               size, alignment: int,
+                               old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
+	using Allocator_Mode;
 
 	match mode {
 	case Alloc:
@@ -788,7 +792,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
 	new_size  := cap * elem_size;
 	allocator := array.allocator;
 
-	new_data := allocator.procedure(allocator.data, Allocator.Mode.Resize, new_size, elem_align, array.data, old_size, 0);
+	new_data := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, elem_align, array.data, old_size, 0);
 	if new_data == nil do return false;
 
 	array.data = new_data;

+ 10 - 9
core/_soft_numbers.odin

@@ -5,16 +5,17 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" {
 	lower_mask :: u128(~u64(0) >> bits_in_dword_2);
 
 
-	TWords :: struct #raw_union {
-		all: u128;
-		using _: struct {
-			when ODIN_ENDIAN == "big" {
-				lo, hi: u64;
-			} else {
-				hi, lo: u64;
-			}
+	when ODIN_ENDIAN == "big" {
+		TWords :: struct #raw_union {
+			all: u128,
+			using _: struct {lo, hi: u64},
 		};
-	};
+	} else {
+		TWords :: struct #raw_union {
+			all: u128,
+			using _: struct {hi, lo: u64},
+		};
+	}
 
 	r: TWords;
 	t: u64;

+ 4 - 4
core/decimal.odin

@@ -3,10 +3,10 @@
 // NOTE: This is only for floating point printing and nothing else
 
 Decimal :: struct {
-	digits:        [384]u8; // big-endian digits
-	count:         int;
-	decimal_point: int;
-	neg, trunc:    bool;
+	digits:        [384]u8, // big-endian digits
+	count:         int,
+	decimal_point: int,
+	neg, trunc:    bool,
 }
 
 decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {

+ 62 - 66
core/fmt.odin

@@ -14,23 +14,23 @@ String_Buffer :: union {
 }
 
 Fmt_Info :: struct {
-	minus:     bool;
-	plus:      bool;
-	space:     bool;
-	zero:      bool;
-	hash:      bool;
-	width_set: bool;
-	prec_set:  bool;
-
-	width:     int;
-	prec:      int;
-	indent:    int;
-
-	reordered:      bool;
-	good_arg_index: bool;
-
-	buf: ^String_Buffer;
-	arg: any; // Temporary
+	minus:     bool,
+	plus:      bool,
+	space:     bool,
+	zero:      bool,
+	hash:      bool,
+	width_set: bool,
+	prec_set:  bool,
+
+	width:     int,
+	prec:      int,
+	indent:    int,
+
+	reordered:      bool,
+	good_arg_index: bool,
+
+	buf: ^String_Buffer,
+	arg: any, // Temporary
 }
 
 
@@ -179,11 +179,10 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		return;
 	}
 
-	using Type_Info;
 	match info in ti.variant {
-	case Named:
+	case Type_Info_Named:
 		write_string(buf, info.name);
-	case Integer:
+	case Type_Info_Integer:
 		match {
 		case ti == type_info_of(int):  write_string(buf, "int");
 		case ti == type_info_of(uint): write_string(buf, "uint");
@@ -192,38 +191,38 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 			else           do write_byte(buf, 'u');
 			write_int(buf, i64(8*ti.size), 10);
 		}
-	case Rune:
+	case Type_Info_Rune:
 		write_string(buf, "rune");
-	case Float:
+	case Type_Info_Float:
 		match ti.size {
 		case 2: write_string(buf, "f16");
 		case 4: write_string(buf, "f32");
 		case 8: write_string(buf, "f64");
 		}
-	case Complex:
+	case Type_Info_Complex:
 		match ti.size {
 		case 4:  write_string(buf, "complex32");
 		case 8:  write_string(buf, "complex64");
 		case 16: write_string(buf, "complex128");
 		}
-	case String:  write_string(buf, "string");
-	case Boolean: write_string(buf, "bool");
-	case Any:
+	case Type_Info_String:  write_string(buf, "string");
+	case Type_Info_Boolean: write_string(buf, "bool");
+	case Type_Info_Any:
 		write_string(buf, "any");
 
-	case Pointer:
+	case Type_Info_Pointer:
 		if info.elem == nil {
 			write_string(buf, "rawptr");
 		} else {
 			write_string(buf, "^");
 			write_type(buf, info.elem);
 		}
-	case Procedure:
+	case Type_Info_Procedure:
 		write_string(buf, "proc");
 		if info.params == nil {
 			write_string(buf, "()");
 		} else {
-			t := info.params.variant.(Tuple);
+			t := info.params.variant.(Type_Info_Tuple);
 			write_string(buf, "(");
 			for t, i in t.types {
 				if i > 0 do write_string(buf, ", ");
@@ -235,7 +234,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 			write_string(buf, " -> ");
 			write_type(buf, info.results);
 		}
-	case Tuple:
+	case Type_Info_Tuple:
 		count := len(info.names);
 		if count != 1 do write_string(buf, "(");
 		for name, i in info.names {
@@ -251,31 +250,31 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		}
 		if count != 1 do write_string(buf, ")");
 
-	case Array:
+	case Type_Info_Array:
 		write_string(buf, "[");
 		fi := Fmt_Info{buf = buf};
 		write_int(buf, i64(info.count), 10);
 		write_string(buf, "]");
 		write_type(buf, info.elem);
-	case Dynamic_Array:
+	case Type_Info_Dynamic_Array:
 		write_string(buf, "[dynamic]");
 		write_type(buf, info.elem);
-	case Slice:
+	case Type_Info_Slice:
 		write_string(buf, "[]");
 		write_type(buf, info.elem);
-	case Vector:
+	case Type_Info_Vector:
 		write_string(buf, "[vector ");
 		write_int(buf, i64(info.count), 10);
 		write_string(buf, "]");
 		write_type(buf, info.elem);
 
-	case Map:
+	case Type_Info_Map:
 		write_string(buf, "map[");
 		write_type(buf, info.key);
 		write_byte(buf, ']');
 		write_type(buf, info.value);
 
-	case Struct:
+	case Type_Info_Struct:
 		write_string(buf, "struct ");
 		if info.is_packed    do write_string(buf, "#packed ");
 		if info.is_ordered   do write_string(buf, "#ordered ");
@@ -294,7 +293,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		}
 		write_byte(buf, '}');
 
-	case Union:
+	case Type_Info_Union:
 		write_string(buf, "union {");
 		for variant, i in info.variants {
 			if i > 0 do write_string(buf, ", ");
@@ -302,7 +301,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		}
 		write_string(buf, "}");
 
-	case Enum:
+	case Type_Info_Enum:
 		write_string(buf, "enum ");
 		write_type(buf, info.base);
 		write_string(buf, " {");
@@ -312,7 +311,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		}
 		write_string(buf, "}");
 
-	case Bit_Field:
+	case Type_Info_Bit_Field:
 		write_string(buf, "bit_field ");
 		if ti.align != 1 {
 			write_string(buf, "#align ");
@@ -651,11 +650,10 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 enum_value_to_string :: proc(v: any) -> (string, bool) {
 	v.type_info = type_info_base(v.type_info);
 
-	using Type_Info;
 	match e in v.type_info.variant {
 	case: return "", false;
-	case Enum:
-		get_str :: proc(i: $T, e: Enum) -> (string, bool) {
+	case Type_Info_Enum:
+		get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) {
 			if types.is_string(e.base) {
 				for val, idx in e.values {
 					if v, ok := val.(T); ok && v == i {
@@ -718,10 +716,9 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		return;
 	}
 
-	using Type_Info;
 	match e in v.type_info.variant {
 	case: fmt_bad_verb(fi, verb);
-	case Enum:
+	case Type_Info_Enum:
 		match verb {
 		case: fmt_bad_verb(fi, verb);
 		case 'd', 'f':
@@ -741,11 +738,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		return;
 	}
 
-	using Type_Info;
 	match info in v.type_info.variant {
-	case Named:
+	case Type_Info_Named:
 		match b in info.base.variant {
-		case Struct:
+		case Type_Info_Struct:
 			if verb != 'v' {
 				fmt_bad_verb(fi, verb);
 				return;
@@ -792,21 +788,21 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_value(fi, any{v.data, info.base}, verb);
 		}
 
-	case Boolean:    fmt_arg(fi, v, verb);
-	case Integer:    fmt_arg(fi, v, verb);
-	case Rune:       fmt_arg(fi, v, verb);
-	case Float:      fmt_arg(fi, v, verb);
-	case Complex:    fmt_arg(fi, v, verb);
-	case String:     fmt_arg(fi, v, verb);
+	case Type_Info_Boolean:    fmt_arg(fi, v, verb);
+	case Type_Info_Integer:    fmt_arg(fi, v, verb);
+	case Type_Info_Rune:       fmt_arg(fi, v, verb);
+	case Type_Info_Float:      fmt_arg(fi, v, verb);
+	case Type_Info_Complex:    fmt_arg(fi, v, verb);
+	case Type_Info_String:     fmt_arg(fi, v, verb);
 
-	case Pointer:
+	case Type_Info_Pointer:
 		if v.type_info == type_info_of(^Type_Info) {
 			write_type(fi.buf, (cast(^^Type_Info)v.data)^);
 		} else {
 			fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
 		}
 
-	case Array:
+	case Type_Info_Array:
 		write_byte(fi.buf, '[');
 		defer write_byte(fi.buf, ']');
 		for i in 0..info.count {
@@ -816,7 +812,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_arg(fi, any{rawptr(data), info.elem}, verb);
 		}
 
-	case Dynamic_Array:
+	case Type_Info_Dynamic_Array:
 		write_byte(fi.buf, '[');
 		defer write_byte(fi.buf, ']');
 		array := cast(^raw.Dynamic_Array)v.data;
@@ -827,7 +823,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_arg(fi, any{rawptr(data), info.elem}, verb);
 		}
 
-	case Slice:
+	case Type_Info_Slice:
 		write_byte(fi.buf, '[');
 		defer write_byte(fi.buf, ']');
 		slice := cast(^[]u8)v.data;
@@ -838,7 +834,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_arg(fi, any{rawptr(data), info.elem}, verb);
 		}
 
-	case Vector:
+	case Type_Info_Vector:
 		write_byte(fi.buf, '<');
 		defer write_byte(fi.buf, '>');
 
@@ -849,7 +845,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_value(fi, any{rawptr(data), info.elem}, verb);
 		}
 
-	case Map:
+	case Type_Info_Map:
 		if verb != 'v' {
 			fmt_bad_verb(fi, verb);
 			return;
@@ -859,9 +855,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		defer write_byte(fi.buf, ']');
 
 		entries    := &((cast(^raw.Map)v.data).entries);
-		gs         := type_info_base(info.generated_struct).variant.(Struct);
-		ed         := type_info_base(gs.types[1]).variant.(Dynamic_Array);
-		entry_type := ed.elem.variant.(Struct);
+		gs         := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
+		ed         := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
+		entry_type := ed.elem.variant.(Type_Info_Struct);
 		entry_size := ed.elem_size;
 
 		for i in 0..entries.len {
@@ -885,7 +881,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 
 
 
-	case Struct:
+	case Type_Info_Struct:
 		if info.is_raw_union {
 			write_string(fi.buf, "(raw_union)");
 			return;
@@ -922,7 +918,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			if hash do write_string(fi.buf, ",\n");
 		}
 
-	case Union:
+	case Type_Info_Union:
 		data := cast(^u8)v.data;
 		tipp := cast(^^Type_Info)(data + info.tag_offset);
 		if data == nil || tipp == nil {
@@ -932,10 +928,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_arg(fi, any{data, ti}, verb);
 		}
 
-	case Enum:
+	case Type_Info_Enum:
 		fmt_enum(fi, v, verb);
 
-	case Procedure:
+	case Type_Info_Procedure:
 		write_type(fi.buf, v.type_info);
 		write_string(fi.buf, " @ ");
 		fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p');

+ 43 - 47
core/mem.odin

@@ -64,9 +64,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
 
 
 
-AllocationHeader :: struct {
-	size: int;
-}
+AllocationHeader :: struct {size: int};
 
 allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
 	header.size = size;
@@ -91,14 +89,14 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
 // Custom allocators
 
 Arena :: struct {
-	backing:    Allocator;
-	memory:     []u8;
-	temp_count: int;
+	backing:    Allocator,
+	memory:     []u8,
+	temp_count: int,
 }
 
 ArenaTempMemory :: struct {
-	arena:          ^Arena;
-	original_count: int;
+	arena:          ^Arena,
+	original_count: int,
 }
 
 
@@ -133,10 +131,10 @@ arena_allocator :: proc(arena: ^Arena) -> Allocator {
 	};
 }
 
-arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
+arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
                              size, alignment: int,
                              old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
-	using Allocator.Mode;
+	using Allocator_Mode;
 	arena := cast(^Arena)allocator_data;
 
 	match mode {
@@ -202,46 +200,45 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
 
 	WORD_SIZE :: size_of(int);
 	MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
-	using Type_Info;
 	match info in type_info.variant {
-	case Named:
+	case Type_Info_Named:
 		return align_of_type_info(info.base);
-	case Integer:
+	case Type_Info_Integer:
 		return type_info.align;
-	case Rune:
+	case Type_Info_Rune:
 		return type_info.align;
-	case Float:
+	case Type_Info_Float:
 		return type_info.align;
-	case String:
+	case Type_Info_String:
 		return WORD_SIZE;
-	case Boolean:
+	case Type_Info_Boolean:
 		return 1;
-	case Any:
+	case Type_Info_Any:
 		return WORD_SIZE;
-	case Pointer:
+	case Type_Info_Pointer:
 		return WORD_SIZE;
-	case Procedure:
+	case Type_Info_Procedure:
 		return WORD_SIZE;
-	case Array:
+	case Type_Info_Array:
 		return align_of_type_info(info.elem);
-	case Dynamic_Array:
+	case Type_Info_Dynamic_Array:
 		return WORD_SIZE;
-	case Slice:
+	case Type_Info_Slice:
 		return WORD_SIZE;
-	case Vector:
+	case Type_Info_Vector:
 		size  := size_of_type_info(info.elem);
 		count := int(max(prev_pow2(i64(info.count)), 1));
 		total := size * count;
 		return clamp(total, 1, MAX_ALIGN);
-	case Tuple:
+	case Type_Info_Tuple:
 		return type_info.align;
-	case Struct:
+	case Type_Info_Struct:
 		return type_info.align;
-	case Union:
+	case Type_Info_Union:
 		return type_info.align;
-	case Enum:
+	case Type_Info_Enum:
 		return align_of_type_info(info.base);
-	case Map:
+	case Type_Info_Map:
 		return align_of_type_info(info.generated_struct);
 	}
 
@@ -255,51 +252,50 @@ align_formula :: proc(size, align: int) -> int {
 
 size_of_type_info :: proc(type_info: ^Type_Info) -> int {
 	WORD_SIZE :: size_of(int);
-	using Type_Info;
 	match info in type_info.variant {
-	case Named:
+	case Type_Info_Named:
 		return size_of_type_info(info.base);
-	case Integer:
+	case Type_Info_Integer:
 		return type_info.size;
-	case Rune:
+	case Type_Info_Rune:
 		return type_info.size;
-	case Float:
+	case Type_Info_Float:
 		return type_info.size;
-	case String:
+	case Type_Info_String:
 		return 2*WORD_SIZE;
-	case Boolean:
+	case Type_Info_Boolean:
 		return 1;
-	case Any:
+	case Type_Info_Any:
 		return 2*WORD_SIZE;
-	case Pointer:
+	case Type_Info_Pointer:
 		return WORD_SIZE;
-	case Procedure:
+	case Type_Info_Procedure:
 		return WORD_SIZE;
-	case Array:
+	case Type_Info_Array:
 		count := info.count;
 		if count == 0 do return 0;
 		size      := size_of_type_info(info.elem);
 		align     := align_of_type_info(info.elem);
 		alignment := align_formula(size, align);
 		return alignment*(count-1) + size;
-	case Dynamic_Array:
+	case Type_Info_Dynamic_Array:
 		return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
-	case Slice:
+	case Type_Info_Slice:
 		return 2*WORD_SIZE;
-	case Vector:
+	case Type_Info_Vector:
 		count := info.count;
 		if count == 0 do return 0;
 		size      := size_of_type_info(info.elem);
 		align     := align_of_type_info(info.elem);
 		alignment := align_formula(size, align);
 		return alignment*(count-1) + size;
-	case Struct:
+	case Type_Info_Struct:
 		return type_info.size;
-	case Union:
+	case Type_Info_Union:
 		return type_info.size;
-	case Enum:
+	case Type_Info_Enum:
 		return size_of_type_info(info.base);
-	case Map:
+	case Type_Info_Map:
 		return size_of_type_info(info.generated_struct);
 	}
 

+ 21 - 21
core/os_linux.odin

@@ -40,9 +40,9 @@ RTLD_GLOBAL       :: 0x100;
 args := _alloc_command_line_arguments();
 
 _File_Time :: struct #ordered {
-	seconds:     i64;
-	nanoseconds: i32;
-	reserved:    i32;
+	seconds:     i64,
+	nanoseconds: i32,
+	reserved:    i32,
 }
 
 // Translated from
@@ -50,27 +50,27 @@ _File_Time :: struct #ordered {
 // Validity is not guaranteed.
 
 Stat :: struct #ordered {
-	device_id:     u64; // ID of device containing file
-	serial:        u64; // File serial number
-	nlink:         u32; // Number of hard links
-	mode:          u32; // Mode of the file
-	uid:           u32; // User ID of the file's owner
-	gid:           u32; // Group ID of the file's group
-	_padding:      i32; // 32 bits of padding
-	rdev:          u64; // Device ID, if device
-	size:          i64; // Size of the file, in bytes
-	block_size:    i64; // Optimal bllocksize for I/O
-	blocks:        i64; // Number of 512-byte blocks allocated
-
-	last_access:   _File_Time; // Time of last access
-	modified:      _File_Time; // Time of last modification
-	status_change: _File_Time; // Time of last status change
+	device_id:     u64, // ID of device containing file
+	serial:        u64, // File serial number
+	nlink:         u32, // Number of hard links
+	mode:          u32, // Mode of the file
+	uid:           u32, // User ID of the file's owner
+	gid:           u32, // Group ID of the file's group
+	_padding:      i32, // 32 bits of padding
+	rdev:          u64, // Device ID, if device
+	size:          i64, // Size of the file, in bytes
+	block_size:    i64, // Optimal bllocksize for I/O
+	blocks:        i64, // Number of 512-byte blocks allocated
+
+	last_access:   _File_Time, // Time of last access
+	modified:      _File_Time, // Time of last modification
+	status_change: _File_Time, // Time of last status change
 
 	_reserve1,
 	_reserve2,
-	_reserve3:     i64;
-	serial_numbe:  u64; // File serial number...? Maybe.
-	_reserve4:     i64;
+	_reserve3:     i64,
+	serial_numbe:  u64, // File serial number...? Maybe.
+	_reserve4:     i64,
 };
 
 // File type

+ 22 - 22
core/os_x.odin

@@ -45,32 +45,32 @@ RTLD_FIRST    :: 0x100;
 args: [dynamic]string;
 
 _File_Time :: struct #ordered {
-	seconds: i64;
-	nanoseconds: i64;
+	seconds: i64,
+	nanoseconds: i64,
 }
 
 Stat :: struct #ordered {
-	device_id:     i32; // ID of device containing file
-	mode:          u16; // Mode of the file
-	nlink:         u16; // Number of hard links
-	serial:        u64; // File serial number
-	uid:           u32; // User ID of the file's owner
-	gid:           u32; // Group ID of the file's group
-	rdev:          i32; // Device ID, if device
-
-	last_access:   File_Time; // Time of last access
-	modified:      File_Time; // Time of last modification
-	status_change: File_Time; // Time of last status change
-	created:       File_Time; // Time of creation
-
-	size:          i64;  // Size of the file, in bytes
-	blocks:        i64;  // Number of blocks allocated for the file
-	block_size:    i32;  // Optimal blocksize for I/O
-	flags:         u32;  // User-defined flags for the file
-	gen_num:       u32;  // File generation number ...?
-	_spare:        i32;  // RESERVED
+	device_id:     i32, // ID of device containing file
+	mode:          u16, // Mode of the file
+	nlink:         u16, // Number of hard links
+	serial:        u64, // File serial number
+	uid:           u32, // User ID of the file's owner
+	gid:           u32, // Group ID of the file's group
+	rdev:          i32, // Device ID, if device
+
+	last_access:   File_Time, // Time of last access
+	modified:      File_Time, // Time of last modification
+	status_change: File_Time, // Time of last status change
+	created:       File_Time, // Time of creation
+
+	size:          i64,  // Size of the file, in bytes
+	blocks:        i64,  // Number of blocks allocated for the file
+	block_size:    i32,  // Optimal blocksize for I/O
+	flags:         u32,  // User-defined flags for the file
+	gen_num:       u32,  // File generation number ...?
+	_spare:        i32,  // RESERVED
 	_reserve1,
-	_reserve2:     i64;  // RESERVED
+	_reserve2:     i64,  // RESERVED
 };
 
 // File type

+ 18 - 18
core/raw.odin

@@ -1,28 +1,28 @@
 Any :: struct #ordered {
-	data:      rawptr;
-	type_info: ^Type_Info;
-};
+	data:      rawptr,
+	type_info: ^Type_Info,
+}
 
 String :: struct #ordered {
-	data: ^u8;
-	len:  int;
-};
+	data: ^u8,
+	len:  int,
+}
 
 Slice :: struct #ordered {
-	data: rawptr;
-	len:  int;
-	cap:  int;
-};
+	data: rawptr,
+	len:  int,
+	cap:  int,
+}
 
 Dynamic_Array :: struct #ordered {
-	data:      rawptr;
-	len:       int;
-	cap:       int;
-	allocator: Allocator;
-};
+	data:      rawptr,
+	len:       int,
+	cap:       int,
+	allocator: Allocator,
+}
 
 Map :: struct #ordered {
-	hashes:  [dynamic]int;
-	entries: Dynamic_Array;
-};
+	hashes:  [dynamic]int,
+	entries: Dynamic_Array,
+}
 

+ 7 - 7
core/strconv.odin

@@ -202,16 +202,16 @@ append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string
 
 
 DecimalSlice :: struct {
-	digits:        []u8;
-	count:         int;
-	decimal_point: int;
-	neg:           bool;
+	digits:        []u8,
+	count:         int,
+	decimal_point: int,
+	neg:           bool,
 }
 
 FloatInfo :: struct {
-	mantbits: uint;
-	expbits:  uint;
-	bias:     int;
+	mantbits: uint,
+	expbits:  uint,
+	bias:     int,
 }
 
 

+ 5 - 5
core/sync_linux.odin

@@ -2,14 +2,14 @@ import "core:atomics.odin";
 import "core:os.odin";
 
 Semaphore :: struct {
-	// _handle: win32.Handle;
+	// _handle: win32.Handle,
 }
 
 Mutex :: struct {
-	_semaphore: Semaphore;
-	_counter:   i32;
-	_owner:     i32;
-	_recursion: i32;
+	_semaphore: Semaphore,
+	_counter:   i32,
+	_owner:     i32,
+	_recursion: i32,
 }
 
 current_thread_id :: proc() -> i32 {

+ 6 - 6
core/sync_windows.odin

@@ -2,20 +2,20 @@ when ODIN_OS == "windows" do import win32 "core:sys/windows.odin";
 import "core:atomics.odin";
 
 Semaphore :: struct {
-	_handle: win32.Handle;
+	_handle: win32.Handle,
 }
 
 /*
 Mutex :: struct {
-	_semaphore: Semaphore;
-	_counter:   i32;
-	_owner:     i32;
-	_recursion: i32;
+	_semaphore: Semaphore,
+	_counter:   i32,
+	_owner:     i32,
+	_recursion: i32,
 }
 */
 
 Mutex :: struct {
-	_critical_section: win32.Critical_Section;
+	_critical_section: win32.Critical_Section,
 }
 
 current_thread_id :: proc() -> i32 {

+ 29 - 29
core/sys/wgl.odin

@@ -14,40 +14,40 @@ Hglrc     :: Handle;
 Color_Ref :: u32;
 
 Layer_Plane_Descriptor :: struct {
-	size:             u16;
-	version:          u16;
-	flags:            u32;
-	pixel_type:       u8;
-	color_bits:       u8;
-	red_bits:         u8;
-	red_shift:        u8;
-	green_bits:       u8;
-	green_shift:      u8;
-	blue_bits:        u8;
-	blue_shift:       u8;
-	alpha_bits:       u8;
-	alpha_shift:      u8;
-	accum_bits:       u8;
-	accum_red_bits:   u8;
-	accum_green_bits: u8;
-	accum_blue_bits:  u8;
-	accum_alpha_bits: u8;
-	depth_bits:       u8;
-	stencil_bits:     u8;
-	aux_buffers:      u8;
-	layer_type:       u8;
-	reserved:         u8;
-	transparent:      Color_Ref;
+	size:             u16,
+	version:          u16,
+	flags:            u32,
+	pixel_type:       u8,
+	color_bits:       u8,
+	red_bits:         u8,
+	red_shift:        u8,
+	green_bits:       u8,
+	green_shift:      u8,
+	blue_bits:        u8,
+	blue_shift:       u8,
+	alpha_bits:       u8,
+	alpha_shift:      u8,
+	accum_bits:       u8,
+	accum_red_bits:   u8,
+	accum_green_bits: u8,
+	accum_blue_bits:  u8,
+	accum_alpha_bits: u8,
+	depth_bits:       u8,
+	stencil_bits:     u8,
+	aux_buffers:      u8,
+	layer_type:       u8,
+	reserved:         u8,
+	transparent:      Color_Ref,
 }
 
 Point_Float :: struct {x, y: f32};
 
 Glyph_Metrics_Float :: struct {
-	black_box_x:  f32;
-	black_box_y:  f32;
-	glyph_origin: Point_Float;
-	cell_inc_x:   f32;
-	cell_inc_y:   f32;
+	black_box_x:  f32,
+	black_box_y:  f32,
+	glyph_origin: Point_Float,
+	cell_inc_x:   f32,
+	cell_inc_y:   f32,
 }
 
 Create_Context_Attribs_ARB_Type :: #type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;

+ 82 - 82
core/sys/windows.odin

@@ -27,86 +27,86 @@ FALSE: Bool : 0;
 TRUE:  Bool : 1;
 
 Point :: struct #ordered {
-	x, y: i32;
+	x, y: i32,
 }
 
 Wnd_Class_Ex_A :: struct #ordered {
-	size, style:           u32;
-	wnd_proc:              Wnd_Proc;
-	cls_extra, wnd_extra:  i32;
-	instance:              Hinstance;
-	icon:                  Hicon;
-	cursor:                Hcursor;
-	background:            Hbrush;
-	menu_name, class_name: ^u8;
-	sm:                    Hicon;
+	size, style:           u32,
+	wnd_proc:              Wnd_Proc,
+	cls_extra, wnd_extra:  i32,
+	instance:              Hinstance,
+	icon:                  Hicon,
+	cursor:                Hcursor,
+	background:            Hbrush,
+	menu_name, class_name: ^u8,
+	sm:                    Hicon,
 }
 
 Msg :: struct #ordered {
-	hwnd:    Hwnd;
-	message: u32;
-	wparam:  Wparam;
-	lparam:  Lparam;
-	time:    u32;
-	pt:      Point;
+	hwnd:    Hwnd,
+	message: u32,
+	wparam:  Wparam,
+	lparam:  Lparam,
+	time:    u32,
+	pt:      Point,
 }
 
 Rect :: struct #ordered {
-	left:   i32;
-	top:    i32;
-	right:  i32;
-	bottom: i32;
+	left:   i32,
+	top:    i32,
+	right:  i32,
+	bottom: i32,
 }
 
 Filetime :: struct #ordered {
-	lo, hi: u32;
+	lo, hi: u32,
 }
 
 Systemtime :: struct #ordered {
-	year, month: u16;
-	day_of_week, day: u16;
-	hour, minute, second, millisecond: u16;
+	year, month: u16,
+	day_of_week, day: u16,
+	hour, minute, second, millisecond: u16,
 }
 
 By_Handle_File_Information :: struct #ordered {
-	file_attributes:      u32;
+	file_attributes:      u32,
 	creation_time,
 	last_access_time,
-	last_write_time:      Filetime;
+	last_write_time:      Filetime,
 	volume_serial_number,
 	file_size_high,
 	file_size_low,
 	number_of_links,
 	file_index_high,
-	file_index_low:       u32;
+	file_index_low:       u32,
 }
 
 File_Attribute_Data :: struct #ordered {
-	file_attributes:  u32;
+	file_attributes:  u32,
 	creation_time,
 	last_access_time,
-	last_write_time:  Filetime;
+	last_write_time:  Filetime,
 	file_size_high,
-	file_size_low:    u32;
+	file_size_low:    u32,
 }
 
 Find_Data :: struct #ordered{
-    file_attributes:     u32;
-    creation_time:       Filetime;
-    last_access_time:    Filetime;
-    last_write_time:     Filetime;
-    file_size_high:      u32;
-    file_size_low:       u32;
-    reserved0:           u32;
-    reserved1:           u32;
-    file_name:           [MAX_PATH]u8;
-    alternate_file_name: [14]u8;
+    file_attributes:     u32,
+    creation_time:       Filetime,
+    last_access_time:    Filetime,
+    last_write_time:     Filetime,
+    file_size_high:      u32,
+    file_size_low:       u32,
+    reserved0:           u32,
+    reserved1:           u32,
+    file_name:           [MAX_PATH]u8,
+    alternate_file_name: [14]u8,
 }
 
 Security_Attributes :: struct #ordered {
-	length:              u32;
-	security_descriptor: rawptr;
-	inherit_handle:      Bool;
+	length:              u32,
+	security_descriptor: rawptr,
+	inherit_handle:      Bool,
 }
 
 
@@ -114,7 +114,7 @@ Security_Attributes :: struct #ordered {
 Pixel_Format_Descriptor :: struct #ordered {
 	size,
 	version,
-	flags: u32;
+	flags: u32,
 
 	pixel_type,
 	color_bits,
@@ -135,33 +135,33 @@ Pixel_Format_Descriptor :: struct #ordered {
 	stencil_bits,
 	aux_buffers,
 	layer_type,
-	reserved: u8;
+	reserved: u8,
 
 	layer_mask,
 	visible_mask,
-	damage_mask: u32;
+	damage_mask: u32,
 }
 
 Critical_Section :: struct #ordered {
-	debug_info:      ^Critical_Section_Debug;
+	debug_info:      ^Critical_Section_Debug,
 
-	lock_count:      i32;
-	recursion_count: i32;
-	owning_thread:   Handle;
-	lock_semaphore:  Handle;
-	spin_count:      ^u32;
+	lock_count:      i32,
+	recursion_count: i32,
+	owning_thread:   Handle,
+	lock_semaphore:  Handle,
+	spin_count:      ^u32,
 }
 
 Critical_Section_Debug :: struct #ordered {
-	typ:                           u16;
-	creator_back_trace_index:      u16;
-	critical_section:              ^Critical_Section;
-	process_locks_list:            ^List_Entry;
-	entry_count:                   u32;
-	contention_count:              u32;
-	flags:                         u32;
-	creator_back_trace_index_high: u16;
-	spare_word:                    u16;
+	typ:                           u16,
+	creator_back_trace_index:      u16,
+	critical_section:              ^Critical_Section,
+	process_locks_list:            ^List_Entry,
+	entry_count:                   u32,
+	contention_count:              u32,
+	flags:                         u32,
+	creator_back_trace_index_high: u16,
+	spare_word:                    u16,
 }
 
 List_Entry :: struct #ordered {flink, blink: ^List_Entry};
@@ -546,35 +546,35 @@ FILE_TYPE_PIPE :: 0x0003;
 
 
 Monitor_Info :: struct #ordered {
-	size:      u32;
-	monitor:   Rect;
-	work:      Rect;
-	flags:     u32;
+	size:      u32,
+	monitor:   Rect,
+	work:      Rect,
+	flags:     u32,
 }
 
 Window_Placement :: struct #ordered {
-	length:     u32;
-	flags:      u32;
-	show_cmd:   u32;
-	min_pos:    Point;
-	max_pos:    Point;
-	normal_pos: Rect;
+	length:     u32,
+	flags:      u32,
+	show_cmd:   u32,
+	min_pos:    Point,
+	max_pos:    Point,
+	normal_pos: Rect,
 }
 
 Bitmap_Info_Header :: struct #ordered {
-	size:              u32;
-	width, height:     i32;
-	planes, bit_count: i16;
-	compression:       u32;
-	size_image:        u32;
-	x_pels_per_meter:  i32;
-	y_pels_per_meter:  i32;
-	clr_used:          u32;
-	clr_important:     u32;
+	size:              u32,
+	width, height:     i32,
+	planes, bit_count: i16,
+	compression:       u32,
+	size_image:        u32,
+	x_pels_per_meter:  i32,
+	y_pels_per_meter:  i32,
+	clr_used:          u32,
+	clr_important:     u32,
 }
 Bitmap_Info :: struct #ordered {
-	using header: Bitmap_Info_Header;
-	colors:       [1]Rgb_Quad;
+	using header: Bitmap_Info_Header,
+	colors:       [1]Rgb_Quad,
 }
 
 

+ 15 - 14
core/thread.odin

@@ -4,24 +4,25 @@ when ODIN_OS == "windows" {
 	import win32 "core:sys/windows.odin";
 }
 
+Thread_Proc :: #type proc(^Thread) -> int;
+
+Thread_Os_Specific :: struct {
+	win32_thread:    win32.Handle,
+	win32_thread_id: u32,
+}
+
 Thread :: struct {
-	using specific:   Os_Specific;
-	procedure:        Proc;
-	data:             any;
-	user_index:       int;
-
-	init_context:     Context;
-	use_init_context: bool;
-
-	Proc :: #type proc(^Thread) -> int;
-	Os_Specific :: struct {
-		win32_thread:    win32.Handle;
-		win32_thread_id: u32;
-	}
+	using specific:   Thread_Os_Specific,
+	procedure:        Thread_Proc,
+	data:             any,
+	user_index:       int,
+
+	init_context:     Context,
+	use_init_context: bool,
 }
 
 
-create :: proc(procedure: Thread.Proc) -> ^Thread {
+create :: proc(procedure: Thread_Proc) -> ^Thread {
 	win32_thread_id: u32;
 
 	__windows_thread_entry_proc :: proc(data: rawptr) -> i32 #cc_c {

+ 21 - 21
core/types.odin

@@ -1,103 +1,103 @@
 is_signed :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
 	match i in type_info_base(info).variant {
-	case Type_Info.Integer: return i.signed;
-	case Type_Info.Float:   return true;
+	case Type_Info_Integer: return i.signed;
+	case Type_Info_Float:   return true;
 	}
 	return false;
 }
 is_integer :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Integer);
+	_, ok := type_info_base(info).variant.(Type_Info_Integer);
 	return ok;
 }
 is_rune :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Rune);
+	_, ok := type_info_base(info).variant.(Type_Info_Rune);
 	return ok;
 }
 is_float :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Float);
+	_, ok := type_info_base(info).variant.(Type_Info_Float);
 	return ok;
 }
 is_complex :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Complex);
+	_, ok := type_info_base(info).variant.(Type_Info_Complex);
 	return ok;
 }
 is_any :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Any);
+	_, ok := type_info_base(info).variant.(Type_Info_Any);
 	return ok;
 }
 is_string :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.String);
+	_, ok := type_info_base(info).variant.(Type_Info_String);
 	return ok;
 }
 is_boolean :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Boolean);
+	_, ok := type_info_base(info).variant.(Type_Info_Boolean);
 	return ok;
 }
 is_pointer :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Pointer);
+	_, ok := type_info_base(info).variant.(Type_Info_Pointer);
 	return ok;
 }
 is_procedure :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Procedure);
+	_, ok := type_info_base(info).variant.(Type_Info_Procedure);
 	return ok;
 }
 is_array :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Array);
+	_, ok := type_info_base(info).variant.(Type_Info_Array);
 	return ok;
 }
 is_dynamic_array :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Dynamic_Array);
+	_, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array);
 	return ok;
 }
 is_dynamic_map :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Map);
+	_, ok := type_info_base(info).variant.(Type_Info_Map);
 	return ok;
 }
 is_slice :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Slice);
+	_, ok := type_info_base(info).variant.(Type_Info_Slice);
 	return ok;
 }
 is_vector :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Vector);
+	_, ok := type_info_base(info).variant.(Type_Info_Vector);
 	return ok;
 }
 is_tuple :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Tuple);
+	_, ok := type_info_base(info).variant.(Type_Info_Tuple);
 	return ok;
 }
 is_struct :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	s, ok := type_info_base(info).variant.(Type_Info.Struct);
+	s, ok := type_info_base(info).variant.(Type_Info_Struct);
 	return ok && !s.is_raw_union;
 }
 is_raw_union :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	s, ok := type_info_base(info).variant.(Type_Info.Struct);
+	s, ok := type_info_base(info).variant.(Type_Info_Struct);
 	return ok && s.is_raw_union;
 }
 is_union :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Union);
+	_, ok := type_info_base(info).variant.(Type_Info_Union);
 	return ok;
 }
 is_enum :: proc(info: ^Type_Info) -> bool {
 	if info == nil do return false;
-	_, ok := type_info_base(info).variant.(Type_Info.Enum);
+	_, ok := type_info_base(info).variant.(Type_Info_Enum);
 	return ok;
 }

+ 45 - 71
examples/demo.odin

@@ -58,8 +58,8 @@ general_stuff :: proc() {
 
 	{ // `expand_to_tuple` built-in procedure
 		Foo :: struct {
-			x: int;
-			b: bool;
+			x: int,
+			b: bool,
 		}
 		f := Foo{137, true};
 		x, b := expand_to_tuple(f);
@@ -77,31 +77,12 @@ general_stuff :: proc() {
 	}
 }
 
-nested_struct_declarations :: proc() {
-	{
-		FooInteger :: int;
-		Foo :: struct {
-			i: FooInteger;
-		};
-		f := Foo{FooInteger(137)};
-	}
-	{
-		Foo :: struct {
-			Integer :: int;
-
-			i: Integer;
-		}
-		f := Foo{Foo.Integer(137)};
-
-	}
-}
-
 default_struct_values :: proc() {
 	{
 		Vector3 :: struct {
-			x: f32;
-			y: f32;
-			z: f32;
+			x: f32,
+			y: f32,
+			z: f32,
 		}
 		v: Vector3;
 		fmt.println(v);
@@ -109,9 +90,9 @@ default_struct_values :: proc() {
 	{
 		// Default values must be constants
 		Vector3 :: struct {
-			x: f32 = 1;
-			y: f32 = 4;
-			z: f32 = 9;
+			x: f32 = 1,
+			y: f32 = 4,
+			z: f32 = 9,
 		}
 		v: Vector3;
 		fmt.println(v);
@@ -129,9 +110,9 @@ default_struct_values :: proc() {
 
 	{
 		Vector3 :: struct {
-			x := 1.0;
-			y := 4.0;
-			z := 9.0;
+			x := 1.0,
+			y := 4.0,
+			z := 9.0,
 		}
 		stack_default: Vector3;
 		stack_literal := Vector3{};
@@ -197,13 +178,8 @@ union_type :: proc() {
 		}
 	}
 
-	Vector3 :: struct {
-		x, y, z: f32;
-	};
-	Quaternion :: struct {
-		x, y, z: f32;
-		w: f32 = 1;
-	};
+	Vector3 :: struct {x, y, z: f32};
+	Quaternion :: struct {x, y, z: f32, w: f32 = 1};
 
 	// More realistic examples
 	{
@@ -214,23 +190,23 @@ union_type :: proc() {
 		// an example of this for a basic game Entity.
 
 		Entity :: struct {
-			id:          u64;
-			name:        string;
-			position:    Vector3;
-			orientation: Quaternion;
+			id:          u64,
+			name:        string,
+			position:    Vector3,
+			orientation: Quaternion,
 
-			derived: any;
+			derived: any,
 		}
 
 		Frog :: struct {
-			using entity: Entity;
-			jump_height:  f32;
+			using entity: Entity,
+			jump_height:  f32,
 		}
 
 		Monster :: struct {
-			using entity: Entity;
-			is_robot:     bool;
-			is_zombie:    bool;
+			using entity: Entity,
+			is_robot:     bool,
+			is_zombie:    bool,
 		}
 
 		// See `parametric_polymorphism` procedure for details
@@ -258,23 +234,23 @@ union_type :: proc() {
 		// basic game Entity but using an union.
 
 		Entity :: struct {
-			id:          u64;
-			name:        string;
-			position:    Vector3;
-			orientation: Quaternion;
+			id:          u64,
+			name:        string,
+			position:    Vector3,
+			orientation: Quaternion,
 
-			derived: union {Frog, Monster};
+			derived: union {Frog, Monster},
 		}
 
 		Frog :: struct {
-			using entity: ^Entity;
-			jump_height:  f32;
+			using entity: ^Entity,
+			jump_height:  f32,
 		}
 
 		Monster :: struct {
-			using entity: ^Entity;
-			is_robot:     bool;
-			is_zombie:    bool;
+			using entity: ^Entity,
+			is_robot:     bool,
+			is_zombie:    bool,
 		}
 
 		// See `parametric_polymorphism` procedure for details
@@ -386,18 +362,17 @@ parametric_polymorphism :: proc() {
 
 
 	{ // Polymorphic Types and Type Specialization
+		Table_Slot :: struct(Key, Value: type) {
+			occupied: bool,
+			hash:     u32,
+			key:      Key,
+			value:    Value,
+		}
+		TABLE_SIZE_MIN :: 32;
 		Table :: struct(Key, Value: type) {
-			Slot :: struct {
-				occupied: bool;
-				hash:     u32;
-				key:      Key;
-				value:    Value;
-			}
-			SIZE_MIN :: 32;
-
-			count:           int;
-			allocator:       Allocator;
-			slots:           []Slot;
+			count:     int,
+			allocator: Allocator,
+			slots:     []Table_Slot(Key, Value),
 		}
 
 		// Only allow types that are specializations of a (polymorphic) slice
@@ -412,7 +387,7 @@ parametric_polymorphism :: proc() {
 			if table.allocator.procedure != nil do c.allocator = table.allocator;
 
 			push_context c {
-				table.slots = make_slice([]T.Slot, max(capacity, T.SIZE_MIN));
+				table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
 			}
 		}
 
@@ -423,7 +398,7 @@ parametric_polymorphism :: proc() {
 			push_context c {
 				old_slots := table.slots;
 
-				cap := max(2*cap(table.slots), T.SIZE_MIN);
+				cap := max(2*cap(table.slots), TABLE_SIZE_MIN);
 				allocate(table, cap);
 
 				for s in old_slots do if s.occupied {
@@ -588,7 +563,6 @@ threading_example :: proc() {
 main :: proc() {
 	when false {
 		fmt.println("\n# general_stuff");              general_stuff();
-		fmt.println("\n# nested_struct_declarations"); nested_struct_declarations();
 		fmt.println("\n# default_struct_values");      default_struct_values();
 		fmt.println("\n# union_type");                 union_type();
 		fmt.println("\n# parametric_polymorphism");    parametric_polymorphism();

+ 142 - 45
src/check_expr.cpp

@@ -986,8 +986,8 @@ void check_struct_field_decl(Checker *c, AstNode *decl, Array<Entity *> *fields,
 }
 
 // Returns filled field_count
-Array<Entity *> check_fields(Checker *c, AstNode *node, Array<AstNode *> decls,
-                             isize init_field_capacity, String context) {
+Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *> params,
+                                    isize init_field_capacity, String context) {
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
 	defer (gb_temp_arena_memory_end(tmp));
 
@@ -998,30 +998,152 @@ Array<Entity *> check_fields(Checker *c, AstNode *node, Array<AstNode *> decls,
 	map_init(&entity_map, c->tmp_allocator, 2*init_field_capacity);
 
 
-	if (node != nullptr) {
-		GB_ASSERT(node->kind != AstNode_UnionType);
+	GB_ASSERT(node->kind == AstNode_StructType);
+
+	isize variable_count = 0;
+	for_array(i, params) {
+		AstNode *field = params[i];
+		if (ast_node_expect(field, AstNode_Field)) {
+			ast_node(f, Field, field);
+			variable_count += gb_max(f->names.count, 1);
+		}
 	}
 
-	check_collect_entities(c, decls);
-	for_array(i, c->context.scope->elements.entries) {
-		Entity *e = c->context.scope->elements.entries[i].value;
-		DeclInfo *d = nullptr;
-		switch (e->kind) {
-		default: continue;
-		case Entity_Constant:
-		case Entity_TypeName:
-			d = decl_info_of_entity(&c->info, e);
-			if (d != nullptr) {
-				check_entity_decl(c, e, d, nullptr);
+	i32 field_src_index = 0;
+	for_array(i, params) {
+		AstNode *param = params[i];
+		if (param->kind != AstNode_Field) {
+			continue;
+		}
+		ast_node(p, Field, param);
+		AstNode *type_expr = p->type;
+		Type *type = nullptr;
+		AstNode *default_value = unparen_expr(p->default_value);
+		ExactValue value = {};
+		bool default_is_nil = false;
+		bool detemine_type_from_operand = false;
+
+
+		if (type_expr == nullptr) {
+			Operand o = {};
+			check_expr_or_type(c, &o, default_value);
+			if (is_operand_nil(o)) {
+				default_is_nil = true;
+			} else if (o.mode != Addressing_Constant) {
+				error(default_value, "Default parameter must be a constant");
+			} else {
+				value = o.value;
+			}
+
+			type = default_type(o.type);
+		} else {
+			type = check_type(c, type_expr);
+
+			if (default_value != nullptr) {
+				Operand o = {};
+				check_expr_with_type_hint(c, &o, default_value, type);
+
+				if (is_operand_nil(o)) {
+					default_is_nil = true;
+				} else if (o.mode != Addressing_Constant) {
+					error(default_value, "Default parameter must be a constant");
+				} else {
+					value = o.value;
+				}
+
+				check_is_assignable_to(c, &o, type);
+			}
+
+			if (is_type_polymorphic(type)) {
+				type = nullptr;
 			}
-			break;
 		}
-	}
+		if (type == nullptr) {
+			error(params[i], "Invalid parameter type");
+			type = t_invalid;
+		}
+		if (is_type_untyped(type)) {
+			if (is_type_untyped_undef(type)) {
+				error(params[i], "Cannot determine parameter type from ---");
+			} else {
+				error(params[i], "Cannot determine parameter type from a nil");
+			}
+			type = t_invalid;
+		}
+		if (is_type_empty_union(type)) {
+			gbString str = type_to_string(type);
+			error(params[i], "Invalid use of an empty union `%s`", str);
+			gb_string_free(str);
+			type = t_invalid;
+		}
+
+		bool is_using = (p->flags&FieldFlag_using) != 0;
+
+		for_array(j, p->names) {
+			AstNode *name = p->names[j];
+			if (!ast_node_expect(name, AstNode_Ident)) {
+				continue;
+			}
 
-	for_array(decl_index, decls) {
-		check_struct_field_decl(c, decls[decl_index], &fields, &entity_map, node, context, context == "struct");
+			Token name_token = name->Ident.token;
+
+			Entity *field = nullptr;
+			field = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, field_src_index);
+			field->Variable.default_value = value;
+			field->Variable.default_is_nil = default_is_nil;
+
+			add_entity(c, c->context.scope, name, field);
+			array_add(&fields, field);
+
+			field_src_index += 1;
+		}
+
+		Entity *using_index_expr = nullptr;
+
+		if (is_using && p->names.count > 0) {
+			Type *first_type = fields[fields.count-1]->type;
+			Type *t = base_type(type_deref(first_type));
+
+			if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) &&
+			    p->names.count >= 1 &&
+			    p->names[0]->kind == AstNode_Ident) {
+				Token name_token = p->names[0]->Ident.token;
+				if (is_type_indexable(t)) {
+					bool ok = true;
+					for_array(emi, entity_map.entries) {
+						Entity *e = entity_map.entries[emi].value;
+						if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) {
+							if (is_type_indexable(e->type)) {
+								if (e->identifier != p->names[0]) {
+									ok = false;
+									using_index_expr = e;
+									break;
+								}
+							}
+						}
+					}
+					if (ok) {
+						using_index_expr = fields[fields.count-1];
+					} else {
+						fields[fields.count-1]->flags &= ~EntityFlag_Using;
+						error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string));
+					}
+				} else {
+					gbString type_str = type_to_string(first_type);
+					error(name_token, "`using` cannot be applied to the field `%.*s` of type `%s`", LIT(name_token.string), type_str);
+					gb_string_free(type_str);
+					continue;
+				}
+			}
+
+			populate_using_entity_map(c, node, type, &entity_map);
+		}
 	}
 
+	// for_array(decl_index, params) {
+		// check_struct_field_decl(c, params[decl_index], &fields, &entity_map, node, context, context == "struct");
+	// }
+
 
 	return fields;
 }
@@ -1278,7 +1400,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
 	Array<Entity *> fields = {};
 
 	if (!is_polymorphic) {
-		fields = check_fields(c, node, st->fields, min_field_count, context);
+		fields = check_struct_fields(c, node, st->fields, min_field_count, context);
 	}
 
 	struct_type->Struct.scope               = c->context.scope;
@@ -1392,31 +1514,6 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
 	}
 }
 
-// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
-// 	GB_ASSERT(node->kind == AstNode_RawUnionType);
-// 	GB_ASSERT(is_type_raw_union(union_type));
-// 	ast_node(ut, RawUnionType, node);
-
-// 	isize min_field_count = 0;
-// 	for_array(i, ut->fields) {
-// 		AstNode *field = ut->fields[i];
-// 		switch (field->kind) {
-// 		case_ast_node(f, ValueDecl, field);
-// 			min_field_count += f->names.count;
-// 		case_end;
-// 		}
-// 	}
-
-// 	union_type->Struct.names = make_names_field_for_struct(c, c->context.scope);
-
-// 	auto fields = check_fields(c, node, ut->fields, min_field_count, str_lit("raw_union"));
-
-// 	union_type->Struct.scope       = c->context.scope;
-// 	union_type->Struct.fields      = fields.data;
-// 	union_type->Struct.field_count = fields.count;
-// }
-
-
 void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
 	ast_node(et, EnumType, node);
 	GB_ASSERT(is_type_enum(enum_type));

+ 2 - 19
src/check_stmt.cpp

@@ -472,24 +472,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
 	switch (e->kind) {
 	case Entity_TypeName: {
 		Type *t = base_type(e->type);
-		if (t->kind == Type_Struct) {
-			Scope *s = t->Struct.scope;
-			if (s != nullptr) {
-				for_array(i, s->elements.entries) {
-					Entity *f = s->elements.entries[i].value;
-					if (f->kind != Entity_Variable) {
-						Entity *found = scope_insert_entity(c->context.scope, f);
-						if (found != nullptr) {
-							gbString expr_str = expr_to_string(expr);
-							error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
-							gb_string_free(expr_str);
-							return false;
-						}
-						f->using_parent = e;
-					}
-				}
-			}
-		} else if (t->kind == Type_Enum) {
+		if (t->kind == Type_Enum) {
 			for (isize i = 0; i < t->Enum.field_count; i++) {
 				Entity *f = t->Enum.fields[i];
 				Entity *found = scope_insert_entity(c->context.scope, f);
@@ -502,7 +485,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
 				f->using_parent = e;
 			}
 		} else {
-			error(us->token, "`using` can be only applied to struct type entities");
+			error(us->token, "`using` can be only applied to enum type entities");
 		}
 	} break;
 

+ 26 - 30
src/checker.cpp

@@ -1595,17 +1595,17 @@ Entity *find_core_entity(Checker *c, String name) {
 	return e;
 }
 
-Entity *find_sub_core_entity(TypeStruct *parent, String name) {
-	GB_ASSERT(parent->scope->parent->is_global);
-	Entity *e = current_scope_lookup_entity(parent->scope, name);
+Type *find_core_type(Checker *c, String name) {
+	Entity *e = current_scope_lookup_entity(c->global_scope, name);
 	if (e == nullptr) {
 		compiler_error("Could not find type declaration for `%.*s`\n"
 		               "Is `_preload.odin` missing from the `core` directory relative to odin.exe?", LIT(name));
 		// NOTE(bill): This will exit the program as it's cannot continue without it!
 	}
-	return e;
+	return e->type;
 }
 
+
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type);
 
 void init_preload(Checker *c) {
@@ -1617,7 +1617,7 @@ void init_preload(Checker *c) {
 		GB_ASSERT(is_type_struct(type_info_entity->type));
 		TypeStruct *tis = &base_type(type_info_entity->type)->Struct;
 
-		Entity *type_info_enum_value = find_sub_core_entity(tis, str_lit("Enum_Value"));
+		Entity *type_info_enum_value = find_core_entity(c, str_lit("Type_Info_Enum_Value"));
 
 		t_type_info_enum_value = type_info_enum_value->type;
 		t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value);
@@ -1627,31 +1627,27 @@ void init_preload(Checker *c) {
 		Entity *type_info_variant = tis->fields_in_src_order[2];
 		Type *tiv_type = type_info_variant->type;
 		GB_ASSERT(is_type_union(tiv_type));
-		TypeUnion *tiv = &tiv_type->Union;
-
-		if (tiv->variants.count != 20) {
-			compiler_error("Invalid `Type_Info` layout");
-		}
-		t_type_info_named         = tiv->variants[ 0];
-		t_type_info_integer       = tiv->variants[ 1];
-		t_type_info_rune          = tiv->variants[ 2];
-		t_type_info_float         = tiv->variants[ 3];
-		t_type_info_complex       = tiv->variants[ 4];
-		t_type_info_string        = tiv->variants[ 5];
-		t_type_info_boolean       = tiv->variants[ 6];
-		t_type_info_any           = tiv->variants[ 7];
-		t_type_info_pointer       = tiv->variants[ 8];
-		t_type_info_procedure     = tiv->variants[ 9];
-		t_type_info_array         = tiv->variants[10];
-		t_type_info_dynamic_array = tiv->variants[11];
-		t_type_info_slice         = tiv->variants[12];
-		t_type_info_vector        = tiv->variants[13];
-		t_type_info_tuple         = tiv->variants[14];
-		t_type_info_struct        = tiv->variants[15];
-		t_type_info_union         = tiv->variants[16];
-		t_type_info_enum          = tiv->variants[17];
-		t_type_info_map           = tiv->variants[18];
-		t_type_info_bit_field     = tiv->variants[19];
+
+		t_type_info_named         = find_core_type(c, str_lit("Type_Info_Named"));
+		t_type_info_integer       = find_core_type(c, str_lit("Type_Info_Integer"));
+		t_type_info_rune          = find_core_type(c, str_lit("Type_Info_Rune"));
+		t_type_info_float         = find_core_type(c, str_lit("Type_Info_Float"));
+		t_type_info_complex       = find_core_type(c, str_lit("Type_Info_Complex"));
+		t_type_info_string        = find_core_type(c, str_lit("Type_Info_String"));
+		t_type_info_boolean       = find_core_type(c, str_lit("Type_Info_Boolean"));
+		t_type_info_any           = find_core_type(c, str_lit("Type_Info_Any"));
+		t_type_info_pointer       = find_core_type(c, str_lit("Type_Info_Pointer"));
+		t_type_info_procedure     = find_core_type(c, str_lit("Type_Info_Procedure"));
+		t_type_info_array         = find_core_type(c, str_lit("Type_Info_Array"));
+		t_type_info_dynamic_array = find_core_type(c, str_lit("Type_Info_Dynamic_Array"));
+		t_type_info_slice         = find_core_type(c, str_lit("Type_Info_Slice"));
+		t_type_info_vector        = find_core_type(c, str_lit("Type_Info_Vector"));
+		t_type_info_tuple         = find_core_type(c, str_lit("Type_Info_Tuple"));
+		t_type_info_struct        = find_core_type(c, str_lit("Type_Info_Struct"));
+		t_type_info_union         = find_core_type(c, str_lit("Type_Info_Union"));
+		t_type_info_enum          = find_core_type(c, str_lit("Type_Info_Enum"));
+		t_type_info_map           = find_core_type(c, str_lit("Type_Info_Map"));
+		t_type_info_bit_field     = find_core_type(c, str_lit("Type_Info_Bit_Field"));
 
 		t_type_info_named_ptr         = make_type_pointer(c->allocator, t_type_info_named);
 		t_type_info_integer_ptr       = make_type_pointer(c->allocator, t_type_info_integer);

+ 7 - 0
src/parser.cpp

@@ -130,6 +130,7 @@ enum FieldFlag {
 	FieldFlag_c_vararg  = 1<<3,
 
 	FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
+	FieldFlag_Struct    = FieldFlag_using,
 };
 
 enum StmtAllowFlag {
@@ -3478,6 +3479,11 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) {
 
 	isize total_name_count = 0;
 
+	AstNode *params = parse_field_list(f, &total_name_count, FieldFlag_Struct, Token_CloseBrace, true, false);
+	if (name_count_) *name_count_ = total_name_count;
+	return params;
+
+#if 0
 	while (f->curr_token.kind != Token_CloseBrace &&
 	       f->curr_token.kind != Token_EOF) {
 		AstNode *decl = parse_stmt(f);
@@ -3508,6 +3514,7 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) {
 
 	if (name_count_) *name_count_ = total_name_count;
 	return ast_field_list(f, start_token, decls);
+#endif
 }
 
 AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters, bool allow_type_token) {