structs are much better now, as far as I can tell
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 30 Dec 2020 04:06:00 +0000 (22:06 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 30 Dec 2020 04:06:00 +0000 (22:06 -0600)
.vimspector.json
docs/bugs
include/onyxtypes.h
onyx
src/onyxsymres.c
src/onyxtypes.c
tests/struct_robustness.onyx

index d9aef1fdcfbeffbd6fa4dbbd07a0355c8a5d2765..57cf6c88e70e2b46f5e0d55ccba13288c08d5866 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["--verbose", "progs/poly_solidify.onyx"],
+                "args": ["--verbose", "tests/struct_robustness.onyx"],
                 "stopAtEntry": true,
                 "cwd": "~/dev/c/onyx",
                 "environment": [],
index b5c6a35d0906b364c8f79d0633e69bb382a6d34c..d3c3580b8d0e5a382a972dae63b2a8e28e963c1a 100644 (file)
--- a/docs/bugs
+++ b/docs/bugs
@@ -55,7 +55,7 @@ List of known bugs:
 
 [X] Polymorphic structs do not recognize default values for members.
 
-[ ] `use` on struct members does not work correctly if the type is a union.
+[X] `use` on struct members does not work correctly if the type is a union.
     ```
     BadUnion :: struct {
         use container : struct #union {
@@ -67,7 +67,7 @@ List of known bugs:
     test :: proc () do print(sizeof BadUnion == 4);
     ```
 
-[ ] `use` on struct members breaks struct literals.
+[X] `use` on struct members breaks struct literals.
     ```
     Vec2   :: struct { x: i32; y: i32; }
     Entity :: struct { use pos: Vec2; }
index 542516395d725e8c32ece055d1e24e0e1a7c0d1b..cec94fa55ac3975c3d34ad2a07c08a5654533079 100644 (file)
@@ -69,8 +69,7 @@ typedef struct StructMember {
     char *name;
 
     struct AstTyped* initial_value;
-
-    b32 member_was_used : 1;
+    b32 included_through_use : 1;
 } StructMember;
 
 #define TYPE_KINDS \
diff --git a/onyx b/onyx
index 2722db43ed545bbccaeeb50a9f94c0cc7419695f..67bca43e39e01d6168eb40a3c802d75917fff9ca 100755 (executable)
Binary files a/onyx and b/onyx differ
index 2d0921c76632ea3e1d99844ae00aefb589454ad3..d368eb065b3c3953be43d3c58795a9079def10b4 100644 (file)
@@ -145,12 +145,6 @@ AstType* symres_type(AstType* type) {
 
                     return type;
                 }
-
-                bh_arr_insertn(s_node->members, i, bh_arr_length(used->members));
-
-                fori (j, 0, bh_arr_length(used->members)) {
-                    s_node->members[i + j + 1] = used->members[j];
-                }
             }
 
             if (member->initial_value != NULL) {
@@ -351,13 +345,14 @@ static void symres_struct_literal(AstStructLiteral* sl) {
             }
             token_toggle_end((*smem)->token);
 
-            if (sl->values[s.idx] != NULL) {
-                onyx_report_error((*smem)->token->pos, "Multiple values given for '%b'.", (*smem)->token->text, (*smem)->token->length);
+            if (s.included_through_use) {
+                onyx_report_error((*smem)->token->pos, "Cannot specify value for member '%b', whic was included through a 'use' statement.", s.name);
                 return;
             }
 
-            if (s.member_was_used) {
-                (*smem)->flags |= Ast_Flag_Struct_Mem_Used;
+            if (sl->values[s.idx] != NULL) {
+                onyx_report_error((*smem)->token->pos, "Multiple values given for '%b'.", (*smem)->token->text, (*smem)->token->length);
+                return;
             }
 
             sl->values[s.idx] = (*smem)->initial_value;
@@ -759,29 +754,23 @@ void symres_function_header(AstFunction* func) {
 
         if (param->local->flags & Ast_Flag_Param_Use) {
             if (type_is_struct(param->local->type)) {
-                AstStructType* st;
+                Type* st;
                 if (param->local->type->kind == Type_Kind_Struct) {
-                    st = (AstStructType *) param->local->type_node;
+                    st = param->local->type;
                 } else {
-                    st = (AstStructType *) ((AstPointerType *) param->local->type_node)->elem;
+                    st = param->local->type->Pointer.elem;
                 }
 
-                if (st->kind == Ast_Kind_Poly_Call_Type) {
-                    st = (AstStructType *) (((AstPolyStructType *) (((AstPolyCallType *) st)->callee))->base_struct);
-                }
-
-                bh_arr_each(AstStructMember *, mem, st->members) {
+                bh_table_each_start(StructMember, st->Struct.members);
                     AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
-                    fa->token = (*mem)->token;
                     fa->expr = (AstTyped *) param->local;
+                    fa->field = value.name;
 
-                    token_toggle_end((*mem)->token);
                     symbol_raw_introduce(semstate.curr_scope,
-                            (*mem)->token->text,
+                            value.name,
                             param->local->token->pos,
                             (AstNode *) fa);
-                    token_toggle_end((*mem)->token);
-                }
+                bh_table_each_end;
 
             } else {
                 onyx_report_error(param->local->token->pos, "can only 'use' structures or pointers to structures.");
index 31ffcc044364bf58194d23608c19bd1e51ff03b3..f8f4aad03eb615a31962d75fd2c4ea83ed80b70c 100644 (file)
@@ -367,32 +367,43 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                     .type = (*member)->type,
                     .idx = idx,
                     .name = bh_strdup(alloc, (*member)->token->text),
-                    .member_was_used = ((*member)->flags & Ast_Flag_Struct_Mem_Used) != 0,
                     .initial_value = (*member)->initial_value,
+                    .included_through_use = 0,
                 };
 
                 bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem);
                 token_toggle_end((*member)->token);
 
+                if (((*member)->flags & Ast_Flag_Struct_Mem_Used) != 0) {
+                    assert((*member)->type->kind == Type_Kind_Struct);
+
+                    bh_arr_each(StructMember*, psmem, (*member)->type->Struct.memarr) {
+                        StructMember new_smem = {
+                            .offset = offset + (*psmem)->offset,
+                            .type   = (*psmem)->type,
+                            .idx    = -1, // Dummy value because I don't think this is needed.
+                            .name   = (*psmem)->name,
+                            .initial_value = (*psmem)->initial_value,
+                            .included_through_use = 1,
+                        };
+
+                        bh_table_put(StructMember, s_type->Struct.members, (*psmem)->name, new_smem);
+                    }
+                }
+
                 u32 type_size = type_size_of((*member)->type);
-                if (((*member)->flags & Ast_Flag_Struct_Mem_Used) == 0) {
-                    if (!is_union) offset += type_size;
-                    if (!is_union) size += type_size;
-                    else           size =  bh_max(size, type_size);
 
-                    idx++;
-                }
+                if (!is_union) offset += type_size;
+                if (!is_union) size += type_size;
+                else           size =  bh_max(size, type_size);
+
+                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.
-            s_type->Struct.mem_count = 0;
             bh_arr_each(AstStructMember *, member, s_node->members) {
-                if ((*member)->flags & Ast_Flag_Struct_Mem_Used) continue;
-
-                s_type->Struct.mem_count++;
-
                 token_toggle_end((*member)->token);
                 bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, (*member)->token->text));
                 token_toggle_end((*member)->token);
@@ -649,8 +660,8 @@ u32 type_get_alignment_log2(Type* type) {
 b32 type_lookup_member(Type* type, char* member, StructMember* smem) {
     if (type->kind == Type_Kind_Pointer) type = type->Pointer.elem;
 
-    smem->member_was_used = 0;
     smem->initial_value = NULL;
+    smem->included_through_use = 0;
 
     switch (type->kind) {
         case Type_Kind_Struct: {
index 1391139e29c968f02d8e19914c0c83bdcbd85889..503d9b3e9b003c28284d8851770844c88a7db598 100644 (file)
@@ -78,27 +78,17 @@ main :: proc (args: [] cstr) {
                        y : f32;        
                }
 
-               // This does not work, but it should.
-               // swu := StructWithUse.{ 1234, UsedMember.{ 1, 2 }, 5678 };
+               swu := StructWithUse.{ 1234, UsedMember.{ 1, 2 }, 5678 };
 
-               // Neither does this, but it also should.
-               // swu := StructWithUse.{
-               //      first_member = 1234,
-               //      used_member  = UsedMember.{ 1, 2 },
-               //      last_member  = 5678,
-               // };
-
-               // This does, when all non-used members are listed out.
-               swu := StructWithUse.{ 1234, 1, 2, 5678 };
-
-               // This also does.
                swu2 := StructWithUse.{
                        first_member = 1234,
-                       x            = 1,
-                       y            = 2,
+                       used_member  = UsedMember.{ 1, 2 },
                        last_member  = 5678,
                };
 
+               // This will not work. `use`d members cannot be set directly.
+               swu3 := StructWithUse.{ 1234, 1, 2, 5678 };
+
                print_swu :: proc (use swu: StructWithUse) {
                        printf("StructWithUse(%i, (%f, %f), %i)\n",
                                first_member, x, y, last_member);