diff --git a/core/_preload.odin b/core/_preload.odin index 1d04a3be5..af0a9270d 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -44,15 +44,6 @@ TypeInfo :: struct #ordered { u8, u16, u32, u64, u128, uint, f32, f64, }; - Record :: struct #ordered { - types: []^TypeInfo; - names: []string; - offsets: []int; // offsets may not be used in tuples - usings: []bool; // usings may not be used in tuples - packed: bool; - ordered: bool; - custom_align: bool; - } // Variant Types Named :: struct #ordered {name: string; base: ^TypeInfo}; @@ -80,9 +71,20 @@ TypeInfo :: struct #ordered { DynamicArray :: struct #ordered {elem: ^TypeInfo; elem_size: int}; Slice :: struct #ordered {elem: ^TypeInfo; elem_size: int}; Vector :: struct #ordered {elem: ^TypeInfo; elem_size, count: int}; - Tuple :: Record; // Only really used for procedures - Struct :: Record; - RawUnion :: Record; + Tuple :: struct #ordered { // Only really used for procedures + types: []^TypeInfo; + names: []string; + }; + Struct :: struct #ordered { + types: []^TypeInfo; + names: []string; + offsets: []int; // offsets may not be used in tuples + usings: []bool; // usings may not be used in tuples + is_packed: bool; + is_ordered: bool; + is_raw_union: bool; + custom_align: bool; + }; Union :: struct #ordered { variants: []^TypeInfo; tag_offset: int; @@ -126,7 +128,6 @@ TypeInfo :: struct #ordered { Vector, Tuple, Struct, - RawUnion, Union, Enum, Map, diff --git a/core/fmt.odin b/core/fmt.odin index 59c624aaf..0c0ecf4f4 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -274,8 +274,9 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) { case Struct: write_string(buf, "struct "); - if info.packed do write_string(buf, "#packed "); - if info.ordered do write_string(buf, "#ordered "); + if info.is_packed do write_string(buf, "#packed "); + if info.is_ordered do write_string(buf, "#ordered "); + if info.is_raw_union do write_string(buf, "#raw_union "); if info.custom_align { write_string(buf, "#align "); write_int(buf, i64(ti.align), 10); @@ -298,16 +299,6 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) { } write_string(buf, "}"); - case RawUnion: - write_string(buf, "raw_union {"); - for name, i in info.names { - if i > 0 do write_string(buf, ", "); - write_string(buf, name); - write_string(buf, ": "); - write_type(buf, info.types[i]); - } - write_string(buf, "}"); - case Enum: write_string(buf, "enum "); write_type(buf, info.base); @@ -317,6 +308,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) { write_string(buf, name); } write_string(buf, "}"); + case BitField: write_string(buf, "bit_field "); if ti.align != 1 { @@ -864,6 +856,11 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { case Struct: + if info.is_raw_union { + write_string(fi.buf, "(raw_union)"); + return; + } + write_byte(fi.buf, '{'); defer write_byte(fi.buf, '}'); @@ -891,10 +888,6 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) { fmt_arg(fi, any{data, ti}, verb); } - - case RawUnion: - write_string(fi.buf, "(raw_union)"); - case Enum: fmt_enum(fi, v, verb); diff --git a/core/mem.odin b/core/mem.odin index 6ff23999e..91d70937a 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -245,8 +245,6 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int { return type_info.align; case Union: return type_info.align; - case RawUnion: - return type_info.align; case Enum: return align_of_type_info(info.base); case Map: @@ -305,8 +303,6 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int { return type_info.size; case Union: return type_info.size; - case RawUnion: - return type_info.size; case Enum: return size_of_type_info(info.base); case Map: diff --git a/core/types.odin b/core/types.odin index fde32fe63..30f48fb6e 100644 --- a/core/types.odin +++ b/core/types.odin @@ -83,19 +83,19 @@ is_tuple :: proc(info: ^TypeInfo) -> bool { } is_struct :: proc(info: ^TypeInfo) -> bool { if info == nil do return false; - _, ok := type_info_base(info).variant.(TypeInfo.Struct); - return ok; + s, ok := type_info_base(info).variant.(TypeInfo.Struct); + return ok && !s.is_raw_union; +} +is_raw_union :: proc(info: ^TypeInfo) -> bool { + if info == nil do return false; + s, ok := type_info_base(info).variant.(TypeInfo.Struct); + return ok && s.is_raw_union; } is_union :: proc(info: ^TypeInfo) -> bool { if info == nil do return false; _, ok := type_info_base(info).variant.(TypeInfo.Union); return ok; } -is_raw_union :: proc(info: ^TypeInfo) -> bool { - if info == nil do return false; - _, ok := type_info_base(info).variant.(TypeInfo.RawUnion); - return ok; -} is_enum :: proc(info: ^TypeInfo) -> bool { if info == nil do return false; _, ok := type_info_base(info).variant.(TypeInfo.Enum); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 38923e494..6e47a2554 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -686,7 +686,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod GB_ASSERT(type->kind == Type_Proc); if (type->Proc.param_count > 0) { TypeTuple *params = &type->Proc.params->Tuple; - for (isize i = 0; i < params->variable_count; i++) { + for_array(i, params->variables) { Entity *e = params->variables[i]; if (e->kind != Entity_Variable) { continue; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ef65409c1..9f30575a2 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -519,7 +519,7 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { } if (is_type_union(dst)) { - for (isize i = 0; i < dst->Union.variant_count; i++) { + for_array(i, dst->Union.variants) { Type *vt = dst->Union.variants[i]; if (are_types_identical(vt, s)) { return 1; @@ -851,8 +851,7 @@ void check_record_field_decl(Checker *c, AstNode *decl, Array *fields, } else { if (o.mode == Addressing_Value && o.type->kind == Type_Tuple) { // NOTE(bill): Tuples are not first class thus never named - isize count = o.type->Tuple.variable_count; - for (isize index = 0; index < count; index++) { + for_array(index, o.type->Tuple.variables) { Operand single = {Addressing_Value}; single.type = o.type->Tuple.variables[index]->type; single.expr = v; @@ -1200,9 +1199,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array 0) { Type *tuple = make_type_tuple(c->allocator); - tuple->Tuple.variables = entities.data; - tuple->Tuple.variable_count = entities.count; - + tuple->Tuple.variables = entities; polymorphic_params = tuple; } } @@ -1314,7 +1311,7 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n GB_ASSERT(is_type_union(union_type)); ast_node(ut, UnionType, node); - isize variant_count = ut->variants.count+1; + isize variant_count = ut->variants.count; gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); @@ -1323,9 +1320,8 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n Array variants = {}; array_init(&variants, c->allocator, variant_count); - array_add(&variants, t_invalid); - union_type->Union.scope = c->context.scope; + union_type->Union.scope = c->context.scope; for_array(i, ut->variants) { AstNode *node = ut->variants[i]; @@ -1356,8 +1352,7 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n } } - union_type->Union.variants = variants.data; - union_type->Union.variant_count = variants.count; + union_type->Union.variants = variants; } // void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) { @@ -1655,8 +1650,8 @@ bool check_type_specialization_to(Checker *c, Type *specialization, Type *type, TypeTuple *s_tuple = &s->Record.polymorphic_params->Tuple; TypeTuple *t_tuple = &t->Record.polymorphic_params->Tuple; - GB_ASSERT(t_tuple->variable_count == s_tuple->variable_count); - for (isize i = 0; i < s_tuple->variable_count; i++) { + GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); + for_array(i, s_tuple->variables) { Entity *s_e = s_tuple->variables[i]; Entity *t_e = t_tuple->variables[i]; Type *st = s_e->type; @@ -1748,10 +1743,10 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c if (source->kind == Type_Union) { TypeUnion *x = &poly->Union; TypeUnion *y = &source->Union; - if (x->variant_count != y->variant_count) { + if (x->variants.count != y->variants.count) { return false; } - for (isize i = 1; i < x->variant_count; i++) { + for_array(i, x->variants) { Type *a = x->variants[i]; Type *b = y->variants[i]; bool ok = is_polymorphic_type_assignable(c, a, b, false, modify_type); @@ -1887,8 +1882,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari bool is_variadic = false; bool is_c_vararg = false; - Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count); - isize variable_index = 0; + Array variables = {}; + array_init(&variables, c->allocator, variable_count); for_array(i, params) { AstNode *param = params[i]; if (param->kind != AstNode_Field) { @@ -2033,7 +2028,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari Entity *param = nullptr; if (is_type_param) { if (operands != nullptr) { - Operand o = (*operands)[variable_index]; + Operand o = (*operands)[variables.count]; if (o.mode == Addressing_Type) { type = o.type; } else { @@ -2067,7 +2062,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari param->TypeName.is_type_alias = true; } else { if (operands != nullptr && is_type_polymorphic_type) { - Operand op = (*operands)[variable_index]; + Operand op = (*operands)[variables.count]; type = determine_type_from_polymorphic(c, type, op); if (type == t_invalid) { success = false; @@ -2093,11 +2088,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari } add_entity(c, scope, name, param); - variables[variable_index++] = param; + array_add(&variables, param); } } - variable_count = variable_index; if (is_variadic) { GB_ASSERT(params.count > 0); @@ -2113,7 +2107,6 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari Type *tuple = make_type_tuple(c->allocator); tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = variable_count; if (success_) *success_ = success; if (is_variadic_) *is_variadic_ = is_variadic; @@ -2142,8 +2135,8 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { } } - Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count); - isize variable_index = 0; + Array variables = {}; + array_init(&variables, c->allocator, variable_count); for_array(i, results) { ast_node(field, Field, results[i]); AstNode *default_value = unparen_expr(field->default_value); @@ -2197,7 +2190,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); param->Variable.default_value = value; param->Variable.default_is_nil = default_is_nil; - variables[variable_index++] = param; + array_add(&variables, param); } else { for_array(j, field->names) { Token token = ast_node_token(results[i]); @@ -2216,17 +2209,17 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); param->Variable.default_value = value; param->Variable.default_is_nil = default_is_nil; - variables[variable_index++] = param; + array_add(&variables, param); } } } - for (isize i = 0; i < variable_index; i++) { + for_array(i, variables) { String x = variables[i]->token.string; if (x.len == 0 || is_blank_ident(x)) { continue; } - for (isize j = i+1; j < variable_index; j++) { + for (isize j = i+1; j < variables.count; j++) { String y = variables[j]->token.string; if (y.len == 0 || is_blank_ident(y)) { continue; @@ -2238,7 +2231,6 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { } tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = variable_index; return tuple; } @@ -2335,7 +2327,7 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) { Type *reduce_tuple_to_single_type(Type *original_type) { if (original_type != nullptr) { Type *t = core_type(original_type); - if (t->kind == Type_Tuple && t->Tuple.variable_count == 1) { + if (t->kind == Type_Tuple && t->Tuple.variables.count == 1) { return t->Tuple.variables[0]->type; } } @@ -2384,9 +2376,10 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) { if (new_type != original_type) { Type *tuple = make_type_tuple(a); - tuple->Tuple.variable_count = 1; - tuple->Tuple.variables = gb_alloc_array(a, Entity *, 1); - tuple->Tuple.variables[0] = make_entity_param(a, original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false); + Array variables = {}; + array_init(&variables, a, 1); + array_add(&variables, make_entity_param(a, original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false)); + tuple->Tuple.variables = variables; new_type = tuple; } @@ -2437,8 +2430,8 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array isize param_count = 0; isize result_count = 0; - if (params) param_count = params ->Tuple.variable_count; - if (results) result_count = results->Tuple.variable_count; + if (params) param_count = params ->Tuple.variables.count; + if (results) result_count = results->Tuple.variables.count; type->Proc.node = proc_type_node; type->Proc.scope = c->context.scope; @@ -2719,10 +2712,9 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { Type *make_optional_ok_type(gbAllocator a, Type *value) { bool typed = true; Type *t = make_type_tuple(a); - t->Tuple.variables = gb_alloc_array(a, Entity *, 2); - t->Tuple.variable_count = 2; - t->Tuple.variables[0] = make_entity_field(a, nullptr, blank_token, value, false, 0); - t->Tuple.variables[1] = make_entity_field(a, nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1); + array_init(&t->Tuple.variables, a, 2); + array_add (&t->Tuple.variables, make_entity_field(a, nullptr, blank_token, value, false, 0)); + array_add (&t->Tuple.variables, make_entity_field(a, nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1)); return t; } @@ -4304,11 +4296,11 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); - i32 count = t->Union.variant_count; + isize count = t->Union.variants.count; i64 *scores = gb_alloc_array(c->tmp_allocator, i64, count); i32 success_count = 0; i32 first_success_index = -1; - for (i32 i = 1; i < count; i++) { + for_array(i, t->Union.variants) { Type *vt = t->Union.variants[i]; i64 score = 0; if (check_is_assignable_to_with_score(c, operand, vt, &score)) { @@ -4358,14 +4350,14 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level } else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); - if (count > 1) { + if (count > 0) { gb_printf_err("`%s` is a union which only excepts the following types:\n", type_str); gb_printf_err("\t"); - for (i32 i = 1; i < count; i++) { + for (i32 i = 0; i < count; i++) { Type *v = t->Union.variants[i]; - if (i > 1 && count > 3) gb_printf_err(", "); + if (i > 0 && count > 2) gb_printf_err(", "); if (i == count-1) { - if (count == 3) { + if (count == 2) { gb_printf_err(" or "); } else { gb_printf_err("or "); @@ -4692,7 +4684,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h i64 max_count = 0; switch (type->kind) { case Type_Record: max_count = type->Record.field_count; break; - case Type_Tuple: max_count = type->Tuple.variable_count; break; + case Type_Tuple: max_count = type->Tuple.variables.count; break; } if (index >= max_count) { @@ -5591,11 +5583,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *tuple = make_type_tuple(a); i32 variable_count = type->Record.field_count; - tuple->Tuple.variables = gb_alloc_array(a, Entity *, variable_count); - tuple->Tuple.variable_count = variable_count; - + array_init_count(&tuple->Tuple.variables, a, variable_count); // TODO(bill): Should I copy each of the entities or is this good enough? - gb_memcopy_array(tuple->Tuple.variables, type->Record.fields_in_src_order, variable_count); + gb_memcopy_array(tuple->Tuple.variables.data, type->Record.fields_in_src_order, variable_count); operand->type = tuple; operand->mode = Addressing_Value; @@ -5957,7 +5947,7 @@ bool check_unpack_arguments(Checker *c, isize lhs_count, Array *operand } } else { TypeTuple *tuple = &o.type->Tuple; - for (isize j = 0; j < tuple->variable_count; j++) { + for_array(j, tuple->variables) { o.type = tuple->variables[j]->type; array_add(operands, o); } @@ -5988,7 +5978,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { if (pt->params != nullptr) { param_tuple = &pt->params->Tuple; - param_count = param_tuple->variable_count; + param_count = param_tuple->variables.count; if (variadic) { param_count--; } @@ -6069,7 +6059,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { TypeProc *pt = &final_proc_type->Proc; GB_ASSERT(pt->params != nullptr); - Entity **sig_params = pt->params->Tuple.variables; + auto sig_params = pt->params->Tuple.variables; isize operand_index = 0; isize max_operand_count = gb_min(param_count, operands.count); for (; operand_index < max_operand_count; operand_index++) { @@ -6564,8 +6554,7 @@ isize lookup_polymorphic_struct_parameter(TypeRecord *st, String parameter_name) if (!st->is_polymorphic) return -1; TypeTuple *params = &st->polymorphic_params->Tuple; - isize param_count = params->variable_count; - for (isize i = 0; i < param_count; i++) { + for_array(i, params->variables) { Entity *e = params->variables[i]; String name = e->token.string; if (is_blank_ident(name)) { @@ -6617,7 +6606,7 @@ CallArgumentError check_polymorphic_struct_type(Checker *c, Operand *operand, As CallArgumentError err = CallArgumentError_None; TypeTuple *tuple = &st->polymorphic_params->Tuple; - isize param_count = tuple->variable_count; + isize param_count = tuple->variables.count; Array ordered_operands = operands; if (named_fields) { @@ -6749,7 +6738,7 @@ CallArgumentError check_polymorphic_struct_type(Checker *c, Operand *operand, As Type *t = base_type(e->type); TypeTuple *tuple = &t->Record.polymorphic_params->Tuple; bool ok = true; - GB_ASSERT(param_count == tuple->variable_count); + GB_ASSERT(param_count == tuple->variables.count); for (isize j = 0; j < param_count; j++) { Entity *p = tuple->variables[j]; Operand o = ordered_operands[j]; @@ -6968,7 +6957,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { operand->mode = Addressing_NoValue; } else { GB_ASSERT(is_type_tuple(result_type)); - switch (result_type->Tuple.variable_count) { + switch (result_type->Tuple.variables.count) { case 0: operand->mode = Addressing_NoValue; break; @@ -7736,7 +7725,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (is_type_union(src)) { bool ok = false; - for (isize i = 1; i < bsrc->Union.variant_count; i++) { + for_array(i, bsrc->Union.variants) { Type *vt = bsrc->Union.variants[i]; if (are_types_identical(vt, dst)) { ok = true; @@ -8120,7 +8109,7 @@ void check_not_tuple(Checker *c, Operand *o) { if (o->mode == Addressing_Value) { // NOTE(bill): Tuples are not first class thus never named if (o->type->kind == Type_Tuple) { - isize count = o->type->Tuple.variable_count; + isize count = o->type->Tuple.variables.count; GB_ASSERT(count != 1); error(o->expr, "%td-valued tuple found where single value expected", count); @@ -8192,6 +8181,10 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_append_length(str, &bd->name[0], bd->name.len); case_end; + case_ast_node(ud, Undef, node); + str = gb_string_appendc(str, "---"); + case_end; + case_ast_node(pl, ProcLit, node); str = write_expr_to_string(str, pl->type); case_end; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 751e9759e..cf8fa2933 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -817,7 +817,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { TypeProc *pt = &proc_type->Proc; isize result_count = 0; if (pt->results) { - result_count = proc_type->Proc.results->Tuple.variable_count; + result_count = proc_type->Proc.results->Tuple.variables.count; } @@ -1474,7 +1474,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (match_type_kind == MatchType_Union) { GB_ASSERT(is_type_union(bt)); bool tag_type_found = false; - for (isize i = 0; i < bt->Union.variant_count; i++) { + for_array(i, bt->Union.variants) { Type *vt = bt->Union.variants[i]; if (are_types_identical(vt, y.type)) { tag_type_found = true; diff --git a/src/checker.cpp b/src/checker.cpp index 98e47c86a..26022b7f2 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1169,7 +1169,7 @@ void add_type_info_type(Checker *c, Type *t) { case Type_Union: add_type_info_type(c, t_int); - for (isize i = 0; i < bt->Union.variant_count; i++) { + for_array(i, bt->Union.variants) { add_type_info_type(c, bt->Union.variants[i]); } break; @@ -1188,7 +1188,7 @@ void add_type_info_type(Checker *c, Type *t) { } break; case Type_Tuple: - for (isize i = 0; i < bt->Tuple.variable_count; i++) { + for_array(i, bt->Tuple.variables) { Entity *var = bt->Tuple.variables[i]; add_type_info_type(c, var->type); } @@ -1341,12 +1341,8 @@ void init_preload(Checker *c) { GB_ASSERT(is_type_struct(type_info_entity->type)); TypeRecord *record = &base_type(type_info_entity->type)->Record; - Entity *type_info_record = find_sub_core_entity(record, str_lit("Record")); Entity *type_info_enum_value = find_sub_core_entity(record, str_lit("EnumValue")); - - t_type_info_record = type_info_record->type; - t_type_info_record_ptr = make_type_pointer(c->allocator, t_type_info_record); t_type_info_enum_value = type_info_enum_value->type; t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value); @@ -1357,30 +1353,29 @@ void init_preload(Checker *c) { GB_ASSERT(is_type_union(tiv_type)); TypeUnion *tiv = &tiv_type->Union; - if (tiv->variant_count != 22) { + if (tiv->variants.count != 20) { compiler_error("Invalid `TypeInfo` layout"); } - t_type_info_named = tiv->variants[ 1]; - t_type_info_integer = tiv->variants[ 2]; - t_type_info_rune = tiv->variants[ 3]; - t_type_info_float = tiv->variants[ 4]; - t_type_info_complex = tiv->variants[ 5]; - t_type_info_string = tiv->variants[ 6]; - t_type_info_boolean = tiv->variants[ 7]; - t_type_info_any = tiv->variants[ 8]; - t_type_info_pointer = tiv->variants[ 9]; - t_type_info_procedure = tiv->variants[10]; - t_type_info_array = tiv->variants[11]; - t_type_info_dynamic_array = tiv->variants[12]; - t_type_info_slice = tiv->variants[13]; - t_type_info_vector = tiv->variants[14]; - t_type_info_tuple = tiv->variants[15]; - t_type_info_struct = tiv->variants[16]; - t_type_info_raw_union = tiv->variants[17]; - t_type_info_union = tiv->variants[18]; - t_type_info_enum = tiv->variants[19]; - t_type_info_map = tiv->variants[20]; - t_type_info_bit_field = tiv->variants[21]; + t_type_info_named = tiv->variants[ 0]; + t_type_info_integer = tiv->variants[ 1]; + t_type_info_rune = tiv->variants[ 2]; + t_type_info_float = tiv->variants[ 3]; + t_type_info_complex = tiv->variants[ 4]; + t_type_info_string = tiv->variants[ 5]; + t_type_info_boolean = tiv->variants[ 6]; + t_type_info_any = tiv->variants[ 7]; + t_type_info_pointer = tiv->variants[ 8]; + t_type_info_procedure = tiv->variants[ 9]; + t_type_info_array = tiv->variants[10]; + t_type_info_dynamic_array = tiv->variants[11]; + t_type_info_slice = tiv->variants[12]; + t_type_info_vector = tiv->variants[13]; + t_type_info_tuple = tiv->variants[14]; + t_type_info_struct = tiv->variants[15]; + t_type_info_union = tiv->variants[16]; + t_type_info_enum = tiv->variants[17]; + t_type_info_map = tiv->variants[18]; + t_type_info_bit_field = tiv->variants[19]; t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named); t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer); @@ -1398,7 +1393,6 @@ void init_preload(Checker *c) { t_type_info_vector_ptr = make_type_pointer(c->allocator, t_type_info_vector); t_type_info_tuple_ptr = make_type_pointer(c->allocator, t_type_info_tuple); t_type_info_struct_ptr = make_type_pointer(c->allocator, t_type_info_struct); - t_type_info_raw_union_ptr = make_type_pointer(c->allocator, t_type_info_raw_union); t_type_info_union_ptr = make_type_pointer(c->allocator, t_type_info_union); t_type_info_enum_ptr = make_type_pointer(c->allocator, t_type_info_enum); t_type_info_map_ptr = make_type_pointer(c->allocator, t_type_info_map); diff --git a/src/ir.cpp b/src/ir.cpp index 61f8d8ffa..dc0bc9f59 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -617,7 +617,7 @@ Type *ir_instr_type(irInstr *instr) { case irInstr_Call: { Type *pt = base_type(instr->Call.type); if (pt != nullptr) { - if (pt->kind == Type_Tuple && pt->Tuple.variable_count == 1) { + if (pt->kind == Type_Tuple && pt->Tuple.variables.count == 1) { return pt->Tuple.variables[0]->type; } return pt; @@ -2382,8 +2382,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { GB_ASSERT(index == -1); return ir_emit_union_tag_ptr(proc, s); } else if (is_type_tuple(t)) { - GB_ASSERT(t->Tuple.variable_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); + GB_ASSERT(t->Tuple.variables.count > 0); result_type = make_type_pointer(a, t->Tuple.variables[index]->type); } else if (is_type_complex(t)) { Type *ft = base_complex_elem_type(t); @@ -2445,8 +2444,7 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { GB_ASSERT(index == -1); return ir_emit_union_tag_value(proc, s); } else if (is_type_tuple(t)) { - GB_ASSERT(t->Tuple.variable_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); + GB_ASSERT(t->Tuple.variables.count > 0); result_type = t->Tuple.variables[index]->type; } else if (is_type_complex(t)) { Type *ft = base_complex_elem_type(t); @@ -2960,7 +2958,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { } if (is_type_union(dst)) { - for (isize i = 1; i < dst->Union.variant_count; i++) { + for_array(i, dst->Union.variants) { Type *vt = dst->Union.variants[i]; if (are_types_identical(vt, src_type)) { ir_emit_comment(proc, str_lit("union - child to parent")); @@ -4861,7 +4859,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { AstNode *a = ce->args[i]; Type *at = base_type(type_of_expr(proc->module->info, a)); if (at->kind == Type_Tuple) { - arg_count += at->Tuple.variable_count; + arg_count += at->Tuple.variables.count; } else { arg_count++; } @@ -4882,7 +4880,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { irValue *a = ir_build_expr(proc, arg); Type *at = ir_type(a); if (at->kind == Type_Tuple) { - for (isize i = 0; i < at->Tuple.variable_count; i++) { + for_array(i, at->Tuple.variables) { Entity *e = at->Tuple.variables[i]; irValue *v = ir_emit_struct_ev(proc, a, i); args[arg_index++] = v; @@ -5129,7 +5127,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr); names_ptr = ir_emit_struct_ep(proc, enum_info, 3); } else if (type->kind == Type_Record) { - irValue *record_info = ir_emit_conv(proc, ti_ptr, t_type_info_record_ptr); + irValue *record_info = ir_emit_conv(proc, ti_ptr, t_type_info_struct_ptr); names_ptr = ir_emit_struct_ep(proc, record_info, 3); } return ir_addr(names_ptr); @@ -6266,7 +6264,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *init = ir_build_expr(proc, vd->values[i]); Type *t = ir_type(init); if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { Entity *e = t->Tuple.variables[i]; irValue *v = ir_emit_struct_ev(proc, init, i); array_add(&inits, v); @@ -6331,7 +6329,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { Type *t = ir_type(init); // TODO(bill): refactor for code reuse as this is repeated a bit if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { Entity *e = t->Tuple.variables[i]; irValue *v = ir_emit_struct_ev(proc, init, i); array_add(&inits, v); @@ -6463,7 +6461,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *res = ir_build_expr(proc, rs->results[res_index]); Type *t = ir_type(res); if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { Entity *e = t->Tuple.variables[i]; irValue *v = ir_emit_struct_ev(proc, res, i); array_add(&results, v); @@ -6934,7 +6932,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *variant_tag = nullptr; Type *ut = base_type(type_deref(parent_type)); GB_ASSERT(ut->kind == Type_Union); - for (isize variant_index = 1; variant_index < ut->Union.variant_count; variant_index++) { + for_array(variant_index, ut->Union.variants) { Type *vt = ut->Union.variants[variant_index]; if (are_types_identical(vt, bt)) { variant_tag = ir_type_info(proc, vt); @@ -7154,7 +7152,7 @@ void ir_begin_procedure_body(irProcedure *proc) { isize q_index = 0; TypeTuple *params = &proc->type->Proc.params->Tuple; - for (isize i = 0; i < params->variable_count; i++) { + for_array(i, params->variables) { ast_node(fl, FieldList, pt->params); GB_ASSERT(fl->list.count > 0); GB_ASSERT(fl->list[0]->kind == AstNode_Field); @@ -7340,13 +7338,13 @@ void ir_init_module(irModule *m, Checker *c) { switch (t->kind) { case Type_Union: - count += t->Union.variant_count; + count += t->Union.variants.count; break; case Type_Record: count += t->Record.field_count; break; case Type_Tuple: - count += t->Tuple.variable_count; + count += t->Tuple.variables.count; break; } } @@ -7718,11 +7716,8 @@ void ir_gen_tree(irGen *s) { Scope *proc_scope = gb_alloc_item(a, Scope); - proc_params->Tuple.variables = gb_alloc_array(a, Entity *, 3); - proc_params->Tuple.variable_count = 3; - - proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1); - proc_results->Tuple.variable_count = 1; + array_init_count(&proc_params->Tuple.variables, a, 3); + array_init_count(&proc_results->Tuple.variables, a, 1); proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false, false); proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, make_token_ident(str_lit("reason")), t_i32, false, false); @@ -8078,10 +8073,10 @@ void ir_gen_tree(irGen *s) { ir_emit_comment(proc, str_lit("TypeInfoTuple")); tag = ir_emit_conv(proc, variant_ptr, t_type_info_tuple_ptr); - irValue *memory_types = ir_type_info_member_types_offset(proc, t->Tuple.variable_count); - irValue *memory_names = ir_type_info_member_names_offset(proc, t->Tuple.variable_count); + irValue *memory_types = ir_type_info_member_types_offset(proc, t->Tuple.variables.count); + irValue *memory_names = ir_type_info_member_names_offset(proc, t->Tuple.variables.count); - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { // NOTE(bill): offset is not used for tuples Entity *f = t->Tuple.variables[i]; @@ -8095,7 +8090,7 @@ void ir_gen_tree(irGen *s) { } } - irValue *count = ir_const_int(a, t->Tuple.variable_count); + irValue *count = ir_const_int(a, t->Tuple.variables.count); 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; @@ -8152,12 +8147,12 @@ void ir_gen_tree(irGen *s) { irValue *variant_types = ir_emit_struct_ep(proc, tag, 0); irValue *tag_offset_ptr = ir_emit_struct_ep(proc, tag, 1); - isize variant_count = gb_max(0, t->Union.variant_count-1); + isize variant_count = gb_max(0, t->Union.variants.count); irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count); // NOTE(bill): Zeroth is nil so ignore it for (isize variant_index = 0; variant_index < variant_count; variant_index++) { - Type *vt = t->Union.variants[variant_index+1]; // Skip zeroth + Type *vt = t->Union.variants[variant_index]; irValue *tip = ir_get_type_info_ptr(proc, vt); irValue *index = ir_const_int(a, variant_index); @@ -8175,77 +8170,57 @@ void ir_gen_tree(irGen *s) { } break; case Type_Record: { - if (t->Record.is_raw_union) { - ir_emit_comment(proc, str_lit("TypeInfoRawUnion")); - tag = ir_emit_conv(proc, variant_ptr, t_type_info_raw_union_ptr); + ir_emit_comment(proc, str_lit("TypeInfoStruct")); + tag = ir_emit_conv(proc, variant_ptr, t_type_info_struct_ptr); - irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); - irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count); - irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, t->Record.field_count); - - for (isize i = 0; i < t->Record.field_count; i++) { - Entity *f = t->Record.fields[i]; - irValue *index = ir_const_int(a, i); - irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index); - // NOTE(bill): Offsets are always 0 - - ir_emit_store(proc, type_info, ir_type_info(proc, f->type)); - if (f->token.string.len > 0) { - irValue *name = ir_emit_ptr_offset(proc, memory_names, index); - ir_emit_store(proc, name, ir_const_string(a, f->token.string)); - } - } - - irValue *count = ir_const_int(a, t->Record.field_count); - 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); - ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count); - } else { - ir_emit_comment(proc, str_lit("TypeInfoStruct")); - tag = ir_emit_conv(proc, variant_ptr, t_type_info_struct_ptr); - - { - irValue *packed = ir_const_bool(a, t->Record.is_packed); - irValue *ordered = ir_const_bool(a, t->Record.is_ordered); - irValue *custom_align = ir_const_bool(a, t->Record.custom_align != 0); - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), packed); - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 5), ordered); - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 6), custom_align); - } - - irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); - irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count); - irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, t->Record.field_count); - irValue *memory_usings = ir_type_info_member_usings_offset(proc, t->Record.field_count); - - type_set_offsets(a, t); // NOTE(bill): Just incase the offsets have not been set yet - for (isize source_index = 0; source_index < t->Record.field_count; source_index++) { - // TODO(bill): Order fields in source order not layout order - Entity *f = t->Record.fields_in_src_order[source_index]; - irValue *tip = ir_get_type_info_ptr(proc, f->type); - i64 foffset = t->Record.offsets[f->Variable.field_index]; - GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); - - irValue *index = ir_const_int(a, source_index); - irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index); - irValue *offset = ir_emit_ptr_offset(proc, memory_offsets, index); - irValue *is_using = ir_emit_ptr_offset(proc, memory_usings, index); - - ir_emit_store(proc, type_info, ir_type_info(proc, f->type)); - if (f->token.string.len > 0) { - irValue *name = ir_emit_ptr_offset(proc, memory_names, index); - ir_emit_store(proc, name, ir_const_string(a, f->token.string)); - } - ir_emit_store(proc, offset, ir_const_int(a, foffset)); - ir_emit_store(proc, is_using, ir_const_bool(a, (f->flags&EntityFlag_Using) != 0)); - } - - irValue *count = ir_const_int(a, t->Record.field_count); - 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); - ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count); - ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings, count, count); + { + irValue *is_packed = ir_const_bool(a, t->Record.is_packed); + irValue *is_ordered = ir_const_bool(a, t->Record.is_ordered); + irValue *is_raw_union = ir_const_bool(a, t->Record.is_raw_union); + irValue *is_custom_align = ir_const_bool(a, t->Record.custom_align != 0); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), is_packed); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 5), is_ordered); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 6), is_raw_union); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 7), is_custom_align); } + + i32 count = t->Record.field_count; + + irValue *memory_types = ir_type_info_member_types_offset (proc, count); + irValue *memory_names = ir_type_info_member_names_offset (proc, count); + irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, count); + irValue *memory_usings = ir_type_info_member_usings_offset (proc, count); + + type_set_offsets(a, t); // NOTE(bill): Just incase the offsets have not been set yet + for (isize source_index = 0; source_index < count; source_index++) { + // TODO(bill): Order fields in source order not layout order + Entity *f = t->Record.fields_in_src_order[source_index]; + irValue *tip = ir_get_type_info_ptr(proc, f->type); + i64 foffset = 0; + if (!t->Record.is_raw_union) { + foffset = t->Record.offsets[f->Variable.field_index]; + } + GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); + + irValue *index = ir_const_int(a, source_index); + irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index); + irValue *offset = ir_emit_ptr_offset(proc, memory_offsets, index); + irValue *is_using = ir_emit_ptr_offset(proc, memory_usings, index); + + ir_emit_store(proc, type_info, ir_type_info(proc, f->type)); + if (f->token.string.len > 0) { + irValue *name = ir_emit_ptr_offset(proc, memory_names, index); + ir_emit_store(proc, name, ir_const_string(a, f->token.string)); + } + ir_emit_store(proc, offset, ir_const_int(a, foffset)); + ir_emit_store(proc, is_using, ir_const_bool(a, (f->flags&EntityFlag_Using) != 0)); + } + + irValue *cv = ir_const_int(a, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, cv, cv); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, cv, cv); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, cv, cv); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings, cv, cv); } break; case Type_Map: { ir_emit_comment(proc, str_lit("TypeInfoMap")); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index deb5b9e34..1b65112f1 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -155,12 +155,11 @@ void ir_print_proc_results(irFileBuffer *f, irModule *m, Type *t) { Type *rt = t->Proc.abi_compat_result_type; if (!is_type_tuple(rt)) { ir_print_type(f, m, rt); - } else if (rt->Tuple.variable_count == 1) { + } else if (rt->Tuple.variables.count == 1) { ir_print_type(f, m, rt->Tuple.variables[0]->type); } else { - isize count = rt->Tuple.variable_count; ir_fprintf(f, "{"); - for (isize i = 0; i < count; i++) { + for_array(i, rt->Tuple.variables) { Entity *e = rt->Tuple.variables[i]; if (i > 0) { ir_fprintf(f, ", "); @@ -344,15 +343,13 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { } return; case Type_Tuple: - if (t->Tuple.variable_count == 1) { + if (t->Tuple.variables.count == 1) { ir_print_type(f, m, t->Tuple.variables[0]->type); } else { ir_fprintf(f, "{"); isize index = 0; - for (isize i = 0; i < t->Tuple.variable_count; i++) { - if (index > 0) { - ir_fprintf(f, ", "); - } + for_array(i, t->Tuple.variables) { + if (index > 0) ir_fprintf(f, ", "); Entity *e = t->Tuple.variables[i]; if (e->kind == Entity_Variable) { ir_print_type(f, m, e->type); @@ -1352,7 +1349,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { TypeTuple *params = &proc_type->Proc.params->Tuple; if (proc_type->Proc.c_vararg) { isize i = 0; - for (; i < params->variable_count-1; i++) { + for (; i < params->variables.count-1; i++) { Entity *e = params->variables[i]; GB_ASSERT(e != nullptr); if (e->kind != Entity_Variable) continue; @@ -1380,9 +1377,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { param_index++; } } else { - GB_ASSERT(call->arg_count == params->variable_count); - isize param_count = params->variable_count; - for (isize i = 0; i < param_count; i++) { + GB_ASSERT(call->arg_count == params->variables.count); + for_array(i, params->variables) { Entity *e = params->variables[i]; GB_ASSERT(e != nullptr); if (e->kind != Entity_Variable) continue; @@ -1645,7 +1641,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { if (e->kind != Entity_Variable) continue; if (param_index > 0) ir_fprintf(f, ", "); - if (i+1 == params->variable_count && proc_type->c_vararg) { + if (i+1 == params->variables.count && proc_type->c_vararg) { ir_fprintf(f, " ..."); } else { ir_print_type(f, m, abi_type); diff --git a/src/parser.cpp b/src/parser.cpp index 48169f4d6..090d3a46e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2291,34 +2291,37 @@ AstNode *parse_operand(AstFile *f, bool lhs) { Token token = expect_token(f, Token_proc); String link_name = {}; AstNode *type = parse_proc_type(f, token, &link_name); + + if (f->allow_type && f->expr_level < 0) { + return type; + } + u64 tags = type->ProcType.tags; if (allow_token(f, Token_Undef)) { return ast_proc_lit(f, type, nullptr, tags, link_name); - } else if (!f->allow_type || f->expr_level >= 0) { - if (f->curr_token.kind == Token_OpenBrace) { - if ((tags & ProcTag_foreign) != 0) { - syntax_error(token, "A procedure tagged as `#foreign` cannot have a body"); - } - AstNode *curr_proc = f->curr_proc; - AstNode *body = nullptr; - f->curr_proc = type; - body = parse_body(f); - f->curr_proc = curr_proc; - - return ast_proc_lit(f, type, body, tags, link_name); - } else if (allow_token(f, Token_do)) { - if ((tags & ProcTag_foreign) != 0) { - syntax_error(token, "A procedure tagged as `#foreign` cannot have a body"); - } - AstNode *curr_proc = f->curr_proc; - AstNode *body = nullptr; - f->curr_proc = type; - body = convert_stmt_to_body(f, parse_stmt(f)); - f->curr_proc = curr_proc; - - return ast_proc_lit(f, type, body, tags, link_name); + } else if (f->curr_token.kind == Token_OpenBrace) { + if ((tags & ProcTag_foreign) != 0) { + syntax_error(token, "A procedure tagged as `#foreign` cannot have a body"); } + AstNode *curr_proc = f->curr_proc; + AstNode *body = nullptr; + f->curr_proc = type; + body = parse_body(f); + f->curr_proc = curr_proc; + + return ast_proc_lit(f, type, body, tags, link_name); + } else if (allow_token(f, Token_do)) { + if ((tags & ProcTag_foreign) != 0) { + syntax_error(token, "A procedure tagged as `#foreign` cannot have a body"); + } + AstNode *curr_proc = f->curr_proc; + AstNode *body = nullptr; + f->curr_proc = type; + body = convert_stmt_to_body(f, parse_stmt(f)); + f->curr_proc = curr_proc; + + return ast_proc_lit(f, type, body, tags, link_name); } if ((tags & ProcTag_foreign) != 0) { diff --git a/src/ssa.cpp b/src/ssa.cpp index a1b5c3827..ef9b03dce 100644 --- a/src/ssa.cpp +++ b/src/ssa.cpp @@ -639,10 +639,10 @@ bool can_ssa_type(Type *t) { case Type_Map: return false; case Type_Tuple: - if (t->Tuple.variable_count > SSA_MAX_STRUCT_FIELD_COUNT) { + if (t->Tuple.variables.count > SSA_MAX_STRUCT_FIELD_COUNT) { return false; } - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { if (!can_ssa_type(t->Tuple.variables[i]->type)) { return false; } @@ -813,14 +813,9 @@ ssaValue *ssa_emit_ptr_index(ssaProc *p, ssaValue *s, i64 index) { GB_ASSERT(t->Record.field_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); result_type = make_type_pointer(a, t->Record.fields[index]->type); - } else if (is_type_union(t)) { - type_set_offsets(a, t); - GB_ASSERT(t->Record.field_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); - result_type = make_type_pointer(a, t->Record.fields[index]->type); } else if (is_type_tuple(t)) { - GB_ASSERT(t->Tuple.variable_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); + GB_ASSERT(t->Tuple.variables.count > 0); + GB_ASSERT(gb_is_between(index, 0, t->Tuple.variables.count-1)); result_type = make_type_pointer(a, t->Tuple.variables[index]->type); } else if (is_type_slice(t)) { switch (index) { @@ -882,8 +877,7 @@ ssaValue *ssa_emit_value_index(ssaProc *p, ssaValue *s, i64 index) { GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); result_type = t->Record.fields[index]->type; } else if (is_type_tuple(t)) { - GB_ASSERT(t->Tuple.variable_count > 0); - GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); + GB_ASSERT(t->Tuple.variables.count > 0); result_type = t->Tuple.variables[index]->type; } else if (is_type_slice(t)) { switch (index) { @@ -2015,7 +2009,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) { Type *t = base_type(init->type); // TODO(bill): refactor for code reuse as this is repeated a bit if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { Entity *e = t->Tuple.variables[i]; ssaValue *v = ssa_emit_value_index(p, init, i); array_add(&inits, v); diff --git a/src/types.cpp b/src/types.cpp index 29a06528d..010d8aec2 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -119,8 +119,7 @@ struct TypeRecord { Entity * max_value; \ }) \ TYPE_KIND(Union, struct { \ - Type ** variants; \ - i32 variant_count; \ + Array variants; \ AstNode *node; \ Scope * scope; \ Entity * union__type_info; \ @@ -133,8 +132,7 @@ struct TypeRecord { Entity *type_name; /* Entity_TypeName */ \ }) \ TYPE_KIND(Tuple, struct { \ - Entity **variables; /* Entity_Variable */ \ - i32 variable_count; \ + Array variables; /* Entity_Variable */ \ bool are_offsets_set; \ i64 * offsets; \ }) \ @@ -330,10 +328,8 @@ gb_global Type *t_string_slice = nullptr; // Type generated for the "preload" file gb_global Type *t_type_info = nullptr; -gb_global Type *t_type_info_record = nullptr; gb_global Type *t_type_info_enum_value = nullptr; gb_global Type *t_type_info_ptr = nullptr; -gb_global Type *t_type_info_record_ptr = nullptr; gb_global Type *t_type_info_enum_value_ptr = nullptr; gb_global Type *t_type_info_named = nullptr; @@ -352,7 +348,6 @@ gb_global Type *t_type_info_slice = nullptr; gb_global Type *t_type_info_vector = nullptr; gb_global Type *t_type_info_tuple = nullptr; gb_global Type *t_type_info_struct = nullptr; -gb_global Type *t_type_info_raw_union = nullptr; gb_global Type *t_type_info_union = nullptr; gb_global Type *t_type_info_enum = nullptr; gb_global Type *t_type_info_map = nullptr; @@ -375,7 +370,6 @@ gb_global Type *t_type_info_slice_ptr = nullptr; gb_global Type *t_type_info_vector_ptr = nullptr; gb_global Type *t_type_info_tuple_ptr = nullptr; gb_global Type *t_type_info_struct_ptr = nullptr; -gb_global Type *t_type_info_raw_union_ptr = nullptr; gb_global Type *t_type_info_union_ptr = nullptr; gb_global Type *t_type_info_enum_ptr = nullptr; gb_global Type *t_type_info_map_ptr = nullptr; @@ -951,7 +945,7 @@ bool is_type_polymorphic(Type *t) { return is_type_polymorphic(t->Slice.elem); case Type_Tuple: - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { if (is_type_polymorphic(t->Tuple.variables[i]->type)) { return true; } @@ -983,7 +977,7 @@ bool is_type_polymorphic(Type *t) { } break; case Type_Union: - for (isize i = 1; i < t->Union.variant_count; i++) { + for_array(i, t->Union.variants) { if (is_type_polymorphic(t->Union.variants[i])) { return true; } @@ -1125,10 +1119,10 @@ bool are_types_identical(Type *x, Type *y) { case Type_Union: if (y->kind == Type_Union) { - if (x->Union.variant_count == y->Union.variant_count && + if (x->Union.variants.count == y->Union.variants.count && x->Union.custom_align == y->Union.custom_align) { // NOTE(bill): zeroth variant is nullptr - for (isize i = 1; i < x->Union.variant_count; i++) { + for_array(i, x->Union.variants) { if (!are_types_identical(x->Union.variants[i], y->Union.variants[i])) { return false; } @@ -1180,8 +1174,8 @@ bool are_types_identical(Type *x, Type *y) { case Type_Tuple: if (y->kind == Type_Tuple) { - if (x->Tuple.variable_count == y->Tuple.variable_count) { - for (isize i = 0; i < x->Tuple.variable_count; i++) { + if (x->Tuple.variables.count == y->Tuple.variables.count) { + for_array(i, x->Tuple.variables) { Entity *xe = x->Tuple.variables[i]; Entity *ye = y->Tuple.variables[i]; if (xe->kind != ye->kind || !are_types_identical(xe->type, ye->type)) { @@ -1299,7 +1293,7 @@ bool is_type_cte_safe(Type *type) { } case Type_Tuple: { - for (isize i = 0; i < type->Tuple.variable_count; i++) { + for_array(i, type->Tuple.variables) { Entity *v = type->Tuple.variables[i]; if (!is_type_cte_safe(v->type)) { return false; @@ -1411,9 +1405,9 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { i64 max_count = 0; switch (type->kind) { - case Type_Record: max_count = type->Record.field_count; break; - case Type_Tuple: max_count = type->Tuple.variable_count; break; - case Type_BitField: max_count = type->BitField.field_count; break; + case Type_Record: max_count = type->Record.field_count; break; + case Type_Tuple: max_count = type->Tuple.variables.count; break; + case Type_BitField: max_count = type->BitField.field_count; break; } if (index >= max_count) { @@ -1813,7 +1807,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Tuple: { i64 max = 1; - for (isize i = 0; i < t->Tuple.variable_count; i++) { + for_array(i, t->Tuple.variables) { i64 align = type_align_of_internal(allocator, t->Tuple.variables[i]->type, path); if (max < align) { max = align; @@ -1834,8 +1828,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Union: { i64 max = build_context.word_size; - // NOTE(bill): field zero is null - for (isize i = 1; i < t->Union.variant_count; i++) { + for_array(i, t->Union.variants) { Type *variant = t->Union.variants[i]; type_path_push(path, variant); if (path->failure) { @@ -1944,7 +1937,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) { } else if (is_type_tuple(t)) { if (!t->Tuple.are_offsets_set) { t->Record.are_offsets_being_processed = true; - t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, t->Tuple.variable_count, false, false); + t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables.data, t->Tuple.variables.count, false, false); t->Tuple.are_offsets_set = true; return true; } @@ -2054,7 +2047,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Tuple: { i64 count, align, size; - count = t->Tuple.variable_count; + count = t->Tuple.variables.count; if (count == 0) { return 0; } @@ -2075,10 +2068,8 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { i64 max = 0; i64 field_size = 0; - isize variant_count = t->Union.variant_count; - - for (isize i = 1; i < variant_count; i++) { + for_array(i, t->Union.variants) { Type *variant_type = t->Union.variants[i]; i64 size = type_size_of_internal(allocator, variant_type, path); if (max < size) { @@ -2158,7 +2149,7 @@ i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) { } } else if (t->kind == Type_Tuple) { type_set_offsets(allocator, t); - if (gb_is_between(index, 0, t->Tuple.variable_count-1)) { + if (gb_is_between(index, 0, t->Tuple.variables.count-1)) { return t->Tuple.offsets[index]; } } else if (t->kind == Type_Basic) { @@ -2309,9 +2300,9 @@ gbString write_type_to_string(gbString str, Type *type) { case Type_Union: str = gb_string_appendc(str, "union{"); - for (isize i = 1; i < type->Union.variant_count; i++) { + for_array(i, type->Union.variants) { Type *t = type->Union.variants[i]; - if (i > 1) str = gb_string_appendc(str, ", "); + if (i > 0) str = gb_string_appendc(str, ", "); str = write_type_to_string(str, t); } str = gb_string_appendc(str, "}"); @@ -2374,8 +2365,8 @@ gbString write_type_to_string(gbString str, Type *type) { break; case Type_Tuple: - if (type->Tuple.variable_count > 0) { - for (isize i = 0; i < type->Tuple.variable_count; i++) { + if (type->Tuple.variables.count > 0) { + for_array(i, type->Tuple.variables) { Entity *var = type->Tuple.variables[i]; if (var != nullptr) { if (i > 0) {