diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7a0088f86..2bfd25260 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -119,7 +119,7 @@ bool check_is_assignable_to_using_subtype(Type *src, Type *dst) { src_is_ptr = src != prev_src; src = base_type(src); - if (!is_type_struct(src) && !is_type_union(src)) { + if (!is_type_struct(src)) { return false; } @@ -1070,7 +1070,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } // NOTE(bill): Must be up here for the `check_init_constant` system - enum_type->Record.enum_base_type = base_type; + enum_type->Enum.base_type = base_type; Map entity_map = {}; // Key: String map_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count)); @@ -1171,17 +1171,17 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod GB_ASSERT(fields.count <= et->fields.count); - enum_type->Record.fields = fields.data; - enum_type->Record.field_count = fields.count; + enum_type->Enum.fields = fields.data; + enum_type->Enum.field_count = fields.count; - enum_type->Record.enum_count = make_entity_constant(c->allocator, c->context.scope, + enum_type->Enum.count = make_entity_constant(c->allocator, c->context.scope, make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count)); - enum_type->Record.enum_min_value = make_entity_constant(c->allocator, c->context.scope, + enum_type->Enum.min_value = make_entity_constant(c->allocator, c->context.scope, make_token_ident(str_lit("min_value")), constant_type, min_value); - enum_type->Record.enum_max_value = make_entity_constant(c->allocator, c->context.scope, + enum_type->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.names = make_names_field_for_record(c, c->context.scope); + enum_type->Enum.names = make_names_field_for_record(c, c->context.scope); } @@ -2569,7 +2569,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) check_open_scope(c, e); check_enum_type(c, *type, named_type, e); check_close_scope(c); - (*type)->Record.node = e; + (*type)->Enum.node = e; return true; case_end; @@ -3069,8 +3069,6 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { if (x->type == err_type && is_operand_nil(*x)) { err_type = y->type; } - gb_printf_err("%d %d\n", is_operand_nil(*x), type_has_nil(y->type)); - gb_printf_err("%d %d\n", is_operand_nil(*y), type_has_nil(x->type)); gbString type_string = type_to_string(err_type); err_str = gb_string_make(c->tmp_allocator, gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(token_strings[op]), type_string)); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 3f7b9a456..2abc6c756 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -489,52 +489,22 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo f->using_parent = e; } } - } else if (is_type_enum(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); - if (found != nullptr) { - gbString expr_str = expr_to_string(expr); - error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); - gb_string_free(expr_str); - return false; - } - f->using_parent = e; + } + } else if (t->kind == Type_Enum) { + for (isize i = 0; i < t->Enum.field_count; i++) { + Entity *f = t->Enum.fields[i]; + Entity *found = scope_insert_entity(c->context.scope, f); + if (found != nullptr) { + gbString expr_str = expr_to_string(expr); + error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); + gb_string_free(expr_str); + return false; } + f->using_parent = e; } } else { error(us->token, "`using` can be only applied to record type entities"); } - /* if (is_type_union(t)) { - TokenPos pos = ast_node_token(expr).pos; - for (isize i = 1; i < t->Record.variant_count; i++) { - Entity *f = t->Record.variants[i]; - // gb_printf_err("%s\n", type_to_string(f->type)); - Entity *found = scope_insert_entity(c->context.scope, f); - if (found != nullptr) { - gbString expr_str = expr_to_string(expr); - error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); - gb_string_free(expr_str); - return false; - } - f->using_parent = e; - } - } else if (is_type_enum(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); - if (found != nullptr) { - gbString expr_str = expr_to_string(expr); - error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); - gb_string_free(expr_str); - return false; - } - f->using_parent = e; - } - - } else { - error(us->token, "`using` can be only applied to `union` or `enum` type entities"); - } */ } break; case Entity_ImportName: { diff --git a/src/checker.cpp b/src/checker.cpp index d239d5953..cbb6afe0d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1148,11 +1148,12 @@ void add_type_info_type(Checker *c, Type *t) { add_type_info_type(c, t_int); break; + case Type_Enum: + add_type_info_type(c, bt->Enum.base_type); + break; + case Type_Record: { switch (bt->Record.kind) { - case TypeRecord_Enum: - add_type_info_type(c, bt->Record.enum_base_type); - break; case TypeRecord_Union: add_type_info_type(c, t_int); for (isize i = 0; i < bt->Record.variant_count; i++) { diff --git a/src/ir.cpp b/src/ir.cpp index 61e693666..bdb9c7c1c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7995,6 +7995,55 @@ void ir_gen_tree(irGen *s) { ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count); ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count); } break; + case Type_Enum: + ir_emit_comment(proc, str_lit("TypeInfoEnum")); + tag = ir_emit_conv(proc, variant_ptr, t_type_info_enum_ptr); + { + GB_ASSERT(t->Enum.base_type != nullptr); + irValue *base = ir_type_info(proc, t->Enum.base_type); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), base); + + if (t->Enum.field_count > 0) { + Entity **fields = t->Enum.fields; + isize count = t->Enum.field_count; + 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->Enum.base_type); + + for (isize i = 0; i < count; i++) { + irValue *name_ep = ir_emit_array_epi(proc, name_array, i); + irValue *value_ep = ir_emit_array_epi(proc, value_array, i); + + ExactValue value = fields[i]->Constant.value; + + if (is_value_int) { + value_ep = ir_emit_conv(proc, value_ep, t_i128_ptr); + ir_emit_store(proc, value_ep, ir_value_constant(a, t_i128, value)); + } else { + GB_ASSERT(is_type_float(t->Enum.base_type)); + f64 f = value.value_float; + value_ep = ir_emit_conv(proc, value_ep, t_f64_ptr); + ir_emit_store(proc, value_ep, ir_const_f64(a, f)); + } + + ir_emit_store(proc, name_ep, ir_const_string(a, fields[i]->token.string)); + } + + irValue *v_count = ir_const_int(a, count); + + irValue *names = ir_emit_struct_ep(proc, tag, 1); + irValue *name_array_elem = ir_array_elem(proc, name_array); + ir_fill_slice(proc, names, name_array_elem, v_count, v_count); + + irValue *values = ir_emit_struct_ep(proc, tag, 2); + irValue *value_array_elem = ir_array_elem(proc, value_array); + ir_fill_slice(proc, values, value_array_elem, v_count, v_count); + } + } + break; case Type_Record: { switch (t->Record.kind) { case TypeRecord_Struct: { @@ -8132,55 +8181,6 @@ void ir_gen_tree(irGen *s) { ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count); ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count); } break; - case TypeRecord_Enum: - ir_emit_comment(proc, str_lit("TypeInfoEnum")); - tag = ir_emit_conv(proc, variant_ptr, t_type_info_enum_ptr); - { - GB_ASSERT(t->Record.enum_base_type != nullptr); - irValue *base = ir_type_info(proc, t->Record.enum_base_type); - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), base); - - if (t->Record.field_count > 0) { - Entity **fields = t->Record.fields; - isize count = t->Record.field_count; - 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); - - for (isize i = 0; i < count; i++) { - irValue *name_ep = ir_emit_array_epi(proc, name_array, i); - irValue *value_ep = ir_emit_array_epi(proc, value_array, i); - - ExactValue value = fields[i]->Constant.value; - - if (is_value_int) { - value_ep = ir_emit_conv(proc, value_ep, t_i128_ptr); - ir_emit_store(proc, value_ep, ir_value_constant(a, t_i128, value)); - } else { - GB_ASSERT(is_type_float(t->Record.enum_base_type)); - f64 f = value.value_float; - value_ep = ir_emit_conv(proc, value_ep, t_f64_ptr); - ir_emit_store(proc, value_ep, ir_const_f64(a, f)); - } - - ir_emit_store(proc, name_ep, ir_const_string(a, fields[i]->token.string)); - } - - irValue *v_count = ir_const_int(a, count); - - irValue *names = ir_emit_struct_ep(proc, tag, 1); - irValue *name_array_elem = ir_array_elem(proc, name_array); - ir_fill_slice(proc, names, name_array_elem, v_count, v_count); - - irValue *values = ir_emit_struct_ep(proc, tag, 2); - irValue *value_array_elem = ir_array_elem(proc, value_array); - ir_fill_slice(proc, values, value_array_elem, v_count, v_count); - } - } - break; } } break; case Type_Map: { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 878291ebf..2ffd23818 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -280,6 +280,11 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { ir_print_type(f, m, t_allocator); ir_fprintf(f, "}"); return; + + case Type_Enum: + ir_print_type(f, m, base_enum_type(t)); + return; + case Type_Record: { switch (t->Record.kind) { case TypeRecord_Struct: @@ -331,9 +336,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { i64 align_of_union = type_align_of(heap_allocator(), t); ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align_of_union, size_of_union); } return; - case TypeRecord_Enum: - ir_print_type(f, m, base_enum_type(t)); - return; } } break; diff --git a/src/types.cpp b/src/types.cpp index a43921d1f..5613d556f 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -74,7 +74,7 @@ enum TypeRecordKind { TypeRecord_Struct, TypeRecord_RawUnion, TypeRecord_Union, // Tagged - TypeRecord_Enum, + // TypeRecord_Enum, TypeRecord_Count, }; @@ -110,10 +110,10 @@ struct TypeRecord { 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; + // Type * enum_base_type; + // Entity * enum_count; + // Entity * enum_min_value; + // Entity * enum_max_value; }; #define TYPE_KINDS \ @@ -126,6 +126,17 @@ struct TypeRecord { TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \ TYPE_KIND(Slice, struct { Type *elem; }) \ TYPE_KIND(Record, TypeRecord) \ + TYPE_KIND(Enum, struct { \ + Entity **fields; \ + i32 field_count; \ + AstNode *node; \ + Scope * scope; \ + Entity * names; \ + Type * base_type; \ + Entity * count; \ + Entity * min_value; \ + Entity * max_value; \ + }) \ TYPE_KIND(Named, struct { \ String name; \ Type * base; \ @@ -423,9 +434,8 @@ Type *base_type(Type *t) { Type *base_enum_type(Type *t) { Type *bt = base_type(t); if (bt != nullptr && - bt->kind == Type_Record && - bt->Record.kind == TypeRecord_Enum) { - return bt->Record.enum_base_type; + bt->kind == Type_Enum) { + return bt->Enum.base_type; } return t; } @@ -443,12 +453,9 @@ Type *core_type(Type *t) { } t = t->Named.base; continue; - case Type_Record: - if (t->Record.kind == TypeRecord_Enum) { - t = t->Record.enum_base_type; - continue; - } - break; + case Type_Enum: + t = t->Enum.base_type; + continue; case Type_Atomic: t = t->Atomic.elem; continue; @@ -544,8 +551,7 @@ Type *make_type_raw_union(gbAllocator a) { } Type *make_type_enum(gbAllocator a) { - Type *t = alloc_type(a, Type_Record); - t->Record.kind = TypeRecord_Enum; + Type *t = alloc_type(a, Type_Enum); return t; } @@ -877,7 +883,7 @@ bool is_type_raw_union(Type *t) { } bool is_type_enum(Type *t) { t = base_type(t); - return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum); + return (t->kind == Type_Enum); } bool is_type_bit_field(Type *t) { t = base_type(t); @@ -989,13 +995,14 @@ bool is_type_polymorphic(Type *t) { #endif break; - case Type_Record: - if (t->Record.kind == TypeRecord_Enum) { - if (t->Record.enum_base_type != nullptr) { - return is_type_polymorphic(t->Record.enum_base_type); + case Type_Enum: + if (t->kind == Type_Enum) { + if (t->Enum.base_type != nullptr) { + return is_type_polymorphic(t->Enum.base_type); } return false; } + case Type_Record: for (isize i = 0; i < t->Record.field_count; i++) { if (is_type_polymorphic(t->Record.fields[i]->type)) { return true; @@ -1070,12 +1077,8 @@ bool is_type_comparable(Type *t) { return true; case Type_Pointer: return true; - case Type_Record: { - if (is_type_enum(t)) { - return is_type_comparable(core_type(t)); - } - return false; - } break; + case Type_Enum: + return is_type_comparable(core_type(t)); case Type_Array: return false; case Type_Vector: @@ -1133,6 +1136,10 @@ bool are_types_identical(Type *x, Type *y) { } break; + + case Type_Enum: + return x == y; // NOTE(bill): All enums are unique + case Type_Record: if (y->kind == Type_Record) { if (x->Record.kind == y->Record.kind) { @@ -1170,9 +1177,6 @@ bool are_types_identical(Type *x, Type *y) { return true; } break; - - case TypeRecord_Enum: - return x == y; // NOTE(bill): All enums are unique } } } @@ -1554,23 +1558,23 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n if (is_type_enum(type)) { // NOTE(bill): These may not have been added yet, so check in case - if (type->Record.enum_count != nullptr) { + if (type->Enum.count != nullptr) { if (field_name == "count") { - sel.entity = type->Record.enum_count; + sel.entity = type->Enum.count; return sel; } if (field_name == "min_value") { - sel.entity = type->Record.enum_min_value; + sel.entity = type->Enum.min_value; return sel; } if (field_name == "max_value") { - sel.entity = type->Record.enum_max_value; + sel.entity = type->Enum.max_value; return sel; } } - for (isize i = 0; i < type->Record.field_count; i++) { - Entity *f = type->Record.fields[i]; + for (isize i = 0; i < type->Enum.field_count; i++) { + Entity *f = type->Enum.fields[i]; GB_ASSERT(f->kind == Entity_Constant); String str = f->token.string; @@ -1821,10 +1825,11 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { GB_PANIC("TODO(bill): Fixed map alignment"); } break; + case Type_Enum: + return type_align_of_internal(allocator, t->Enum.base_type, path); + case Type_Record: { switch (t->Record.kind) { - case TypeRecord_Enum: - return type_align_of_internal(allocator, t->Record.enum_base_type, path); case TypeRecord_Struct: if (t->Record.custom_align > 0) { return gb_clamp(t->Record.custom_align, 1, build_context.max_align); @@ -2072,10 +2077,11 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return align_formula(size, align); } break; + case Type_Enum: + return type_size_of_internal(allocator, t->Enum.base_type, path); + case Type_Record: { switch (t->Record.kind) { - case TypeRecord_Enum: - return type_size_of_internal(allocator, t->Record.enum_base_type, path); case TypeRecord_Struct: { i64 count = t->Record.field_count; @@ -2317,6 +2323,25 @@ gbString write_type_to_string(gbString str, Type *type) { str = write_type_to_string(str, type->DynamicArray.elem); break; + case Type_Enum: + str = gb_string_appendc(str, "enum"); + if (type->Enum.base_type != nullptr) { + str = gb_string_appendc(str, " "); + str = write_type_to_string(str, type->Enum.base_type); + } + str = gb_string_appendc(str, " {"); + for (isize i = 0; i < type->Enum.field_count; i++) { + Entity *f = type->Enum.fields[i]; + GB_ASSERT(f->kind == Entity_Constant); + if (i > 0) { + str = gb_string_appendc(str, ", "); + } + str = gb_string_append_length(str, f->token.string.text, f->token.string.len); + // str = gb_string_appendc(str, " = "); + } + str = gb_string_appendc(str, "}"); + break; + case Type_Record: { switch (type->Record.kind) { case TypeRecord_Struct: @@ -2377,25 +2402,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"); - if (type->Record.enum_base_type != nullptr) { - str = gb_string_appendc(str, " "); - str = write_type_to_string(str, type->Record.enum_base_type); - } - str = gb_string_appendc(str, " {"); - for (isize i = 0; i < type->Record.field_count; i++) { - Entity *f = type->Record.fields[i]; - GB_ASSERT(f->kind == Entity_Constant); - if (i > 0) { - str = gb_string_appendc(str, ", "); - } - str = gb_string_append_length(str, f->token.string.text, f->token.string.len); - // str = gb_string_appendc(str, " = "); - } - str = gb_string_appendc(str, "}"); - break; } } break;