Browse Source

Change record field syntax

Ginger Bill 8 years ago
parent
commit
4c10fbdcd4
11 changed files with 190 additions and 301 deletions
  1. 55 55
      core/_preload.odin
  2. 6 6
      core/mem.odin
  3. 4 4
      core/os_windows.odin
  4. 5 5
      core/sync.odin
  5. 45 45
      core/sys/windows.odin
  6. 1 1
      core/utf8.odin
  7. 34 78
      src/checker/expr.c
  8. 3 14
      src/checker/stmt.c
  9. 12 14
      src/checker/types.c
  10. 20 66
      src/parser.c
  11. 5 13
      src/ssa.c

+ 55 - 55
core/_preload.odin

@@ -13,67 +13,67 @@
 // IMPORTANT NOTE(bill): Do not change the order of any of this data
 // The compiler relies upon this _exact_ order
 type Type_Info_Member struct #ordered {
-	name:      string;     // can be empty if tuple
-	type_info: ^Type_Info;
-	offset:    int;        // offsets are not used in tuples
-};
+	name      string;     // can be empty if tuple
+	type_info ^Type_Info;
+	offset    int;        // offsets are not used in tuples
+}
 type Type_Info_Record struct #ordered {
-	fields:  []Type_Info_Member;
-	size:    int; // in bytes
-	align:   int; // in bytes
-	packed:  bool;
-	ordered: bool;
-};
+	fields  []Type_Info_Member;
+	size    int; // in bytes
+	align   int; // in bytes
+	packed  bool;
+	ordered bool;
+}
 
 type Type_Info union {
-	Named: struct #ordered {
-		name: string;
-		base: ^Type_Info; // This will _not_ be a Type_Info.Named
+	Named struct #ordered {
+		name string;
+		base ^Type_Info; // This will _not_ be a Type_Info.Named
 	};
-	Integer: struct #ordered {
-		size:   int; // in bytes
-		signed: bool;
+	Integer struct #ordered {
+		size   int; // in bytes
+		signed bool;
 	};
-	Float: struct #ordered {
-		size: int; // in bytes
+	Float struct #ordered {
+		size int; // in bytes
 	};
-	Any:     struct #ordered {};
-	String:  struct #ordered {};
-	Boolean: struct #ordered {};
-	Pointer: struct #ordered {
-		elem: ^Type_Info; // nil -> rawptr
+	Any     struct #ordered {};
+	String  struct #ordered {};
+	Boolean struct #ordered {};
+	Pointer struct #ordered {
+		elem ^Type_Info; // nil -> rawptr
 	};
-	Maybe: struct #ordered {
-		elem: ^Type_Info;
+	Maybe struct #ordered {
+		elem ^Type_Info;
 	};
-	Procedure: struct #ordered {
-		params:   ^Type_Info; // Type_Info.Tuple
-		results:  ^Type_Info; // Type_Info.Tuple
-		variadic: bool;
+	Procedure struct #ordered {
+		params   ^Type_Info; // Type_Info.Tuple
+		results  ^Type_Info; // Type_Info.Tuple
+		variadic bool;
 	};
-	Array: struct #ordered {
-		elem:      ^Type_Info;
-		elem_size: int;
-		count:     int;
+	Array struct #ordered {
+		elem      ^Type_Info;
+		elem_size int;
+		count     int;
 	};
-	Slice: struct #ordered {
-		elem:      ^Type_Info;
-		elem_size: int;
+	Slice struct #ordered {
+		elem      ^Type_Info;
+		elem_size int;
 	};
-	Vector: struct #ordered {
-		elem:      ^Type_Info;
-		elem_size: int;
-		count:     int;
-		align:     int;
+	Vector struct #ordered {
+		elem      ^Type_Info;
+		elem_size int;
+		count     int;
+		align     int;
 	};
-	Tuple:     Type_Info_Record;
-	Struct:    Type_Info_Record;
-	Union:     Type_Info_Record;
-	Raw_Union: Type_Info_Record;
-	Enum: struct #ordered {
-		base:   ^Type_Info;
-		values: []i64;
-		names:  []string;
+	Tuple     Type_Info_Record;
+	Struct    Type_Info_Record;
+	Union     Type_Info_Record;
+	Raw_Union Type_Info_Record;
+	Enum struct #ordered {
+		base   ^Type_Info;
+		values []i64;
+		names  []string;
 	};
 };
 
@@ -126,18 +126,18 @@ type Allocator_Proc proc(allocator_data rawptr, mode Allocator_Mode,
 
 
 type Allocator struct #ordered {
-	procedure: Allocator_Proc;
-	data:      rawptr;
+	procedure Allocator_Proc;
+	data      rawptr;
 }
 
 
 type Context struct #ordered {
-	thread_id: int;
+	thread_id int;
 
-	allocator: Allocator;
+	allocator Allocator;
 
-	user_data:  rawptr;
-	user_index: int;
+	user_data  rawptr;
+	user_index int;
 }
 
 #thread_local var __context Context;

+ 6 - 6
core/mem.odin

@@ -90,7 +90,7 @@ proc align_forward(ptr rawptr, align int) -> rawptr {
 
 
 type Allocation_Header struct {
-	size: int;
+	size int;
 }
 proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) {
 	header.size = size;
@@ -115,14 +115,14 @@ proc allocation_header(data rawptr) -> ^Allocation_Header {
 // Custom allocators
 
 type Arena struct {
-	backing:    Allocator;
-	memory:     []byte;
-	temp_count: int;
+	backing    Allocator;
+	memory     []byte;
+	temp_count int;
 }
 
 type Arena_Temp_Memory struct {
-	arena:          ^Arena;
-	original_count: int;
+	arena          ^Arena;
+	original_count int;
 }
 
 

+ 4 - 4
core/os_windows.odin

@@ -4,13 +4,13 @@
 type File_Time u64;
 
 type File_Handle raw_union {
-	p: rawptr;
-	i: int;
+	p rawptr;
+	i int;
 }
 
 type File struct {
-	handle:          File_Handle;
-	last_write_time: File_Time;
+	handle          File_Handle;
+	last_write_time File_Time;
 }
 
 proc open(name string) -> (File, bool) {

+ 5 - 5
core/sync.odin

@@ -2,14 +2,14 @@
 #import "atomic.odin";
 
 type Semaphore struct {
-	handle: win32.HANDLE;
+	handle win32.HANDLE;
 }
 
 type Mutex struct {
-	semaphore: Semaphore;
-	counter:   i32;
-	owner:     i32;
-	recursion: i32;
+	semaphore Semaphore;
+	counter   i32;
+	owner     i32;
+	recursion i32;
 }
 
 

+ 45 - 45
core/sys/windows.odin

@@ -51,62 +51,62 @@ const SM_CYSCREEN = 1;
 const SW_SHOW = 5;
 
 type POINT struct #ordered {
-	x, y: i32;
+	x, y i32;
 }
 
 
 type WNDCLASSEXA struct #ordered {
-	size, style:           u32;
-	wnd_proc:              WNDPROC;
-	cls_extra, wnd_extra:  i32;
-	instance:              HINSTANCE;
-	icon:                  HICON;
-	cursor:                HCURSOR;
-	background:            HBRUSH;
-	menu_name, class_name: ^u8;
-	sm:                    HICON;
+	size, style           u32;
+	wnd_proc              WNDPROC;
+	cls_extra, wnd_extra  i32;
+	instance              HINSTANCE;
+	icon                  HICON;
+	cursor                HCURSOR;
+	background            HBRUSH;
+	menu_name, class_name ^u8;
+	sm                    HICON;
 }
 
 type MSG struct #ordered {
-	hwnd:    HWND;
-	message: u32;
-	wparam:  WPARAM;
-	lparam:  LPARAM;
-	time:    u32;
-	pt:      POINT;
+	hwnd    HWND;
+	message u32;
+	wparam  WPARAM;
+	lparam  LPARAM;
+	time    u32;
+	pt      POINT;
 }
 
 type RECT struct #ordered {
-	left:   i32;
-	top:    i32;
-	right:  i32;
-	bottom: i32;
+	left   i32;
+	top    i32;
+	right  i32;
+	bottom i32;
 }
 
 type FILETIME struct #ordered {
-	low_date_time, high_date_time: u32;
+	low_date_time, high_date_time u32;
 }
 
 type BY_HANDLE_FILE_INFORMATION struct #ordered {
-	file_attributes:      u32;
+	file_attributes      u32;
 	creation_time,
 	last_access_time,
-	last_write_time:      FILETIME;
+	last_write_time      FILETIME;
 	volume_serial_number,
 	file_size_high,
 	file_size_low,
 	number_of_links,
 	file_index_high,
-	file_index_low:       u32;
+	file_index_low       u32;
 }
 
 type WIN32_FILE_ATTRIBUTE_DATA struct #ordered {
-	file_attributes:  u32;
+	file_attributes  u32;
 	creation_time,
 	last_access_time,
-	last_write_time:  FILETIME;
+	last_write_time  FILETIME;
 	file_size_high,
-	file_size_low:    u32;
+	file_size_low    u32;
 }
 
 type GET_FILEEX_INFO_LEVELS i32;
@@ -209,9 +209,9 @@ const HEAP_ZERO_MEMORY = 0x00000008;
 // Synchronization
 
 type SECURITY_ATTRIBUTES struct #ordered {
-	length:              u32;
-	security_descriptor: rawptr;
-	inherit_handle:      BOOL;
+	length              u32;
+	security_descriptor rawptr;
+	inherit_handle      BOOL;
 }
 
 const INFINITE = 0xffffffff;
@@ -242,24 +242,24 @@ proc ReadBarrier     () #foreign
 // GDI
 
 type BITMAPINFOHEADER struct #ordered {
-	size:              u32;
-	width, height:     i32;
-	planes, bit_count: i16;
-	compression:       u32;
-	size_image:        u32;
-	x_pels_per_meter:  i32;
-	y_pels_per_meter:  i32;
-	clr_used:          u32;
-	clr_important:     u32;
+	size              u32;
+	width, height     i32;
+	planes, bit_count i16;
+	compression       u32;
+	size_image        u32;
+	x_pels_per_meter  i32;
+	y_pels_per_meter  i32;
+	clr_used          u32;
+	clr_important     u32;
 }
 type BITMAPINFO struct #ordered {
-	using header: BITMAPINFOHEADER;
-	colors:       [1]RGBQUAD;
+	using header BITMAPINFOHEADER;
+	colors       [1]RGBQUAD;
 }
 
 
 type RGBQUAD struct #ordered {
-	blue, green, red, reserved: byte;
+	blue, green, red, reserved byte;
 }
 
 const BI_RGB         = 0;
@@ -315,7 +315,7 @@ type wglCreateContextAttribsARBType proc(hdc HDC, hshareContext rawptr, attribLi
 type PIXELFORMATDESCRIPTOR struct #ordered {
 	size,
 	version,
-	flags: u32;
+	flags u32;
 
 	pixel_type,
 	color_bits,
@@ -336,11 +336,11 @@ type PIXELFORMATDESCRIPTOR struct #ordered {
 	stencil_bits,
 	aux_buffers,
 	layer_type,
-	reserved: byte;
+	reserved byte;
 
 	layer_mask,
 	visible_mask,
-	damage_mask: u32;
+	damage_mask u32;
 }
 
 proc GetDC            (h HANDLE) -> HDC #foreign

+ 1 - 1
core/utf8.odin

@@ -11,7 +11,7 @@ const SURROGATE_MAX = 0xdfff;
 
 
 type Accept_Range struct {
-	lo, hi: u8;
+	lo, hi u8;
 };
 
 accept_ranges := [5]Accept_Range{

+ 34 - 78
src/checker/expr.c

@@ -464,37 +464,29 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, MapEntity *en
 
 void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
                   Entity **fields, isize field_count,
-                  Entity **other_fields, isize other_field_count,
                   String context) {
 	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*(field_count+other_field_count));
+	map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*field_count);
 
 	isize other_field_index = 0;
 	Entity *using_index_expr = NULL;
 
-	DelayedOtherFields dof = {0};
-	dof.other_fields = other_fields;
-	dof.other_field_count = other_field_count;
-	dof.entity_map = &entity_map;
-
-	check_scope_decls(c, decls, 1.2*other_field_count, &dof);
-
 	if (node->kind == AstNode_UnionType) {
 		isize field_index = 0;
 		fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
 		for_array(decl_index, decls) {
 			AstNode *decl = decls.e[decl_index];
-			if (decl->kind != AstNode_VarDecl) {
+			if (decl->kind != AstNode_Parameter) {
 				continue;
 			}
 
-			ast_node(vd, VarDecl, decl);
-			Type *base_type = check_type_extra(c, vd->type, NULL);
+			ast_node(p, Parameter, decl);
+			Type *base_type = check_type_extra(c, p->type, NULL);
 
-			for_array(name_index, vd->names) {
-				AstNode *name = vd->names.e[name_index];
+			for_array(name_index, p->names) {
+				AstNode *name = p->names.e[name_index];
 				if (!ast_node_expect(name, AstNode_Ident)) {
 					continue;
 				}
@@ -526,28 +518,28 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 		isize field_index = 0;
 		for_array(decl_index, decls) {
 			AstNode *decl = decls.e[decl_index];
-			if (decl->kind != AstNode_VarDecl) {
+			if (decl->kind != AstNode_Parameter) {
 				continue;
 			}
-			ast_node(vd, VarDecl, decl);
+			ast_node(param, Parameter, decl);
 
-			Type *type = check_type_extra(c, vd->type, NULL);
+			Type *type = check_type_extra(c, param->type, NULL);
 
-			if (vd->is_using) {
-				if (vd->names.count > 1) {
-					error_node(vd->names.e[0], "Cannot apply `using` to more than one of the same type");
+			if (param->is_using) {
+				if (param->names.count > 1) {
+					error_node(param->names.e[0], "Cannot apply `using` to more than one of the same type");
 				}
 			}
 
-			for_array(name_index, vd->names) {
-				AstNode *name = vd->names.e[name_index];
+			for_array(name_index, param->names) {
+				AstNode *name = param->names.e[name_index];
 				if (!ast_node_expect(name, AstNode_Ident)) {
 					continue;
 				}
 
 				Token name_token = name->Ident;
 
-				Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
+				Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, param->is_using, cast(i32)field_index);
 				e->identifier = name;
 				if (str_eq(name_token.string, str_lit("_"))) {
 					fields[field_index++] = e;
@@ -566,19 +558,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 			}
 
 
-			if (vd->is_using) {
+			if (param->is_using) {
 				Type *t = base_type(type_deref(type));
 				if (!is_type_struct(t) && !is_type_raw_union(t) &&
-				    vd->names.count >= 1 &&
-				    vd->names.e[0]->kind == AstNode_Ident) {
-					Token name_token = vd->names.e[0]->Ident;
+				    param->names.count >= 1 &&
+				    param->names.e[0]->kind == AstNode_Ident) {
+					Token name_token = param->names.e[0]->Ident;
 					if (is_type_indexable(t)) {
 						bool ok = true;
 						for_array(emi, entity_map.entries) {
 							Entity *e = entity_map.entries.e[emi].value;
 							if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
 								if (is_type_indexable(e->type)) {
-									if (e->identifier != vd->names.e[0]) {
+									if (e->identifier != param->names.e[0]) {
 										ok = false;
 										using_index_expr = e;
 										break;
@@ -643,36 +635,24 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
 	ast_node(st, StructType, node);
 
 	isize field_count = 0;
-	isize other_field_count = 0;
 	for_array(field_index, st->fields) {
 		AstNode *field = st->fields.e[field_index];
 		switch (field->kind) {
-		case_ast_node(vd, VarDecl, field);
-			field_count += vd->names.count;
-		case_end;
-
-		case_ast_node(cd, ConstDecl, field);
-			other_field_count += cd->names.count;
-		case_end;
-
-		case_ast_node(td, TypeDecl, field);
-			other_field_count += 1;
+		case_ast_node(p, Parameter, field);
+			field_count += p->names.count;
 		case_end;
 		}
 	}
 
 	Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
-	Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
 
-	check_fields(c, node, st->fields, fields, field_count, other_fields, other_field_count, str_lit("struct"));
+	check_fields(c, node, st->fields, fields, field_count, str_lit("struct"));
 
 	struct_type->Record.struct_is_packed    = st->is_packed;
 	struct_type->Record.struct_is_ordered   = st->is_ordered;
 	struct_type->Record.fields              = fields;
 	struct_type->Record.fields_in_src_order = fields;
 	struct_type->Record.field_count         = field_count;
-	struct_type->Record.other_fields        = other_fields;
-	struct_type->Record.other_field_count   = other_field_count;
 
 	if (!st->is_packed && !st->is_ordered) {
 		// NOTE(bill): Reorder fields for reduced size/performance
@@ -704,33 +684,21 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
 	ast_node(ut, UnionType, node);
 
 	isize field_count = 1;
-	isize other_field_count = 0;
 	for_array(field_index, ut->fields) {
 		AstNode *field = ut->fields.e[field_index];
 		switch (field->kind) {
-		case_ast_node(vd, VarDecl, field);
-			field_count += vd->names.count;
-		case_end;
-
-		case_ast_node(cd, ConstDecl, field);
-			other_field_count += cd->names.count;
-		case_end;
-
-		case_ast_node(td, TypeDecl, field);
-			other_field_count += 1;
+		case_ast_node(p, Parameter, field);
+			field_count += p->names.count;
 		case_end;
 		}
 	}
 
 	Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
-	Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
 
-	check_fields(c, node, ut->fields, fields, field_count, other_fields, other_field_count, str_lit("union"));
+	check_fields(c, node, ut->fields, fields, field_count, str_lit("union"));
 
 	union_type->Record.fields            = fields;
 	union_type->Record.field_count       = field_count;
-	union_type->Record.other_fields      = other_fields;
-	union_type->Record.other_field_count = other_field_count;
 }
 
 void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
@@ -739,33 +707,21 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
 	ast_node(ut, RawUnionType, node);
 
 	isize field_count = 0;
-	isize other_field_count = 0;
 	for_array(field_index, ut->fields) {
 		AstNode *field = ut->fields.e[field_index];
 		switch (field->kind) {
-		case_ast_node(vd, VarDecl, field);
-			field_count += vd->names.count;
-		case_end;
-
-		case_ast_node(cd, ConstDecl, field);
-			other_field_count += cd->names.count;
-		case_end;
-
-		case_ast_node(td, TypeDecl, field);
-			other_field_count += 1;
+		case_ast_node(p, Parameter, field);
+			field_count += p->names.count;
 		case_end;
 		}
 	}
 
 	Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
-	Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
 
-	check_fields(c, node, ut->fields, fields, field_count, other_fields, other_field_count, str_lit("raw union"));
+	check_fields(c, node, ut->fields, fields, field_count, str_lit("raw_union"));
 
 	union_type->Record.fields = fields;
 	union_type->Record.field_count = field_count;
-	union_type->Record.other_fields = other_fields;
-	union_type->Record.other_field_count = other_field_count;
 }
 
 GB_COMPARE_PROC(cmp_enum_order) {
@@ -895,11 +851,11 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 
 	gb_sort_array(fields, field_index, cmp_enum_order);
 
-	enum_type->Record.other_fields = fields;
-	enum_type->Record.other_field_count = field_index;
+	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.other_field_count));
+		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,
@@ -3599,8 +3555,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 			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.other_field_count; i++) {
-					Entity *f = type->Record.other_fields[i];
+				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) {

+ 3 - 14
src/checker/stmt.c

@@ -907,9 +907,9 @@ 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_struct(t) || is_type_enum(t)) {
-					for (isize i = 0; i < t->Record.other_field_count; i++) {
-						Entity *f = t->Record.other_fields[i];
+				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);
@@ -931,17 +931,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 						}
 						f->using_parent = e;
 					}
-					for (isize i = 0; i < t->Record.other_field_count; i++) {
-						Entity *f = t->Record.other_fields[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;
-					}
 				}
 			} break;
 

+ 12 - 14
src/checker/types.c

@@ -84,6 +84,8 @@ typedef struct TypeRecord {
 			Entity * enum_count;
 			Entity * min_value;
 			Entity * max_value;
+			Entity **enum_values;
+			i32      enum_value_count;
 		};
 		struct { // struct only
 			i64 *    struct_offsets;
@@ -93,10 +95,6 @@ typedef struct TypeRecord {
 			Entity **fields_in_src_order; // Entity_Variable
 		};
 	};
-
-	// Entity_Constant or Entity_TypeName
-	Entity **other_fields;
-	i32      other_field_count;
 } TypeRecord;
 
 #define TYPE_KINDS \
@@ -984,19 +982,19 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 			}
 		}
 
-		for (isize i = 0; i < type->Record.other_field_count; i++) {
-			Entity *f = type->Record.other_fields[i];
-			GB_ASSERT(f->kind != Entity_Variable);
-			String str = f->token.string;
+		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)) {
+					sel.entity = f;
+					selection_add_index(&sel, i);
+					return sel;
+				}
 			}
-		}
 
-		if (is_type_enum(type)) {
 			if (str_eq(field_name, str_lit("count"))) {
 				sel.entity = type->Record.enum_count;
 				return sel;

+ 20 - 66
src/parser.c

@@ -1646,8 +1646,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
 			f->expr_level++;
 			open = expect_token(f, Token_OpenBracket);
 
-			if (f->curr_token.kind != Token_Colon)
+			if (f->curr_token.kind != Token_Colon) {
 				indices[0] = parse_expr(f, false);
+			}
 			isize colon_count = 0;
 			Token colons[2] = {0};
 
@@ -2062,8 +2063,9 @@ AstNode *parse_proc_type(AstFile *f) {
 }
 
 
-AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow) {
+AstNodeArray parse_parameter_list(AstFile *f, isize *name_count_, bool allow_using, TokenKind separator, TokenKind follow) {
 	AstNodeArray params = make_ast_node_array(f);
+	isize name_count = 0;
 
 	while (f->curr_token.kind != follow &&
 	       f->curr_token.kind != Token_EOF) {
@@ -2088,6 +2090,8 @@ AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow
 			is_using = false;
 		}
 
+		name_count += names.count;
+
 		// expect_token_after(f, Token_Colon, "parameter list");
 
 		AstNode *type = NULL;
@@ -2114,77 +2118,27 @@ AstNodeArray parse_parameter_list(AstFile *f, bool allow_using, TokenKind follow
 			syntax_error(f->curr_token, "Expected a type for this parameter declaration");
 		}
 
-		array_add(&params, make_parameter(f, names, type, is_using));
-		if (!allow_token(f, Token_Comma)) {
-			break;
-		}
-	}
-
-	return params;
-}
-
-
-AstNodeArray parse_record_params(AstFile *f, isize *decl_count_, bool allow_using, String context) {
-	AstNodeArray decls = make_ast_node_array(f);
-	isize decl_count = 0;
-
-	while (f->curr_token.kind != Token_CloseBrace &&
-	       f->curr_token.kind != Token_EOF) {
-		AstNode *decl = parse_stmt(f);
-		if (is_ast_node_decl(decl) ||
-		    decl->kind == AstNode_UsingStmt ||
-		    decl->kind == AstNode_EmptyStmt) {
-			switch (decl->kind) {
-			case AstNode_EmptyStmt:
-				break;
-
-			case AstNode_ProcDecl:
-				syntax_error(f->curr_token, "Procedure declarations are not allowed within a %.*s", LIT(context));
-				break;
-
-			case AstNode_UsingStmt: {
-				bool is_using = true;
-				if (!allow_using) {
-					syntax_error(f->curr_token, "Cannot apply `using` to members of a %.*s", LIT(context));
-					is_using = false;
-				}
-				if (decl->UsingStmt.node->kind == AstNode_VarDecl) {
-					AstNode *vd = decl->UsingStmt.node;
-					vd->VarDecl.is_using = is_using && allow_using;
-					if (vd->VarDecl.values.count > 0) {
-						syntax_error(f->curr_token, "Default variable assignments within a %.*s will be ignored", LIT(context));
-					}
-					array_add(&decls, vd);
-				} else {
-					syntax_error_node(decl, "Illegal %.*s field", LIT(context));
-				}
-			} break;
+		AstNode *param = make_parameter(f, names, type, is_using);
+		array_add(&params, param);
 
-			case AstNode_VarDecl: {
-				if (decl->VarDecl.values.count > 0) {
-					syntax_error(f->curr_token, "Default variable assignments within a %.*s will be ignored", LIT(context));
-				}
-				array_add(&decls, decl);
-			}
 
-			case AstNode_BadDecl:
-				break;
-
-			case AstNode_ConstDecl:
-			case AstNode_TypeDecl:
-			default:
-				decl_count += 1;
-				array_add(&decls, decl);
+		if (separator == Token_Semicolon) {
+			expect_semicolon(f, param);
+		} else {
+			if (!allow_token(f, separator)) {
 				break;
 			}
-		} else {
-			syntax_error_node(decl, "Illegal record field: %.*s", LIT(ast_node_strings[decl->kind]));
 		}
 	}
 
-	if (decl_count_) *decl_count_ = decl_count;
+	if (name_count_) *name_count_ = name_count;
+
+	return params;
+}
+
 
-	return decls;
+AstNodeArray parse_record_params(AstFile *f, isize *field_count_, bool allow_using, String context) {
+	return parse_parameter_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
 }
 
 AstNode *parse_identifier_or_type(AstFile *f) {
@@ -2380,7 +2334,7 @@ void parse_proc_signature(AstFile *f,
                           AstNodeArray *params,
                           AstNodeArray *results) {
 	expect_token(f, Token_OpenParen);
-	*params = parse_parameter_list(f, true, Token_CloseParen);
+	*params = parse_parameter_list(f, NULL, true, Token_Comma, Token_CloseParen);
 	expect_token_after(f, Token_CloseParen, "parameter list");
 	*results = parse_results(f);
 }

+ 5 - 13
src/ssa.c

@@ -2522,15 +2522,8 @@ void ssa_gen_global_type_name(ssaModule *m, Entity *e, String name) {
 	ssa_module_add_value(m, e, t);
 	map_ssa_value_set(&m->members, hash_string(name), t);
 
-	Type *bt = base_type(e->type);
-	if (bt->kind == Type_Record) {
-		TypeRecord *s = &bt->Record;
-		for (isize j = 0; j < s->other_field_count; j++) {
-			ssa_mangle_sub_type_name(m, s->other_fields[j], name);
-		}
-	}
-
-	if (is_type_union(bt)) {
+	if (is_type_union(e->type)) {
+		Type *bt = base_type(e->type);
 		TypeRecord *s = &bt->Record;
 		// NOTE(bill): Zeroth entry is null (for `match type` stmts)
 		for (isize j = 1; j < s->field_count; j++) {
@@ -5418,13 +5411,12 @@ void ssa_gen_tree(ssaGen *s) {
 						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.other_field_count > 0) {
-							Entity **fields = t->Record.other_fields;
-							isize count = t->Record.other_field_count;
+						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;