From 7afbb824c20c92431f1e1f2b3bac8fe6d6c908b1 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 15 Mar 2022 22:17:12 -0500 Subject: [PATCH] changed struct generation internals --- include/astnodes.h | 9 ++- include/types.h | 11 +++- src/checker.c | 15 ++++- src/symres.c | 14 +++-- src/types.c | 154 ++++++++++++++++++++++----------------------- 5 files changed, 113 insertions(+), 90 deletions(-) diff --git a/include/astnodes.h b/include/astnodes.h index 068bafe7..b43869ed 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -888,6 +888,11 @@ struct AstStructType { // a struct type is kind of complicated and should // only happen once. Type *stcache; + + // NOTE: This type is used when the structure has not been + // completely generated, but is a valid pointer to where the + // type will be generated to. + Type *pending_type; // NOTE: Used to store statically bound expressions in the struct. Scope* scope; @@ -898,8 +903,8 @@ struct AstStructType { OnyxFilePos polymorphic_error_loc; ConstraintContext constraints; - b32 stcache_is_valid : 1; - b32 is_union : 1; + b32 pending_type_is_valid : 1; + b32 is_union : 1; }; struct AstStructMember { AstTyped_base; diff --git a/include/types.h b/include/types.h index fa03138d..9ed77e53 100644 --- a/include/types.h +++ b/include/types.h @@ -76,6 +76,7 @@ typedef struct StructMember { // be many struct members, and iterating through an array would be // easier and less costly. - brendanfh 2020/09/17 char *name; + struct OnyxToken* token; struct AstTyped** initial_value; i32 use_through_pointer_index; @@ -91,6 +92,12 @@ struct TypeWithOffset { u32 offset; }; +typedef enum StructProcessingStatus { + SPS_Start, + SPS_Members_Done, + SPS_Uses_Done, +} StructProcessingStatus; + #define TYPE_KINDS \ TYPE_KIND(Basic, TypeBasic) \ TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \ @@ -105,12 +112,13 @@ struct TypeWithOffset { char* name; \ u32 size; \ u16 alignment, mem_count; \ - Table(StructMember) members; \ + Table(StructMember *) members; \ bh_arr(StructMember *) memarr; \ bh_arr(struct AstPolySolution) poly_sln; \ bh_arr(TypeWithOffset) linear_members; \ struct AstType *constructed_from; \ bh_arr(struct AstTyped *) meta_tags; \ + StructProcessingStatus status; \ }) \ TYPE_KIND(PolyStruct, struct { \ char* name; \ @@ -199,6 +207,7 @@ Type* type_make_dynarray(bh_allocator alloc, Type* of); Type* type_make_varargs(bh_allocator alloc, Type* of); void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u32 offset); +b32 type_struct_member_apply_use(bh_allocator alloc, Type *s_type, StructMember *smem); const char* type_get_unique_name(Type* type); const char* type_get_name(Type* type); diff --git a/src/checker.c b/src/checker.c index 5712060a..88de40ae 100644 --- a/src/checker.c +++ b/src/checker.c @@ -2163,17 +2163,26 @@ CheckStatus check_struct(AstStructType* s_node) { } } - // NOTE: fills in the stcache + // NOTE: fills in the pending_type. type_build_from_ast(context.ast_alloc, (AstType *) s_node); - if (s_node->stcache == NULL || !s_node->stcache_is_valid) + if (s_node->pending_type == NULL || !s_node->pending_type_is_valid) YIELD(s_node->token->pos, "Waiting for type to be constructed."); - bh_arr_each(StructMember *, smem, s_node->stcache->Struct.memarr) { + bh_arr_each(StructMember *, smem, s_node->pending_type->Struct.memarr) { if ((*smem)->type->kind == Type_Kind_Compound) { ERROR(s_node->token->pos, "Compound types are not allowed as struct member types."); } + + if ((*smem)->used) { + if (!type_struct_member_apply_use(context.ast_alloc, s_node->pending_type, *smem)) { + YIELD((*smem)->token->pos, "Waiting for use to be applied."); + } + } } + s_node->stcache = s_node->pending_type; + s_node->stcache->Struct.status = SPS_Uses_Done; + return Check_Success; } diff --git a/src/symres.c b/src/symres.c index bf173503..88b7e5b8 100644 --- a/src/symres.c +++ b/src/symres.c @@ -770,9 +770,9 @@ static SymresStatus symres_use(AstUse* use) { st = st->Pointer.elem; fori (i, 0, shlen(st->Struct.members)) { - StructMember value = st->Struct.members[i].value; - AstFieldAccess* fa = make_field_access(context.ast_alloc, use->expr, value.name); - symbol_raw_introduce(curr_scope, value.name, use->token->pos, (AstNode *) fa); + StructMember* value = st->Struct.members[i].value; + AstFieldAccess* fa = make_field_access(context.ast_alloc, use->expr, value->name); + symbol_raw_introduce(curr_scope, value->name, use->token->pos, (AstNode *) fa); } return Symres_Success; @@ -1045,10 +1045,12 @@ SymresStatus symres_function(AstFunction* func) { st = param->local->type->Pointer.elem; } + if (st->Struct.status != SPS_Uses_Done) return Symres_Yield_Macro; + fori (i, 0, shlen(st->Struct.members)) { - StructMember value = st->Struct.members[i].value; - AstFieldAccess* fa = make_field_access(context.ast_alloc, (AstTyped *) param->local, value.name); - symbol_raw_introduce(curr_scope, value.name, param->local->token->pos, (AstNode *) fa); + StructMember* value = st->Struct.members[i].value; + AstFieldAccess* fa = make_field_access(context.ast_alloc, (AstTyped *) param->local, value->name); + symbol_raw_introduce(curr_scope, value->name, param->local->token->pos, (AstNode *) fa); } param->use_processed = 1; diff --git a/src/types.c b/src/types.c index cd913e5e..daf88fc8 100644 --- a/src/types.c +++ b/src/types.c @@ -337,18 +337,20 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { case Ast_Kind_Struct_Type: { AstStructType* s_node = (AstStructType *) type_node; - if (s_node->stcache != NULL && s_node->stcache_is_valid) return s_node->stcache; + if (s_node->stcache != NULL) return s_node->stcache; + if (s_node->pending_type != NULL && s_node->pending_type_is_valid) return s_node->pending_type; Type* s_type; - if (s_node->stcache == NULL) { + if (s_node->pending_type == NULL) { s_type = type_create(Type_Kind_Struct, alloc, 0); - s_node->stcache = s_type; + s_node->pending_type = s_type; s_type->ast_type = type_node; s_type->Struct.name = s_node->name; s_type->Struct.mem_count = bh_arr_length(s_node->members); s_type->Struct.meta_tags = s_node->meta_tags; s_type->Struct.constructed_from = NULL; + s_type->Struct.status = SPS_Start; type_register(s_type); s_type->Struct.memarr = NULL; @@ -356,17 +358,16 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { bh_arr_new(global_heap_allocator, s_type->Struct.memarr, s_type->Struct.mem_count); } else { - s_type = s_node->stcache; + s_type = s_node->pending_type; } s_type->Struct.poly_sln = NULL; bh_arr_clear(s_type->Struct.memarr); - // bh_table_clear(s_type->Struct.members); shfree(s_type->Struct.members); sh_new_arena(s_type->Struct.members); - s_node->stcache_is_valid = 1; + s_node->pending_type_is_valid = 1; b32 is_union = s_node->is_union; u32 size = 0; @@ -378,7 +379,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { (*member)->type = type_build_from_ast(alloc, (*member)->type_node); if ((*member)->type == NULL) { - s_node->stcache_is_valid = 0; + s_node->pending_type_is_valid = 0; return NULL; } @@ -397,64 +398,22 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return NULL; } - StructMember smem = { - .offset = offset, - .type = (*member)->type, - .idx = idx, - .name = bh_strdup(alloc, (*member)->token->text), - .initial_value = &(*member)->initial_value, - .meta_tags = (*member)->meta_tags, - - .included_through_use = 0, - .used = (*member)->is_used, - .use_through_pointer_index = -1, - }; + StructMember* smem = bh_alloc_item(alloc, StructMember); + smem->offset = offset; + smem->type = (*member)->type; + smem->idx = idx; + smem->name = bh_strdup(alloc, (*member)->token->text); + smem->token = (*member)->token; + smem->initial_value = &(*member)->initial_value; + smem->meta_tags = (*member)->meta_tags; + + smem->included_through_use = 0; + smem->used = (*member)->is_used; + smem->use_through_pointer_index = -1; shput(s_type->Struct.members, (*member)->token->text, smem); + bh_arr_push(s_type->Struct.memarr, smem); token_toggle_end((*member)->token); - if (smem.used) { - Type* used_type = (*member)->type; - - b32 type_is_pointer = 0; - if (used_type->kind == Type_Kind_Pointer) { - type_is_pointer = 1; - used_type = type_get_contained_type(used_type); - } - - if (used_type->kind != Type_Kind_Struct) { - onyx_report_error((*member)->token->pos, Error_Critical, "Can only use things of structure, or pointer to structure type."); - return NULL; - } - - bh_arr_each(StructMember*, psmem, used_type->Struct.memarr) { - if (shgeti(s_type->Struct.members, (*psmem)->name) != -1) { - onyx_report_error((*member)->token->pos, Error_Critical, "Used name '%s' conflicts with existing struct member.", (*psmem)->name); - return NULL; - } - - StructMember new_smem; - new_smem.type = (*psmem)->type; - new_smem.name = (*psmem)->name; - new_smem.meta_tags = (*psmem)->meta_tags; - new_smem.used = 0; - new_smem.included_through_use = 1; - - if (type_is_pointer) { - new_smem.offset = (*psmem)->offset; - new_smem.idx = (*psmem)->idx; - new_smem.initial_value = NULL; - new_smem.use_through_pointer_index = idx; - } else { - new_smem.offset = offset + (*psmem)->offset; - new_smem.idx = -1; // Dummy value because I don't think this is needed. - new_smem.initial_value = (*psmem)->initial_value; - new_smem.use_through_pointer_index = -1; - } - - shput(s_type->Struct.members, (*psmem)->name, new_smem); - } - } - u32 type_size = type_size_of((*member)->type); if (!is_union) { @@ -467,15 +426,6 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { idx++; } - // NOTE: Need to do a second pass because the references to the - // elements of the table may change if the internal arrays of the - // table need to be resized. - bh_arr_each(AstStructMember *, member, s_node->members) { - token_toggle_end((*member)->token); - bh_arr_push(s_type->Struct.memarr, &s_type->Struct.members[shgeti(s_type->Struct.members, (*member)->token->text)].value); - token_toggle_end((*member)->token); - } - alignment = bh_max(s_node->min_alignment, alignment); bh_align(size, alignment); size = bh_max(s_node->min_size, size); @@ -487,6 +437,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { bh_arr_new(global_heap_allocator, s_type->Struct.linear_members, s_type->Struct.mem_count); build_linear_types_with_offset(s_type, &s_type->Struct.linear_members, 0); + s_type->Struct.status = SPS_Members_Done; return s_type; } @@ -867,6 +818,53 @@ void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u } } +b32 type_struct_member_apply_use(bh_allocator alloc, Type *s_type, StructMember *smem) { + Type* used_type = smem->type; + + b32 type_is_pointer = 0; + if (used_type->kind == Type_Kind_Pointer) { + type_is_pointer = 1; + used_type = type_get_contained_type(used_type); + } + + if (used_type->kind != Type_Kind_Struct) { + onyx_report_error(smem->token->pos, Error_Critical, "Can only use things of structure, or pointer to structure type."); + return 0; + } + + if (used_type->Struct.status == SPS_Start) return 0; + + bh_arr_each(StructMember*, psmem, used_type->Struct.memarr) { + if (shgeti(s_type->Struct.members, (*psmem)->name) != -1) { + onyx_report_error(smem->token->pos, Error_Critical, "Used name '%s' conflicts with existing struct member.", (*psmem)->name); + return 0; + } + + StructMember* new_smem = bh_alloc_item(alloc, StructMember); + new_smem->type = (*psmem)->type; + new_smem->name = (*psmem)->name; + new_smem->meta_tags = (*psmem)->meta_tags; + new_smem->used = 0; + new_smem->included_through_use = 1; + + if (type_is_pointer) { + new_smem->offset = (*psmem)->offset; + new_smem->idx = (*psmem)->idx; + new_smem->initial_value = NULL; + new_smem->use_through_pointer_index = smem->idx; + } else { + new_smem->offset = smem->offset + (*psmem)->offset; + new_smem->idx = -1; // Dummy value because I don't think this is needed. + new_smem->initial_value = (*psmem)->initial_value; + new_smem->use_through_pointer_index = -1; + } + + shput(s_type->Struct.members, (*psmem)->name, new_smem); + } + + return 1; +} + const char* type_get_unique_name(Type* type) { if (type == NULL) return "unknown"; @@ -1018,15 +1016,15 @@ Type* type_get_contained_type(Type* type) { } static const StructMember slice_members[] = { - { 0, 0, NULL, "data", NULL, -1, 0, 0 }, - { POINTER_SIZE, 1, &basic_types[Basic_Kind_U32], "count", NULL, -1, 0, 0 }, + { 0, 0, NULL, "data", NULL, NULL, -1, 0, 0 }, + { POINTER_SIZE, 1, &basic_types[Basic_Kind_U32], "count", NULL, NULL, -1, 0, 0 }, }; static const StructMember array_members[] = { - { 0, 0, NULL, "data", NULL, -1, 0, 0 }, - { POINTER_SIZE, 1, &basic_types[Basic_Kind_U32], "count", NULL, -1, 0, 0 }, - { POINTER_SIZE + 4, 2, &basic_types[Basic_Kind_U32], "capacity", NULL, -1, 0, 0 }, - { POINTER_SIZE + 8, 3, NULL, "allocator", NULL, -1, 0, 0 }, + { 0, 0, NULL, "data", NULL, NULL, -1, 0, 0 }, + { POINTER_SIZE, 1, &basic_types[Basic_Kind_U32], "count", NULL, NULL, -1, 0, 0 }, + { POINTER_SIZE + 4, 2, &basic_types[Basic_Kind_U32], "capacity", NULL, NULL, -1, 0, 0 }, + { POINTER_SIZE + 8, 3, NULL, "allocator", NULL, NULL, -1, 0, 0 }, }; b32 type_lookup_member(Type* type, char* member, StructMember* smem) { @@ -1038,7 +1036,7 @@ b32 type_lookup_member(Type* type, char* member, StructMember* smem) { i32 index = shgeti(stype->members, member); if (index == -1) return 0; - *smem = stype->members[index].value; + *smem = *stype->members[index].value; return 1; } -- 2.25.1