From: Brendan Hansen Date: Wed, 30 Dec 2020 04:06:00 +0000 (-0600) Subject: structs are much better now, as far as I can tell X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ccc342f915aa284eefd2075c992b9c8519d16f03;p=onyx.git structs are much better now, as far as I can tell --- diff --git a/.vimspector.json b/.vimspector.json index d9aef1fd..57cf6c88 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -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": [], diff --git a/docs/bugs b/docs/bugs index b5c6a35d..d3c3580b 100644 --- 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; } diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 54251639..cec94fa5 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -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 2722db43..67bca43e 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 2d0921c7..d368eb06 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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."); diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 31ffcc04..f8f4aad0 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -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: { diff --git a/tests/struct_robustness.onyx b/tests/struct_robustness.onyx index 1391139e..503d9b3e 100644 --- a/tests/struct_robustness.onyx +++ b/tests/struct_robustness.onyx @@ -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);