From ca0e7bbc0dcedb8a73493a286f907ab5b1a38bd1 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 1 Oct 2022 13:56:40 -0500 Subject: [PATCH] 'use' for struct members is now transitive; fixed defined_test --- compiler/include/types.h | 1 + compiler/src/checker.c | 33 +++++++++++++++++++++------------ compiler/src/types.c | 37 +++++++++++++++++++++++-------------- core/hash.onyx | 3 ++- tests/defined_test | 2 +- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/compiler/include/types.h b/compiler/include/types.h index fadbc915..183bd81d 100644 --- a/compiler/include/types.h +++ b/compiler/include/types.h @@ -82,6 +82,7 @@ typedef struct StructMember { i32 use_through_pointer_index; b32 included_through_use : 1; b32 used : 1; + b32 use_processed : 1; bh_arr(struct AstTyped *) meta_tags; } StructMember; diff --git a/compiler/src/checker.c b/compiler/src/checker.c index f3e4d268..cc0c9adb 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -1721,19 +1721,26 @@ CheckStatus check_field_access(AstFieldAccess** pfield) { // NOTE: If this member was included into the structure through a "use x: ^T" kind of statement, // then we have to insert a intermediate field access in order to access the correct member. if (smem.use_through_pointer_index >= 0) { - StructMember containing_member; - assert(type_lookup_member_by_idx(field->expr->type, smem.use_through_pointer_index, &containing_member)); + StructMember containing_member = smem; - AstFieldAccess *new_access = onyx_ast_node_new(context.ast_alloc, sizeof(AstFieldAccess), Ast_Kind_Field_Access); - new_access->token = field->token; - new_access->offset = containing_member.offset; - new_access->idx = containing_member.idx; - new_access->type = containing_member.type; - new_access->expr = field->expr; - new_access->flags |= Ast_Flag_Has_Been_Checked; - new_access->flags |= Ast_Flag_Extra_Field_Access; + // TODO: The following code is not right after it loops, but this should never loop + // due to a check in types.c line 947. + AstTyped **dest = &field->expr; + do { + assert(type_lookup_member_by_idx((*dest)->type, containing_member.use_through_pointer_index, &containing_member)); - field->expr = (AstTyped *) new_access; + AstFieldAccess *new_access = onyx_ast_node_new(context.ast_alloc, sizeof(AstFieldAccess), Ast_Kind_Field_Access); + new_access->token = field->token; + new_access->offset = containing_member.offset; + new_access->idx = containing_member.idx; + new_access->type = containing_member.type; + new_access->expr = *dest; + new_access->flags |= Ast_Flag_Has_Been_Checked; + new_access->flags |= Ast_Flag_Extra_Field_Access; + + *dest = (AstTyped *) new_access; + dest = &new_access->expr; + } while (containing_member.use_through_pointer_index >= 0); } field->offset = smem.offset; @@ -2453,10 +2460,12 @@ CheckStatus check_struct(AstStructType* s_node) { ERROR(s_node->token->pos, "Compound types are not allowed as struct member types."); } - if ((*smem)->used) { + if ((*smem)->used && !(*smem)->use_processed) { if (!type_struct_member_apply_use(context.ast_alloc, s_node->pending_type, *smem)) { YIELD((*smem)->token->pos, "Waiting for use to be applied."); } + + (*smem)->use_processed = 1; } } diff --git a/compiler/src/types.c b/compiler/src/types.c index 23ff6d4d..c5e22243 100644 --- a/compiler/src/types.c +++ b/compiler/src/types.c @@ -936,34 +936,43 @@ b32 type_struct_member_apply_use(bh_allocator alloc, Type *s_type, StructMember return 0; } - if (used_type->Struct.status == SPS_Start) return 0; + if (used_type->Struct.status < SPS_Uses_Done) 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); + fori (i, 0, shlen(used_type->Struct.members)) { + StructMember *nsmem = used_type->Struct.members[i].value; + + // + // TODO: :Bugfix Currently, nested use through pointers are not + // working correctly and I need to rethink them entirely. + if (nsmem->use_through_pointer_index >= 0) { + continue; + } + + if (shgeti(s_type->Struct.members, nsmem->name) != -1) { + onyx_report_error(smem->token->pos, Error_Critical, "Used name '%s' conflicts with existing struct member.", nsmem->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->type = nsmem->type; + new_smem->name = nsmem->name; + new_smem->meta_tags = nsmem->meta_tags; + new_smem->used = nsmem->used; new_smem->included_through_use = 1; if (type_is_pointer) { - new_smem->offset = (*psmem)->offset; - new_smem->idx = (*psmem)->idx; + new_smem->offset = nsmem->offset; + new_smem->idx = nsmem->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->offset = smem->offset + nsmem->offset; + new_smem->idx = nsmem->idx; // Dummy value because I don't think this is needed. + new_smem->initial_value = nsmem->initial_value; new_smem->use_through_pointer_index = -1; } - shput(s_type->Struct.members, (*psmem)->name, new_smem); + shput(s_type->Struct.members, nsmem->name, new_smem); } return 1; diff --git a/core/hash.onyx b/core/hash.onyx index fa4a30dc..8935dda7 100644 --- a/core/hash.onyx +++ b/core/hash.onyx @@ -13,7 +13,8 @@ to_u32 :: #match { }, (key: type_expr) -> u32 { return to_u32(cast(u32) key); }, - #precedence 10000 macro (key: $T/HasHashMethod) => key->hash() + #precedence 10000 + macro (key: $T/HasHashMethod) => key->hash() } Hashable :: interface (t: $T) { diff --git a/tests/defined_test b/tests/defined_test index 87f8d93a..36bc6136 100644 --- a/tests/defined_test +++ b/tests/defined_test @@ -1,3 +1,3 @@ true false -true +false -- 2.25.1