'use' for struct members is now transitive; fixed defined_test
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 1 Oct 2022 18:56:40 +0000 (13:56 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 1 Oct 2022 18:56:40 +0000 (13:56 -0500)
compiler/include/types.h
compiler/src/checker.c
compiler/src/types.c
core/hash.onyx
tests/defined_test

index fadbc91588919eed7a05a221ab43883a188e2efe..183bd81df972113d58151d0e024cf6bb773f84c5 100644 (file)
@@ -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;
index f3e4d26886a1a980acf9819618e8f5569b855add..cc0c9adba96ed46ef4d56fbd2bceb72745af7726 100644 (file)
@@ -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;
         }
     }
 
index 23ff6d4df8e2599067d80f0e4ff8c1e8453d1368..c5e22243c4c651bbbff705194635d6236bc51e8a 100644 (file)
@@ -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;
index fa4a30dca20c5cbf6e6cf4495aa78821fbf6634a..8935dda7da54df6b4bee6799a8ea4e3583378a02 100644 (file)
@@ -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) {
index 87f8d93a01b044d6424a58ef053f0efacaa42bd3..36bc6136b8bf401f53cd1d67f1c27ac466778ec5 100644 (file)
@@ -1,3 +1,3 @@
 true
 false
-true
+false