added using struct member that are pointers
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 30 Nov 2021 19:02:18 +0000 (13:02 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 30 Nov 2021 19:02:18 +0000 (13:02 -0600)
core/io/stream.onyx
include/types.h
src/checker.c
src/types.c
src/utils.c

index 260c2e228fd5062cbcfe4b27fbefded4dcee9263..486ce7be6e82a5fdb2e1b4906c4ca9e672b5864d 100644 (file)
@@ -3,7 +3,7 @@ package core.io
 use package core
 
 Stream :: struct {
-    vtable : ^Stream_Vtable;
+    use vtable : ^Stream_Vtable;
 }
 
 // #package
index 999443c5b897b16ff89810d09a9d9478547efef5..1e95215790a0cc43480f86568ecba21db7d167bd 100644 (file)
@@ -76,6 +76,7 @@ typedef struct StructMember {
     char *name;
 
     struct AstTyped** initial_value;
+    i32 use_through_pointer_index;
     b32 included_through_use : 1;
     b32 used : 1;
 
index 85dd3c1ce4427c8f0c1ed0c945d115c569eb0d11..adcd680de0440d571d660bbe0543d85575787c37 100644 (file)
@@ -1505,9 +1505,10 @@ CheckStatus check_subscript(AstSubscript** psub) {
 
 CheckStatus check_field_access(AstFieldAccess** pfield) {
     AstFieldAccess* field = *pfield;
+    if (field->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
+
     CHECK(expression, &field->expr);
     if (field->expr->type == NULL) {
-        // onyx_report_error(field->token->pos, "Unable to deduce type of expression for accessing field.");
         YIELD(field->token->pos, "Trying to resolve type of source expression.");
     }
 
@@ -1524,16 +1525,13 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
         field->expr = ((AstDereference *) field->expr)->expr;
     }
 
-    StructMember smem;
     if (field->token != NULL && field->field == NULL) {
         token_toggle_end(field->token);
-        // CLEANUP: Duplicating the string here isn't the best for effiency,
-        // but it fixes a lot of bugs, so here we are.
-        //                                      - brendanfh  2020/12/08
         field->field = bh_strdup(context.ast_alloc, field->token->text);
         token_toggle_end(field->token);
     }
 
+    StructMember smem;
     if (!type_lookup_member(field->expr->type, field->field, &smem)) {
         if (field->expr->type->kind == Type_Kind_Array) {
             if (!strcmp(field->field, "count")) {
@@ -1557,10 +1555,27 @@ 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));
+
+        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;
+
+        field->expr = (AstTyped *) new_access;
+    }
+
     field->offset = smem.offset;
     field->idx = smem.idx;
     field->type = smem.type;
-
+    field->flags |= Ast_Flag_Has_Been_Checked;
     return Check_Success;
 }
 
index aeaf3c93dbeff0b7295c5c8304bcda315f5f0d0c..9850512fe011a675f5ce319f9daee01c071f2107 100644 (file)
@@ -388,57 +388,80 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                 }
 
                 if (mem_alignment > alignment) alignment = mem_alignment;
-                if (offset % mem_alignment != 0) {
-                    offset += mem_alignment - (offset % mem_alignment);
-                }
+                bh_align(offset, mem_alignment);
 
                 token_toggle_end((*member)->token);
+                if (shgeti(s_type->Struct.members, (*member)->token->text) != -1) {
+                    onyx_report_error((*member)->token->pos, "Duplicate struct member, '%s'.", (*member)->token->text);
+                    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,
-                    .meta_tags = (*member)->meta_tags,
+                    .use_through_pointer_index = -1,
                 };
-
-                if (shgeti(s_type->Struct.members, (*member)->token->text) != -1) {
-                    onyx_report_error((*member)->token->pos, "Duplicate struct member, '%s'.", (*member)->token->text);
-                    return NULL;
-                }
                 shput(s_type->Struct.members, (*member)->token->text, smem);
                 token_toggle_end((*member)->token);
 
                 if (smem.used) {
-                    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,
-                            .used = 0,
-                            .meta_tags = (*psmem)->meta_tags,
-                        };
+                    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, "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, "Duplicate struct member, '%s'.", (*psmem)->name);
+                            onyx_report_error((*member)->token->pos, "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 = 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) offset += type_size;
-                if (!is_union) size = offset;
-                else           size = bh_max(size, type_size);
+                if (!is_union) {
+                    offset += type_size;
+                    size = offset;
+                } else {
+                    size = bh_max(size, type_size);
+                }
 
                 idx++;
             }
@@ -453,13 +476,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             }
 
             alignment = bh_max(s_node->min_alignment, alignment);
-            s_type->Struct.alignment = alignment;
-
-            if (size % alignment != 0) {
-                size += alignment - (size % alignment);
-            }
-
+            bh_align(size, alignment);
             size = bh_max(s_node->min_size, size);
+
+            s_type->Struct.alignment = alignment;
             s_type->Struct.size = size;
 
             s_type->Struct.linear_members = NULL;
@@ -1000,15 +1020,15 @@ Type* type_get_contained_type(Type* type) {
 }
 
 static const StructMember slice_members[] = {
-    { 0, 0, NULL,                         "data",  NULL, 0, 0 },
-    { 8, 1, &basic_types[Basic_Kind_U32], "count", NULL, 0, 0 },
+    { 0, 0, NULL,                         "data",  NULL, -1, 0, 0 },
+    { 8, 1, &basic_types[Basic_Kind_U32], "count", NULL, -1, 0, 0 },
 };
 
 static const StructMember array_members[] = {
-    { 0,  0, NULL,                         "data",      NULL, 0, 0 },
-    { 8,  1, &basic_types[Basic_Kind_U32], "count",     NULL, 0, 0 },
-    { 12, 2, &basic_types[Basic_Kind_U32], "capacity",  NULL, 0, 0 },
-    { 16, 3, NULL,                         "allocator", NULL, 0, 0 },
+    { 0,  0, NULL,                         "data",      NULL, -1, 0, 0 },
+    { 8,  1, &basic_types[Basic_Kind_U32], "count",     NULL, -1, 0, 0 },
+    { 12, 2, &basic_types[Basic_Kind_U32], "capacity",  NULL, -1, 0, 0 },
+    { 16, 3, NULL,                         "allocator", NULL, -1, 0, 0 },
 };
 
 b32 type_lookup_member(Type* type, char* member, StructMember* smem) {
index 900acf2dd6af7d8518352138b31e18e0c5d36986..1be2a5be5a40de3c50ff8fe85cce703c73416995 100644 (file)
@@ -510,10 +510,12 @@ void expand_macro(AstCall** pcall, AstFunction* template) {
 
     // HACK HACK HACK This is probably very wrong. I don't know what guarentees that
     // the paramters and arguments are going to be in the same order exactly.
+    // Type *any_type = type_build_from_ast(context.ast_alloc, builtin_any_type);
     fori (i, 0, bh_arr_length(call->args.values)) {
-        symbol_introduce(argument_scope,
-            template->params[i].local->token,
-            (AstNode *) ((AstArgument *) call->args.values[i])->value);
+        AstNode *value = (AstNode *) ((AstArgument *) call->args.values[i])->value;
+        // assert(template->params[i].local->type);
+
+        symbol_introduce(argument_scope, template->params[i].local->token, value);
     }
 
     if (template->poly_scope != NULL)