From: Brendan Hansen Date: Sun, 23 Aug 2020 15:44:45 +0000 (-0500) Subject: allowing non simple structures to be stored and loaded X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ebd868bb620c14cd2b59a7175bf34ac77581e592;p=onyx.git allowing non simple structures to be stored and loaded --- diff --git a/Makefile b/Makefile index f92c3aa4..05c150b3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -RELEASE=0 +RELEASE=1 OBJ_FILES=\ build/onyxlex.o \ @@ -19,9 +19,9 @@ LIBS= TARGET=./onyx ifeq ($(RELEASE), 1) - FLAGS=-O2 + FLAGS=-O3 else - FLAGS=-g + FLAGS=-g3 -Og endif build/%.o: src/%.c include/bh.h diff --git a/core/alloc.onyx b/core/alloc.onyx index f1ae4509..eb01f0ca 100644 --- a/core/alloc.onyx +++ b/core/alloc.onyx @@ -187,7 +187,7 @@ scratch_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32 ss.curr_ptr = ss.base_ptr; retval = ss.base_ptr; } - + return retval; } diff --git a/core/builtin.onyx b/core/builtin.onyx index 6a7d9b7a..18788c37 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -2,7 +2,7 @@ package builtin string :: struct { data : ^u8; - len : u32; + len : u32; } cstring :: #type ^u8; \ No newline at end of file diff --git a/core/string.onyx b/core/string.onyx index 4ff1f2fd..e414f022 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -83,7 +83,7 @@ string_split :: proc (a: Allocator, str: string, delim: u8) -> StringSplitResult StringBuilder :: struct { // FIX(nested-structs): This should not be a pointer eventually. - // Currently nested structures cannot be passed as arguments or returned from procedures. + // Currently nested structures cannot be passed as arguments. // When this issue is fixed, change this to Allocator. alloc : ^Allocator; diff --git a/docs/plan b/docs/plan index a3e2cb00..0cc1c40c 100644 --- a/docs/plan +++ b/docs/plan @@ -187,8 +187,6 @@ HOW: [X] returning structs - This will put forward a lot of the work that will be done for multiple return values - [ ] implicit overloading - [ ] 'use' enums and packages at an arbitrary scope [ ] convert to using an 'atom' like table diff --git a/onyx b/onyx index fc892e9a..0acd7e55 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/wasi_test.onyx b/progs/wasi_test.onyx index d0fbf8da..5f7dfb93 100644 --- a/progs/wasi_test.onyx +++ b/progs/wasi_test.onyx @@ -61,15 +61,17 @@ print_u64_with_base :: proc (n_: u64, base: u64) { print(c + 1); } -print_string :: proc (s: string) { +print_string :: proc (s: string) -> u32 { vec := IOVec.{ buf = s.data, len = s.len }; tmp : Size; fd_write(1, IOVecArray.{ ^vec, 1 }, ^tmp); fd_datasync(1); + + return tmp; } -print_u8 :: proc (s: cstring) { - string_make(s) |> print_string(); +print_u8 :: proc (s: cstring) -> u32 { + return string_make(s) |> print_string(); } print :: proc #overloaded { print_string, print_u8 } @@ -163,8 +165,33 @@ is_prime :: proc (n: u32) -> bool { return true; } +Vec3 :: struct { + x: f32; + y: f32; + z: f32; +} + +S :: struct { + name: string; + age: u32; + pos: Vec3; +} + +output_s :: proc (sb: ^StringBuilder, s: ^S) -> ^StringBuilder { + sb |> sba("Hello, I'm ") + |> sba(s.name) + |> sba(". I am ") + |> sba(cast(u64) s.age) + |> sba(" years old. I am at (") + |> sba(cast(u64) s.pos.x) |> sba(", ") + |> sba(cast(u64) s.pos.y) |> sba(", ") + |> sba(cast(u64) s.pos.z) |> sba(").\n"); + + return sb; +} + main :: proc (argc: u32, argv: ^cstring) { - sb := string_builder_make(^heap_allocator, 16); + sb := string_builder_make(^heap_allocator, 256); timer := timer_start(); defer { @@ -176,13 +203,9 @@ main :: proc (argc: u32, argv: ^cstring) { |> print(); } - ^sb |> sba("\x01\x02\x03There are ") + ^sb |> sba("There are ") |> sba(cast(u64) argc) - |> sba(" arguments.\n") - |> string_builder_to_string() - |> print(); - - string_builder_clear(^sb); + |> sba(" arguments.\n"); for i: 0, argc do ^sb |> sba(argv[i]) |> sba(" "); ^sb |> sba("\n") @@ -257,4 +280,11 @@ main :: proc (argc: u32, argv: ^cstring) { string_builder_clear(^sb); ^sb |> sba("The program evaluated to '") |> sba(cast(u64) acc) |> sba("'\n"); ^sb |> string_builder_to_string() |> print(); + ^sb |> string_builder_clear(); + + person := S.{ name = "Tester", age = 45, pos = Vec3.{ 1.0f, 2.0f, 3.0f } }; + ^sb |> output_s(^person) + |> sba("Here is another message in the same string!\n") + |> string_builder_to_string() + |> print(); } diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 789f2405..a90494ee 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -207,6 +207,15 @@ CHECK(call, AstCall* call) { return 1; } + if (actual_param->value->type->kind == Type_Kind_Struct) { + if (!type_struct_is_simple(actual_param->value->type)) { + onyx_message_add(Msg_Type_Literal, + actual_param->token->pos, + "can only pass simple structs as parameters (no nested structures). passing by pointer is the only way for now."); + return 1; + } + } + prev_param = (AstNode **) &actual_param->next; actual_param = (AstArgument *) actual_param->next; } diff --git a/src/onyxlex.c b/src/onyxlex.c index fdbfb8b1..5439dda5 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -234,52 +234,101 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { goto token_parsed; } - LITERAL_TOKEN("package", 1, Token_Type_Keyword_Package); - LITERAL_TOKEN("struct", 1, Token_Type_Keyword_Struct); - LITERAL_TOKEN("enum" , 1, Token_Type_Keyword_Enum); - LITERAL_TOKEN("use", 1, Token_Type_Keyword_Use); - LITERAL_TOKEN("if", 1, Token_Type_Keyword_If); - LITERAL_TOKEN("elseif", 1, Token_Type_Keyword_Elseif); - LITERAL_TOKEN("else", 1, Token_Type_Keyword_Else); - LITERAL_TOKEN("global", 1, Token_Type_Keyword_Global); - LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return); - LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc); - LITERAL_TOKEN("as", 1, Token_Type_Keyword_As); - LITERAL_TOKEN("cast", 1, Token_Type_Keyword_Cast); - LITERAL_TOKEN("while", 1, Token_Type_Keyword_While); - LITERAL_TOKEN("for", 1, Token_Type_Keyword_For); - LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break); - LITERAL_TOKEN("continue", 1, Token_Type_Keyword_Continue); - LITERAL_TOKEN("sizeof", 1, Token_Type_Keyword_Sizeof); - LITERAL_TOKEN("alignof", 1, Token_Type_Keyword_Alignof); - LITERAL_TOKEN("defer", 1, Token_Type_Keyword_Defer); - LITERAL_TOKEN("do", 1, Token_Type_Keyword_Do); - LITERAL_TOKEN("true", 1, Token_Type_Literal_True); - LITERAL_TOKEN("false", 1, Token_Type_Literal_False); - LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow); - LITERAL_TOKEN("<-", 0, Token_Type_Right_Arrow); - LITERAL_TOKEN("---", 0, Token_Type_Empty_Block); - LITERAL_TOKEN("|>", 0, Token_Type_Pipe); - LITERAL_TOKEN("&&", 0, Token_Type_And_And); - LITERAL_TOKEN("||", 0, Token_Type_Or_Or); - LITERAL_TOKEN(">>>=", 0, Token_Type_Sar_Equal); - LITERAL_TOKEN(">>=", 0, Token_Type_Shr_Equal); - LITERAL_TOKEN("<<=", 0, Token_Type_Shl_Equal); - LITERAL_TOKEN(">>>", 0, Token_Type_Shift_Arith_Right); - LITERAL_TOKEN(">>", 0, Token_Type_Shift_Right); - LITERAL_TOKEN("<<", 0, Token_Type_Shift_Left); - LITERAL_TOKEN("&=", 0, Token_Type_And_Equal); - LITERAL_TOKEN("|=", 0, Token_Type_Or_Equal); - LITERAL_TOKEN("^=", 0, Token_Type_Xor_Equal); - LITERAL_TOKEN("<=", 0, Token_Type_Less_Equal); - LITERAL_TOKEN(">=", 0, Token_Type_Greater_Equal); - LITERAL_TOKEN("==", 0, Token_Type_Equal_Equal); - LITERAL_TOKEN("!=", 0, Token_Type_Not_Equal); - LITERAL_TOKEN("+=", 0, Token_Type_Plus_Equal); - LITERAL_TOKEN("-=", 0, Token_Type_Minus_Equal); - LITERAL_TOKEN("*=", 0, Token_Type_Star_Equal); - LITERAL_TOKEN("/=", 0, Token_Type_Fslash_Equal); - LITERAL_TOKEN("%=", 0, Token_Type_Percent_Equal); + char curr = *tokenizer->curr; + switch (curr) { + case 'a': + LITERAL_TOKEN("alignof", 1, Token_Type_Keyword_Alignof); + LITERAL_TOKEN("as", 1, Token_Type_Keyword_As); + break; + case 'b': + LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break); + break; + case 'c': + LITERAL_TOKEN("cast", 1, Token_Type_Keyword_Cast); + LITERAL_TOKEN("continue", 1, Token_Type_Keyword_Continue); + break; + case 'd': + LITERAL_TOKEN("defer", 1, Token_Type_Keyword_Defer); + LITERAL_TOKEN("do", 1, Token_Type_Keyword_Do); + break; + case 'e': + LITERAL_TOKEN("enum" , 1, Token_Type_Keyword_Enum); + LITERAL_TOKEN("elseif", 1, Token_Type_Keyword_Elseif); + LITERAL_TOKEN("else", 1, Token_Type_Keyword_Else); + break; + case 'f': + LITERAL_TOKEN("for", 1, Token_Type_Keyword_For); + LITERAL_TOKEN("false", 1, Token_Type_Literal_False); + break; + case 'g': + LITERAL_TOKEN("global", 1, Token_Type_Keyword_Global); + break; + case 'i': + LITERAL_TOKEN("if", 1, Token_Type_Keyword_If); + break; + case 'p': + LITERAL_TOKEN("package", 1, Token_Type_Keyword_Package); + LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc); + break; + case 'r': + LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return); + break; + case 's': + LITERAL_TOKEN("sizeof", 1, Token_Type_Keyword_Sizeof); + LITERAL_TOKEN("struct", 1, Token_Type_Keyword_Struct); + break; + case 't': + LITERAL_TOKEN("true", 1, Token_Type_Literal_True); + break; + case 'u': + LITERAL_TOKEN("use", 1, Token_Type_Keyword_Use); + break; + case 'w': + LITERAL_TOKEN("while", 1, Token_Type_Keyword_While); + break; + + case '-': + LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow); + LITERAL_TOKEN("---", 0, Token_Type_Empty_Block); + LITERAL_TOKEN("-=", 0, Token_Type_Minus_Equal); + break; + + case '<': + LITERAL_TOKEN("<-", 0, Token_Type_Right_Arrow); + LITERAL_TOKEN("<<=", 0, Token_Type_Shl_Equal); + LITERAL_TOKEN("<<", 0, Token_Type_Shift_Left); + LITERAL_TOKEN("<=", 0, Token_Type_Less_Equal); + break; + + case '>': + LITERAL_TOKEN(">>>=", 0, Token_Type_Sar_Equal); + LITERAL_TOKEN(">>=", 0, Token_Type_Shr_Equal); + LITERAL_TOKEN(">>>", 0, Token_Type_Shift_Arith_Right); + LITERAL_TOKEN(">>", 0, Token_Type_Shift_Right); + LITERAL_TOKEN(">=", 0, Token_Type_Greater_Equal); + break; + + case '&': + LITERAL_TOKEN("&&", 0, Token_Type_And_And); + LITERAL_TOKEN("&=", 0, Token_Type_And_Equal); + break; + + case '|': + LITERAL_TOKEN("|>", 0, Token_Type_Pipe); + LITERAL_TOKEN("||", 0, Token_Type_Or_Or); + LITERAL_TOKEN("|=", 0, Token_Type_Or_Equal); + break; + + default: + LITERAL_TOKEN("^=", 0, Token_Type_Xor_Equal); + LITERAL_TOKEN("==", 0, Token_Type_Equal_Equal); + LITERAL_TOKEN("!=", 0, Token_Type_Not_Equal); + LITERAL_TOKEN("+=", 0, Token_Type_Plus_Equal); + LITERAL_TOKEN("*=", 0, Token_Type_Star_Equal); + LITERAL_TOKEN("/=", 0, Token_Type_Fslash_Equal); + LITERAL_TOKEN("%=", 0, Token_Type_Percent_Equal); + break; + } // Symbols if (char_is_alpha(*tk.text) || *tokenizer->curr == '_') { diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 8133520a..7c23f9ad 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -1186,16 +1186,27 @@ COMPILE_FUNC(struct_store, Type* type, u64 offset) { WIL(WI_LOCAL_SET, loc_idx); bh_arr_rev_each(StructMember *, smem, type->Struct.memarr) { - WasmType wt = onyx_type_to_wasm_type((*smem)->type); - u64 tmp_idx = local_raw_allocate(mod->local_alloc, wt); + if ((*smem)->type->kind == Type_Kind_Struct) { + if (bh_arr_last(code).type == WI_LOCAL_SET && bh_arr_last(code).data.l == loc_idx) { + bh_arr_last(code).type = WI_LOCAL_TEE; + } else { + WIL(WI_LOCAL_GET, loc_idx); + } + + compile_struct_store(mod, &code, (*smem)->type, offset + (*smem)->offset); - WIL(WI_LOCAL_SET, tmp_idx); - WIL(WI_LOCAL_GET, loc_idx); - WIL(WI_LOCAL_GET, tmp_idx); + } else { + WasmType wt = onyx_type_to_wasm_type((*smem)->type); + u64 tmp_idx = local_raw_allocate(mod->local_alloc, wt); + + WIL(WI_LOCAL_SET, tmp_idx); + WIL(WI_LOCAL_GET, loc_idx); + WIL(WI_LOCAL_GET, tmp_idx); - compile_store_instruction(mod, &code, (*smem)->type, offset + (*smem)->offset); + compile_store_instruction(mod, &code, (*smem)->type, offset + (*smem)->offset); - local_raw_free(mod->local_alloc, wt); + local_raw_free(mod->local_alloc, wt); + } } local_raw_free(mod->local_alloc, WASM_TYPE_INT32);