Explorar o código

Remove Maybe type; Enum `names`

Ginger Bill %!s(int64=8) %!d(string=hai) anos
pai
achega
f18ae89931
Modificáronse 15 ficheiros con 304 adicións e 364 borrados
  1. 38 39
      code/demo.odin
  2. 19 16
      core/_preload.odin
  3. 8 18
      core/fmt.odin
  4. 0 4
      core/math.odin
  5. 34 35
      core/mem.odin
  6. 1 0
      core/sys/windows.odin
  7. 8 8
      core/types.odin
  8. 12 9
      src/check_expr.c
  9. 53 46
      src/checker.c
  10. 1 0
      src/entity.c
  11. 90 70
      src/ir.c
  12. 0 21
      src/ir_print.c
  13. 0 31
      src/parser.c
  14. 9 7
      src/tokenizer.c
  15. 31 60
      src/types.c

+ 38 - 39
code/demo.odin

@@ -10,17 +10,28 @@
 #import ht "http_test.odin";
 #import ht "http_test.odin";
 
 
 main :: proc() {
 main :: proc() {
+	{
+		Fruit :: enum {
+			APPLE,
+			BANANA,
+			COCONUT,
+		}
+
+		fmt.println(Fruit.names);
+	}
+
+when false {
 	{
 	{
 		m: map[f32]int;
 		m: map[f32]int;
-		reserve(^m, 16);
+		reserve(m, 16);
 		defer free(m);
 		defer free(m);
 
 
 		m[1.0] = 1278;
 		m[1.0] = 1278;
 		m[2.0] = 7643;
 		m[2.0] = 7643;
 		m[3.0] = 564;
 		m[3.0] = 564;
-		c := m[3.0];
 		_, ok := m[3.0];
 		_, ok := m[3.0];
-		// assert(ok && c == 564);
+		c := m[3.0];
+		assert(ok && c == 564);
 
 
 		fmt.print("map[");
 		fmt.print("map[");
 		i := 0;
 		i := 0;
@@ -28,7 +39,7 @@ main :: proc() {
 			if i > 0 {
 			if i > 0 {
 				fmt.print(", ");
 				fmt.print(", ");
 			}
 			}
-			fmt.printf("%f=%v", key, val);
+			fmt.printf("%v=%v", key, val);
 			i += 1;
 			i += 1;
 		}
 		}
 		fmt.println("]");
 		fmt.println("]");
@@ -48,48 +59,36 @@ main :: proc() {
 		fmt.println(m);
 		fmt.println(m);
 	}
 	}
 
 
-
-
-	// fm: map[128, int]f32;
-
-/*
 	{
 	{
-		sig: u32;
-		x := __cpuid(0, ^sig);
-		fmt.println(sig, x);
-	}
-
-
-
-	i: int;
-
-	fmt.println("Hellope!");
+		fmt.println("Hellope!");
 
 
-	x: [dynamic]f64;
-	defer free(x);
-	append(^x, 2_000_000.500_000, 3, 5, 7);
+		x: [dynamic]f64;
+		reserve(x, 16);
+		defer free(x);
+		append(x, 2_000_000.500_000, 3, 5, 7);
 
 
-	for p, i in x {
-		if i > 0 { fmt.print(", "); }
-		fmt.print(p);
-	}
-	fmt.println();
+		for p, i in x {
+			if i > 0 { fmt.print(", "); }
+			fmt.print(p);
+		}
+		fmt.println();
 
 
-	{
-		Vec3 :: [vector 3]f32;
+		{
+			Vec3 :: [vector 3]f32;
 
 
-		x := Vec3{1, 2, 3};
-		y := Vec3{4, 5, 6};
-		fmt.println(x < y);
-		fmt.println(x + y);
-		fmt.println(x - y);
-		fmt.println(x * y);
-		fmt.println(x / y);
+			x := Vec3{1, 2, 3};
+			y := Vec3{4, 5, 6};
+			fmt.println(x < y);
+			fmt.println(x + y);
+			fmt.println(x - y);
+			fmt.println(x * y);
+			fmt.println(x / y);
 
 
-		for i in x {
-			fmt.println(i);
+			for i in x {
+				fmt.println(i);
+			}
 		}
 		}
 	}
 	}
-*/
+}
 }
 }
 
 

+ 19 - 16
core/_preload.odin

@@ -52,15 +52,12 @@ Type_Info :: union {
 	Float: struct #ordered {
 	Float: struct #ordered {
 		size: int, // in bytes
 		size: int, // in bytes
 	},
 	},
-	Any:     struct #ordered {},
 	String:  struct #ordered {},
 	String:  struct #ordered {},
 	Boolean: struct #ordered {},
 	Boolean: struct #ordered {},
+	Any:     struct #ordered {},
 	Pointer: struct #ordered {
 	Pointer: struct #ordered {
 		elem: ^Type_Info, // nil -> rawptr
 		elem: ^Type_Info, // nil -> rawptr
 	},
 	},
-	Maybe: struct #ordered {
-		elem: ^Type_Info,
-	},
 	Procedure: struct #ordered {
 	Procedure: struct #ordered {
 		params:     ^Type_Info, // Type_Info.Tuple
 		params:     ^Type_Info, // Type_Info.Tuple
 		results:    ^Type_Info, // Type_Info.Tuple
 		results:    ^Type_Info, // Type_Info.Tuple
@@ -146,6 +143,8 @@ __cpuid :: proc(level: u32, sig: ^u32) -> i32 #foreign __llvm_core "__get_cpuid"
 
 
 
 
 
 
+
+
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
 // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
 Allocator_Mode :: enum u8 {
 Allocator_Mode :: enum u8 {
 	ALLOC,
 	ALLOC,
@@ -199,23 +198,17 @@ free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
 	if ptr == nil {
 	if ptr == nil {
 		return;
 		return;
 	}
 	}
-	a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0);
-}
-
-__free_raw_dynamic_array :: proc(a: ^Raw_Dynamic_Array) {
-	if a.allocator.procedure == nil {
-		return;
-	}
-	if a.data == nil {
+	if a.procedure == nil {
 		return;
 		return;
 	}
 	}
-	free_ptr_with_allocator(a.allocator, a.data);
+	a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0);
 }
 }
 
 
 free_ptr :: proc(ptr: rawptr) #inline {
 free_ptr :: proc(ptr: rawptr) #inline {
 	__check_context();
 	__check_context();
 	free_ptr_with_allocator(context.allocator, ptr);
 	free_ptr_with_allocator(context.allocator, ptr);
 }
 }
+
 free_all :: proc() #inline {
 free_all :: proc() #inline {
 	__check_context();
 	__check_context();
 	a := context.allocator;
 	a := context.allocator;
@@ -306,11 +299,11 @@ __string_eq :: proc(a, b: string) -> bool {
 	if a.data == b.data {
 	if a.data == b.data {
 		return true;
 		return true;
 	}
 	}
-	return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, a.count) == 0;
+	return __string_cmp(a, b) == 0;
 }
 }
 
 
 __string_cmp :: proc(a, b: string) -> int {
 __string_cmp :: proc(a, b: string) -> int {
-	return mem.compare(cast(rawptr)a.data, cast(rawptr)b.data, min(a.count, b.count));
+	return mem.compare(cast([]byte)a, cast([]byte)b);
 }
 }
 
 
 __string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
 __string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
@@ -504,7 +497,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
 	nm: Raw_Dynamic_Map;
 	nm: Raw_Dynamic_Map;
 	new_header.m = ^nm;
 	new_header.m = ^nm;
 
 
-	reserve(^nm.hashes, new_count);
+	reserve(nm.hashes, new_count);
 	nm.hashes.count = nm.hashes.capacity;
 	nm.hashes.count = nm.hashes.capacity;
 	__dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.count);
 	__dynamic_array_reserve(^nm.entries, entry_size, entry_align, m.entries.count);
 	for _, i in nm.hashes {
 	for _, i in nm.hashes {
@@ -660,3 +653,13 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {
 		m.hashes[last.hash_index] = fr.entry_index;
 		m.hashes[last.hash_index] = fr.entry_index;
 	}
 	}
 }
 }
+
+
+__print_ti_ptr :: proc(ti: ^Type_Info) {
+	fmt.println(ti);
+	match type e in ti {
+	case Type_Info.Enum:
+		fmt.println(e.names);
+	}
+}
+

+ 8 - 18
core/fmt.odin

@@ -134,9 +134,6 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
 			buffer_write_string(buf, "^");
 			buffer_write_string(buf, "^");
 			buffer_write_type(buf, info.elem);
 			buffer_write_type(buf, info.elem);
 		}
 		}
-	case Maybe:
-		buffer_write_string(buf, "?");
-		buffer_write_type(buf, info.elem);
 	case Procedure:
 	case Procedure:
 		buffer_write_string(buf, "proc");
 		buffer_write_string(buf, "proc");
 		if info.params == nil {
 		if info.params == nil {
@@ -420,8 +417,9 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
 }
 }
 
 
 fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
 fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
-	negative := signed && cast(i64)u < 0;
-	u = abs(u);
+	s := cast(i64)u;
+	negative := signed && s < 0;
+	u = cast(u64)abs(s);
 	buf: [256]byte;
 	buf: [256]byte;
 	if fi.width_set || fi.prec_set {
 	if fi.width_set || fi.prec_set {
 		width := fi.width + fi.prec + 3;
 		width := fi.width + fi.prec + 3;
@@ -628,6 +626,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
 fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 	match verb {
 	match verb {
 	case 'p', 'v':
 	case 'p', 'v':
+		// Okay
 	default:
 	default:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 		return;
 		return;
@@ -747,16 +746,6 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
 			fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
 		}
 		}
 
 
-	case Maybe:
-		// TODO(bill): Correct verbs for Maybe types?
-		size := mem.size_of_type_info(info.elem);
-		data := slice_ptr(cast(^byte)v.data, size+1);
-		if data[size] != 0 {
-			fmt_arg(fi, any{info.elem, v.data}, verb);
-		} else {
-			buffer_write_string(fi.buf, "nil");
-		}
-
 	case Array:
 	case Array:
 		if verb != 'v' {
 		if verb != 'v' {
 			fmt_bad_verb(fi, verb);
 			fmt_bad_verb(fi, verb);
@@ -799,9 +788,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 		buffer_write_string(fi.buf, "map[");
 		buffer_write_string(fi.buf, "map[");
 		defer buffer_write_byte(fi.buf, ']');
 		defer buffer_write_byte(fi.buf, ']');
 		entries := ^(cast(^Raw_Dynamic_Map)v.data).entries;
 		entries := ^(cast(^Raw_Dynamic_Map)v.data).entries;
-		gs, _ := union_cast(^Struct)info.generated_struct;
-		ed, _ := union_cast(^Dynamic_Array)gs.fields[1].type_info;
-		entry_type, _ := union_cast(^Struct)ed.elem;
+		gs, gs_ok := union_cast(^Struct)type_info_base(info.generated_struct);         assert(gs_ok);
+		ed, ed_ok := union_cast(^Dynamic_Array)type_info_base(gs.fields[1].type_info); assert(ed_ok);
+
+		entry_type, et_ok := union_cast(^Struct)ed.elem; assert(et_ok);
 		entry_size := ed.elem_size;
 		entry_size := ed.elem_size;
 		for i in 0..<entries.count {
 		for i in 0..<entries.count {
 			if i > 0 {
 			if i > 0 {

+ 0 - 4
core/math.odin

@@ -46,10 +46,6 @@ bit_reverse :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16";
 bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32";
 bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32";
 bit_reverse :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64";
 bit_reverse :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64";
 
 
-byte_swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
-byte_swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
-byte_swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
-
 fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
 fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
 fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
 fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
 
 

+ 34 - 35
core/mem.odin

@@ -1,6 +1,11 @@
 #import "fmt.odin";
 #import "fmt.odin";
 #import "os.odin";
 #import "os.odin";
 
 
+swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
+swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
+swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
+
+
 set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" {
 set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" {
 	llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
 	llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
 	llvm_memset_64bit(data, cast(byte)value, len, 1, false);
 	llvm_memset_64bit(data, cast(byte)value, len, 1, false);
@@ -12,22 +17,21 @@ zero :: proc(data: rawptr, len: int) -> rawptr #link_name "__mem_zero" {
 }
 }
 
 
 copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" {
 copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" {
-	// NOTE(bill): This _must_ implemented like C's memmove
+	// NOTE(bill): This _must_ be implemented like C's memmove
 	llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
 	llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
 	llvm_memmove_64bit(dst, src, len, 1, false);
 	llvm_memmove_64bit(dst, src, len, 1, false);
 	return dst;
 	return dst;
 }
 }
 
 
 copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" {
 copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" {
-	// NOTE(bill): This _must_ implemented like C's memcpy
+	// NOTE(bill): This _must_ be implemented like C's memcpy
 	llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
 	llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
 	llvm_memcpy_64bit(dst, src, len, 1, false);
 	llvm_memcpy_64bit(dst, src, len, 1, false);
 	return dst;
 	return dst;
 }
 }
 
 
-compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
-	a := slice_ptr(cast(^byte)dst, n);
-	b := slice_ptr(cast(^byte)src, n);
+compare :: proc(a, b: []byte) -> int #link_name "__mem_compare" {
+	n := min(a.count, b.count);
 	for i in 0..<n {
 	for i in 0..<n {
 		match {
 		match {
 		case a[i] < b[i]:
 		case a[i] < b[i]:
@@ -43,8 +47,8 @@ compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
 
 
 kilobytes :: proc(x: int) -> int #inline { return          (x) * 1024; }
 kilobytes :: proc(x: int) -> int #inline { return          (x) * 1024; }
 megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
 megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
-gigabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
-terabytes :: proc(x: int) -> int #inline { return terabytes(x) * 1024; }
+gigabytes :: proc(x: int) -> int #inline { return megabytes(x) * 1024; }
+terabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
 
 
 is_power_of_two :: proc(x: int) -> bool {
 is_power_of_two :: proc(x: int) -> bool {
 	if x <= 0 {
 	if x <= 0 {
@@ -213,7 +217,6 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
 	WORD_SIZE :: size_of(int);
 	WORD_SIZE :: size_of(int);
 	MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
 	MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
 	using Type_Info;
 	using Type_Info;
-
 	match type info in type_info {
 	match type info in type_info {
 	case Named:
 	case Named:
 		return align_of_type_info(info.base);
 		return align_of_type_info(info.base);
@@ -225,14 +228,16 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
 		return WORD_SIZE;
 		return WORD_SIZE;
 	case Boolean:
 	case Boolean:
 		return 1;
 		return 1;
+	case Any:
+		return WORD_SIZE;
 	case Pointer:
 	case Pointer:
 		return WORD_SIZE;
 		return WORD_SIZE;
-	case Maybe:
-		return max(align_of_type_info(info.elem), 1);
 	case Procedure:
 	case Procedure:
 		return WORD_SIZE;
 		return WORD_SIZE;
 	case Array:
 	case Array:
 		return align_of_type_info(info.elem);
 		return align_of_type_info(info.elem);
+	case Dynamic_Array:
+		return WORD_SIZE;
 	case Slice:
 	case Slice:
 		return WORD_SIZE;
 		return WORD_SIZE;
 	case Vector:
 	case Vector:
@@ -240,12 +245,18 @@ align_of_type_info :: proc(type_info: ^Type_Info) -> int {
 		count := cast(int)max(prev_pow2(cast(i64)info.count), 1);
 		count := cast(int)max(prev_pow2(cast(i64)info.count), 1);
 		total := size * count;
 		total := size * count;
 		return clamp(total, 1, MAX_ALIGN);
 		return clamp(total, 1, MAX_ALIGN);
+	case Tuple:
+		return info.align;
 	case Struct:
 	case Struct:
 		return info.align;
 		return info.align;
 	case Union:
 	case Union:
 		return info.align;
 		return info.align;
 	case Raw_Union:
 	case Raw_Union:
 		return info.align;
 		return info.align;
+	case Enum:
+		return align_of_type_info(info.base);
+	case Map:
+		return align_of_type_info(info.generated_struct);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -266,16 +277,14 @@ size_of_type_info :: proc(type_info: ^Type_Info) -> int {
 		return info.size;
 		return info.size;
 	case Float:
 	case Float:
 		return info.size;
 		return info.size;
-	case Any:
-		return 2*WORD_SIZE;
 	case String:
 	case String:
 		return 2*WORD_SIZE;
 		return 2*WORD_SIZE;
 	case Boolean:
 	case Boolean:
 		return 1;
 		return 1;
+	case Any:
+		return 2*WORD_SIZE;
 	case Pointer:
 	case Pointer:
 		return WORD_SIZE;
 		return WORD_SIZE;
-	case Maybe:
-		return size_of_type_info(info.elem) + 1;
 	case Procedure:
 	case Procedure:
 		return WORD_SIZE;
 		return WORD_SIZE;
 	case Array:
 	case Array:
@@ -287,39 +296,29 @@ size_of_type_info :: proc(type_info: ^Type_Info) -> int {
 		align     := align_of_type_info(info.elem);
 		align     := align_of_type_info(info.elem);
 		alignment := align_formula(size, align);
 		alignment := align_formula(size, align);
 		return alignment*(count-1) + size;
 		return alignment*(count-1) + size;
+	case Dynamic_Array:
+		return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
 	case Slice:
 	case Slice:
-		return 3*WORD_SIZE;
+		return 2*WORD_SIZE;
 	case Vector:
 	case Vector:
-		is_bool :: proc(type_info: ^Type_Info) -> bool {
-			match type info in type_info {
-			case Named:
-				return is_bool(info.base);
-			case Boolean:
-				return true;
-			}
-			return false;
-		}
-
 		count := info.count;
 		count := info.count;
 		if count == 0 {
 		if count == 0 {
 			return 0;
 			return 0;
 		}
 		}
-		bit_size := 8*size_of_type_info(info.elem);
-		if is_bool(info.elem) {
-			// NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
-			// Silly LLVM spec
-			bit_size = 1;
-		}
-		total_size_in_bits := bit_size * count;
-		total_size := (total_size_in_bits+7)/8;
-		return total_size;
-
+		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 Struct:
 		return info.size;
 		return info.size;
 	case Union:
 	case Union:
 		return info.size;
 		return info.size;
 	case Raw_Union:
 	case Raw_Union:
 		return info.size;
 		return info.size;
+	case Enum:
+		return size_of_type_info(info.base);
+	case Map:
+		return size_of_type_info(info.generated_struct);
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 1 - 0
core/sys/windows.odin

@@ -1,3 +1,4 @@
+_ := compile_assert(ODIN_OS == "windows");
 #foreign_system_library "kernel32.lib";
 #foreign_system_library "kernel32.lib";
 #foreign_system_library "user32.lib";
 #foreign_system_library "user32.lib";
 #foreign_system_library "gdi32.lib";
 #foreign_system_library "gdi32.lib";

+ 8 - 8
core/types.odin

@@ -56,14 +56,6 @@ is_pointer :: proc(info: ^Type_Info) -> bool {
 	}
 	}
 	return false;
 	return false;
 }
 }
-is_maybe :: proc(info: ^Type_Info) -> bool {
-	if info == nil { return false; }
-
-	match type i in type_info_base(info) {
-	case Type_Info.Maybe: return true;
-	}
-	return false;
-}
 is_procedure :: proc(info: ^Type_Info) -> bool {
 is_procedure :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
 	if info == nil { return false; }
 
 
@@ -88,6 +80,14 @@ is_dynamic_array :: proc(info: ^Type_Info) -> bool {
 	}
 	}
 	return false;
 	return false;
 }
 }
+is_dynamic_map :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Map: return i.count == 0;
+	}
+	return false;
+}
 is_slice :: proc(info: ^Type_Info) -> bool {
 is_slice :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false; }
 	if info == nil { return false; }
 
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 12 - 9
src/check_expr.c


+ 53 - 46
src/checker.c

@@ -630,11 +630,12 @@ void init_universal_scope(BuildContext *bc) {
 	}
 	}
 
 
 
 
-	t_u8_ptr  = make_type_pointer(a, t_u8);
-	t_int_ptr = make_type_pointer(a, t_int);
-	t_i64_ptr = make_type_pointer(a, t_i64);
-	t_f64_ptr = make_type_pointer(a, t_f64);
-	t_byte_slice = make_type_slice(a, t_byte);
+	t_u8_ptr       = make_type_pointer(a, t_u8);
+	t_int_ptr      = make_type_pointer(a, t_int);
+	t_i64_ptr      = make_type_pointer(a, t_i64);
+	t_f64_ptr      = make_type_pointer(a, t_f64);
+	t_byte_slice   = make_type_slice(a, t_byte);
+	t_string_slice = make_type_slice(a, t_string);
 }
 }
 
 
 
 
@@ -911,11 +912,6 @@ void add_type_info_type(Checker *c, Type *t) {
 		}
 		}
 	} break;
 	} break;
 
 
-	case Type_Maybe:
-		add_type_info_type(c, bt->Maybe.elem);
-		add_type_info_type(c, t_bool);
-		break;
-
 	case Type_Pointer:
 	case Type_Pointer:
 		add_type_info_type(c, bt->Pointer.elem);
 		add_type_info_type(c, bt->Pointer.elem);
 		break;
 		break;
@@ -1099,48 +1095,46 @@ void init_preload(Checker *c) {
 
 
 
 
 
 
-		if (record->field_count != 20) {
+		if (record->field_count != 19) {
 			compiler_error("Invalid `Type_Info` layout");
 			compiler_error("Invalid `Type_Info` layout");
 		}
 		}
 		t_type_info_named         = record->fields[ 1]->type;
 		t_type_info_named         = record->fields[ 1]->type;
 		t_type_info_integer       = record->fields[ 2]->type;
 		t_type_info_integer       = record->fields[ 2]->type;
 		t_type_info_float         = record->fields[ 3]->type;
 		t_type_info_float         = record->fields[ 3]->type;
-		t_type_info_any           = record->fields[ 4]->type;
-		t_type_info_string        = record->fields[ 5]->type;
-		t_type_info_boolean       = record->fields[ 6]->type;
+		t_type_info_string        = record->fields[ 4]->type;
+		t_type_info_boolean       = record->fields[ 5]->type;
+		t_type_info_any           = record->fields[ 6]->type;
 		t_type_info_pointer       = record->fields[ 7]->type;
 		t_type_info_pointer       = record->fields[ 7]->type;
-		t_type_info_maybe         = record->fields[ 8]->type;
-		t_type_info_procedure     = record->fields[ 9]->type;
-		t_type_info_array         = record->fields[10]->type;
-		t_type_info_dynamic_array = record->fields[11]->type;
-		t_type_info_slice         = record->fields[12]->type;
-		t_type_info_vector        = record->fields[13]->type;
-		t_type_info_tuple         = record->fields[14]->type;
-		t_type_info_struct        = record->fields[15]->type;
-		t_type_info_union         = record->fields[16]->type;
-		t_type_info_raw_union     = record->fields[17]->type;
-		t_type_info_enum          = record->fields[18]->type;
-		t_type_info_map           = record->fields[19]->type;
-
-		t_type_info_named_ptr         = make_type_pointer(heap_allocator(), t_type_info_named);
-		t_type_info_integer_ptr       = make_type_pointer(heap_allocator(), t_type_info_integer);
-		t_type_info_float_ptr         = make_type_pointer(heap_allocator(), t_type_info_float);
-		t_type_info_any_ptr           = make_type_pointer(heap_allocator(), t_type_info_any);
-		t_type_info_string_ptr        = make_type_pointer(heap_allocator(), t_type_info_string);
-		t_type_info_boolean_ptr       = make_type_pointer(heap_allocator(), t_type_info_boolean);
-		t_type_info_pointer_ptr       = make_type_pointer(heap_allocator(), t_type_info_pointer);
-		t_type_info_maybe_ptr         = make_type_pointer(heap_allocator(), t_type_info_maybe);
-		t_type_info_procedure_ptr     = make_type_pointer(heap_allocator(), t_type_info_procedure);
-		t_type_info_array_ptr         = make_type_pointer(heap_allocator(), t_type_info_array);
-		t_type_info_dynamic_array_ptr = make_type_pointer(heap_allocator(), t_type_info_dynamic_array);
-		t_type_info_slice_ptr         = make_type_pointer(heap_allocator(), t_type_info_slice);
-		t_type_info_vector_ptr        = make_type_pointer(heap_allocator(), t_type_info_vector);
-		t_type_info_tuple_ptr         = make_type_pointer(heap_allocator(), t_type_info_tuple);
-		t_type_info_struct_ptr        = make_type_pointer(heap_allocator(), t_type_info_struct);
-		t_type_info_union_ptr         = make_type_pointer(heap_allocator(), t_type_info_union);
-		t_type_info_raw_union_ptr     = make_type_pointer(heap_allocator(), t_type_info_raw_union);
-		t_type_info_enum_ptr          = make_type_pointer(heap_allocator(), t_type_info_enum);
-		t_type_info_map_ptr           = make_type_pointer(heap_allocator(), t_type_info_map);
+		t_type_info_procedure     = record->fields[ 8]->type;
+		t_type_info_array         = record->fields[ 9]->type;
+		t_type_info_dynamic_array = record->fields[10]->type;
+		t_type_info_slice         = record->fields[11]->type;
+		t_type_info_vector        = record->fields[12]->type;
+		t_type_info_tuple         = record->fields[13]->type;
+		t_type_info_struct        = record->fields[14]->type;
+		t_type_info_union         = record->fields[15]->type;
+		t_type_info_raw_union     = record->fields[16]->type;
+		t_type_info_enum          = record->fields[17]->type;
+		t_type_info_map           = record->fields[18]->type;
+
+		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);
+		t_type_info_float_ptr         = make_type_pointer(c->allocator, t_type_info_float);
+		t_type_info_string_ptr        = make_type_pointer(c->allocator, t_type_info_string);
+		t_type_info_boolean_ptr       = make_type_pointer(c->allocator, t_type_info_boolean);
+		t_type_info_any_ptr           = make_type_pointer(c->allocator, t_type_info_any);
+		t_type_info_pointer_ptr       = make_type_pointer(c->allocator, t_type_info_pointer);
+		t_type_info_procedure_ptr     = make_type_pointer(c->allocator, t_type_info_procedure);
+		t_type_info_array_ptr         = make_type_pointer(c->allocator, t_type_info_array);
+		t_type_info_dynamic_array_ptr = make_type_pointer(c->allocator, t_type_info_dynamic_array);
+		t_type_info_slice_ptr         = make_type_pointer(c->allocator, t_type_info_slice);
+		t_type_info_vector_ptr        = make_type_pointer(c->allocator, t_type_info_vector);
+		t_type_info_tuple_ptr         = make_type_pointer(c->allocator, t_type_info_tuple);
+		t_type_info_struct_ptr        = make_type_pointer(c->allocator, t_type_info_struct);
+		t_type_info_union_ptr         = make_type_pointer(c->allocator, t_type_info_union);
+		t_type_info_raw_union_ptr     = make_type_pointer(c->allocator, t_type_info_raw_union);
+		t_type_info_enum_ptr          = make_type_pointer(c->allocator, t_type_info_enum);
+		t_type_info_map_ptr           = make_type_pointer(c->allocator, t_type_info_map);
 	}
 	}
 
 
 	if (t_allocator == NULL) {
 	if (t_allocator == NULL) {
@@ -1714,6 +1708,19 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 			file_str = import_file;
 			file_str = import_file;
 		}
 		}
 
 
+		if (fl->cond != NULL) {
+			Operand operand = {Addressing_Invalid};
+			check_expr(c, &operand, fl->cond);
+			if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
+				error_node(fl->cond, "Non-constant boolean `when` condition");
+				continue;
+			}
+			if (operand.value.kind == ExactValue_Bool &&
+			    !operand.value.value_bool) {
+				continue;
+			}
+		}
+
 		String library_name = path_to_entity_name(fl->library_name.string, file_str);
 		String library_name = path_to_entity_name(fl->library_name.string, file_str);
 		if (str_eq(library_name, str_lit("_"))) {
 		if (str_eq(library_name, str_lit("_"))) {
 			error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
 			error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));

+ 1 - 0
src/entity.c

@@ -37,6 +37,7 @@ typedef enum EntityFlag {
 	EntityFlag_VectorElem = 1<<5,
 	EntityFlag_VectorElem = 1<<5,
 	EntityFlag_Ellipsis   = 1<<6,
 	EntityFlag_Ellipsis   = 1<<6,
 	EntityFlag_NoAlias    = 1<<7,
 	EntityFlag_NoAlias    = 1<<7,
+	EntityFlag_EnumField  = 1<<8,
 } EntityFlag;
 } EntityFlag;
 
 
 typedef enum OverloadKind {
 typedef enum OverloadKind {

+ 90 - 70
src/ir.c

@@ -1788,11 +1788,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
 		case 0: result_type = make_type_pointer(a, t_type_info_ptr); break;
 		case 0: result_type = make_type_pointer(a, t_type_info_ptr); break;
 		case 1: result_type = make_type_pointer(a, t_rawptr);        break;
 		case 1: result_type = make_type_pointer(a, t_rawptr);        break;
 		}
 		}
-	} else if (is_type_maybe(t)) {
-		switch (index) {
-		case 0: result_type = make_type_pointer(a, t->Maybe.elem); break;
-		case 1: result_type = make_type_pointer(a, t_bool);        break;
-		}
 	} else if (is_type_dynamic_array(t)) {
 	} else if (is_type_dynamic_array(t)) {
 		switch (index) {
 		switch (index) {
 		case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->DynamicArray.elem)); break;
 		case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->DynamicArray.elem)); break;
@@ -1848,11 +1843,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
 		case 0: result_type = t_type_info_ptr; break;
 		case 0: result_type = t_type_info_ptr; break;
 		case 1: result_type = t_rawptr;        break;
 		case 1: result_type = t_rawptr;        break;
 		}
 		}
-	} else if (is_type_maybe(t)) {
-		switch (index) {
-		case 0: result_type = t->Maybe.elem; break;
-		case 1: result_type = t_bool;        break;
-		}
 	} else if (is_type_dynamic_array(t)) {
 	} else if (is_type_dynamic_array(t)) {
 		switch (index) {
 		switch (index) {
 		case 0: result_type = make_type_pointer(a, t->DynamicArray.elem); break;
 		case 0: result_type = make_type_pointer(a, t->DynamicArray.elem); break;
@@ -2165,15 +2155,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
 		return value;
 		return value;
 	}
 	}
 
 
-	if (is_type_maybe(dst)) {
-		irValue *maybe = ir_add_local_generated(proc, dst);
-		irValue *val = ir_emit_struct_ep(proc, maybe, 0);
-		irValue *set = ir_emit_struct_ep(proc, maybe, 1);
-		ir_emit_store(proc, val, value);
-		ir_emit_store(proc, set, v_true);
-		return ir_emit_load(proc, maybe);
-	}
-
 	// integer -> integer
 	// integer -> integer
 	if (is_type_integer(src) && is_type_integer(dst)) {
 	if (is_type_integer(src) && is_type_integer(dst)) {
 		GB_ASSERT(src->kind == Type_Basic &&
 		GB_ASSERT(src->kind == Type_Basic &&
@@ -2396,7 +2377,6 @@ bool ir_is_type_aggregate(Type *t) {
 
 
 	case Type_Array:
 	case Type_Array:
 	case Type_Slice:
 	case Type_Slice:
-	case Type_Maybe:
 	case Type_Record:
 	case Type_Record:
 	case Type_Tuple:
 	case Type_Tuple:
 		return true;
 		return true;
@@ -3130,22 +3110,33 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 						args[1] = ptr;
 						args[1] = ptr;
 						return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
 						return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
 					} else if (is_type_dynamic_map(type)) {
 					} else if (is_type_dynamic_map(type)) {
-						// irValue *val = ir_build_expr(proc, node);
-						// irValue *map_ptr = ir_address_from_load_or_generate_local(proc, val);
-
-						// {
-						// 	irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 0), t_raw_dynamic_array_ptr);
-						// 	irValue **args = gb_alloc_array(a, irValue *, 1);
-						// 	args[0] = array;
-						// 	ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1);
-						// }
-						// {
-						// 	irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 1), t_raw_dynamic_array_ptr);
-						// 	irValue **args = gb_alloc_array(a, irValue *, 1);
-						// 	args[0] = array;
-						// 	ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1);
-						// }
+						irValue *map = ir_build_expr(proc, node);
+						irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map);
+
+						{
+							irValue *array = ir_emit_struct_ep(proc, map_ptr, 0);
+
+							irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
+							irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
+							da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
+
+							irValue **args = gb_alloc_array(a, irValue *, 1);
+							args[0] = da_allocator;
+							args[1] = da_ptr;
+							ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
+						}
+						{
+							irValue *array = ir_emit_struct_ep(proc, map_ptr, 1);
+
+							irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
+							irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
+							da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
 
 
+							irValue **args = gb_alloc_array(a, irValue *, 1);
+							args[0] = da_allocator;
+							args[1] = da_ptr;
+							ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
+						}
 						return NULL;
 						return NULL;
 					}
 					}
 
 
@@ -3176,7 +3167,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 					ir_emit_comment(proc, str_lit("reserve"));
 					ir_emit_comment(proc, str_lit("reserve"));
 					gbAllocator a = proc->module->allocator;
 					gbAllocator a = proc->module->allocator;
 
 
-					irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
+					irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr;
 					Type *type = ir_type(ptr);
 					Type *type = ir_type(ptr);
 					GB_ASSERT(is_type_pointer(type));
 					GB_ASSERT(is_type_pointer(type));
 					type = base_type(type_deref(type));
 					type = base_type(type_deref(type));
@@ -3208,8 +3199,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 				} break;
 				} break;
 
 
 				case BuiltinProc_clear: {
 				case BuiltinProc_clear: {
-					ir_emit_comment(proc, str_lit("reserve"));
-					irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
+					ir_emit_comment(proc, str_lit("clear"));
+					irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr;
 					Type *t = base_type(type_deref(ir_type(ptr)));
 					Type *t = base_type(type_deref(ir_type(ptr)));
 					if (is_type_dynamic_array(t)) {
 					if (is_type_dynamic_array(t)) {
 						irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
 						irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
@@ -3229,7 +3220,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 					ir_emit_comment(proc, str_lit("append"));
 					ir_emit_comment(proc, str_lit("append"));
 					gbAllocator a = proc->module->allocator;
 					gbAllocator a = proc->module->allocator;
 
 
-					irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]);
+					irValue *array_ptr = ir_build_addr(proc, ce->args.e[0]).addr;
 					Type *type = ir_type(array_ptr);
 					Type *type = ir_type(array_ptr);
 					GB_ASSERT(is_type_pointer(type));
 					GB_ASSERT(is_type_pointer(type));
 					type = base_type(type_deref(type));
 					type = base_type(type_deref(type));
@@ -3348,7 +3339,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 					ir_emit_jump(proc, done);
 					ir_emit_jump(proc, done);
 					ir_start_block(proc, done);
 					ir_start_block(proc, done);
 
 
-					return NULL;
+					return cond;
 				} break;
 				} break;
 
 
 				case BuiltinProc_panic: {
 				case BuiltinProc_panic: {
@@ -3596,10 +3587,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 		return ir_emit_call(proc, value, args, arg_count);
 		return ir_emit_call(proc, value, args, arg_count);
 	case_end;
 	case_end;
 
 
-	case_ast_node(de, DemaybeExpr, expr);
-		return ir_addr_load(proc, ir_build_addr(proc, expr));
-	case_end;
-
 	case_ast_node(se, SliceExpr, expr);
 	case_ast_node(se, SliceExpr, expr);
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 	case_end;
 	case_end;
@@ -3722,7 +3709,34 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		AstNode *sel = unparen_expr(se->selector);
 		AstNode *sel = unparen_expr(se->selector);
 		if (sel->kind == AstNode_Ident) {
 		if (sel->kind == AstNode_Ident) {
 			String selector = sel->Ident.string;
 			String selector = sel->Ident.string;
-			Type *type = base_type(type_of_expr(proc->module->info, se->expr));
+			Type *type = type_of_expr(proc->module->info, se->expr);
+
+			if (is_type_enum(type)) {
+				Selection sel = lookup_field(proc->module->allocator, type, selector, true);
+				Entity *e = sel.entity;
+				GB_ASSERT(e->kind == Entity_Variable);
+				i32 index = e->Variable.field_index;
+				switch (index) {
+				case 0: {
+					irValue *ti_ptr = ir_type_info(proc, type);
+					{
+						irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1);
+						args[0] = ti_ptr;
+						ti_ptr = ir_emit_global_call(proc, "type_info_base", args, 1);
+					}
+
+
+					irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr);
+					irValue *names_ptr = ir_emit_struct_ep(proc, enum_info, 1);
+					return ir_make_addr(names_ptr);
+				} break;
+				default:
+					GB_PANIC("Unhandled enum index %d %.*s", index, LIT(selector));
+					break;
+				}
+			}
+
+			type = base_type(type);
 
 
 			if (type == t_invalid) {
 			if (type == t_invalid) {
 				// NOTE(bill): Imports
 				// NOTE(bill): Imports
@@ -4056,18 +4070,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		return ir_make_addr(addr);
 		return ir_make_addr(addr);
 	case_end;
 	case_end;
 
 
-	case_ast_node(de, DemaybeExpr, expr);
-		ir_emit_comment(proc, str_lit("DemaybeExpr"));
-		irValue *maybe = ir_build_expr(proc, de->expr);
-		Type *t = default_type(type_of_expr(proc->module->info, expr));
-		GB_ASSERT(is_type_tuple(t));
-
-		irValue *result = ir_add_local_generated(proc, t);
-		ir_emit_store(proc, result, maybe);
-
-		return ir_make_addr(result);
-	case_end;
-
 	case_ast_node(ce, CallExpr, expr);
 	case_ast_node(ce, CallExpr, expr);
 		// NOTE(bill): This is make sure you never need to have an `array_ev`
 		// NOTE(bill): This is make sure you never need to have an `array_ev`
 		irValue *e = ir_build_expr(proc, expr);
 		irValue *e = ir_build_expr(proc, expr);
@@ -5276,6 +5278,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 
 
 		String tag_var_name = ms->var->Ident.string;
 		String tag_var_name = ms->var->Ident.string;
 
 
+
 		AstNodeArray default_stmts = {0};
 		AstNodeArray default_stmts = {0};
 		irBlock *default_block = NULL;
 		irBlock *default_block = NULL;
 
 
@@ -5291,19 +5294,32 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 				default_block = ir_new_block(proc, clause, "type-match.dflt.body");
 				default_block = ir_new_block(proc, clause, "type-match.dflt.body");
 				continue;
 				continue;
 			}
 			}
+			GB_ASSERT(cc->list.count == 1);
 
 
 
 
 			irBlock *body = ir_new_block(proc, clause, "type-match.case.body");
 			irBlock *body = ir_new_block(proc, clause, "type-match.case.body");
 
 
-			Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause));
-			Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name);
-			GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name));
+			Entity *tag_var_entity = NULL;
+			Type *tag_var_type = NULL;
+			if (str_eq(tag_var_name, str_lit("_"))) {
+				Type *t = type_of_expr(proc->module->info, cc->list.e[0]);
+				if (is_union_ptr) {
+					t = make_type_pointer(proc->module->allocator, t);
+				}
+				tag_var_type = t;
+			} else {
+				Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause));
+				tag_var_entity = current_scope_lookup_entity(scope, tag_var_name);
+				GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name));
+				tag_var_type = tag_var_entity->type;
+			}
+			GB_ASSERT(tag_var_type != NULL);
 
 
 			irBlock *next_cond = NULL;
 			irBlock *next_cond = NULL;
 			irValue *cond = NULL;
 			irValue *cond = NULL;
 
 
 			if (is_union_ptr) {
 			if (is_union_ptr) {
-				Type *bt = type_deref(tag_var_entity->type);
+				Type *bt = type_deref(tag_var_type);
 				irValue *index = NULL;
 				irValue *index = NULL;
 				Type *ut = base_type(type_deref(ir_type(parent)));
 				Type *ut = base_type(type_deref(ir_type(parent)));
 				GB_ASSERT(ut->Record.kind == TypeRecord_Union);
 				GB_ASSERT(ut->Record.kind == TypeRecord_Union);
@@ -5316,16 +5332,25 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 				}
 				}
 				GB_ASSERT(index != NULL);
 				GB_ASSERT(index != NULL);
 
 
-				irValue *tag_var = ir_add_local(proc, tag_var_entity);
-				irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_entity->type);
+				irValue *tag_var = NULL;
+				if (tag_var_entity != NULL) {
+					tag_var = ir_add_local(proc, tag_var_entity);
+				} else {
+					tag_var = ir_add_local_generated(proc, tag_var_type);
+				}
+
+
+				irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_type);
 				ir_emit_store(proc, tag_var, data_ptr);
 				ir_emit_store(proc, tag_var, data_ptr);
 
 
 				cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index);
 				cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index);
 			} else if (is_any) {
 			} else if (is_any) {
-				Type *type = tag_var_entity->type;
+				Type *type = tag_var_type;
 				irValue *any_data = ir_emit_struct_ev(proc, parent, 1);
 				irValue *any_data = ir_emit_struct_ev(proc, parent, 1);
 				irValue *data = ir_emit_conv(proc, any_data, make_type_pointer(proc->module->allocator, type));
 				irValue *data = ir_emit_conv(proc, any_data, make_type_pointer(proc->module->allocator, type));
-				ir_module_add_value(proc->module, tag_var_entity, data);
+				if (tag_var_entity != NULL) {
+					ir_module_add_value(proc->module, tag_var_entity, data);
+				}
 
 
 				irValue *any_ti  = ir_emit_struct_ev(proc, parent, 0);
 				irValue *any_ti  = ir_emit_struct_ev(proc, parent, 0);
 				irValue *case_ti = ir_type_info(proc, type);
 				irValue *case_ti = ir_type_info(proc, type);
@@ -6228,11 +6253,6 @@ void ir_gen_tree(irGen *s) {
 					irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
 					irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
 					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
 					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
 				} break;
 				} break;
-				case Type_Maybe: {
-					tag = ir_emit_conv(proc, ti_ptr, t_type_info_maybe_ptr);
-					irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Maybe.elem);
-					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
-				} break;
 				case Type_Array: {
 				case Type_Array: {
 					tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr);
 					tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr);
 					irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem);
 					irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem);

+ 0 - 21
src/ir_print.c

@@ -172,13 +172,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 		ir_print_type(f, m, t->Pointer.elem);
 		ir_print_type(f, m, t->Pointer.elem);
 		ir_fprintf(f, "*");
 		ir_fprintf(f, "*");
 		return;
 		return;
-	case Type_Maybe:
-		ir_fprintf(f, "{");
-		ir_print_type(f, m, t->Maybe.elem);
-		ir_fprintf(f, ", ");
-		ir_print_type(f, m, t_bool);
-		ir_fprintf(f, "}");
-		return;
 	case Type_Array:
 	case Type_Array:
 		ir_fprintf(f, "[%lld x ", t->Array.count);
 		ir_fprintf(f, "[%lld x ", t->Array.count);
 		ir_print_type(f, m, t->Array.elem);
 		ir_print_type(f, m, t->Array.elem);
@@ -306,25 +299,11 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type
 	ir_print_type(f, m, elem_type);
 	ir_print_type(f, m, elem_type);
 	ir_fprintf(f, " ");
 	ir_fprintf(f, " ");
 
 
-	if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) {
-		Type *t = base_type(elem_type)->Maybe.elem;
-		ir_fprintf(f, "{");
-		ir_print_type(f, m, t);
-		ir_fprintf(f, " ");
-	}
-
 	if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
 	if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
 		ir_fprintf(f, "zeroinitializer");
 		ir_fprintf(f, "zeroinitializer");
 	} else {
 	} else {
 		ir_print_exact_value(f, m, v, elem_type);
 		ir_print_exact_value(f, m, v, elem_type);
 	}
 	}
-
-	if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) {
-		ir_fprintf(f, ", ");
-		ir_print_type(f, m, t_bool);
-		ir_fprintf(f, " ");
-		ir_fprintf(f, "true}");
-	}
 }
 }
 
 
 void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {
 void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {

+ 0 - 31
src/parser.c

@@ -147,7 +147,6 @@ AST_NODE_KIND(_ExprBegin,  "",  i32) \
 	AST_NODE_KIND(SelectorExpr, "selector expression",    struct { Token token; AstNode *expr, *selector; }) \
 	AST_NODE_KIND(SelectorExpr, "selector expression",    struct { Token token; AstNode *expr, *selector; }) \
 	AST_NODE_KIND(IndexExpr,    "index expression",       struct { AstNode *expr, *index; Token open, close; }) \
 	AST_NODE_KIND(IndexExpr,    "index expression",       struct { AstNode *expr, *index; Token open, close; }) \
 	AST_NODE_KIND(DerefExpr,    "dereference expression", struct { Token op; AstNode *expr; }) \
 	AST_NODE_KIND(DerefExpr,    "dereference expression", struct { Token op; AstNode *expr; }) \
-	AST_NODE_KIND(DemaybeExpr,  "demaybe expression",     struct { Token op; AstNode *expr; }) \
 	AST_NODE_KIND(SliceExpr, "slice expression", struct { \
 	AST_NODE_KIND(SliceExpr, "slice expression", struct { \
 		AstNode *expr; \
 		AstNode *expr; \
 		Token open, close, interval; \
 		Token open, close, interval; \
@@ -333,10 +332,6 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
 		Token token; \
 		Token token; \
 		AstNode *type; \
 		AstNode *type; \
 	}) \
 	}) \
-	AST_NODE_KIND(MaybeType, "maybe type", struct { \
-		Token token; \
-		AstNode *type; \
-	}) \
 	AST_NODE_KIND(ArrayType, "array type", struct { \
 	AST_NODE_KIND(ArrayType, "array type", struct { \
 		Token token; \
 		Token token; \
 		AstNode *count; \
 		AstNode *count; \
@@ -469,7 +464,6 @@ Token ast_node_token(AstNode *node) {
 	case AstNode_CastExpr:     return node->CastExpr.token;
 	case AstNode_CastExpr:     return node->CastExpr.token;
 	case AstNode_FieldValue:   return node->FieldValue.eq;
 	case AstNode_FieldValue:   return node->FieldValue.eq;
 	case AstNode_DerefExpr:    return node->DerefExpr.op;
 	case AstNode_DerefExpr:    return node->DerefExpr.op;
-	case AstNode_DemaybeExpr:  return node->DemaybeExpr.op;
 	case AstNode_BlockExpr:    return node->BlockExpr.open;
 	case AstNode_BlockExpr:    return node->BlockExpr.open;
 	case AstNode_GiveExpr:     return node->GiveExpr.token;
 	case AstNode_GiveExpr:     return node->GiveExpr.token;
 	case AstNode_IfExpr:       return node->IfExpr.token;
 	case AstNode_IfExpr:       return node->IfExpr.token;
@@ -513,7 +507,6 @@ Token ast_node_token(AstNode *node) {
 	case AstNode_HelperType:       return node->HelperType.token;
 	case AstNode_HelperType:       return node->HelperType.token;
 	case AstNode_ProcType:         return node->ProcType.token;
 	case AstNode_ProcType:         return node->ProcType.token;
 	case AstNode_PointerType:      return node->PointerType.token;
 	case AstNode_PointerType:      return node->PointerType.token;
-	case AstNode_MaybeType:        return node->MaybeType.token;
 	case AstNode_ArrayType:        return node->ArrayType.token;
 	case AstNode_ArrayType:        return node->ArrayType.token;
 	case AstNode_DynamicArrayType: return node->DynamicArrayType.token;
 	case AstNode_DynamicArrayType: return node->DynamicArrayType.token;
 	case AstNode_VectorType:       return node->VectorType.token;
 	case AstNode_VectorType:       return node->VectorType.token;
@@ -693,13 +686,6 @@ AstNode *ast_deref_expr(AstFile *f, AstNode *expr, Token op) {
 	return result;
 	return result;
 }
 }
 
 
-AstNode *ast_demaybe_expr(AstFile *f, AstNode *expr, Token op) {
-	AstNode *result = make_ast_node(f, AstNode_DemaybeExpr);
-	result->DemaybeExpr.expr = expr;
-	result->DemaybeExpr.op = op;
-	return result;
-}
-
 AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
 AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
 	AstNode *result = make_ast_node(f, AstNode_IntervalExpr);
 	AstNode *result = make_ast_node(f, AstNode_IntervalExpr);
 
 
@@ -1031,13 +1017,6 @@ AstNode *ast_pointer_type(AstFile *f, Token token, AstNode *type) {
 	return result;
 	return result;
 }
 }
 
 
-AstNode *ast_maybe_type(AstFile *f, Token token, AstNode *type) {
-	AstNode *result = make_ast_node(f, AstNode_MaybeType);
-	result->MaybeType.token = token;
-	result->MaybeType.type = type;
-	return result;
-}
-
 AstNode *ast_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
 AstNode *ast_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
 	AstNode *result = make_ast_node(f, AstNode_ArrayType);
 	AstNode *result = make_ast_node(f, AstNode_ArrayType);
 	result->ArrayType.token = token;
 	result->ArrayType.token = token;
@@ -1999,10 +1978,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
 			operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer));
 			operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer));
 			break;
 			break;
 
 
-		case Token_Maybe: // Demaybe
-			operand = ast_demaybe_expr(f, operand, expect_token(f, Token_Maybe));
-			break;
-
 		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);
 				operand = parse_literal_value(f, operand);
@@ -2565,12 +2540,6 @@ AstNode *parse_type_or_ident(AstFile *f) {
 		return ast_pointer_type(f, token, elem);
 		return ast_pointer_type(f, token, elem);
 	}
 	}
 
 
-	case Token_Maybe: {
-		Token token = expect_token(f, Token_Maybe);
-		AstNode *elem = parse_type(f);
-		return ast_maybe_type(f, token, elem);
-	}
-
 	case Token_OpenBracket: {
 	case Token_OpenBracket: {
 		Token token = expect_token(f, Token_OpenBracket);
 		Token token = expect_token(f, Token_OpenBracket);
 		AstNode *count_expr = NULL;
 		AstNode *count_expr = NULL;

+ 9 - 7
src/tokenizer.c

@@ -17,7 +17,7 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
 	TOKEN_KIND(Token_Hash,    "#"), \
 	TOKEN_KIND(Token_Hash,    "#"), \
 	TOKEN_KIND(Token_At,      "@"), \
 	TOKEN_KIND(Token_At,      "@"), \
 	TOKEN_KIND(Token_Pointer, "^"), \
 	TOKEN_KIND(Token_Pointer, "^"), \
-	TOKEN_KIND(Token_Maybe,   "?"), \
+	/* TOKEN_KIND(Token_Maybe,   "?"), */ \
 	TOKEN_KIND(Token_Add,     "+"), \
 	TOKEN_KIND(Token_Add,     "+"), \
 	TOKEN_KIND(Token_Sub,     "-"), \
 	TOKEN_KIND(Token_Sub,     "-"), \
 	TOKEN_KIND(Token_Mul,     "*"), \
 	TOKEN_KIND(Token_Mul,     "*"), \
@@ -55,6 +55,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
 TOKEN_KIND(Token__AssignOpEnd,   "_AssignOpEnd"), \
 TOKEN_KIND(Token__AssignOpEnd,   "_AssignOpEnd"), \
 	TOKEN_KIND(Token_ArrowRight, "->"), \
 	TOKEN_KIND(Token_ArrowRight, "->"), \
 	TOKEN_KIND(Token_ArrowLeft,  "<-"), \
 	TOKEN_KIND(Token_ArrowLeft,  "<-"), \
+	TOKEN_KIND(Token_Increment,  "++"), \
+	TOKEN_KIND(Token_Decrement,  "--"), \
 \
 \
 TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
 TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
 	TOKEN_KIND(Token_CmpEq, "=="), \
 	TOKEN_KIND(Token_CmpEq, "=="), \
@@ -80,7 +82,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
 TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
 TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
 \
 \
 TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
-	/* TODO(bill): So of these keywords are not used but "reserved", why not remove them? */ \
+	/* TODO(bill): Of these keywords are not used but "reserved", why not remove them? */ \
 	TOKEN_KIND(Token_when,           "when"), \
 	TOKEN_KIND(Token_when,           "when"), \
 	TOKEN_KIND(Token_if,             "if"), \
 	TOKEN_KIND(Token_if,             "if"), \
 	TOKEN_KIND(Token_else,           "else"), \
 	TOKEN_KIND(Token_else,           "else"), \
@@ -870,9 +872,9 @@ Token tokenizer_get_token(Tokenizer *t) {
 		case '^':
 		case '^':
 			token.kind = Token_Pointer;
 			token.kind = Token_Pointer;
 			break;
 			break;
-		case '?':
-			token.kind = Token_Maybe;
-			break;
+		// case '?':
+			// token.kind = Token_Maybe;
+			// break;
 		case ';':
 		case ';':
 			token.kind = Token_Semicolon;
 			token.kind = Token_Semicolon;
 			break;
 			break;
@@ -907,10 +909,10 @@ Token tokenizer_get_token(Tokenizer *t) {
 		case '~': token.kind = token_kind_variant2(t, Token_Xor,   Token_XorEq);     break;
 		case '~': token.kind = token_kind_variant2(t, Token_Xor,   Token_XorEq);     break;
 		case '!': token.kind = token_kind_variant2(t, Token_Not,   Token_NotEq);     break;
 		case '!': token.kind = token_kind_variant2(t, Token_Not,   Token_NotEq);     break;
 		case '+':
 		case '+':
-			token.kind = token_kind_variant2(t, Token_Add, Token_AddEq);
+			token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment);
 			break;
 			break;
 		case '-':
 		case '-':
-			token.kind = token_kind_variant3(t, Token_Sub, Token_SubEq, '>', Token_ArrowRight);
+			token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight);
 			break;
 			break;
 		case '/': {
 		case '/': {
 			if (t->curr_rune == '/') {
 			if (t->curr_rune == '/') {

+ 31 - 60
src/types.c

@@ -11,6 +11,20 @@ typedef enum BasicKind {
 	Basic_u32,
 	Basic_u32,
 	Basic_i64,
 	Basic_i64,
 	Basic_u64,
 	Basic_u64,
+
+/* 	Basic_i16le,
+	Basic_i16be,
+	Basic_u16le,
+	Basic_u16be,
+	Basic_i32le,
+	Basic_i32be,
+	Basic_u32le,
+	Basic_u32be,
+	Basic_i64le,
+	Basic_i64be,
+	Basic_u64le,
+	Basic_u64be, */
+
 	// Basic_i128,
 	// Basic_i128,
 	// Basic_u128,
 	// Basic_u128,
 	// Basic_f16,
 	// Basic_f16,
@@ -93,6 +107,7 @@ typedef struct TypeRecord {
 	Entity * enum_count;
 	Entity * enum_count;
 	Entity * enum_min_value;
 	Entity * enum_min_value;
 	Entity * enum_max_value;
 	Entity * enum_max_value;
+	Entity * enum_names;
 } TypeRecord;
 } TypeRecord;
 
 
 #define TYPE_KINDS                                        \
 #define TYPE_KINDS                                        \
@@ -102,7 +117,6 @@ typedef struct TypeRecord {
 	TYPE_KIND(DynamicArray, struct { Type *elem; })       \
 	TYPE_KIND(DynamicArray, struct { Type *elem; })       \
 	TYPE_KIND(Vector,  struct { Type *elem; i64 count; }) \
 	TYPE_KIND(Vector,  struct { Type *elem; i64 count; }) \
 	TYPE_KIND(Slice,   struct { Type *elem; })            \
 	TYPE_KIND(Slice,   struct { Type *elem; })            \
-	TYPE_KIND(Maybe,   struct { Type *elem; })            \
 	TYPE_KIND(Record,  TypeRecord)                        \
 	TYPE_KIND(Record,  TypeRecord)                        \
 	TYPE_KIND(Named, struct {                             \
 	TYPE_KIND(Named, struct {                             \
 		String  name;                                     \
 		String  name;                                     \
@@ -177,16 +191,16 @@ typedef struct BaseTypeSizes {
 } BaseTypeSizes;
 } BaseTypeSizes;
 
 
 
 
-typedef Array(isize) Array_isize;
+typedef Array(i32) Array_i32;
 
 
 typedef struct Selection {
 typedef struct Selection {
-	Entity *    entity;
-	Array_isize index;
-	bool        indirect; // Set if there was a pointer deref anywhere down the line
+	Entity *  entity;
+	Array_i32 index;
+	bool      indirect; // Set if there was a pointer deref anywhere down the line
 } Selection;
 } Selection;
 Selection empty_selection = {0};
 Selection empty_selection = {0};
 
 
-Selection make_selection(Entity *entity, Array_isize index, bool indirect) {
+Selection make_selection(Entity *entity, Array_i32 index, bool indirect) {
 	Selection s = {entity, index, indirect};
 	Selection s = {entity, index, indirect};
 	return s;
 	return s;
 }
 }
@@ -273,6 +287,7 @@ gb_global Type *t_int_ptr = NULL;
 gb_global Type *t_i64_ptr = NULL;
 gb_global Type *t_i64_ptr = NULL;
 gb_global Type *t_f64_ptr = NULL;
 gb_global Type *t_f64_ptr = NULL;
 gb_global Type *t_byte_slice = NULL;
 gb_global Type *t_byte_slice = NULL;
+gb_global Type *t_string_slice = NULL;
 
 
 
 
 gb_global Type *t_type_info                = NULL;
 gb_global Type *t_type_info                = NULL;
@@ -289,7 +304,6 @@ gb_global Type *t_type_info_any           = NULL;
 gb_global Type *t_type_info_string        = NULL;
 gb_global Type *t_type_info_string        = NULL;
 gb_global Type *t_type_info_boolean       = NULL;
 gb_global Type *t_type_info_boolean       = NULL;
 gb_global Type *t_type_info_pointer       = NULL;
 gb_global Type *t_type_info_pointer       = NULL;
-gb_global Type *t_type_info_maybe         = NULL;
 gb_global Type *t_type_info_procedure     = NULL;
 gb_global Type *t_type_info_procedure     = NULL;
 gb_global Type *t_type_info_array         = NULL;
 gb_global Type *t_type_info_array         = NULL;
 gb_global Type *t_type_info_dynamic_array = NULL;
 gb_global Type *t_type_info_dynamic_array = NULL;
@@ -310,7 +324,6 @@ gb_global Type *t_type_info_any_ptr           = NULL;
 gb_global Type *t_type_info_string_ptr        = NULL;
 gb_global Type *t_type_info_string_ptr        = NULL;
 gb_global Type *t_type_info_boolean_ptr       = NULL;
 gb_global Type *t_type_info_boolean_ptr       = NULL;
 gb_global Type *t_type_info_pointer_ptr       = NULL;
 gb_global Type *t_type_info_pointer_ptr       = NULL;
-gb_global Type *t_type_info_maybe_ptr         = NULL;
 gb_global Type *t_type_info_procedure_ptr     = NULL;
 gb_global Type *t_type_info_procedure_ptr     = NULL;
 gb_global Type *t_type_info_array_ptr         = NULL;
 gb_global Type *t_type_info_array_ptr         = NULL;
 gb_global Type *t_type_info_dynamic_array_ptr = NULL;
 gb_global Type *t_type_info_dynamic_array_ptr = NULL;
@@ -393,12 +406,6 @@ Type *make_type_pointer(gbAllocator a, Type *elem) {
 	return t;
 	return t;
 }
 }
 
 
-Type *make_type_maybe(gbAllocator a, Type *elem) {
-	Type *t = alloc_type(a, Type_Maybe);
-	t->Maybe.elem = elem;
-	return t;
-}
-
 Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
 Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
 	Type *t = alloc_type(a, Type_Array);
 	Type *t = alloc_type(a, Type_Array);
 	t->Array.elem = elem;
 	t->Array.elem = elem;
@@ -630,10 +637,6 @@ bool is_type_pointer(Type *t) {
 	}
 	}
 	return t->kind == Type_Pointer;
 	return t->kind == Type_Pointer;
 }
 }
-bool is_type_maybe(Type *t) {
-	t = base_type(t);
-	return t->kind == Type_Maybe;
-}
 bool is_type_tuple(Type *t) {
 bool is_type_tuple(Type *t) {
 	t = base_type(t);
 	t = base_type(t);
 	return t->kind == Type_Tuple;
 	return t->kind == Type_Tuple;
@@ -780,7 +783,6 @@ bool type_has_nil(Type *t) {
 	case Type_DynamicArray:
 	case Type_DynamicArray:
 	case Type_Proc:
 	case Type_Proc:
 	case Type_Pointer:
 	case Type_Pointer:
-	case Type_Maybe:
 		return true;
 		return true;
 	}
 	}
 	return false;
 	return false;
@@ -890,12 +892,6 @@ bool are_types_identical(Type *x, Type *y) {
 		}
 		}
 		break;
 		break;
 
 
-	case Type_Maybe:
-		if (y->kind == Type_Maybe) {
-			return are_types_identical(x->Maybe.elem, y->Maybe.elem);
-		}
-		break;
-
 	case Type_Named:
 	case Type_Named:
 		if (y->kind == Type_Named) {
 		if (y->kind == Type_Named) {
 			return x->Named.base == y->Named.base;
 			return x->Named.base == y->Named.base;
@@ -981,9 +977,6 @@ bool is_type_cte_safe(Type *type) {
 	case Type_Slice:
 	case Type_Slice:
 		return false;
 		return false;
 
 
-	case Type_Maybe:
-		return is_type_cte_safe(type->Maybe.elem);
-
 	case Type_Record: {
 	case Type_Record: {
 		if (type->Record.kind != TypeRecord_Struct) {
 		if (type->Record.kind != TypeRecord_Struct) {
 			return false;
 			return false;
@@ -1026,12 +1019,14 @@ typedef enum ProcTypeOverloadKind {
 	ProcOverload_ResultCount,
 	ProcOverload_ResultCount,
 	ProcOverload_ResultTypes,
 	ProcOverload_ResultTypes,
 
 
+	ProcOverload_NotProcedure,
+
 } ProcTypeOverloadKind;
 } ProcTypeOverloadKind;
 
 
 
 
 ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
 ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
-	GB_ASSERT(is_type_proc(x));
-	GB_ASSERT(is_type_proc(y));
+ 	if (!is_type_proc(x)) return ProcOverload_NotProcedure;
+ 	if (!is_type_proc(y)) return ProcOverload_NotProcedure;
 	TypeProc *px = &base_type(x)->Proc;
 	TypeProc *px = &base_type(x)->Proc;
 	TypeProc *py = &base_type(y)->Proc;
 	TypeProc *py = &base_type(y)->Proc;
 
 
@@ -1113,7 +1108,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
 			Entity *f = type->Record.fields[i];
 			Entity *f = type->Record.fields[i];
 			if (f->kind == Entity_Variable) {
 			if (f->kind == Entity_Variable) {
 				if (f->Variable.field_src_index == index) {
 				if (f->Variable.field_src_index == index) {
-					Array_isize sel_array = {0};
+					Array_i32 sel_array = {0};
 					array_init_count(&sel_array, a, 1);
 					array_init_count(&sel_array, a, 1);
 					sel_array.e[0] = i;
 					sel_array.e[0] = i;
 					return make_selection(f, sel_array, false);
 					return make_selection(f, sel_array, false);
@@ -1125,7 +1120,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
 		for (isize i = 0; i < max_count; i++) {
 		for (isize i = 0; i < max_count; i++) {
 			Entity *f = type->Tuple.variables[i];
 			Entity *f = type->Tuple.variables[i];
 			if (i == index) {
 			if (i == index) {
-				Array_isize sel_array = {0};
+				Array_i32 sel_array = {0};
 				array_init_count(&sel_array, a, 1);
 				array_init_count(&sel_array, a, 1);
 				sel_array.e[0] = i;
 				sel_array.e[0] = i;
 				return make_selection(f, sel_array, false);
 				return make_selection(f, sel_array, false);
@@ -1352,6 +1347,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 					sel.entity = type->Record.enum_max_value;
 					sel.entity = type->Record.enum_max_value;
 					return sel;
 					return sel;
 				}
 				}
+				if (str_eq(field_name, str_lit("names"))) {
+					sel.entity = type->Record.enum_names;
+					return sel;
+				}
 			}
 			}
 
 
 			for (isize i = 0; i < type->Record.field_count; i++) {
 			for (isize i = 0; i < type->Record.field_count; i++) {
@@ -1558,17 +1557,6 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
 		return max;
 		return max;
 	} break;
 	} break;
 
 
-	case Type_Maybe: {
-		Type *elem = t->Maybe.elem;
-		type_path_push(path, elem);
-		if (path->failure) {
-			return FAILURE_ALIGNMENT;
-		}
-		i64 align = gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path));
-		type_path_pop(path);
-		return align;
-	}
-
 	case Type_Map: {
 	case Type_Map: {
 		if (t->Map.count == 0) { // Dynamic
 		if (t->Map.count == 0) { // Dynamic
 			return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path);
 			return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path);
@@ -1773,18 +1761,6 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
 	case Type_Slice: // ptr + count
 	case Type_Slice: // ptr + count
 		return 2 * s.word_size;
 		return 2 * s.word_size;
 
 
-	case Type_Maybe: { // value + bool
-		i64 align, size;
-		Type *elem = t->Maybe.elem;
-		align = type_align_of_internal(s, allocator, elem, path);
-		if (path->failure) {
-			return FAILURE_SIZE;
-		}
-		size = align_formula(type_size_of_internal(s, allocator, elem, path), align);
-		size += type_size_of_internal(s, allocator, t_bool, path);
-		return align_formula(size, align);
-	}
-
 	case Type_Map: {
 	case Type_Map: {
 		if (t->Map.count == 0) { // Dynamic
 		if (t->Map.count == 0) { // Dynamic
 			return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path);
 			return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path);
@@ -1969,11 +1945,6 @@ gbString write_type_to_string(gbString str, Type *type) {
 		str = write_type_to_string(str, type->Pointer.elem);
 		str = write_type_to_string(str, type->Pointer.elem);
 		break;
 		break;
 
 
-	case Type_Maybe:
-		str = gb_string_appendc(str, "?");
-		str = write_type_to_string(str, type->Maybe.elem);
-		break;
-
 	case Type_Array:
 	case Type_Array:
 		str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count));
 		str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count));
 		str = write_type_to_string(str, type->Array.elem);
 		str = write_type_to_string(str, type->Array.elem);

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio