Browse Source

Remove `enum` for favour of Go-style enumerations

Ginger Bill 8 years ago
parent
commit
478d63424f
15 changed files with 279 additions and 912 deletions
  1. 3 3
      code/demo.odin
  2. 19 37
      core/_preload.odin
  3. 0 20
      core/fmt.odin
  4. 4 9
      core/mem.odin
  5. 10 9
      core/os_windows.odin
  6. 154 153
      core/sys/windows.odin
  7. 4 83
      src/checker/checker.c
  8. 11 11
      src/checker/decl.c
  9. 1 0
      src/checker/entity.c
  10. 11 252
      src/checker/expr.c
  11. 44 49
      src/checker/stmt.c
  12. 8 93
      src/checker/types.c
  13. 6 45
      src/parser.c
  14. 4 145
      src/ssa.c
  15. 0 3
      src/ssa_print.c

+ 3 - 3
code/demo.odin

@@ -29,8 +29,8 @@ const (
 	EB;
 );
 
+
 proc main() {
-	fmt.println(X, Y, Z);
-	fmt.println(A, B, C);
-	fmt.println(KB, MB, GB, TB, PB, EB);
+	var x = 123;
+	fmt.println(x);
 }

+ 19 - 37
core/_preload.odin

@@ -70,11 +70,6 @@ type Type_Info union {
 	Struct    Type_Info_Record;
 	Union     Type_Info_Record;
 	Raw_Union Type_Info_Record;
-	Enum struct #ordered {
-		base   ^Type_Info;
-		values []i64;
-		names  []string;
-	};
 };
 
 proc type_info_base(info ^Type_Info) -> ^Type_Info {
@@ -113,12 +108,13 @@ proc fmuladd64(a, b, c f64) -> f64 #foreign "llvm.fmuladd.f64"
 
 
 
-type Allocator_Mode enum {
-	ALLOC,
-	FREE,
-	FREE_ALL,
-	RESIZE,
-}
+type Allocator_Mode int;
+const (
+	ALLOCATOR_ALLOC Allocator_Mode = iota;
+	ALLOCATOR_FREE;
+	ALLOCATOR_FREE_ALL;
+	ALLOCATOR_RESIZE;
+);
 type Allocator_Proc proc(allocator_data rawptr, mode Allocator_Mode,
                          size, alignment int,
                          old_memory rawptr, old_size int, flags u64) -> rawptr;
@@ -162,20 +158,20 @@ proc alloc(size int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNM
 proc alloc_align(size, alignment int) -> rawptr #inline {
 	__check_context();
 	var a = context.allocator;
-	return a.procedure(a.data, Allocator_Mode.ALLOC, size, alignment, nil, 0, 0);
+	return a.procedure(a.data, ALLOCATOR_ALLOC, size, alignment, nil, 0, 0);
 }
 
 proc free(ptr rawptr) #inline {
 	__check_context();
 	var a = context.allocator;
 	if ptr != nil {
-		a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0);
+		a.procedure(a.data, ALLOCATOR_FREE, 0, 0, ptr, 0, 0);
 	}
 }
 proc free_all() #inline {
 	__check_context();
 	var a = context.allocator;
-	a.procedure(a.data, Allocator_Mode.FREE_ALL, 0, 0, nil, 0, 0);
+	a.procedure(a.data, ALLOCATOR_FREE_ALL, 0, 0, nil, 0, 0);
 }
 
 
@@ -183,7 +179,7 @@ proc resize      (ptr rawptr, old_size, new_size int) -> rawptr #inline { return
 proc resize_align(ptr rawptr, old_size, new_size, alignment int) -> rawptr #inline {
 	__check_context();
 	var a = context.allocator;
-	return a.procedure(a.data, Allocator_Mode.RESIZE, new_size, alignment, ptr, old_size, 0);
+	return a.procedure(a.data, ALLOCATOR_RESIZE, new_size, alignment, ptr, old_size, 0);
 }
 
 
@@ -216,10 +212,9 @@ proc default_resize_align(old_memory rawptr, old_size, new_size, alignment int)
 proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
                             size, alignment int,
                             old_memory rawptr, old_size int, flags u64) -> rawptr {
-	using Allocator_Mode;
 	when false {
 		match mode {
-		case ALLOC:
+		case ALLOCATOR_ALLOC:
 			var total_size = size + alignment + size_of(mem.AllocationHeader);
 			var ptr = os.heap_alloc(total_size);
 			var header = ptr as ^mem.AllocationHeader;
@@ -227,14 +222,14 @@ proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
 			mem.allocation_header_fill(header, ptr, size);
 			return mem.zero(ptr, size);
 
-		case FREE:
+		case ALLOCATOR_FREE:
 			os.heap_free(mem.allocation_header(old_memory));
 			return nil;
 
-		case FREE_ALL:
+		case ALLOCATOR_FREE_ALL:
 			// NOTE(bill): Does nothing
 
-		case RESIZE:
+		case ALLOCATOR_RESIZE:
 			var total_size = size + alignment + size_of(mem.AllocationHeader);
 			var ptr = os.heap_resize(mem.allocation_header(old_memory), total_size);
 			var header = ptr as ^mem.AllocationHeader;
@@ -244,17 +239,17 @@ proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
 		}
 	} else {
 		match mode {
-		case ALLOC:
+		case ALLOCATOR_ALLOC:
 			return os.heap_alloc(size);
 
-		case FREE:
+		case ALLOCATOR_FREE:
 			os.heap_free(old_memory);
 			return nil;
 
-		case FREE_ALL:
+		case ALLOCATOR_FREE_ALL:
 			// NOTE(bill): Does nothing
 
-		case RESIZE:
+		case ALLOCATOR_RESIZE:
 			return os.heap_resize(old_memory, size);
 		}
 	}
@@ -332,17 +327,4 @@ proc __substring_expr_error(file string, line, column int, low, high int) {
 	__debug_trap();
 }
 
-proc __enum_to_string(info ^Type_Info, value i64) -> string {
-	match type ti : type_info_base(info) {
-	case Type_Info.Enum:
-		// TODO(bill): Search faster than linearly
-		for var i = 0; i < ti.values.count; i++ {
-			if ti.values[i] == value {
-				return ti.names[i];
-			}
-		}
-	}
-	return "";
-}
-
 

+ 0 - 20
core/fmt.odin

@@ -290,11 +290,6 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
 			bprint_type(buf, info.fields[i].type_info);
 		}
 		bprint_string(buf, "}");
-
-	case Enum:
-		bprint_string(buf, "enum ");
-		bprint_type(buf, info.base);
-		bprint_string(buf, "{}");
 	}
 }
 
@@ -392,21 +387,6 @@ proc bprint_any(buf ^[]byte, arg any) {
 			bprint_string(buf, "nil");
 		}
 
-	case Enum:
-		var value i64 = 0;
-
-		match type i : make_any(info.base, arg.data) {
-		case i8:   value = i as i64;
-		case i16:  value = i as i64;
-		case i32:  value = i as i64;
-		case i64:  value = i as i64;
-		case u8:   value = i as i64;
-		case u16:  value = i as i64;
-		case u32:  value = i as i64;
-		case u64:  value = i as i64;
-		}
-		bprint_string(buf, __enum_to_string(arg.type_info, value));
-
 	case Array:
 		bprintf(buf, "[%]%{", info.count, info.elem);
 		defer bprint_string(buf, "}");

+ 4 - 9
core/mem.odin

@@ -162,9 +162,8 @@ proc arena_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
                           old_memory rawptr, old_size int, flags u64) -> rawptr {
 	var arena = allocator_data as ^Arena;
 
-	using Allocator_Mode;
 	match mode {
-	case ALLOC:
+	case ALLOCATOR_ALLOC:
 		var total_size = size + alignment;
 
 		if arena.memory.count + total_size > arena.memory.capacity {
@@ -178,14 +177,14 @@ proc arena_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
 		arena.memory.count += total_size;
 		return zero(ptr, size);
 
-	case FREE:
+	case ALLOCATOR_FREE:
 		// NOTE(bill): Free all at once
 		// Use Arena_Temp_Memory if you want to free a block
 
-	case FREE_ALL:
+	case ALLOCATOR_FREE_ALL:
 		arena.memory.count = 0;
 
-	case RESIZE:
+	case ALLOCATOR_RESIZE:
 		return default_resize_align(old_memory, old_size, size, alignment);
 	}
 
@@ -263,8 +262,6 @@ proc align_of_type_info(type_info ^Type_Info) -> int {
 		return info.align;
 	case Raw_Union:
 		return info.align;
-	case Enum:
-		return align_of_type_info(info.base);
 	}
 
 	return 0;
@@ -339,8 +336,6 @@ proc size_of_type_info(type_info ^Type_Info) -> int {
 		return info.size;
 	case Raw_Union:
 		return info.size;
-	case Enum:
-		return size_of_type_info(info.base);
 	}
 
 	return 0;

+ 10 - 9
core/os_windows.odin

@@ -83,23 +83,24 @@ proc last_write_time_by_name(name string) -> File_Time {
 
 
 
+const (
+	FILE_STANDARD_INPUT = iota;
+	FILE_STANDARD_OUTPUT;
+	FILE_STANDARD_ERROR;
 
-type File_Standard enum {
-	INPUT,
-	OUTPUT,
-	ERROR,
-}
+	FILE_STANDARD_COUNT;
+);
 
 // NOTE(bill): Uses startup to initialize it
-var __std_files = [File_Standard.count]File{
+var __std_files = [FILE_STANDARD_COUNT]File{
 	{handle = win32.GetStdHandle(win32.STD_INPUT_HANDLE)  transmute File_Handle },
 	{handle = win32.GetStdHandle(win32.STD_OUTPUT_HANDLE) transmute File_Handle },
 	{handle = win32.GetStdHandle(win32.STD_ERROR_HANDLE)  transmute File_Handle },
 };
 
-var stdin  = ^__std_files[File_Standard.INPUT];
-var stdout = ^__std_files[File_Standard.OUTPUT];
-var stderr = ^__std_files[File_Standard.ERROR];
+var stdin  = ^__std_files[FILE_STANDARD_INPUT];
+var stdout = ^__std_files[FILE_STANDARD_OUTPUT];
+var stderr = ^__std_files[FILE_STANDARD_ERROR];
 
 
 

+ 154 - 153
core/sys/windows.odin

@@ -369,157 +369,158 @@ proc is_key_down(key Key_Code) -> bool {
 	return GetAsyncKeyState(key as i32) < 0;
 }
 
-type Key_Code enum i32 {
-	LBUTTON    = 0x01,
-	RBUTTON    = 0x02,
-	CANCEL     = 0x03,
-	MBUTTON    = 0x04,
-
-	BACK       = 0x08,
-	TAB        = 0x09,
-
-	CLEAR      = 0x0C,
-	RETURN     = 0x0D,
-
-	SHIFT      = 0x10,
-	CONTROL    = 0x11,
-	MENU       = 0x12,
-	PAUSE      = 0x13,
-	CAPITAL    = 0x14,
-
-	KANA       = 0x15,
-	HANGEUL    = 0x15,
-	HANGUL     = 0x15,
-	JUNJA      = 0x17,
-	FINAL      = 0x18,
-	HANJA      = 0x19,
-	KANJI      = 0x19,
-
-	ESCAPE     = 0x1B,
-
-	CONVERT    = 0x1C,
-	NONCONVERT = 0x1D,
-	ACCEPT     = 0x1E,
-	MODECHANGE = 0x1F,
-
-	SPACE      = 0x20,
-	PRIOR      = 0x21,
-	NEXT       = 0x22,
-	END        = 0x23,
-	HOME       = 0x24,
-	LEFT       = 0x25,
-	UP         = 0x26,
-	RIGHT      = 0x27,
-	DOWN       = 0x28,
-	SELECT     = 0x29,
-	PRINT      = 0x2A,
-	EXECUTE    = 0x2B,
-	SNAPSHOT   = 0x2C,
-	INSERT     = 0x2D,
-	DELETE     = 0x2E,
-	HELP       = 0x2F,
-
-	NUM0 = '0',
-	NUM1 = '1',
-	NUM2 = '2',
-	NUM3 = '3',
-	NUM4 = '4',
-	NUM5 = '5',
-	NUM6 = '6',
-	NUM7 = '7',
-	NUM8 = '8',
-	NUM9 = '9',
-
-	A = 'A',
-	B = 'B',
-	C = 'C',
-	D = 'D',
-	E = 'E',
-	F = 'F',
-	G = 'G',
-	H = 'H',
-	I = 'I',
-	J = 'J',
-	K = 'K',
-	L = 'L',
-	M = 'M',
-	N = 'N',
-	O = 'O',
-	P = 'P',
-	Q = 'Q',
-	R = 'R',
-	S = 'S',
-	T = 'T',
-	U = 'U',
-	V = 'V',
-	W = 'W',
-	X = 'X',
-	Y = 'Y',
-	Z = 'Z',
-
-	LWIN       = 0x5B,
-	RWIN       = 0x5C,
-	APPS       = 0x5D,
-
-	NUMPAD0    = 0x60,
-	NUMPAD1    = 0x61,
-	NUMPAD2    = 0x62,
-	NUMPAD3    = 0x63,
-	NUMPAD4    = 0x64,
-	NUMPAD5    = 0x65,
-	NUMPAD6    = 0x66,
-	NUMPAD7    = 0x67,
-	NUMPAD8    = 0x68,
-	NUMPAD9    = 0x69,
-	MULTIPLY   = 0x6A,
-	ADD        = 0x6B,
-	SEPARATOR  = 0x6C,
-	SUBTRACT   = 0x6D,
-	DECIMAL    = 0x6E,
-	DIVIDE     = 0x6F,
-	F1         = 0x70,
-	F2         = 0x71,
-	F3         = 0x72,
-	F4         = 0x73,
-	F5         = 0x74,
-	F6         = 0x75,
-	F7         = 0x76,
-	F8         = 0x77,
-	F9         = 0x78,
-	F10        = 0x79,
-	F11        = 0x7A,
-	F12        = 0x7B,
-	F13        = 0x7C,
-	F14        = 0x7D,
-	F15        = 0x7E,
-	F16        = 0x7F,
-	F17        = 0x80,
-	F18        = 0x81,
-	F19        = 0x82,
-	F20        = 0x83,
-	F21        = 0x84,
-	F22        = 0x85,
-	F23        = 0x86,
-	F24        = 0x87,
-
-	NUMLOCK    = 0x90,
-	SCROLL     = 0x91,
-
-	LSHIFT     = 0xA0,
-	RSHIFT     = 0xA1,
-	LCONTROL   = 0xA2,
-	RCONTROL   = 0xA3,
-	LMENU      = 0xA4,
-	RMENU      = 0xA5,
-	PROCESSKEY = 0xE5,
-	ATTN       = 0xF6,
-	CRSEL      = 0xF7,
-	EXSEL      = 0xF8,
-	EREOF      = 0xF9,
-	PLAY       = 0xFA,
-	ZOOM       = 0xFB,
-	NONAME     = 0xFC,
-	PA1        = 0xFD,
-	OEM_CLEAR  = 0xFE,
-}
+type Key_Code i32;
+const (
+	KEY_LBUTTON Key_Code = 0x01;
+	KEY_RBUTTON          = 0x02;
+	KEY_CANCEL           = 0x03;
+	KEY_MBUTTON          = 0x04;
+
+	KEY_BACK             = 0x08;
+	KEY_TAB              = 0x09;
+
+	KEY_CLEAR            = 0x0C;
+	KEY_RETURN           = 0x0D;
+
+	KEY_SHIFT            = 0x10;
+	KEY_CONTROL          = 0x11;
+	KEY_MENU             = 0x12;
+	KEY_PAUSE            = 0x13;
+	KEY_CAPITAL          = 0x14;
+
+	KEY_KANA             = 0x15;
+	KEY_HANGEUL          = 0x15;
+	KEY_HANGUL           = 0x15;
+	KEY_JUNJA            = 0x17;
+	KEY_FINAL            = 0x18;
+	KEY_HANJA            = 0x19;
+	KEY_KANJI            = 0x19;
+
+	KEY_ESCAPE           = 0x1B;
+
+	KEY_CONVERT          = 0x1C;
+	KEY_NONCONVERT       = 0x1D;
+	KEY_ACCEPT           = 0x1E;
+	KEY_MODECHANGE       = 0x1F;
+
+	KEY_SPACE            = 0x20;
+	KEY_PRIOR            = 0x21;
+	KEY_NEXT             = 0x22;
+	KEY_END              = 0x23;
+	KEY_HOME             = 0x24;
+	KEY_LEFT             = 0x25;
+	KEY_UP               = 0x26;
+	KEY_RIGHT            = 0x27;
+	KEY_DOWN             = 0x28;
+	KEY_SELECT           = 0x29;
+	KEY_PRINT            = 0x2A;
+	KEY_EXECUTE          = 0x2B;
+	KEY_SNAPSHOT         = 0x2C;
+	KEY_INSERT           = 0x2D;
+	KEY_DELETE           = 0x2E;
+	KEY_HELP             = 0x2F;
+
+	KEY_NUM0 = '0';
+	KEY_NUM1 = '1';
+	KEY_NUM2 = '2';
+	KEY_NUM3 = '3';
+	KEY_NUM4 = '4';
+	KEY_NUM5 = '5';
+	KEY_NUM6 = '6';
+	KEY_NUM7 = '7';
+	KEY_NUM8 = '8';
+	KEY_NUM9 = '9';
+
+	KEY_A = 'A';
+	KEY_B = 'B';
+	KEY_C = 'C';
+	KEY_D = 'D';
+	KEY_E = 'E';
+	KEY_F = 'F';
+	KEY_G = 'G';
+	KEY_H = 'H';
+	KEY_I = 'I';
+	KEY_J = 'J';
+	KEY_K = 'K';
+	KEY_L = 'L';
+	KEY_M = 'M';
+	KEY_N = 'N';
+	KEY_O = 'O';
+	KEY_P = 'P';
+	KEY_Q = 'Q';
+	KEY_R = 'R';
+	KEY_S = 'S';
+	KEY_T = 'T';
+	KEY_U = 'U';
+	KEY_V = 'V';
+	KEY_W = 'W';
+	KEY_X = 'X';
+	KEY_Y = 'Y';
+	KEY_Z = 'Z';
+
+	KEY_LWIN       = 0x5B;
+	KEY_RWIN       = 0x5C;
+	KEY_APPS       = 0x5D;
+
+	KEY_NUMPAD0    = 0x60;
+	KEY_NUMPAD1    = 0x61;
+	KEY_NUMPAD2    = 0x62;
+	KEY_NUMPAD3    = 0x63;
+	KEY_NUMPAD4    = 0x64;
+	KEY_NUMPAD5    = 0x65;
+	KEY_NUMPAD6    = 0x66;
+	KEY_NUMPAD7    = 0x67;
+	KEY_NUMPAD8    = 0x68;
+	KEY_NUMPAD9    = 0x69;
+	KEY_MULTIPLY   = 0x6A;
+	KEY_ADD        = 0x6B;
+	KEY_SEPARATOR  = 0x6C;
+	KEY_SUBTRACT   = 0x6D;
+	KEY_DECIMAL    = 0x6E;
+	KEY_DIVIDE     = 0x6F;
+	KEY_F1         = 0x70;
+	KEY_F2         = 0x71;
+	KEY_F3         = 0x72;
+	KEY_F4         = 0x73;
+	KEY_F5         = 0x74;
+	KEY_F6         = 0x75;
+	KEY_F7         = 0x76;
+	KEY_F8         = 0x77;
+	KEY_F9         = 0x78;
+	KEY_F10        = 0x79;
+	KEY_F11        = 0x7A;
+	KEY_F12        = 0x7B;
+	KEY_F13        = 0x7C;
+	KEY_F14        = 0x7D;
+	KEY_F15        = 0x7E;
+	KEY_F16        = 0x7F;
+	KEY_F17        = 0x80;
+	KEY_F18        = 0x81;
+	KEY_F19        = 0x82;
+	KEY_F20        = 0x83;
+	KEY_F21        = 0x84;
+	KEY_F22        = 0x85;
+	KEY_F23        = 0x86;
+	KEY_F24        = 0x87;
+
+	KEY_NUMLOCK    = 0x90;
+	KEY_SCROLL     = 0x91;
+
+	KEY_LSHIFT     = 0xA0;
+	KEY_RSHIFT     = 0xA1;
+	KEY_LCONTROL   = 0xA2;
+	KEY_RCONTROL   = 0xA3;
+	KEY_LMENU      = 0xA4;
+	KEY_RMENU      = 0xA5;
+	KEY_PROCESSKEY = 0xE5;
+	KEY_ATTN       = 0xF6;
+	KEY_CRSEL      = 0xF7;
+	KEY_EXSEL      = 0xF8;
+	KEY_EREOF      = 0xF9;
+	KEY_PLAY       = 0xFA;
+	KEY_ZOOM       = 0xFB;
+	KEY_NONAME     = 0xFC;
+	KEY_PA1        = 0xFD;
+	KEY_OEM_CLEAR  = 0xFE;
+);
 

+ 4 - 83
src/checker/checker.c

@@ -127,8 +127,6 @@ typedef enum BuiltinProcId {
 	BuiltinProc_abs,
 	BuiltinProc_clamp,
 
-	BuiltinProc_enum_to_string,
-
 	BuiltinProc_Count,
 } BuiltinProcId;
 typedef struct BuiltinProc {
@@ -171,8 +169,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("max"),              2, false, Expr_Expr},
 	{STR_LIT("abs"),              1, false, Expr_Expr},
 	{STR_LIT("clamp"),            3, false, Expr_Expr},
-
-	{STR_LIT("enum_to_string"),   1, false, Expr_Expr},
 };
 
 typedef enum ImplicitValueId {
@@ -681,7 +677,9 @@ void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode m
 }
 
 void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
-	GB_ASSERT(expression != NULL);
+	if (expression == NULL) {
+		return;
+	}
 	if (mode == Addressing_Invalid) {
 		return;
 	}
@@ -864,10 +862,6 @@ void add_type_info_type(Checker *c, Type *t) {
 
 	case Type_Record: {
 		switch (bt->Record.kind) {
-		case TypeRecord_Enum:
-			add_type_info_type(c, bt->Record.enum_base);
-			break;
-
 		case TypeRecord_Union:
 			add_type_info_type(c, t_int);
 			/* fallthrough */
@@ -1012,7 +1006,7 @@ void init_preload(Checker *c) {
 		t_type_info_member = type_info_member_entity->type;
 		t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
 
-		if (record->field_count != 18) {
+		if (record->field_count != 17) {
 			compiler_error("Invalid `Type_Info` layout");
 		}
 		t_type_info_named     = record->fields[ 1]->type;
@@ -1031,7 +1025,6 @@ void init_preload(Checker *c) {
 		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;
 	}
 
 	if (t_allocator == NULL) {
@@ -1253,78 +1246,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
 			DelayedDecl di = {parent_scope, decl};
 			array_add(&c->delayed_foreign_libraries, di);
 		case_end;
-		case_ast_node(vd, VarDecl, decl);
-			if (!parent_scope->is_file) {
-				// NOTE(bill): Within a procedure, variables must be in order
-				continue;
-			}
-
-			// NOTE(bill): You need to store the entity information here unline a constant declaration
-			isize entity_count = vd->names.count;
-			isize entity_index = 0;
-			Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
-			DeclInfo *di = NULL;
-			if (vd->values.count > 0) {
-				di = make_declaration_info(heap_allocator(), parent_scope);
-				di->entities = entities;
-				di->entity_count = entity_count;
-				di->type_expr = vd->type;
-				di->init_expr = vd->values.e[0];
-			}
-
-			for_array(i, vd->names) {
-				AstNode *name = vd->names.e[i];
-				AstNode *value = NULL;
-				if (i < vd->values.count) {
-					value = vd->values.e[i];
-				}
-				if (name->kind != AstNode_Ident) {
-					error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
-					continue;
-				}
-				Entity *e = make_entity_variable(c->allocator, parent_scope, name->Ident, NULL);
-				e->identifier = name;
-				entities[entity_index++] = e;
-
-				DeclInfo *d = di;
-				if (d == NULL) {
-					AstNode *init_expr = value;
-					d = make_declaration_info(heap_allocator(), e->scope);
-					d->type_expr = vd->type;
-					d->init_expr = init_expr;
-					d->var_decl_tags = vd->tags;
-				}
-
-				add_entity_and_decl_info(c, name, e, d);
-			}
-		case_end;
-		case_ast_node(cd, ConstDecl, decl);
-			for_array(i, cd->values) {
-				AstNode *name = cd->names.e[i];
-				AstNode *value = unparen_expr(cd->values.e[i]);
-				if (name->kind != AstNode_Ident) {
-					error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
-					continue;
-				}
-
-				ExactValue v = {ExactValue_Invalid};
-				Entity *e = make_entity_constant(c->allocator, parent_scope, name->Ident, NULL, v);
-				e->identifier = name;
-				DeclInfo *di = make_declaration_info(c->allocator, e->scope);
-				di->type_expr = cd->type;
-				di->init_expr = value;
-				add_entity_and_decl_info(c, name, e, di);
-			}
-
-			isize lhs_count = cd->names.count;
-			isize rhs_count = cd->values.count;
-
-			if (rhs_count == 0 && cd->type == NULL) {
-				error_node(decl, "Missing type or initial expression");
-			} else if (lhs_count < rhs_count) {
-				error_node(decl, "Extra initial expression");
-			}
-		case_end;
 		case_ast_node(td, TypeDecl, decl);
 			if (td->name->kind != AstNode_Ident) {
 				error_node(td->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[td->name->kind]));

+ 11 - 11
src/checker/decl.c

@@ -98,15 +98,14 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 	gb_temp_arena_memory_end(tmp);
 }
 
-
-void check_var_decl_node(Checker *c, AstNode *node) {
-	ast_node(vd, VarDecl, node);
-	isize entity_count = vd->names.count;
+void check_var_spec_node(Checker *c, AstNodeValueSpec *vs) {
+	GB_ASSERT(vs->keyword == Token_var);
+	isize entity_count = vs->names.count;
 	isize entity_index = 0;
 	Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
 
-	for_array(i, vd->names) {
-		AstNode *name = vd->names.e[i];
+	for_array(i, vs->names) {
+		AstNode *name = vs->names.e[i];
 		Entity *entity = NULL;
 		if (name->kind == AstNode_Ident) {
 			Token token = name->Ident;
@@ -137,8 +136,8 @@ void check_var_decl_node(Checker *c, AstNode *node) {
 	}
 
 	Type *init_type = NULL;
-	if (vd->type) {
-		init_type = check_type_extra(c, vd->type, NULL);
+	if (vs->type) {
+		init_type = check_type_extra(c, vs->type, NULL);
 		if (init_type == NULL) {
 			init_type = t_invalid;
 		}
@@ -157,11 +156,12 @@ void check_var_decl_node(Checker *c, AstNode *node) {
 			e->type = init_type;
 	}
 
-	check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
 
-	for_array(i, vd->names) {
+	check_init_variables(c, entities, entity_count, vs->values, str_lit("variable declaration"));
+
+	for_array(i, vs->names) {
 		if (entities[i] != NULL) {
-			add_entity(c, c->context.scope, vd->names.e[i], entities[i]);
+			add_entity(c, c->context.scope, vs->names.e[i], entities[i]);
 		}
 	}
 

+ 1 - 0
src/checker/entity.c

@@ -55,6 +55,7 @@ struct Entity {
 			ExactValue value;
 		} Constant;
 		struct {
+			b32 is_let;
 			i32 field_index;
 			i32 field_src_index;
 		} Variable;

+ 11 - 252
src/checker/expr.c

@@ -131,76 +131,6 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
 				}
 			}
 		case_end;
-		case_ast_node(cd, ConstDecl, node);
-			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-
-			isize entity_count = cd->names.count;
-			isize entity_index = 0;
-			Entity **entities = gb_alloc_array(c->tmp_allocator, Entity *, entity_count);
-
-			for_array(i, cd->values) {
-				AstNode *name = cd->names.e[i];
-				AstNode *value = unparen_expr(cd->values.e[i]);
-				if (name->kind != AstNode_Ident) {
-					error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
-					entities[entity_index++] = NULL;
-					continue;
-				}
-
-				ExactValue v = {ExactValue_Invalid};
-				Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
-				e->identifier = name;
-				entities[entity_index++] = e;
-				DeclInfo *d = make_declaration_info(c->allocator, e->scope);
-				d->type_expr = cd->type;
-				d->init_expr = value;
-				add_entity_and_decl_info(c, name, e, d);
-
-				DelayedEntity delay = {name, e, d};
-				array_add(delayed_entities, delay);
-			}
-
-			isize lhs_count = cd->names.count;
-			isize rhs_count = cd->values.count;
-
-			// TODO(bill): Better error messages or is this good enough?
-			if (rhs_count == 0 && cd->type == NULL) {
-				error_node(node, "Missing type or initial expression");
-			} else if (lhs_count < rhs_count) {
-				error_node(node, "Extra initial expression");
-			}
-
-			if (dof != NULL) {
-				// NOTE(bill): Within a record
-				for_array(i, cd->names) {
-					Entity *e = entities[i];
-					if (e == NULL) {
-						continue;
-					}
-					AstNode *name = cd->names.e[i];
-					if (name->kind != AstNode_Ident) {
-						continue;
-					}
-					Token name_token = name->Ident;
-					if (str_eq(name_token.string, str_lit("_"))) {
-						dof->other_fields[dof->other_field_index++] = e;
-					} else {
-						HashKey key = hash_string(name_token.string);
-						if (map_entity_get(dof->entity_map, key) != NULL) {
-							// TODO(bill): Scope checking already checks the declaration
-							error(name_token, "`%.*s` is already declared in this record", LIT(name_token.string));
-						} else {
-							map_entity_set(dof->entity_map, key, e);
-							dof->other_fields[dof->other_field_index++] = e;
-						}
-						add_entity(c, c->context.scope, name, e);
-					}
-				}
-			}
-
-			gb_temp_arena_memory_end(tmp);
-		case_end;
-
 #if 0
 		case_ast_node(pd, ProcDecl, node);
 			if (!ast_node_expect(pd->name, AstNode_Ident)) {
@@ -362,9 +292,6 @@ bool check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
 	}
 
 	if (are_types_identical(dst, src) && (!is_type_named(dst) || !is_type_named(src))) {
-		if (is_type_enum(dst) && is_type_enum(src))  {
-			return are_types_identical(s, type);
-		}
 		return true;
 	}
 
@@ -794,127 +721,6 @@ GB_COMPARE_PROC(cmp_enum_order) {
 	return i < j ? -1 : i > j;
 }
 
-
-
-void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
-	GB_ASSERT(node->kind == AstNode_EnumType);
-	GB_ASSERT(is_type_enum(enum_type));
-	ast_node(et, EnumType, node);
-
-	Type *base_type = t_int;
-	if (et->base_type != NULL) {
-		base_type = check_type(c, et->base_type);
-	}
-
-	if (base_type == NULL || !is_type_integer(base_type)) {
-		error(et->token, "Base type for enumeration must be an integer");
-		return;
-	} else
-	if (base_type == NULL) {
-		base_type = t_int;
-	}
-	enum_type->Record.enum_base = base_type;
-
-	Entity **fields = gb_alloc_array(c->allocator, Entity *, et->fields.count);
-	isize field_index = 0;
-	ExactValue iota = make_exact_value_integer(-1);
-	i64 min_value = 0;
-	i64 max_value = 0;
-
-	Type *constant_type = enum_type;
-	if (named_type != NULL) {
-		constant_type = named_type;
-	}
-
-
-	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-
-	MapEntity entity_map = {0};
-	map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count));
-
-	Entity *blank_entity = make_entity_constant(c->allocator, c->context.scope, blank_token, constant_type, make_exact_value_integer(0));;
-
-	for_array(i, et->fields) {
-		AstNode *field = et->fields.e[i];
-
-		if (!ast_node_expect(field, AstNode_FieldValue)) {
-			continue;
-		}
-
-		ast_node(f, FieldValue, field);
-		Token name_token = f->field->Ident;
-
-		if (str_eq(name_token.string, str_lit("count"))) {
-			error(name_token, "`count` is a reserved identifier for enumerations");
-			fields[field_index++] = blank_entity;
-			continue;
-		} else if (str_eq(name_token.string, str_lit("min_value"))) {
-			error(name_token, "`min_value` is a reserved identifier for enumerations");
-			fields[field_index++] = blank_entity;
-			continue;
-		} else if (str_eq(name_token.string, str_lit("max_value"))) {
-			error(name_token, "`max_value` is a reserved identifier for enumerations");
-			fields[field_index++] = blank_entity;
-			continue;
-		}
-
-		Operand o = {0};
-		if (f->value != NULL) {
-			check_expr(c, &o, f->value);
-			if (o.mode != Addressing_Constant) {
-				error_node(f->value, "Enumeration value must be a constant integer %d");
-				o.mode = Addressing_Invalid;
-			}
-			if (o.mode != Addressing_Invalid) {
-				check_assignment(c, &o, constant_type, str_lit("enumeration"));
-			}
-			if (o.mode != Addressing_Invalid) {
-				iota = o.value;
-			} else {
-				iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
-			}
-		} else {
-			iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
-		}
-
-
-		Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, constant_type, iota);
-		if (min_value > iota.value_integer) {
-			min_value = iota.value_integer;
-		}
-		if (max_value < iota.value_integer) {
-			max_value = iota.value_integer;
-		}
-
-		HashKey key = hash_string(name_token.string);
-		if (map_entity_get(&entity_map, key)) {
-			// TODO(bill): Scope checking already checks the declaration
-			error(name_token, "`%.*s` is already declared in this enumeration", LIT(name_token.string));
-		} else {
-			map_entity_set(&entity_map, key, e);
-			add_entity(c, c->context.scope, NULL, e);
-			fields[field_index++] = e;
-		}
-		add_entity_use(c, f->field, e);
-	}
-
-	GB_ASSERT(field_index <= et->fields.count);
-
-	gb_sort_array(fields, field_index, cmp_enum_order);
-
-	enum_type->Record.enum_values = fields;
-	enum_type->Record.enum_value_count = field_index;
-
-	enum_type->Record.enum_count = make_entity_constant(c->allocator, NULL,
-		make_token_ident(str_lit("count")), t_int, make_exact_value_integer(enum_type->Record.enum_value_count));
-	enum_type->Record.min_value  = make_entity_constant(c->allocator, NULL,
-		make_token_ident(str_lit("min_value")), constant_type, make_exact_value_integer(min_value));
-	enum_type->Record.max_value  = make_entity_constant(c->allocator, NULL,
-		make_token_ident(str_lit("max_value")), constant_type, make_exact_value_integer(max_value));
-
-	gb_temp_arena_memory_end(tmp);
-}
-
 Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_variadic_) {
 	if (params.count == 0) {
 		return NULL;
@@ -1165,6 +971,11 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
 	Type *type = NULL;
 	gbString err_str = NULL;
 
+	if (e == NULL) {
+		type = t_invalid;
+		goto end;
+	}
+
 	switch (e->kind) {
 	case_ast_node(i, Ident, e);
 		Operand o = {0};
@@ -1291,16 +1102,6 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
 		goto end;
 	case_end;
 
-	case_ast_node(et, EnumType, e);
-		type = make_type_enum(c->allocator);
-		set_base_type(named_type, type);
-		check_open_scope(c, e);
-		check_enum_type(c, type, named_type, e);
-		check_close_scope(c);
-		type->Record.node = e;
-		goto end;
-	case_end;
-
 	case_ast_node(pt, ProcType, e);
 		type = alloc_type(c->allocator, Type_Proc);
 		set_base_type(named_type, type);
@@ -1357,7 +1158,7 @@ end:
 
 bool check_unary_op(Checker *c, Operand *o, Token op) {
 	// TODO(bill): Handle errors correctly
-	Type *type = base_type(get_enum_base_type(base_vector_type(o->type)));
+	Type *type = base_type(base_vector_type(o->type));
 	gbString str = NULL;
 	switch (op.kind) {
 	case Token_Add:
@@ -1393,7 +1194,7 @@ bool check_unary_op(Checker *c, Operand *o, Token op) {
 
 bool check_binary_op(Checker *c, Operand *o, Token op) {
 	// TODO(bill): Handle errors correctly
-	Type *type = base_type(get_enum_base_type(base_vector_type(o->type)));
+	Type *type = base_type(base_vector_type(o->type));
 	switch (op.kind) {
 	case Token_Sub:
 	case Token_SubEq:
@@ -1470,8 +1271,6 @@ bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exa
 		return true;
 	}
 
-	type = get_enum_base_type(type);
-
 	if (is_type_boolean(type)) {
 		return in_value.kind == ExactValue_Bool;
 	} else if (is_type_string(type)) {
@@ -1554,8 +1353,8 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) {
 	if (!check_value_is_expressible(c, o->value, type, &o->value)) {
 		gbString a = expr_to_string(o->expr);
 		gbString b = type_to_string(type);
-		if (is_type_numeric(get_enum_base_type(o->type)) && is_type_numeric(get_enum_base_type(type))) {
-			if (!is_type_integer(get_enum_base_type(o->type)) && is_type_integer(get_enum_base_type(type))) {
+		if (is_type_numeric(o->type) && is_type_numeric(type)) {
+			if (!is_type_integer(o->type) && is_type_integer(type)) {
 				error_node(o->expr, "`%s` truncated to `%s`", a, b);
 			} else {
 				error_node(o->expr, "`%s = %lld` overflows `%s`", a, o->value.value_integer, b);
@@ -1859,8 +1658,6 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
 	if (are_types_identical(xb, yb)) {
 		return true;
 	}
-	xb = get_enum_base_type(x);
-	yb = get_enum_base_type(y);
 
 
 	// Cast between booleans and integers
@@ -2460,7 +2257,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
 		return;
 	}
 
-	Type *t = get_enum_base_type(base_type(target_type));
+	Type *t = base_type(target_type);
 	switch (t->kind) {
 	case Type_Basic:
 		if (operand->mode == Addressing_Constant) {
@@ -2531,7 +2328,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val
 		return false;
 	}
 
-	if (!is_type_integer(get_enum_base_type(operand.type))) {
+	if (!is_type_integer(operand.type)) {
 		gbString expr_str = expr_to_string(operand.expr);
 		error_node(operand.expr, "Index `%s` must be an integer", expr_str);
 		gb_string_free(expr_str);
@@ -3598,44 +3395,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 			}
 		}
 	} break;
-
-	case BuiltinProc_enum_to_string: {
-		Type *type = base_type(operand->type);
-		if (!is_type_enum(type)) {
-			gbString type_str = type_to_string(operand->type);
-			gb_string_free(type_str);
-			error_node(call,
-			      "Expected an enum to `enum_to_string`, got `%s`",
-			      type_str);
-			return false;
-		}
-
-		if (operand->mode == Addressing_Constant) {
-			ExactValue value = make_exact_value_string(str_lit(""));
-			if (operand->value.kind == ExactValue_Integer) {
-				i64 index = operand->value.value_integer;
-				for (isize i = 0; i < type->Record.enum_value_count; i++) {
-					Entity *f = type->Record.enum_values[i];
-					if (f->kind == Entity_Constant && f->Constant.value.kind == ExactValue_Integer) {
-						i64 fv = f->Constant.value.value_integer;
-						if (index == fv) {
-							value = make_exact_value_string(f->token.string);
-							break;
-						}
-					}
-				}
-			}
-
-			operand->value = value;
-			operand->type = t_string;
-			return true;
-		}
-
-		add_type_info_type(c, operand->type);
-
-		operand->mode = Addressing_Value;
-		operand->type = t_string;
-	} break;
 	}
 
 	return true;

+ 44 - 49
src/checker/stmt.c

@@ -279,6 +279,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 	c->context.stmt_state_flags = prev_stmt_state_flags;
 }
 
+
+
 typedef struct TypeAndToken {
 	Type *type;
 	Token token;
@@ -907,19 +909,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			switch (e->kind) {
 			case Entity_TypeName: {
 				Type *t = base_type(e->type);
-				if (is_type_enum(t)) {
-					for (isize i = 0; i < t->Record.enum_value_count; i++) {
-						Entity *f = t->Record.enum_values[i];
-						Entity *found = scope_insert_entity(c->context.scope, f);
-						if (found != NULL) {
-							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;
-						}
-						f->using_parent = e;
-					}
-				} else if (is_type_union(t)) {
+				if (is_type_union(t)) {
 					for (isize i = 0; i < t->Record.field_count; i++) {
 						Entity *f = t->Record.fields[i];
 						Entity *found = scope_insert_entity(c->context.scope, f);
@@ -931,6 +921,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 						}
 						f->using_parent = e;
 					}
+				} else {
+					error(us->token, "`using` can be only applied to `union` type entities");
 				}
 			} break;
 
@@ -1008,40 +1000,52 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 		case_end;
 
-		case_ast_node(vd, VarDecl, us->node);
-			if (vd->names.count > 1 && vd->type != NULL) {
-				error(us->token, "`using` can only be applied to one variable of the same type");
-			}
-			check_var_decl_node(c, us->node);
+		case_ast_node(gd, GenericDecl, us->node);
+			for_array(spec_index, gd->specs) {
+				AstNode *spec = gd->specs.e[spec_index];
+				switch (spec->kind) {
+				case_ast_node(vs, ValueSpec, spec);
+					if (vs->keyword != Token_var) {
+						error_node(spec, "`using` can only be applied to a variable declaration");
+						return;
+					}
 
-			for_array(name_index, vd->names) {
-				AstNode *item = vd->names.e[name_index];
-				ast_node(i, Ident, item);
-				String name = i->string;
-				Entity *e = scope_lookup_entity(c->context.scope, name);
-				Type *t = base_type(type_deref(e->type));
-				if (is_type_struct(t) || is_type_raw_union(t)) {
-					Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
-					GB_ASSERT(found != NULL);
-					for_array(i, (*found)->elements.entries) {
-						Entity *f = (*found)->elements.entries.e[i].value;
-						if (f->kind == Entity_Variable) {
-							Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
-							Entity *prev = scope_insert_entity(c->context.scope, uvar);
-							if (prev != NULL) {
-								error(us->token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
-								return;
+					if (vs->names.count > 1 && vs->type != NULL) {
+						error(us->token, "`using` can only be applied to one variable of the same type");
+					}
+
+					check_var_spec_node(c, vs);
+
+					for_array(name_index, vs->names) {
+						AstNode *item = vs->names.e[name_index];
+						ast_node(i, Ident, item);
+						String name = i->string;
+						Entity *e = scope_lookup_entity(c->context.scope, name);
+						Type *t = base_type(type_deref(e->type));
+						if (is_type_struct(t) || is_type_raw_union(t)) {
+							Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
+							GB_ASSERT(found != NULL);
+							for_array(i, (*found)->elements.entries) {
+								Entity *f = (*found)->elements.entries.e[i].value;
+								if (f->kind == Entity_Variable) {
+									Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+									Entity *prev = scope_insert_entity(c->context.scope, uvar);
+									if (prev != NULL) {
+										error(us->token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
+										return;
+									}
+								}
 							}
+						} else {
+							error(us->token, "`using` can only be applied to variables of type struct or raw_union");
+							return;
 						}
 					}
-				} else {
-					error(us->token, "`using` can only be applied to variables of type struct or raw_union");
-					return;
+				case_end;
 				}
 			}
 		case_end;
 
-
 		default:
 			error(us->token, "Invalid AST: Using Statement");
 			break;
@@ -1068,12 +1072,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 
 
-
-
-	case_ast_node(vd, VarDecl, node);
-		check_var_decl_node(c, node);
-	case_end;
-
 	case_ast_node(gd, GenericDecl, node);
 		for_array(spec_index, gd->specs) {
 			AstNode *spec = gd->specs.e[spec_index];
@@ -1136,6 +1134,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 						if (e->type == NULL)
 							e->type = init_type;
 					}
+					check_arity_match(c, vs, NULL);
 
 					check_init_variables(c, entities, entity_count, vs->values, str_lit("variable declaration"));
 
@@ -1158,10 +1157,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		}
 	case_end;
 
-	case_ast_node(cd, ConstDecl, node);
-		// NOTE(bill): Handled elsewhere
-	case_end;
-
 	case_ast_node(td, TypeDecl, node);
 		// NOTE(bill): Handled elsewhere
 	case_end;

+ 8 - 93
src/checker/types.c

@@ -62,7 +62,6 @@ typedef enum TypeRecordKind {
 	TypeRecord_Invalid,
 
 	TypeRecord_Struct,
-	TypeRecord_Enum,
 	TypeRecord_RawUnion,
 	TypeRecord_Union, // Tagged
 
@@ -78,23 +77,11 @@ typedef struct TypeRecord {
 	i32      field_count; // == offset_count is struct
 	AstNode *node;
 
-	union { // NOTE(bill): Reduce size_of Type
-		struct { // enum only
-			Type *   enum_base; // Default is `int`
-			Entity * enum_count;
-			Entity * min_value;
-			Entity * max_value;
-			Entity **enum_values;
-			i32      enum_value_count;
-		};
-		struct { // struct only
-			i64 *    struct_offsets;
-			bool     struct_are_offsets_set;
-			bool     struct_is_packed;
-			bool     struct_is_ordered;
-			Entity **fields_in_src_order; // Entity_Variable
-		};
-	};
+	i64 *    struct_offsets;
+	bool     struct_are_offsets_set;
+	bool     struct_is_packed;
+	bool     struct_is_ordered;
+	Entity **fields_in_src_order; // Entity_Variable
 } TypeRecord;
 
 #define TYPE_KINDS \
@@ -282,7 +269,6 @@ gb_global Type *t_type_info_tuple      = NULL;
 gb_global Type *t_type_info_struct     = NULL;
 gb_global Type *t_type_info_union      = NULL;
 gb_global Type *t_type_info_raw_union  = NULL;
-gb_global Type *t_type_info_enum       = NULL;
 
 gb_global Type *t_allocator            = NULL;
 gb_global Type *t_allocator_ptr        = NULL;
@@ -380,11 +366,6 @@ Type *make_type_raw_union(gbAllocator a) {
 	return t;
 }
 
-Type *make_type_enum(gbAllocator a) {
-	Type *t = alloc_type(a, Type_Record);
-	t->Record.kind = TypeRecord_Enum;
-	return t;
-}
 
 
 
@@ -437,15 +418,6 @@ Type *type_deref(Type *t) {
 	return t;
 }
 
-Type *get_enum_base_type(Type *t) {
-	Type *bt = base_type(t);
-	if (bt->kind == Type_Record && bt->Record.kind == TypeRecord_Enum) {
-		GB_ASSERT(bt->Record.enum_base != NULL);
-		return bt->Record.enum_base;
-	}
-	return t;
-}
-
 bool is_type_named(Type *t) {
 	if (t->kind == Type_Basic) {
 		return true;
@@ -508,7 +480,7 @@ bool is_type_untyped(Type *t) {
 	return false;
 }
 bool is_type_ordered(Type *t) {
-	t = base_type(get_enum_base_type(t));
+	t = base_type(t);
 	if (t->kind == Type_Basic) {
 		return (t->Basic.flags & BasicFlag_Ordered) != 0;
 	}
@@ -522,9 +494,6 @@ bool is_type_constant_type(Type *t) {
 	if (t->kind == Type_Basic) {
 		return (t->Basic.flags & BasicFlag_ConstantType) != 0;
 	}
-	if (t->kind == Type_Record) {
-		return t->Record.kind == TypeRecord_Enum;
-	}
 	return false;
 }
 bool is_type_float(Type *t) {
@@ -615,10 +584,6 @@ Type *base_vector_type(Type *t) {
 }
 
 
-bool is_type_enum(Type *t) {
-	t = base_type(t);
-	return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum);
-}
 bool is_type_struct(Type *t) {
 	t = base_type(t);
 	return (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct);
@@ -656,20 +621,13 @@ bool type_has_nil(Type *t) {
 
 	case Type_Tuple:
 		return false;
-
-	case Type_Record:
-		switch (t->Record.kind) {
-		case TypeRecord_Enum:
-			return false;
-		}
-		break;
 	}
 	return true;
 }
 
 
 bool is_type_comparable(Type *t) {
-	t = base_type(get_enum_base_type(t));
+	t = base_type(t);
 	switch (t->kind) {
 	case Type_Basic:
 		return t->kind != Basic_UntypedNil;
@@ -682,8 +640,6 @@ bool is_type_comparable(Type *t) {
 				if (!is_type_comparable(t->Record.fields[i]->type))
 					return false;
 			}
-		} else if (is_type_enum(t)) {
-			return is_type_comparable(t->Record.enum_base);
 		}
 		return false;
 	} break;
@@ -753,10 +709,6 @@ bool are_types_identical(Type *x, Type *y) {
 						return true;
 					}
 					break;
-
-				case TypeRecord_Enum:
-					// NOTE(bill): Each enum is unique
-					return x == y;
 				}
 			}
 		}
@@ -981,33 +933,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				}
 			}
 		}
-
-		if (is_type_enum(type)) {
-			for (isize i = 0; i < type->Record.enum_value_count; i++) {
-				Entity *f = type->Record.enum_values[i];
-				GB_ASSERT(f->kind != Entity_Variable);
-				String str = f->token.string;
-
-				if (str_eq(field_name, str)) {
-					sel.entity = f;
-					selection_add_index(&sel, i);
-					return sel;
-				}
-			}
-
-			if (str_eq(field_name, str_lit("count"))) {
-				sel.entity = type->Record.enum_count;
-				return sel;
-			} else if (str_eq(field_name, str_lit("min_value"))) {
-				sel.entity = type->Record.min_value;
-				return sel;
-			} else if (str_eq(field_name, str_lit("max_value"))) {
-				sel.entity = type->Record.max_value;
-				return sel;
-			}
-		}
-
-	} else if (!is_type_enum(type) && !is_type_union(type)) {
+	} else if (!is_type_union(type)) {
 		for (isize i = 0; i < type->Record.field_count; i++) {
 			Entity *f = type->Record.fields[i];
 			GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
@@ -1247,8 +1173,6 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
 			}
 			return max;
 		} break;
-		case TypeRecord_Enum:
-			return type_align_of_internal(s, allocator, t->Record.enum_base, path);
 		}
 	} break;
 	}
@@ -1437,10 +1361,6 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
 			// TODO(bill): Is this how it should work?
 			return align_formula(max, align);
 		} break;
-
-		case TypeRecord_Enum: {
-			return type_size_of_internal(s, allocator, t->Record.enum_base, path);
-		} break;
 		}
 	} break;
 	}
@@ -1591,11 +1511,6 @@ gbString write_type_to_string(gbString str, Type *type) {
 			}
 			str = gb_string_appendc(str, "}");
 			break;
-
-		case TypeRecord_Enum:
-			str = gb_string_appendc(str, "enum ");
-			str = write_type_to_string(str, type->Record.enum_base);
-			break;
 		}
 	} break;
 

+ 6 - 45
src/parser.c

@@ -241,21 +241,6 @@ AST_NODE_KIND(_DeclBegin,      "", i32) \
 		u64          tags;        \
 		bool         is_using;    \
 	}) \
-	AST_NODE_KIND(VarDecl,  "variable declaration", struct { \
-		u64          tags;     \
-		bool         is_using; \
-		AstNodeArray names;    \
-		AstNode *    type;     \
-		AstNodeArray values;   \
-		AstNode *    note;     \
-	}) \
-	AST_NODE_KIND(ConstDecl,  "constant declaration", struct { \
-		u64          tags;   \
-		AstNodeArray names;  \
-		AstNode *    type;   \
-		AstNodeArray values; \
-		AstNode *    note;   \
-	}) \
 	AST_NODE_KIND(TypeDecl,   "type declaration",   struct { \
 		Token token;   \
 		AstNode *name; \
@@ -480,10 +465,6 @@ Token ast_node_token(AstNode *node) {
 		return node->BadDecl.begin;
 	case AstNode_GenericDecl:
 		return node->GenericDecl.token;
-	case AstNode_VarDecl:
-		return ast_node_token(node->VarDecl.names.e[0]);
-	case AstNode_ConstDecl:
-		return ast_node_token(node->ConstDecl.names.e[0]);
 	case AstNode_ProcDecl:
 		return ast_node_token(node->ProcDecl.name);
 	case AstNode_TypeDecl:
@@ -917,22 +898,6 @@ AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
 	return result;
 }
 
-AstNode *make_var_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
-	AstNode *result = make_node(f, AstNode_VarDecl);
-	result->VarDecl.names = names;
-	result->VarDecl.type = type;
-	result->VarDecl.values = values;
-	return result;
-}
-
-AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
-	AstNode *result = make_node(f, AstNode_ConstDecl);
-	result->ConstDecl.names = names;
-	result->ConstDecl.type = type;
-	result->ConstDecl.values = values;
-	return result;
-}
-
 AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, bool is_using) {
 	AstNode *result = make_node(f, AstNode_Parameter);
 	result->Parameter.names = names;
@@ -2814,8 +2779,8 @@ AstNode *parse_stmt(AstFile *f) {
 				valid = true;
 			}
 		} break;
-		case AstNode_VarDecl:
-			valid = true;
+		case AstNode_GenericDecl:
+			valid = node->GenericDecl.token.kind == Token_var;
 			break;
 		}
 
@@ -2952,9 +2917,8 @@ AstNode *parse_stmt(AstFile *f) {
 			return s;
 		} else if (str_eq(tag, str_lit("thread_local"))) {
 			AstNode *decl = parse_simple_stmt(f);
-			if (decl->kind != AstNode_VarDecl &&
-			    (decl->kind == AstNode_GenericDecl &&
-			     decl->GenericDecl.token.kind != Token_var)) {
+			if (decl->kind == AstNode_GenericDecl &&
+			    decl->GenericDecl.token.kind != Token_var) {
 				syntax_error(token, "#thread_local may only be applied to variable declarations");
 				return make_bad_decl(f, token, ast_node_token(decl));
 			}
@@ -2962,11 +2926,8 @@ AstNode *parse_stmt(AstFile *f) {
 				syntax_error(token, "#thread_local is only allowed at the file scope");
 				return make_bad_decl(f, token, ast_node_token(decl));
 			}
-			if (decl->kind == AstNode_VarDecl) {
-				decl->VarDecl.tags |= VarDeclTag_thread_local;
-			} else if (decl->kind == AstNode_GenericDecl) {
-				decl->GenericDecl.tags |= VarDeclTag_thread_local;
-			}
+			GB_ASSERT(decl->kind == AstNode_GenericDecl);
+			decl->GenericDecl.tags |= VarDeclTag_thread_local;
 			return decl;
 		} else if (str_eq(tag, str_lit("bounds_check"))) {
 			s = parse_stmt(f);

+ 4 - 145
src/ssa.c

@@ -1919,8 +1919,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
 		return value;
 	}
 
-	Type *src = base_type(get_enum_base_type(src_type));
-	Type *dst = base_type(get_enum_base_type(t));
+	Type *src = base_type(src_type);
+	Type *dst = base_type(t);
 
 	if (value->kind == ssaValue_Constant) {
 		if (is_type_any(dst)) {
@@ -2172,7 +2172,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
 }
 
 bool ssa_is_type_aggregate(Type *t) {
-	t = base_type(get_enum_base_type(t));
+	t = base_type(t);
 	switch (t->kind) {
 	case Type_Basic:
 		switch (t->Basic.kind) {
@@ -3088,19 +3088,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 					x    = ssa_emit_select(proc, cond,   max, x);
 					return x;
 				} break;
-
-				case BuiltinProc_enum_to_string: {
-					ssa_emit_comment(proc, str_lit("enum_to_string"));
-					ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
-					Type *t = ssa_type(x);
-					ssaValue *ti = ssa_type_info(proc, t);
-
-
-					ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 2);
-					args[0] = ti;
-					args[1] = ssa_emit_conv(proc, x, t_i64);
-					return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
-				} break;
 				}
 			}
 		}
@@ -3849,8 +3836,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 
 	case_ast_node(us, UsingStmt, node);
 		AstNode *decl = unparen_expr(us->node);
-		if (decl->kind == AstNode_VarDecl &&
-		    decl->kind == AstNode_GenericDecl) {
+		if (decl->kind == AstNode_GenericDecl) {
 			ssa_build_stmt(proc, decl);
 		}
 	case_end;
@@ -3928,61 +3914,6 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
 		}
 	case_end;
 
-	case_ast_node(vd, VarDecl, node);
-		ssaModule *m = proc->module;
-		gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
-
-		if (vd->values.count == 0) { // declared and zero-initialized
-			for_array(i, vd->names) {
-				AstNode *name = vd->names.e[i];
-				if (!ssa_is_blank_ident(name)) {
-					ssa_add_local_for_identifier(proc, name, true);
-				}
-			}
-		} else { // Tuple(s)
-			Array(ssaAddr) lvals;
-			ssaValueArray  inits;
-			array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
-			array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
-
-			for_array(i, vd->names) {
-				AstNode *name = vd->names.e[i];
-				ssaAddr lval = ssa_make_addr(NULL, NULL);
-				if (!ssa_is_blank_ident(name)) {
-					ssa_add_local_for_identifier(proc, name, false);
-					lval = ssa_build_addr(proc, name);
-				}
-
-				array_add(&lvals, lval);
-			}
-
-			for_array(i, vd->values) {
-				ssaValue *init = ssa_build_expr(proc, vd->values.e[i]);
-				Type *t = ssa_type(init);
-				if (t->kind == Type_Tuple) {
-					for (isize i = 0; i < t->Tuple.variable_count; i++) {
-						Entity *e = t->Tuple.variables[i];
-						ssaValue *v = ssa_emit_struct_ev(proc, init, i);
-						array_add(&inits, v);
-					}
-				} else {
-					array_add(&inits, init);
-				}
-			}
-
-
-			for_array(i, inits) {
-				if (lvals.e[i].addr == NULL) {
-					continue;
-				}
-				ssaValue *v = ssa_emit_conv(proc, inits.e[i], ssa_addr_type(lvals.e[i]));
-				ssa_addr_store(proc, lvals.e[i], v);
-			}
-		}
-
-		gb_temp_arena_memory_end(tmp);
-	case_end;
-
 	case_ast_node(pd, ProcDecl, node);
 		if (pd->body != NULL) {
 			CheckerInfo *info = proc->module->info;
@@ -5472,78 +5403,6 @@ void ssa_gen_tree(ssaGen *s) {
 						ssa_emit_store(proc, len, field_count);
 						ssa_emit_store(proc, cap, field_count);
 					} break;
-					case TypeRecord_Enum: {
-						tag = ssa_add_local_generated(proc, t_type_info_enum);
-						Type *enum_base = t->Record.enum_base;
-						if (enum_base == NULL) {
-							enum_base = t_int;
-						}
-						ssaValue *base = ssa_emit_struct_ep(proc, tag, 0);
-						ssa_emit_store(proc, base, ssa_get_type_info_ptr(proc, type_info_data, enum_base));
-
-						if (t->Record.enum_value_count > 0) {
-							Entity **fields = t->Record.enum_values;
-							isize count = t->Record.enum_value_count;
-							ssaValue *value_array = NULL;
-							ssaValue *name_array = NULL;
-
-							{
-								Token token = {Token_Ident};
-								i32 id = cast(i32)entry_index;
-								char name_base[] = "__$enum_values";
-								isize name_len = gb_size_of(name_base) + 10;
-								token.string.text = gb_alloc_array(a, u8, name_len);
-								token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
-								                               "%s-%d", name_base, id)-1;
-								Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_i64, count));
-								value_array = ssa_make_value_global(a, e, NULL);
-								value_array->Global.is_private = true;
-								ssa_module_add_value(m, e, value_array);
-								map_ssa_value_set(&m->members, hash_string(token.string), value_array);
-							}
-							{
-								Token token = {Token_Ident};
-								i32 id = cast(i32)entry_index;
-								char name_base[] = "__$enum_names";
-								isize name_len = gb_size_of(name_base) + 10;
-								token.string.text = gb_alloc_array(a, u8, name_len);
-								token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
-								                               "%s-%d", name_base, id)-1;
-								Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_string, count));
-								name_array = ssa_make_value_global(a, e, NULL);
-								name_array->Global.is_private = true;
-								ssa_module_add_value(m, e, name_array);
-								map_ssa_value_set(&m->members, hash_string(token.string), name_array);
-							}
-
-							for (isize i = 0; i < count; i++) {
-								ssaValue *value_gep = ssa_emit_array_epi(proc, value_array, i);
-								ssaValue *name_gep  = ssa_emit_array_epi(proc, name_array, i);
-
-								ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer));
-								ssa_emit_store(proc, name_gep,  ssa_make_const_string(a, fields[i]->token.string));
-							}
-
-							ssaValue *v_count = ssa_make_const_int(a, count);
-
-
-							ssaValue *values = ssa_emit_struct_ep(proc, tag, 1);
-							ssaValue *names  = ssa_emit_struct_ep(proc, tag, 2);
-							ssaValue *value_slice = ssa_add_local_generated(proc, type_deref(t_i64_slice_ptr));
-							ssaValue *name_slice  = ssa_add_local_generated(proc, type_deref(t_string_slice_ptr));
-
-							ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 0), ssa_array_elem(proc, value_array));
-							ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 1), v_count);
-							ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 2), v_count);
-
-							ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 0), ssa_array_elem(proc, name_array));
-							ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 1), v_count);
-							ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 2), v_count);
-
-							ssa_emit_store(proc, values, ssa_emit_load(proc, value_slice));
-							ssa_emit_store(proc, names,  ssa_emit_load(proc, name_slice));
-						}
-					} break;
 					}
 				} break;
 

+ 0 - 3
src/ssa_print.c

@@ -225,9 +225,6 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
 			i64 align_of_union = type_align_of(s, heap_allocator(), t);
 			ssa_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align_of_union, size_of_union);
 		} break;
-		case TypeRecord_Enum:
-			ssa_print_type(f, m, t->Record.enum_base);
-			break;
 		}
 	} break;