allowing non simple structures to be stored and loaded
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 Aug 2020 15:44:45 +0000 (10:44 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 Aug 2020 15:44:45 +0000 (10:44 -0500)
Makefile
core/alloc.onyx
core/builtin.onyx
core/string.onyx
docs/plan
onyx
progs/wasi_test.onyx
src/onyxchecker.c
src/onyxlex.c
src/onyxwasm.c

index f92c3aa4281e6993512ef183bc0a6e7552e7d3e8..05c150b3b7215d3313901151d154c916b6bb66d5 100644 (file)
--- 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
index f1ae45093e34364e485a1caad667e702d18a1b11..eb01f0cae2794bc4da852c153f4e84ce81d4949d 100644 (file)
@@ -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;
     }
 
index 6a7d9b7a139f81c5ab3fe4ce135abae09773715b..18788c3744cdf0ceb14a816491f1617be5a46b1e 100644 (file)
@@ -2,7 +2,7 @@ package builtin
 
 string :: struct {
        data : ^u8;
-       len  : u32;     
+       len  : u32;
 }
 
 cstring :: #type ^u8;
\ No newline at end of file
index 4ff1f2fd4604628d81f3fd54e46f2fb34d49bc36..e414f022ee3ad22a40130b671e8f1b18e562b181 100644 (file)
@@ -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;
 
index a3e2cb00bca64b2c1f9115a933dc0654c837b7c5..0cc1c40c230a045d534d10e4bbb3de9ebbb56de2 100644 (file)
--- 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 fc892e9a2dd75a61d07eeb80ed4ff661d685e5c0..0acd7e5597013097b9412cf2746d829cd57e7b50 100755 (executable)
Binary files a/onyx and b/onyx differ
index d0fbf8da8edf4b0c6ad09595f6f6e976e821b8e1..5f7dfb93f02f460bfd094ca09dd677d38a69b8ba 100644 (file)
@@ -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();
 }
index 789f2405a95c7cff5e9048a6a0732c7b4a411e0f..a90494eeea8809ec616a4c7e622e873c433a5e7a 100644 (file)
@@ -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;
     }
index fdbfb8b1681630bd3fe618d35652b9aba080cc9e..5439dda526633244b108fa6a50238db7db4456bf 100644 (file)
@@ -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 == '_') {
index 8133520ac589f6bc314a1d1de9042805f5263305..7c23f9ad1e11250b346212123094a7f74fd4c5a8 100644 (file)
@@ -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);