From: Brendan Hansen Date: Tue, 30 Nov 2021 19:02:18 +0000 (-0600) Subject: added using struct member that are pointers X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=dfda888329175cef3626df4c22328bdcaf9624fe;p=onyx.git added using struct member that are pointers --- diff --git a/core/io/stream.onyx b/core/io/stream.onyx index 260c2e22..486ce7be 100644 --- a/core/io/stream.onyx +++ b/core/io/stream.onyx @@ -3,7 +3,7 @@ package core.io use package core Stream :: struct { - vtable : ^Stream_Vtable; + use vtable : ^Stream_Vtable; } // #package diff --git a/include/types.h b/include/types.h index 999443c5..1e952157 100644 --- a/include/types.h +++ b/include/types.h @@ -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; diff --git a/src/checker.c b/src/checker.c index 85dd3c1c..adcd680d 100644 --- a/src/checker.c +++ b/src/checker.c @@ -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; } diff --git a/src/types.c b/src/types.c index aeaf3c93..9850512f 100644 --- a/src/types.c +++ b/src/types.c @@ -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) { diff --git a/src/utils.c b/src/utils.c index 900acf2d..1be2a5be 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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)