فهرست منبع

Only check files that have been truly imported.

Ginger Bill 8 سال پیش
والد
کامیت
346aa5f71c
10فایلهای تغییر یافته به همراه283 افزوده شده و 198 حذف شده
  1. 1 10
      code/demo.odin
  2. 2 2
      core/_preload.odin
  3. 5 6
      core/sys/windows.odin
  4. 52 23
      src/check_expr.c
  5. 11 3
      src/check_stmt.c
  6. 18 0
      src/checker.c
  7. 1 1
      src/entity.c
  8. 117 104
      src/ir.c
  9. 67 44
      src/parser.c
  10. 9 5
      src/types.c

+ 1 - 10
code/demo.odin

@@ -1,22 +1,13 @@
 #import "fmt.odin";
-#import "atomic.odin";
-#import "hash.odin";
-#import "math.odin";
-#import "mem.odin";
-#import "opengl.odin";
-#import "os.odin";
-#import "sync.odin";
-#import "utf8.odin";
-#import ht "http_test.odin";
 
 main :: proc() {
+
 	{
 		Fruit :: enum {
 			APPLE,
 			BANANA,
 			COCONUT,
 		}
-
 		fmt.println(Fruit.names);
 	}
 

+ 2 - 2
core/_preload.odin

@@ -17,7 +17,7 @@
 Type_Info_Member :: struct #ordered {
 	name:      string,     // can be empty if tuple
 	type_info: ^Type_Info,
-	offset:    int,        // offsets are not used in tuples
+	offset:    int,        // offsets may not be used in tuples
 }
 Type_Info_Record :: struct #ordered {
 	fields:       []Type_Info_Member,
@@ -83,7 +83,7 @@ Type_Info :: union {
 		count:     int,
 		align:     int,
 	},
-	Tuple:     Type_Info_Record,
+	Tuple:     Type_Info_Record, // Only really used for procedures
 	Struct:    Type_Info_Record,
 	Union:     Type_Info_Record,
 	Raw_Union: Type_Info_Record,

+ 5 - 6
core/sys/windows.odin

@@ -1,9 +1,8 @@
-_ := compile_assert(ODIN_OS == "windows");
-#foreign_system_library "kernel32.lib";
-#foreign_system_library "user32.lib";
-#foreign_system_library "gdi32.lib";
-#foreign_system_library "winmm.lib";
-#foreign_system_library "opengl32.lib";
+#foreign_system_library "kernel32.lib" when ODIN_OS == "windows";
+#foreign_system_library "user32.lib"   when ODIN_OS == "windows";
+#foreign_system_library "gdi32.lib"    when ODIN_OS == "windows";
+#foreign_system_library "winmm.lib"    when ODIN_OS == "windows";
+#foreign_system_library "opengl32.lib" when ODIN_OS == "windows";
 
 HANDLE    :: rawptr;
 HWND      :: HANDLE;

+ 52 - 23
src/check_expr.c

@@ -360,6 +360,11 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 
 				Token name_token = name->Ident;
 
+				if (str_eq(name_token.string, str_lit(""))) {
+					error(name_token, "`names` is a reserved identifier for unions");
+					continue;
+				}
+
 				Type *type = make_type_named(c->allocator, name_token.string, base_type, NULL);
 				Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, type);
 				type->Named.type_name = e;
@@ -521,6 +526,11 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
 	struct_type->Record.fields_in_src_order = fields;
 	struct_type->Record.field_count         = field_count;
 
+	// struct_type->Record.names = make_entity_field(c->allocator, c->context.scope,
+	// 	make_token_ident(str_lit("names")), t_string_slice, false, 0);
+	// struct_type->Record.names->Variable.is_immutable = true;
+	// struct_type->Record.names->flags |= EntityFlag_TypeField;
+
 	if (!st->is_packed && !st->is_ordered) {
 		// NOTE(bill): Reorder fields for reduced size/performance
 
@@ -605,6 +615,11 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
 
 	union_type->Record.fields            = fields;
 	union_type->Record.field_count       = field_count;
+
+	// union_type->Record.names = make_entity_field(c->allocator, c->context.scope,
+	// 	make_token_ident(str_lit("names")), t_string_slice, false, 0);
+	// union_type->Record.names->Variable.is_immutable = true;
+	// union_type->Record.names->flags |= EntityFlag_TypeField;
 }
 
 void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
@@ -628,6 +643,11 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
 
 	union_type->Record.fields = fields;
 	union_type->Record.field_count = field_count;
+
+// 	union_type->Record.names = make_entity_field(c->allocator, c->context.scope,
+// 		make_token_ident(str_lit("names")), t_string_slice, false, 0);
+// 	union_type->Record.names->Variable.is_immutable = true;
+// 	union_type->Record.names->flags |= EntityFlag_TypeField;
 }
 
 // GB_COMPARE_PROC(cmp_enum_order) {
@@ -664,6 +684,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 		error_node(node, "Base type for enumeration must be numeric");
 		return;
 	}
+	if (is_type_enum(base_type)) {
+		error_node(node, "Base type for enumeration cannot be another enumeration");
+		return;
+	}
 
 	// NOTE(bill): Must be up here for the `check_init_constant` system
 	enum_type->Record.enum_base_type = base_type;
@@ -764,8 +788,9 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 			add_entity_use(c, field, e);
 		}
 	}
-
 	GB_ASSERT(field_count <= et->fields.count);
+	gb_temp_arena_memory_end(tmp);
+
 
 	enum_type->Record.fields = fields;
 	enum_type->Record.field_count = field_count;
@@ -777,12 +802,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 	enum_type->Record.enum_max_value = make_entity_constant(c->allocator, c->context.scope,
 		make_token_ident(str_lit("max_value")), constant_type, max_value);
 
-	enum_type->Record.enum_names = make_entity_field(c->allocator, c->context.scope,
+	enum_type->Record.names = make_entity_field(c->allocator, c->context.scope,
 		make_token_ident(str_lit("names")), t_string_slice, false, 0);
-	enum_type->Record.enum_names->Variable.is_immutable = true;
-	enum_type->Record.enum_names->flags |= EntityFlag_EnumField;
-
-	gb_temp_arena_memory_end(tmp);
+	enum_type->Record.names->Variable.is_immutable = true;
+	enum_type->Record.names->flags |= EntityFlag_TypeField;
 }
 
 
@@ -2513,11 +2536,13 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 			check_op_expr = false;
 			entity = scope_lookup_entity(e->ImportName.scope, sel_name);
 			bool is_declared = entity != NULL;
-			if (entity->kind == Entity_Builtin) {
-				is_declared = false;
-			}
-			if (entity->scope->is_global && !e->ImportName.scope->is_global) {
-				is_declared = false;
+			if (is_declared) {
+				if (entity->kind == Entity_Builtin) {
+					is_declared = false;
+				}
+				if (entity->scope->is_global && !e->ImportName.scope->is_global) {
+					is_declared = false;
+				}
 			}
 			if (!is_declared) {
 				error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name));
@@ -2613,8 +2638,8 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 		sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type);
 		entity = sel.entity;
 
-		// NOTE(bill): Add enum type info needed for fields like `names`
-		if (entity != NULL && (entity->flags&EntityFlag_EnumField)) {
+		// NOTE(bill): Add type info needed for fields like `names`
+		if (entity != NULL && (entity->flags&EntityFlag_TypeField)) {
 			add_type_info_type(c, operand->type);
 		}
 	}
@@ -4575,18 +4600,28 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 		case Type_Slice:
 		case Type_Array:
 		case Type_Vector:
+		case Type_DynamicArray:
 		{
 			Type *elem_type = NULL;
 			String context_name = {0};
+			i64 max_type_count = -1;
 			if (t->kind == Type_Slice) {
 				elem_type = t->Slice.elem;
 				context_name = str_lit("slice literal");
 			} else if (t->kind == Type_Vector) {
 				elem_type = t->Vector.elem;
 				context_name = str_lit("vector literal");
-			} else {
+				max_type_count = t->Vector.count;
+			} else if (t->kind == Type_Array) {
 				elem_type = t->Array.elem;
 				context_name = str_lit("array literal");
+				max_type_count = t->Array.count;
+			} else if (t->kind == Type_DynamicArray) {
+				elem_type = t->DynamicArray.elem;
+				context_name = str_lit("dynamic array literal");
+				is_constant = false;
+			} else {
+				GB_PANIC("unreachable");
 			}
 
 
@@ -4606,15 +4641,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 					continue;
 				}
 
-				if (t->kind == Type_Array &&
-				    t->Array.count >= 0 &&
-				    index >= t->Array.count) {
-					error_node(e, "Index %lld is out of bounds (>= %lld) for array literal", index, t->Array.count);
-				}
-				if (t->kind == Type_Vector &&
-				    t->Vector.count >= 0 &&
-				    index >= t->Vector.count) {
-					error_node(e, "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count);
+				if (0 <= max_type_count && max_type_count <= index) {
+					error_node(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name));
 				}
 
 				Operand operand = {0};
@@ -5153,6 +5181,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 		}
 	case_end;
 
+	case AstNode_HelperType:
 	case AstNode_ProcType:
 	case AstNode_PointerType:
 	case AstNode_ArrayType:

+ 11 - 3
src/check_stmt.c

@@ -999,7 +999,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		}
 
 
-		if (unparen_expr(lhs)->kind != AstNode_Ident) {
+		if (lhs->kind != AstNode_Ident) {
 			error_node(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind]));
 			break;
 		}
@@ -1067,9 +1067,17 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 
 			check_open_scope(c, stmt);
-			if (case_type != NULL) {
-				add_type_info_type(c, case_type);
+			if (case_type == NULL) {
+				if (is_union_ptr) {
+					case_type = type_deref(x.type);
+				} else {
+					case_type = x.type;
+				}
+			}
+
+			add_type_info_type(c, case_type);
 
+			{
 				// NOTE(bill): Dummy type
 				Type *tt = case_type;
 				if (is_union_ptr) {

+ 18 - 0
src/checker.c

@@ -208,6 +208,7 @@ typedef struct Scope {
 	bool           is_global;
 	bool           is_file;
 	bool           is_init;
+	bool           has_been_imported; // This is only applicable to file scopes
 	AstFile *      file;
 } Scope;
 gb_global Scope *universal_scope = NULL;
@@ -1529,6 +1530,10 @@ void check_all_global_entities(Checker *c) {
 		}
 		add_curr_ast_file(c, d->scope->file);
 
+		if (!d->scope->has_been_imported) {
+			continue;
+		}
+
 		if (e->kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
 			if (e->scope->is_init) {
 				error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
@@ -1606,6 +1611,12 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 		ast_node(id, ImportDecl, decl);
 		Token token = id->relpath;
 
+		GB_ASSERT(parent_scope->is_file);
+
+		if (!parent_scope->has_been_imported) {
+			continue;
+		}
+
 		HashKey key = hash_string(id->fullpath);
 		Scope **found = map_scope_get(file_scopes, key);
 		if (found == NULL) {
@@ -1652,6 +1663,8 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 			warning(token, "Multiple #import of the same file within this scope");
 		}
 
+		scope->has_been_imported = true;
+
 		if (str_eq(id->import_name.string, str_lit("."))) {
 			// NOTE(bill): Add imported entities to this file's scope
 			for_array(elem_index, scope->elements.entries) {
@@ -1721,6 +1734,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 			}
 		}
 
+
 		String library_name = path_to_entity_name(fl->library_name.string, file_str);
 		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));
@@ -1755,6 +1769,10 @@ void check_parsed_files(Checker *c) {
 			array_add(&c->global_scope->shared, scope);
 		}
 
+		if (scope->is_init || scope->is_global) {
+			scope->has_been_imported = true;
+		}
+
 		f->scope = scope;
 		f->decl_info = make_declaration_info(c->allocator, f->scope);
 		HashKey key = hash_string(f->tokenizer.fullpath);

+ 1 - 1
src/entity.c

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

+ 117 - 104
src/ir.c

@@ -1008,6 +1008,22 @@ irValue *ir_make_value_procedure(gbAllocator a, irModule *m, Entity *entity, Typ
 	return v;
 }
 
+
+irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefix, i64 id) {
+	gbAllocator a = m->allocator;
+	Token token = {Token_Ident};
+	isize name_len = prefix.len + 10;
+	token.string.text = gb_alloc_array(a, u8, name_len);
+	token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
+	                               "%.*s-%llx", LIT(prefix), id)-1;
+	Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, elem_type, count), false);
+	irValue *value = ir_make_value_global(a, e, NULL);
+	value->Global.is_private = true;
+	ir_module_add_value(m, e, value);
+	map_ir_value_set(&m->members, hash_string(token.string), value);
+	return value;
+}
+
 irBlock *ir_new_block(irProcedure *proc, AstNode *node, char *label) {
 	Scope *scope = NULL;
 	if (node != NULL) {
@@ -3709,50 +3725,55 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		AstNode *sel = unparen_expr(se->selector);
 		if (sel->kind == AstNode_Ident) {
 			String selector = sel->Ident.string;
-			Type *type = type_of_expr(proc->module->info, se->expr);
+			TypeAndValue *tav = type_and_value_of_expression(proc->module->info, se->expr);
 
-			if (is_type_enum(type)) {
+			if (tav == NULL) {
+				// NOTE(bill): Imports
+				Entity *imp = entity_of_ident(proc->module->info, se->expr);
+				if (imp != NULL) {
+					GB_ASSERT(imp->kind == Entity_ImportName);
+				}
+				return ir_build_addr(proc, unparen_expr(se->selector));
+			}
+
+
+			Type *type = base_type(tav->type);
+			if (tav->mode == Addressing_Type) { // Addressing_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: {
+				GB_ASSERT(e->flags & EntityFlag_TypeField);
+				String name = e->token.string;
+				if (str_eq(name, str_lit("names"))) {
 					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 **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 *names_ptr = NULL;
+
+					if (is_type_enum(type)) {
+						irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr);
+						names_ptr = ir_emit_struct_ep(proc, enum_info, 1);
+					} else {
+						GB_PANIC("TODO(bill): `names` for records");
+						// irValue *record_info = ir_emit_conv(proc, ti_ptr, t_type_info_record_ptr);
+						// names_ptr = ir_emit_struct_ep(proc, record_info, 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;
+				} else {
+					GB_PANIC("Unhandled TypeField %.*s", LIT(name));
 				}
+				GB_PANIC("Unreachable");
 			}
 
-			type = base_type(type);
-
-			if (type == t_invalid) {
-				// NOTE(bill): Imports
-				Entity *imp = entity_of_ident(proc->module->info, se->expr);
-				if (imp != NULL) {
-					GB_ASSERT(imp->kind == Entity_ImportName);
-				}
-				return ir_build_addr(proc, unparen_expr(se->selector));
-			} else {
-				Selection sel = lookup_field(proc->module->allocator, type, selector, false);
-				GB_ASSERT(sel.entity != NULL);
+			Selection sel = lookup_field(proc->module->allocator, type, selector, false);
+			GB_ASSERT(sel.entity != NULL);
 
-				irValue *a = ir_build_addr(proc, se->expr).addr;
-				a = ir_emit_deep_field_gep(proc, type, a, sel);
-				return ir_make_addr(a);
-			}
+			irValue *a = ir_build_addr(proc, se->expr).addr;
+			a = ir_emit_deep_field_gep(proc, type, a, sel);
+			return ir_make_addr(a);
 		} else {
 			Type *type = base_type(type_of_expr(proc->module->info, se->expr));
 			GB_ASSERT(is_type_integer(type));
@@ -4117,33 +4138,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 					ir_emit_store(proc, gep, ev);
 				}
 			}
-
-
-			// irValue *result = ir_add_module_constant(proc->module, type, make_exact_value_compound(expr));
-			// for_array(index, cl->elems) {
-			// 	AstNode *elem = cl->elems.e[index];
-			// 	if (ir_is_elem_const(proc->module, elem, et)) {
-			// 		continue;
-			// 	}
-			// 	irValue *field_elem = ir_build_expr(proc, elem);
-			// 	Type *t = ir_type(field_elem);
-			// 	GB_ASSERT(t->kind != Type_Tuple);
-			// 	irValue *ev = ir_emit_conv(proc, field_elem, et);
-			// 	irValue *i = ir_make_const_int(proc->module->allocator, index);
-			// 	result = ir_emit(proc, ir_make_instr_insert_element(proc, result, ev, i));
-			// }
-
-			// if (cl->elems.count == 1 && bt->Vector.count > 1) {
-			// 	isize index_count = bt->Vector.count;
-			// 	i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
-			// 	for (isize i = 0; i < index_count; i++) {
-			// 		indices[i] = 0;
-			// 	}
-			// 	irValue *sv = ir_emit(proc, ir_make_instr_vector_shuffle(proc, result, indices, index_count));
-			// 	ir_emit_store(proc, v, sv);
-			// 	return ir_make_addr(v);
-			// }
-			// ir_emit_store(proc, v, result);
 		} break;
 
 		case Type_Record: {
@@ -4186,13 +4180,51 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			}
 		} break;
 
-		case Type_Map: {
+		case Type_DynamicArray: {
 			if (cl->elems.count == 0) {
 				break;
 			}
+			Type *elem = bt->DynamicArray.elem;
 			gbAllocator a = proc->module->allocator;
+			irValue *size  = ir_make_const_int(a, type_size_of(proc->module->sizes, a, elem));
+			irValue *align = ir_make_const_int(a, type_align_of(proc->module->sizes, a, elem));
 			{
 				irValue **args = gb_alloc_array(a, irValue *, 4);
+				args[0] = ir_emit_conv(proc, v, t_rawptr);
+				args[1] = size;
+				args[2] = align;
+				args[3] = ir_make_const_int(a, 2*cl->elems.count);
+				ir_emit_global_call(proc, "__dynamic_array_reserve", args, 4);
+			}
+
+			i64 item_count = cl->elems.count;
+			irValue *items = ir_generate_array(proc->module, elem, item_count, str_lit("__dacl$"), cast(i64)cast(intptr)expr);
+
+			for_array(field_index, cl->elems) {
+				AstNode *f = cl->elems.e[field_index];
+				irValue *value = ir_emit_conv(proc, ir_build_expr(proc, f), elem);
+				irValue *ep = ir_emit_array_epi(proc, items, field_index);
+				ir_emit_store(proc, ep, value);
+			}
+
+			{
+				irValue **args = gb_alloc_array(a, irValue *, 5);
+				args[0] = ir_emit_conv(proc, v, t_rawptr);
+				args[1] = size;
+				args[2] = align;
+				args[3] = ir_emit_conv(proc, items, t_rawptr);
+				args[4] = ir_make_const_int(a, item_count);
+				ir_emit_global_call(proc, "__dynamic_array_append", args, 5);
+			}
+		} break;
+
+		case Type_Map: {
+			if (cl->elems.count == 0) {
+				break;
+			}
+			gbAllocator a = proc->module->allocator;
+			{
+				irValue **args = gb_alloc_array(a, irValue *, 2);
 				args[0] = ir_gen_map_header(proc, v, type);
 				args[1] = ir_make_const_int(a, 2*cl->elems.count);
 				ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2);
@@ -5294,17 +5326,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 			AstNode *clause = body->stmts.e[i];
 			ast_node(cc, CaseClause, clause);
 
-			if (cc->list.count == 0) {
-				// default case
-				default_stmts = cc->stmts;
-				default_block = ir_new_block(proc, clause, "type-match.dflt.body");
-				continue;
-			}
-			GB_ASSERT(cc->list.count == 1);
-
-
-			irBlock *body = ir_new_block(proc, clause, "type-match.case.body");
-
 			Entity *tag_var_entity = NULL;
 			Type *tag_var_type = NULL;
 			if (str_eq(tag_var_name, str_lit("_"))) {
@@ -5324,6 +5345,26 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 			irBlock *next_cond = NULL;
 			irValue *cond = NULL;
 
+			if (cc->list.count == 0) {
+				// default case
+				default_stmts = cc->stmts;
+				default_block = ir_new_block(proc, clause, "type-match.dflt.body");
+
+
+				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);
+				}
+				ir_emit_store(proc, tag_var, parent);
+				continue;
+			}
+			GB_ASSERT(cc->list.count == 1);
+
+			irBlock *body = ir_new_block(proc, clause, "type-match.case.body");
+
+
 			if (is_union_ptr) {
 				Type *bt = type_deref(tag_var_type);
 				irValue *index = NULL;
@@ -6409,38 +6450,10 @@ void ir_gen_tree(irGen *s) {
 							if (t->Record.field_count > 0) {
 								Entity **fields = t->Record.fields;
 								isize count = t->Record.field_count;
-								irValue *name_array = NULL;
-								irValue *value_array = NULL;
-
-								{
-									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), false);
-									name_array = ir_make_value_global(a, e, NULL);
-									name_array->Global.is_private = true;
-									ir_module_add_value(m, e, name_array);
-									map_ir_value_set(&m->members, hash_string(token.string), name_array);
-								}
-
-								{
-									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_type_info_enum_value, count), false);
-									value_array = ir_make_value_global(a, e, NULL);
-									value_array->Global.is_private = true;
-									ir_module_add_value(m, e, value_array);
-									map_ir_value_set(&m->members, hash_string(token.string), value_array);
-								}
+								irValue *name_array  = ir_generate_array(m, t_string, count,
+								                                         str_lit("__$enum_names"), cast(i64)entry_index);
+								irValue *value_array = ir_generate_array(m, t_type_info_enum_value, count,
+								                                         str_lit("__$enum_values"), cast(i64)entry_index);
 
 								bool is_value_int = is_type_integer(t->Record.enum_base_type);
 

+ 67 - 44
src/parser.c

@@ -2337,26 +2337,6 @@ bool parse_expect_separator(AstFile *f, TokenKind separator, AstNode *param) {
 	return false;
 }
 
-AstNodeArray convert_to_ident_list(AstFile *f, AstNodeArray list) {
-	AstNodeArray idents = {0};
-	array_init_reserve(&idents, heap_allocator(), list.count);
-	// Convert to ident list
-	for_array(i, list) {
-		AstNode *ident = list.e[i];
-		switch (ident->kind) {
-		case AstNode_Ident:
-		case AstNode_BadExpr:
-			break;
-		default:
-			error_node(ident, "Expected an identifier");
-			ident = ast_ident(f, blank_token);
-			break;
-		}
-		array_add(&idents, ident);
-	}
-	return idents;
-}
-
 AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) {
 	if (allow_ellipsis && f->curr_token.kind == Token_Ellipsis) {
 		Token tok = f->curr_token;
@@ -2377,16 +2357,24 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) {
 	return type;
 }
 
+bool is_token_field_prefix(TokenKind kind) {
+	switch (kind) {
+	case Token_using:
+	case Token_no_alias:
+	// case Token_immutable:
+		return true;
+	}
+	return false;
+}
+
 
 u32 parse_field_prefixes(AstFile *f) {
 	i32 using_count     = 0;
 	i32 no_alias_count  = 0;
 	i32 immutable_count = 0;
 
-	bool loop = true;
-	while (loop) {
+	while (is_token_field_prefix(f->curr_token.kind)) {
 		switch (f->curr_token.kind) {
-		default: loop = false; break;
 		case Token_using:     using_count     += 1; next_token(f); break;
 		case Token_no_alias:  no_alias_count  += 1; next_token(f); break;
 		// case Token_immutable: immutable_count += 1; next_token(f); break;
@@ -2404,8 +2392,8 @@ u32 parse_field_prefixes(AstFile *f) {
 	return field_flags;
 }
 
-u32 check_field_prefixes(AstFile *f, AstNodeArray names, u32 allowed_flags, u32 set_flags) {
-	if (names.count > 1 && (set_flags&FieldFlag_using)) {
+u32 check_field_prefixes(AstFile *f, isize name_count, u32 allowed_flags, u32 set_flags) {
+	if (name_count > 1 && (set_flags&FieldFlag_using)) {
 		syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
 		set_flags &= ~FieldFlag_using;
 	}
@@ -2425,19 +2413,54 @@ u32 check_field_prefixes(AstFile *f, AstNodeArray names, u32 allowed_flags, u32
 	return set_flags;
 }
 
+typedef struct AstNodeAndFlags {
+	AstNode *node;
+	u32      flags;
+} AstNodeAndFlags;
+
+typedef Array(AstNodeAndFlags) AstNodeAndFlagsArray;
+
+AstNodeArray convert_to_ident_list(AstFile *f, AstNodeAndFlagsArray list, bool ignore_flags) {
+	AstNodeArray idents = {0};
+	array_init_reserve(&idents, heap_allocator(), list.count);
+	// Convert to ident list
+	for_array(i, list) {
+		AstNode *ident = list.e[i].node;
+
+		if (!ignore_flags) {
+			if (i != 0) {
+				error_node(ident, "Illegal use of prefixes in parameter list");
+			}
+		}
+
+		switch (ident->kind) {
+		case AstNode_Ident:
+		case AstNode_BadExpr:
+			break;
+		default:
+			error_node(ident, "Expected an identifier");
+			ident = ast_ident(f, blank_token);
+			break;
+		}
+		array_add(&idents, ident);
+	}
+	return idents;
+}
+
 AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
                               TokenKind separator, TokenKind follow) {
 	AstNodeArray params = make_ast_node_array(f);
-	AstNodeArray list   = make_ast_node_array(f);
-	isize name_count    = 0;
+	AstNodeAndFlagsArray list = {0}; array_init(&list, heap_allocator()); // LEAK(bill):
+	isize total_name_count = 0;
 	bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
 
-	u32 set_flags = parse_field_prefixes(f);
 	while (f->curr_token.kind != follow &&
 	       f->curr_token.kind != Token_Colon &&
 	       f->curr_token.kind != Token_EOF) {
+		u32 flags = parse_field_prefixes(f);
 		AstNode *param = parse_var_type(f, allow_ellipsis);
-		array_add(&list, param);
+		AstNodeAndFlags naf = {param, flags};
+		array_add(&list, naf);
 		if (f->curr_token.kind != Token_Comma) {
 			break;
 		}
@@ -2445,12 +2468,16 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
 	}
 
 	if (f->curr_token.kind == Token_Colon) {
-		AstNodeArray names = convert_to_ident_list(f, list); // Copy for semantic reasons
+		AstNodeArray names = convert_to_ident_list(f, list, true); // Copy for semantic reasons
 		if (names.count == 0) {
 			syntax_error(f->curr_token, "Empty field declaration");
 		}
-		set_flags = check_field_prefixes(f, names, allowed_flags, set_flags);
-		name_count += names.count;
+		u32 set_flags = 0;
+		if (list.count > 0) {
+			set_flags = list.e[0].flags;
+		}
+		set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags);
+		total_name_count += names.count;
 
 		expect_token_after(f, Token_Colon, "field list");
 		AstNode *type = parse_var_type(f, allow_ellipsis);
@@ -2467,8 +2494,8 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
 				syntax_error(f->curr_token, "Empty field declaration");
 				break;
 			}
-			set_flags = check_field_prefixes(f, names, allowed_flags, set_flags);
-			name_count += names.count;
+			set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags);
+			total_name_count += names.count;
 
 			expect_token_after(f, Token_Colon, "field list");
 			AstNode *type = parse_var_type(f, allow_ellipsis);
@@ -2480,25 +2507,25 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
 			}
 		}
 
-		if (name_count_) *name_count_ = name_count;
+		if (name_count_) *name_count_ = total_name_count;
 		return params;
 	}
 
-	set_flags = check_field_prefixes(f, list, allowed_flags, set_flags);
 	for_array(i, list) {
 		AstNodeArray names = {0};
-		AstNode *type = list.e[i];
+		AstNode *type = list.e[i].node;
 		Token token = blank_token;
 
 		array_init_count(&names, heap_allocator(), 1);
 		token.pos = ast_node_token(type).pos;
 		names.e[0] = ast_ident(f, token);
+		u32 flags = check_field_prefixes(f, list.count, allowed_flags, list.e[i].flags);
 
-		AstNode *param = ast_field(f, names, list.e[i], set_flags);
+		AstNode *param = ast_field(f, names, list.e[i].node, flags);
 		array_add(&params, param);
 	}
 
-	if (name_count_) *name_count_ = name_count;
+	if (name_count_) *name_count_ = total_name_count;
 	return params;
 }
 
@@ -2627,12 +2654,10 @@ AstNode *parse_type_or_ident(AstFile *f) {
 
 		f->expr_level = prev_level;
 
-
 		if (is_packed && is_ordered) {
 			syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering");
 		}
 
-
 		Token open = expect_token_after(f, Token_OpenBrace, "struct");
 		isize decl_count = 0;
 		AstNodeArray decls = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("struct"));
@@ -2685,12 +2710,10 @@ AstNode *parse_type_or_ident(AstFile *f) {
 	}
 
 	case Token_OpenParen: {
-		// NOTE(bill): Skip the paren expression
 		Token    open  = expect_token(f, Token_OpenParen);
 		AstNode *type  = parse_type(f);
 		Token    close = expect_token(f, Token_CloseParen);
-		return type;
-		// return ast_paren_expr(f, type, open, close);
+		return ast_paren_expr(f, type, open, close);
 	} break;
 	}
 

+ 9 - 5
src/types.c

@@ -102,12 +102,12 @@ typedef struct TypeRecord {
 	Entity **fields_in_src_order; // Entity_Variable
 
 	i64      custom_align; // NOTE(bill): Only used in structs at the moment
+	Entity * names;
 
 	Type *   enum_base_type;
 	Entity * enum_count;
 	Entity * enum_min_value;
 	Entity * enum_max_value;
-	Entity * enum_names;
 } TypeRecord;
 
 #define TYPE_KINDS                                        \
@@ -1318,6 +1318,14 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 		return sel;
 	}
 	if (is_type) {
+		if (type->kind == Type_Record) {
+			if (type->Record.names != NULL &&
+			    str_eq(field_name, str_lit("names"))) {
+				sel.entity = type->Record.names;
+				return sel;
+			}
+		}
+
 		if (is_type_union(type)) {
 			// NOTE(bill): The subtype for a union are stored in the fields
 			// as they are "kind of" like variables but not
@@ -1347,10 +1355,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 					sel.entity = type->Record.enum_max_value;
 					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++) {