From: Brendan Hansen Date: Tue, 8 Sep 2020 13:23:47 +0000 (-0500) Subject: added 'using' struct members X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ccacc0145571afc32c79d7d9c38dc37e81321cd7;p=onyx.git added 'using' struct members --- diff --git a/.vimspector.json b/.vimspector.json index 899b511c..bf221152 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -6,7 +6,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/onyx", - "args": ["-verbose", "progs/poly_test.onyx"], + "args": ["-verbose", "progs/odin_example.onyx"], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], diff --git a/core/stdio.onyx b/core/stdio.onyx index 2c74f7a3..3b84e9e7 100644 --- a/core/stdio.onyx +++ b/core/stdio.onyx @@ -20,7 +20,7 @@ print_cstring :: proc (s: cstring) do string_builder_append(^print_buffer, s); print_i64 :: proc (n: i64, base := 10l) do string_builder_append(^print_buffer, n, base); print_i32 :: proc (n: i32, base := 10) do string_builder_append(^print_buffer, cast(i64) n, cast(u64) base); print_bool :: proc (b: bool) do string_builder_append(^print_buffer, b); -print_ptr :: proc (p: rawptr) do string_builder_append(^print_buffer, cast(i64) p, 16l); +print_ptr :: proc (p: ^void) do string_builder_append(^print_buffer, cast(i64) p, 16l); print_range :: proc (r: range, sep := " ") { for i: r { diff --git a/core/string.onyx b/core/string.onyx index 6e073198..405ede87 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -77,7 +77,7 @@ string_substr :: proc (str: string, sub: string) -> string { } string_contains :: proc (str: string, c: u8) -> bool { - for i: 0 .. str.count do if str[i] == c do return true; + for ch: str do if ch == c do return true; return false; } diff --git a/docs/plan b/docs/plan index 604acdcf..04eadb19 100644 --- a/docs/plan +++ b/docs/plan @@ -275,6 +275,7 @@ HOW: [ ] look into creating a source map - first-look looks really gross - whoever came up with the source map spec should be fired... why are people so afraid of binary files?? + - DWARF looks like it might be easier, but it still doesn't look fun. [ ] convert to using an 'atom' like table - All identifier tokens are given a unique atom ptr, up to string equality. diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index c0bda210..d58a3df7 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -183,6 +183,8 @@ typedef enum AstFlags { Ast_Flag_Cannot_Take_Addr = BH_BIT(19), Ast_Flag_Arg_Is_VarArg = BH_BIT(20), + + Ast_Flag_Struct_Mem_Used = BH_BIT(21), } AstFlags; typedef enum UnaryOp { @@ -666,6 +668,7 @@ static inline CallingConvention type_function_get_cc(Type* type) { if (type->kind != Type_Kind_Function) return CC_Undefined; if (type->Function.return_type->kind == Type_Kind_Struct) return CC_Return_Stack; if (type->Function.return_type->kind == Type_Kind_Slice) return CC_Return_Stack; + if (type->Function.return_type->kind == Type_Kind_DynArray) return CC_Return_Stack; return CC_Return_Wasm; } diff --git a/onyx b/onyx index 4f86f2c1..8338bfe5 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/odin_example.onyx b/progs/odin_example.onyx index 24c29d1f..7fc7dbcd 100644 --- a/progs/odin_example.onyx +++ b/progs/odin_example.onyx @@ -2,7 +2,68 @@ use package core + +Foo :: struct { + data1 : i32; + data2 : f32; +} + +Bar :: struct { + use foo : Foo; + bar_data : string; + // bar_data2 : cstring; +} + +// BUG: This should cause some kind of error since this should be +// infinite in size, but it doesn't so... fix that. +// - brendanfh 2020/09/08 +// Link :: struct { +// data : i32; +// next : Link; +// } + + +// bar : Bar; +// bar.data1 = 123; +// bar.data2 = 524782.1f; + +// asdf :: proc (f: Foo) -> ... +// asdf(bar.foo); + +print_foo :: proc (f: ^Foo) { + print("Foo: \n"); + print(f.data1); + print("\n"); + print(cast(i32) f.data2); + print("\n"); +} + +print_bar :: proc (bar: ^Bar) { + print(bar.data1); + print("\n"); + print(cast(i32) bar.data2); + print("\n"); + print(bar.bar_data); + print("\n"); +} + +make_bar :: proc -> Bar { + bar : Bar; + bar.data1 = 1234; + bar.data2 = 12.34f; + bar.bar_data = "This is a test"; + + return bar; +} + main :: proc (args: [] cstring) { + bar := make_bar(); + + print(sizeof Bar); + print("\n"); + print_bar(^bar); + print_foo(^bar.foo); + program := "+ + * s - /"; accumulator := 0; diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx index eff90783..fe728568 100644 --- a/progs/poly_test.onyx +++ b/progs/poly_test.onyx @@ -134,6 +134,10 @@ print_strings :: proc (ss: ..string) { } multi_max :: proc (nums: ..$T) -> T { + print("Got this many args: "); + print(nums.count); + print("\n"); + max := nums[0]; for num: nums do if num > max do max = num; return max; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 42781cd1..d8862bd0 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -584,7 +584,7 @@ b32 check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) { if (check_binaryop(&binop_node, 0)) return 1; } - if (!types_are_compatible(binop->right->type, binop->right->type)) { + if (!types_are_compatible(binop->right->type, binop->left->type)) { onyx_report_error(binop->token->pos, "Cannot assign value of type '%s' to a '%s'.", type_get_name(binop->right->type), @@ -819,8 +819,8 @@ b32 check_struct_literal(AstStructLiteral* sl) { onyx_report_error(sl->token->pos, "'%s' expects %d values, given %d.", type_get_name(sl->type), - bh_arr_length(sl->values), - mem_count); + mem_count, + bh_arr_length(sl->values)); return 1; } diff --git a/src/onyxparser.c b/src/onyxparser.c index 1bfd8aa2..67a9c17a 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1359,6 +1359,11 @@ static AstStructType* parse_struct(OnyxParser* parser) { AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member); + if (parser->curr->type == Token_Type_Keyword_Use) { + consume_token(parser); + mem->flags |= Ast_Flag_Struct_Mem_Used; + } + mem->token = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); mem->type_node = parse_type(parser); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 55bdd862..987aab01 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -89,10 +89,27 @@ static AstType* symres_type(AstType* type) { s_node->flags |= Ast_Flag_Type_Is_Resolved; - bh_arr_each(AstStructMember *, member, s_node->members) { - (*member)->type_node = symres_type((*member)->type_node); - if ((*member)->initial_value != NULL) { - symres_expression(&(*member)->initial_value); + fori (i, 0, bh_arr_length(s_node->members)) { + AstStructMember *member = s_node->members[i]; + member->type_node = symres_type(member->type_node); + + if (member->flags & Ast_Flag_Struct_Mem_Used) { + if (member->type_node->kind != Ast_Kind_Struct_Type) { + onyx_report_error(member->token->pos, + "Can only 'use' members of struct type."); + } + + AstStructType *used = (AstStructType *) member->type_node; + + 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) { + symres_expression(&member->initial_value); } } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 21908b52..0b4e0be6 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -139,6 +139,8 @@ b32 types_are_compatible(Type* t1, Type* t2) { return types_are_compatible(t1->Pointer.elem, t2->Pointer.elem); } + if (t2->kind == Type_Kind_Basic && t2->Basic.kind == Basic_Kind_Rawptr) return 1; + break; } @@ -341,17 +343,24 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { token_toggle_end((*member)->token); u32 type_size = type_size_of((*member)->type); - if (!is_union) offset += type_size; - if (!is_union) size += type_size; - else size = bh_max(size, type_size); + 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++; + 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); @@ -637,13 +646,15 @@ b32 type_struct_is_simple(Type* type) { if (type->kind != Type_Kind_Struct) return 0; b32 is_simple = 1; - bh_table_each_start(StructMember, type->Struct.members); - if (value.type->kind == Type_Kind_Struct - || value.type->kind == Type_Kind_Array) { + bh_arr_each(StructMember *, mem, type->Struct.memarr) { + if ((*mem)->type->kind == Type_Kind_Struct + || (*mem)->type->kind == Type_Kind_Array + || (*mem)->type->kind == Type_Kind_Slice + || (*mem)->type->kind == Type_Kind_DynArray) { is_simple = 0; break; } - bh_table_each_end; + } return is_simple; }