From 9491c13a5c967ff0fa6d5ce3c330dcbf13888d6c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Jun 2021 11:09:41 +0100 Subject: [PATCH] Fix #1011 by unifying the logic --- src/check_type.cpp | 317 ++++++++++----------------------------------- src/checker.hpp | 1 + 2 files changed, 69 insertions(+), 249 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 0252bc989..c1f0298c9 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2175,10 +2175,13 @@ void check_map_type(CheckerContext *ctx, Type *type, Ast *node) { // error(node, "'map' types are not yet implemented"); } -Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem, i64 count, Type *generic_type) { + +Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem, i64 count, Type *generic_type, StructSoaKind soa_kind) { Type *bt_elem = base_type(elem); - if (!is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) { + bool is_polymorphic = is_type_polymorphic(elem); + + if ((!is_polymorphic || soa_kind == StructSoa_Fixed) && !is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) { gbString str = type_to_string(elem); error(elem_expr, "Invalid type for an #soa array, expected a struct or array of length 4 or below, got '%s'", str); gb_string_free(str); @@ -2188,13 +2191,36 @@ Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_ Type *soa_struct = nullptr; Scope *scope = nullptr; - if (is_type_array(elem)) { - Type *old_array = base_type(elem); + isize field_count = 0; + i32 extra_field_count = 0; + switch (soa_kind) { + case StructSoa_Fixed: extra_field_count = 0; break; + case StructSoa_Slice: extra_field_count = 1; break; + case StructSoa_Dynamic: extra_field_count = 3; break; + } + if (is_polymorphic && soa_kind != StructSoa_Fixed) { + field_count = 0; + soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), old_array->Array.count); - soa_struct->Struct.tags = array_make(heap_allocator(), old_array->Array.count); + soa_struct->Struct.fields = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.tags = array_make(heap_allocator(), field_count+extra_field_count); soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Fixed; + soa_struct->Struct.soa_kind = soa_kind; + soa_struct->Struct.soa_elem = elem; + soa_struct->Struct.soa_count = 0; + soa_struct->Struct.is_polymorphic = true; + + scope = create_scope(ctx->scope); + soa_struct->Struct.scope = scope; + } else if (is_type_array(elem)) { + Type *old_array = base_type(elem); + field_count = old_array->Array.count; + + soa_struct = alloc_type_struct(); + soa_struct->Struct.fields = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.tags = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.node = array_typ_expr; + soa_struct->Struct.soa_kind = soa_kind; soa_struct->Struct.soa_elem = elem; soa_struct->Struct.soa_count = count; @@ -2223,11 +2249,14 @@ Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_ GB_ASSERT(is_type_struct(elem)); Type *old_struct = base_type(elem); + field_count = old_struct->Struct.fields.count; + GB_ASSERT(old_struct->Struct.tags.count == field_count); + soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), old_struct->Struct.fields.count); - soa_struct->Struct.tags = array_make(heap_allocator(), old_struct->Struct.tags.count); + soa_struct->Struct.fields = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.tags = array_make(heap_allocator(), field_count+extra_field_count); soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Fixed; + soa_struct->Struct.soa_kind = soa_kind; soa_struct->Struct.soa_elem = elem; soa_struct->Struct.soa_count = count; @@ -2250,6 +2279,28 @@ Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_ } } + if (soa_kind != StructSoa_Fixed) { + Entity *len_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+0); + soa_struct->Struct.fields[field_count+0] = len_field; + add_entity(ctx->checker, scope, nullptr, len_field); + add_entity_use(ctx, nullptr, len_field); + + if (soa_kind == StructSoa_Dynamic) { + Entity *cap_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count+1); + soa_struct->Struct.fields[field_count+1] = cap_field; + add_entity(ctx->checker, scope, nullptr, cap_field); + add_entity_use(ctx, nullptr, cap_field); + + Token token = {}; + token.string = str_lit("allocator"); + init_mem_allocator(ctx->checker); + Entity *allocator_field = alloc_entity_field(scope, token, t_allocator, false, cast(i32)field_count+2); + soa_struct->Struct.fields[field_count+2] = allocator_field; + add_entity(ctx->checker, scope, nullptr, allocator_field); + add_entity_use(ctx, nullptr, allocator_field); + } + } + Token token = {}; token.string = str_lit("Base_Type"); Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); @@ -2260,252 +2311,20 @@ Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_ return soa_struct; } + +Type *make_soa_struct_fixed(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem, i64 count, Type *generic_type) { + return make_soa_struct_internal(ctx, array_typ_expr, elem_expr, elem, count, generic_type, StructSoa_Fixed); +} + Type *make_soa_struct_slice(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem) { - Type *bt_elem = base_type(elem); - - - bool is_polymorphic = is_type_polymorphic(elem); - - if (!is_polymorphic && !is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) { - GB_ASSERT(elem_expr != nullptr); - - gbString str = type_to_string(elem); - error(elem_expr, "Invalid type for an #soa array, expected a struct or array of length 4 or below, got '%s'", str); - gb_string_free(str); - return alloc_type_slice(elem); - } - - Type *soa_struct = nullptr; - Scope *scope = nullptr; - - isize field_count = 0; - - if (is_polymorphic) { - field_count = 0; - - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+1); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+1); - soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Slice; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = 0; - soa_struct->Struct.is_polymorphic = true; - - scope = create_scope(ctx->scope); - soa_struct->Struct.scope = scope; - } else if (is_type_array(elem)) { - Type *old_array = base_type(elem); - field_count = old_array->Array.count; - - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+1); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+1); - soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Slice; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = 0; - - scope = create_scope(ctx->scope); - soa_struct->Struct.scope = scope; - - String params_xyzw[4] = { - str_lit("x"), - str_lit("y"), - str_lit("z"), - str_lit("w") - }; - - for (i64 i = 0; i < field_count; i++) { - Type *array_type = alloc_type_pointer(old_array->Array.elem); - Token token = {}; - token.string = params_xyzw[i]; - - Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i); - new_field->flags |= EntityFlag_SoaPtrField; - soa_struct->Struct.fields[i] = new_field; - add_entity(ctx->checker, scope, nullptr, new_field); - add_entity_use(ctx, nullptr, new_field); - } - - } else { - GB_ASSERT(is_type_struct(elem)); - - Type *old_struct = base_type(elem); - field_count = old_struct->Struct.fields.count; - - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+1); - soa_struct->Struct.tags = array_make(heap_allocator(), old_struct->Struct.tags.count+1); - soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Slice; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = 0; - - scope = create_scope(old_struct->Struct.scope->parent); - soa_struct->Struct.scope = scope; - - for_array(i, old_struct->Struct.fields) { - Entity *old_field = old_struct->Struct.fields[i]; - if (old_field->kind == Entity_Variable) { - Type *array_type = alloc_type_pointer(old_field->type); - Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index); - new_field->flags |= EntityFlag_SoaPtrField; - soa_struct->Struct.fields[i] = new_field; - add_entity(ctx->checker, scope, nullptr, new_field); - add_entity_use(ctx, nullptr, new_field); - } else { - soa_struct->Struct.fields[i] = old_field; - } - - soa_struct->Struct.tags[i] = old_struct->Struct.tags[i]; - } - - } - Entity *len_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count); - soa_struct->Struct.fields[field_count] = len_field; - add_entity(ctx->checker, scope, nullptr, len_field); - add_entity_use(ctx, nullptr, len_field); - - Token token = {}; - token.string = str_lit("Base_Type"); - Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); - add_entity(ctx->checker, scope, nullptr, base_type_entity); - - add_type_info_type(ctx, soa_struct); - - return soa_struct; + return make_soa_struct_internal(ctx, array_typ_expr, elem_expr, elem, -1, nullptr, StructSoa_Slice); } Type *make_soa_struct_dynamic_array(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem) { - Type *bt_elem = base_type(elem); - - bool is_polymorphic = is_type_polymorphic(elem); - - if (!is_polymorphic && !is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) { - GB_ASSERT(elem_expr != nullptr); - - gbString str = type_to_string(elem); - error(elem_expr, "Invalid type for an #soa array, expected a struct or array of length 4 or below, got '%s'", str); - gb_string_free(str); - return alloc_type_dynamic_array(elem); - } - - Type *soa_struct = nullptr; - Scope *scope = nullptr; - - isize field_count = 0; - - if (is_polymorphic) { - field_count = 0; - - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+3); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+3); - soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Dynamic; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = 0; - soa_struct->Struct.is_polymorphic = true; - - scope = create_scope(ctx->scope); - soa_struct->Struct.scope = scope; - } else if (is_type_array(elem)) { - Type *old_array = base_type(elem); - field_count = old_array->Array.count; - - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+3); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+3); - soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Dynamic; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = 0; - - scope = create_scope(ctx->scope); - soa_struct->Struct.scope = scope; - - String params_xyzw[4] = { - str_lit("x"), - str_lit("y"), - str_lit("z"), - str_lit("w") - }; - - for (i64 i = 0; i < field_count; i++) { - Type *array_type = alloc_type_pointer(old_array->Array.elem); - Token token = {}; - token.string = params_xyzw[i]; - - Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i); - new_field->flags |= EntityFlag_SoaPtrField; - soa_struct->Struct.fields[i] = new_field; - add_entity(ctx->checker, scope, nullptr, new_field); - add_entity_use(ctx, nullptr, new_field); - } - } else { - GB_ASSERT(is_type_struct(elem)); - - Type *old_struct = base_type(elem); - field_count = old_struct->Struct.fields.count; - - soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+3); - soa_struct->Struct.tags = array_make(heap_allocator(), old_struct->Struct.tags.count+3); - soa_struct->Struct.node = array_typ_expr; - soa_struct->Struct.soa_kind = StructSoa_Dynamic; - soa_struct->Struct.soa_elem = elem; - soa_struct->Struct.soa_count = 0; - - scope = create_scope(old_struct->Struct.scope->parent); - soa_struct->Struct.scope = scope; - - for_array(i, old_struct->Struct.fields) { - Entity *old_field = old_struct->Struct.fields[i]; - if (old_field->kind == Entity_Variable) { - Type *array_type = alloc_type_pointer(old_field->type); - Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index); - new_field->flags |= EntityFlag_SoaPtrField; - soa_struct->Struct.fields[i] = new_field; - add_entity(ctx->checker, scope, nullptr, new_field); - add_entity_use(ctx, nullptr, new_field); - } else { - soa_struct->Struct.fields[i] = old_field; - } - - soa_struct->Struct.tags[i] = old_struct->Struct.tags[i]; - } - } - - Entity *len_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count); - soa_struct->Struct.fields[field_count+0] = len_field; - add_entity(ctx->checker, scope, nullptr, len_field); - add_entity_use(ctx, nullptr, len_field); - - Entity *cap_field = alloc_entity_field(scope, empty_token, t_int, false, cast(i32)field_count); - soa_struct->Struct.fields[field_count+1] = cap_field; - add_entity(ctx->checker, scope, nullptr, cap_field); - add_entity_use(ctx, nullptr, cap_field); - - Token token = {}; - token.string = str_lit("allocator"); - Entity *allocator_field = alloc_entity_field(scope, token, t_allocator, false, cast(i32)field_count); - soa_struct->Struct.fields[field_count+2] = allocator_field; - add_entity(ctx->checker, scope, nullptr, allocator_field); - add_entity_use(ctx, nullptr, allocator_field); - - token.string = str_lit("Base_Type"); - Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved); - add_entity(ctx->checker, scope, nullptr, base_type_entity); - - add_type_info_type(ctx, soa_struct); - - return soa_struct; + return make_soa_struct_internal(ctx, array_typ_expr, elem_expr, elem, -1, nullptr, StructSoa_Dynamic); } - - bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_type) { GB_ASSERT_NOT_NULL(type); if (e == nullptr) { diff --git a/src/checker.hpp b/src/checker.hpp index f0f116a02..f590b89fe 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -419,3 +419,4 @@ void check_poly_path_push(CheckerContext *c, Type *t); Type *check_poly_path_pop (CheckerContext *c); void init_core_context(Checker *c); +void init_mem_allocator(Checker *c);