"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": [],
[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 {
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; }
char *name;
struct AstTyped* initial_value;
-
- b32 member_was_used : 1;
+ b32 included_through_use : 1;
} StructMember;
#define TYPE_KINDS \
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) {
}
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;
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.");
.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);
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: {
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);