random improvements
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Aug 2020 02:06:14 +0000 (21:06 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Aug 2020 02:06:14 +0000 (21:06 -0500)
14 files changed:
.vimspector.json
Makefile
docs/plan
include/bh.h
misc/onyx.sublime-syntax
onyx
progs/alloc.onyx
progs/alloc_test.onyx
progs/print_funcs.onyx
progs/stack_based.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index 343544d8da763434d1a4109c557bec9e96054430..41b49cb7edeea24d2e72e29ac8b8d72d358a9898 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/alloc_test.onyx"],
+                "args": ["progs/stack_based.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index 6a575b282e20f57fc1e2e7133d374497dbadb4ff..0e514db6108e81017afbacf2eac82318593c4738 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-RELEASE=0
+RELEASE=1
 
 OBJ_FILES=\
        build/onyxlex.o \
index 94de23d3ed4f6189c0f820d9ad11bd3a4149b47b..7c5ac2ca1a231f9c0329b21fa9222fd060293692 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -148,18 +148,31 @@ HOW:
 
         [X] Be smart about when to use the stack versus use the wasm locals
 
-        [ ] Array literals
+        [ ] Better numeric literals
+            - suffix 'f' for float32
+            - no suffix 'f', but has decimal for float64
+            - suffix 'l' for int64
+            - nothing special for i32 or below
+
+        [ ] Char literals
 
         [ ] Properly checking binary operators
+            - Shouldn't be able to add two structs/arrays together
+
+        [ ] Array literals
 
         [ ] Better checking for casts
+            - Checking which things are allowed to cast to/from should be checked in the checker,
+                not in the wasm generatation
+
+        [ ] Start work on evaluating compile time known values.
+            - An expression marked COMPTIME will be reduced to its value in the parse tree.
 
         [ ] All code paths return correct value
 
         [ ] #initialize structs
 
-        [ ] Start work on evaluating compile time known values.
-            - An expression marked COMPTIME will be reduced to its value in the parse tree.
+        [ ] Variadic arguments
 
         [ ] Switch statements
 
index 3760fda290e57e2594dc3ed0b75354a2dd07a187..5d498f84856e9fd95ba9de8b9e28aecf412d1ff4 100644 (file)
@@ -101,22 +101,39 @@ inline i64 chars_match(char* ptr1, char* ptr2) {
 
 static inline u64 log2_dumb(u64 n) {
     switch (n) {
-    case 1:    return 0;
-    case 2:    return 1;
-    case 4:    return 2;
-    case 8:    return 3;
-    case 16:   return 4;
-    case 32:   return 5;
-    case 64:   return 6;
-    case 128:  return 7;
-    case 256:  return 8;
-    case 512:  return 9;
-    case 1024: return 10;
-    case 2048: return 11;
-    case 4096: return 12;
-    case 8192: return 13;
-
-    // Don't need all of them right now
+    case 1 << 0:  return 0;
+    case 1 << 1:  return 1;
+    case 1 << 2:  return 2;
+    case 1 << 3:  return 3;
+    case 1 << 4:  return 4;
+    case 1 << 5:  return 5;
+    case 1 << 6:  return 6;
+    case 1 << 7:  return 7;
+    case 1 << 8:  return 8;
+    case 1 << 9:  return 9;
+    case 1 << 10: return 10;
+    case 1 << 11: return 11;
+    case 1 << 12: return 12;
+    case 1 << 13: return 13;
+    case 1 << 14: return 14;
+    case 1 << 15: return 15;
+    case 1 << 16: return 16;
+    case 1 << 17: return 17;
+    case 1 << 18: return 18;
+    case 1 << 19: return 19;
+    case 1 << 20: return 20;
+    case 1 << 21: return 21;
+    case 1 << 22: return 22;
+    case 1 << 23: return 23;
+    case 1 << 24: return 24;
+    case 1 << 25: return 25;
+    case 1 << 26: return 26;
+    case 1 << 27: return 27;
+    case 1 << 28: return 28;
+    case 1 << 29: return 29;
+    case 1 << 30: return 30;
+    case 1 << 31: return 31;
+
     default:   return 0;
     }
 }
@@ -262,6 +279,17 @@ BH_ALLOCATOR_PROC(bh_scratch_allocator_proc);
 
 
 
+//-------------------------------------------------------------------------------------
+// Allocator based string functions
+//-------------------------------------------------------------------------------------
+
+char* bh_strdup(bh_allocator a, char* str);
+
+
+
+
+
+
 
 
 
@@ -1169,9 +1197,19 @@ u8* double_to_ieee754(f64 f, b32 reverse) {
 
 
 
+//-------------------------------------------------------------------------------------
+// STRING IMPLEMENTATION
+//-------------------------------------------------------------------------------------
+char* bh_strdup(bh_allocator a, char* str) {
+    u32 len = strlen(str);
+    char* buf = bh_alloc(a, len + 1);
 
+    char* t = buf;
+    while (*t++ = *str++);
 
-
+    *t = 0;
+    return buf;
+}
 
 
 
@@ -1336,7 +1374,7 @@ i64 bh_file_size(bh_file* file) {
 bh_file_contents bh_file_read_contents_bh_file(bh_allocator alloc, bh_file* file) {
     bh_file_contents fc = {
         .allocator = alloc,
-        .filename  = file->filename,
+        .filename  = bh_strdup(alloc, (char *) file->filename),
         .length = 0, .data = NULL
     };
 
index c728bf370619ff466f29e9393ae15e40ebefd99a..e60ade0408fbc120e136834f93e1af0f0d0c5d05 100644 (file)
@@ -33,7 +33,7 @@ contexts:
       scope: constant.boolean.onyx
 
     # Numbers
-    - match: '\b(-)?[0-9.]+\b'
+    - match: '\b(-)?[0-9.]+(f|l)?\b'
       scope: constant.numeric.onyx
 
     - match: '\b0x[0-9A-Fa-f]+\b'
diff --git a/onyx b/onyx
index 376fff4dd8ac50d50e4bcaad5a5dda682cffcf92..ec5938bda814e7c885cc0be7a5d61d3c3786c68c 100755 (executable)
Binary files a/onyx and b/onyx differ
index b432d7698a0829334b40714f24e048019e9e91b2..ec753e5e6e1f77cdaf2afe576d18c03a3e1bd92e 100644 (file)
@@ -39,12 +39,14 @@ free :: proc (use a: ^Allocator, ptr: rawptr) {
 
 heap_allocator : Allocator;
 
+#private
 heap_state : struct {
     free_list       : ^heap_block;
     next_alloc      : rawptr;
     remaining_space : u32;
 }
 
+#private
 heap_block :: struct {
     size : u32;
     next : ^heap_block;
@@ -59,6 +61,7 @@ heap_init :: proc {
     heap_allocator.func = heap_alloc_proc;
 }
 
+#private
 heap_alloc :: proc (size_: u32, align: u32) -> rawptr {
     if size_ == 0 do return null;
 
@@ -109,6 +112,7 @@ heap_alloc :: proc (size_: u32, align: u32) -> rawptr {
     return cast(rawptr) (cast(u32) ret + sizeof heap_block);
 }
 
+#private
 heap_free :: proc (ptr: rawptr) {
     hb_ptr := cast(^heap_block) (cast(u32) ptr - sizeof heap_block);
 
@@ -119,6 +123,7 @@ heap_free :: proc (ptr: rawptr) {
     heap_state.free_list = hb_ptr;
 }
 
+#private
 heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
     if aa == AllocAction.Alloc do return heap_alloc(size, align);
     if aa == AllocAction.Free {
@@ -129,10 +134,5 @@ heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, o
     return null;
 }
 
-malloc :: proc (size: u32) -> rawptr {
-    return alloc(^heap_allocator, size);
-}
-
-mfree :: proc (ptr: rawptr) {
-    free(^heap_allocator, ptr);
-}
\ No newline at end of file
+malloc :: proc (size: u32) -> rawptr do return alloc(^heap_allocator, size);
+mfree  :: proc (ptr: rawptr) do free(^heap_allocator, ptr);
index c8accc5b9c57fd3edab64cf6d0236df97dff5078..7e6156ad85b7532b4f2ea835e0e60298f70cc1ed 100644 (file)
@@ -5,7 +5,7 @@ use package memory
 use package printing
 
 deferred_example :: proc -> i32 {
-    arr := cast([] i64) malloc(sizeof [8] i64);
+    arr := cast(^i64) malloc(sizeof [8] i64);
     if cast(rawptr) arr == null do return 0;
     defer mfree(arr);
 
@@ -13,23 +13,23 @@ deferred_example :: proc -> i32 {
 
     walker := cast(^i64) arr;
     for _: 0, 8 {
-        print(*walker);
+        print_u64(cast(i64) *walker);
         walker += 1;
     }
 
     return cast(i32) (arr[1] + arr[7]);
 }
 
-proc #export "main" {
+proc #export "start" {
     print(#file_contents "progs/filetest");
     heap_init();
 
     print(deferred_example());
 
-    first := cast([] i32) malloc(sizeof [4] i32);
+    first: [4] i32;
     for i: 0, 4 do first[i] = i * 2;
 
-    second := cast([] f32) malloc(sizeof [24] f32);
+    second := cast(^f32) malloc(sizeof [24] f32);
     for i: 0, 24 do second[i] = cast(f32) i;
 
     print(cast(u32) first);
@@ -48,7 +48,7 @@ proc #export "main" {
 
     mfree(second);
 
-    fourth := cast([] i32) malloc(sizeof [128]i32);
+    fourth := cast(^i32) malloc(sizeof [128]i32);
     print(cast(u32) fourth);
 
     fifth := cast(^i32) malloc(sizeof i32);
index d368c5f71ee8bbc894f7e6b96a4685fd7afa4a51..aa668d043d62dd479cb21e766f6a2c2f6d4c1e95 100644 (file)
@@ -28,7 +28,7 @@ print_f64arr :: proc (arr: [] f64, len: i32) {
 }
 
 // NOTE: print null-terminated string
-print_str :: proc (str: ^u8) {
+print_str_by_byte :: proc (str: ^u8) {
     c := str;
     while *c != cast(u8) 0 {
         print(cast(i32) (*c));
@@ -36,10 +36,48 @@ print_str :: proc (str: ^u8) {
     }
 }
 
+print_str :: proc #foreign "host" "print_str" (str: ^u8) ---
+
 print_str_len :: proc (str: [] u8, len: i32) {
     for i: 0, len do print(cast(i32) str[i]);
 }
 
+print_u64 :: proc (n_: u64) {
+    n := n_;
+    str: [128] u8;
+    c := cast(^u8) ^str[127];
+    *c = cast(u8) 0;
+    c -= 1;
+
+    if n == cast(u64) 0 {
+        *c = cast(u8) 0x30;
+        c -= 1;
+    } else {
+        while n > cast(u64) 0 {
+            m :: n % cast(u64) 10;
+
+            ch := cast(u8) 0;
+            if m == cast(u64) 0 do ch = cast(u8) 0x30;
+            if m == cast(u64) 1 do ch = cast(u8) 0x31;
+            if m == cast(u64) 2 do ch = cast(u8) 0x32;
+            if m == cast(u64) 3 do ch = cast(u8) 0x33;
+            if m == cast(u64) 4 do ch = cast(u8) 0x34;
+            if m == cast(u64) 5 do ch = cast(u8) 0x35;
+            if m == cast(u64) 6 do ch = cast(u8) 0x36;
+            if m == cast(u64) 7 do ch = cast(u8) 0x37;
+            if m == cast(u64) 8 do ch = cast(u8) 0x38;
+            if m == cast(u64) 9 do ch = cast(u8) 0x39;
+
+            *c = ch;
+            c -= 1;
+
+            n /= cast(u64) 10;
+        }
+    }
+
+    print(c + 1);
+}
+
 print :: proc #overloaded {
     print_bool,
     print_i32,
index e1b2b6eee75ead368d75127f9d35fb8e9c466926..1abc86d2c7d5d03462d2e89b1236f1442777b406 100644 (file)
@@ -24,10 +24,7 @@ sumN :: proc (x: [N] i32) -> i32 {
 
 summing :: proc (x: ^i32) -> i32 {
     s := 0;
-    for i: 0, N {
-        tmp :: ^i;
-        s += x[i];
-    }
+    for i: 0, N do s += x[i];
     return s;
 }
 
@@ -41,32 +38,54 @@ mag_squared :: proc (v: Vec3) -> i32 {
     return v.x * v.x + v.y * v.y + v.z * v.z;
 }
 
-stuff :: #file_contents "Makefile"
+vec_add :: proc (v: Vec3, u: Vec3, use out: ^Vec3) {
+    x = v.x + u.x;
+    y = v.y + u.y;
+    z = v.z + u.z;
+}
 
-main :: proc #export {
+start :: proc #export {
     heap_init();
     print("Hello, World!");
     print(cast(i32) __heap_start);
 
     a := 12345;
 
-    arr: [N] i32;
-    arr[0] = 10;
-    arr[1] = 20;
-    arr[2] = 30;
-    arr[3] = 40;
-    arr[4] = 50;
-    arr[9] = 123;
-    print(sumN(arr));
-    print(summing(cast(^i32) arr));
-
-    v: Vec3;
-    v.x = 2;
-    v.y = 4;
-    v.z = 10;
-    print(mag_squared(v));
+    arr: [N][N] i32;
+    arr[1][0] = 10;
+    arr[1][1] = 20;
+    arr[1][2] = 30;
+    arr[1][3] = 40;
+    arr[1][4] = 50;
+    arr[1][9] = 123;
+    print(sumN(arr[1]));
+    print(summing(cast(^i32) arr[1]));
+
+    v1: Vec3;
+    v1.x = 2;
+    v1.y = 4;
+    v1.z = 10;
+
+    v2: Vec3;
+    v2.x = 4;
+    v2.y = 2;
+    v2.z = 1;
+
+    v3: Vec3;
+    vec_add(v1, v2, ^v3);
+    print(v3.x);
+    print(v3.y);
+    print(v3.z);
+    print(mag_squared(v3));
 
     print(ret_val(10, 4));
     
-    for i: 0, N do print(arr[i]);
+    for i: 0, N do print(arr[1][i]);
+
+    soa: struct { x: [5] i32; y: [5] i32; };
+    for i: 0, 5 {
+        soa.x[i] = i;
+        soa.y[i] = i * i;
+    }
+    print(soa.y[3]);
 }
\ No newline at end of file
index e5aace0ba7823b82af098f0756ed149d4354442b..73c262605473ec655b5cdeb1335274c71d384f29 100644 (file)
@@ -87,33 +87,45 @@ CHECK(while, AstWhile* whilenode) {
 CHECK(for, AstFor* fornode) {
     if (check_expression(&fornode->start)) return 1;
     if (check_expression(&fornode->end)) return 1;
-    if (fornode->step)
-        if (check_expression(&fornode->step)) return 1;
+    if (check_expression(&fornode->step)) return 1;
 
+    fornode->var->type_node = fornode->start->type_node;
     if (check_expression((AstTyped **) &fornode->var)) return 1;
 
-    // HACK
-    if (!types_are_compatible(fornode->start->type, &basic_types[Basic_Kind_I32])) {
+    if (!type_is_integer(fornode->start->type)) {
         onyx_message_add(Msg_Type_Literal,
                 fornode->start->token->pos,
-                "expected expression of type i32 for start");
+                "expected expression of integer type for start");
         return 1;
     }
 
-    if (!types_are_compatible(fornode->end->type, &basic_types[Basic_Kind_I32])) {
+    if (!type_is_integer(fornode->end->type)) {
         onyx_message_add(Msg_Type_Literal,
                 fornode->end->token->pos,
-                "expected expression of type i32 for end");
+                "expected expression of integer type for end");
         return 1;
     }
 
-    if (fornode->step)
-        if (!types_are_compatible(fornode->step->type, &basic_types[Basic_Kind_I32])) {
-            onyx_message_add(Msg_Type_Literal,
-                    fornode->start->token->pos,
-                    "expected expression of type i32 for step");
-            return 1;
-        }
+    if (!type_is_integer(fornode->step->type)) {
+        onyx_message_add(Msg_Type_Literal,
+                fornode->step->token->pos,
+                "expected expression of integer type for step");
+        return 1;
+    }
+
+    if (!types_are_compatible(fornode->end->type, fornode->start->type)) {
+        onyx_message_add(Msg_Type_Literal,
+                fornode->end->token->pos,
+                "type of end does not match type of start");
+        return 1;
+    }
+
+    if (!types_are_compatible(fornode->step->type, fornode->start->type)) {
+        onyx_message_add(Msg_Type_Literal,
+                fornode->start->token->pos,
+                "type of step does not match type of start");
+        return 1;
+    }
 
 
     if (check_block(fornode->stmt)) return 1;
index 2a7b53c42aa28f6c59034a25893f036664e8aca3..5b0c3ffcddb027359bf952ca52ba22fb37153e5c 100644 (file)
@@ -612,6 +612,10 @@ static AstFor* parse_for_stmt(OnyxParser* parser) {
     if (parser->curr->type == ',') {
         consume_token(parser);
         for_node->step = parse_expression(parser);
+    } else {
+        for_node->step = make_node(AstNumLit, Ast_Kind_NumLit);
+        for_node->step->type_node = (AstType *) &basic_type_i32;
+        ((AstNumLit *) for_node->step)->value.i = 1;
     }
 
     for_node->stmt = parse_block(parser);
index 0320cab49a7e6b1e5cb1d740e2766d9012f6e6db..116eb15895d8088cf4adbb60cb7dd48f3c64cbfa 100644 (file)
@@ -297,7 +297,7 @@ static void symres_for(AstFor* fornode) {
 
     symres_expression(&fornode->start);
     symres_expression(&fornode->end);
-    if (fornode->step) symres_expression(&fornode->step);
+    symres_expression(&fornode->step);
 
     symres_block(fornode->stmt);
 
index caff5d93d98d2f6c3897a2df2ec31410f28b15c5..7033abef074946bab2102bcc120893b309c7da7f 100644 (file)
@@ -580,6 +580,11 @@ COMPILE_FUNC(for, AstFor* for_node) {
     u32 it_idx = (u32) (tmp & ~LOCAL_IS_WASM);
     u64 offset = 0;
 
+    WasmType var_type = onyx_type_to_wasm_type(for_node->var->type);
+    assert(var_type == WASM_TYPE_INT32 || var_type == WASM_TYPE_INT64);
+    WasmInstructionType add_instr = var_type == WASM_TYPE_INT32 ? WI_I32_ADD  : WI_I64_ADD;
+    WasmInstructionType ge_instr  = var_type == WASM_TYPE_INT32 ? WI_I32_GE_S : WI_I64_GE_S;
+
     if (it_is_local) {
         compile_expression(mod, &code, for_node->start);
         WID(WI_LOCAL_SET, it_idx);
@@ -603,7 +608,7 @@ COMPILE_FUNC(for, AstFor* for_node) {
         compile_load_instruction(mod, &code, var->type, offset);
     }
     compile_expression(mod, &code, for_node->end);
-    WI(WI_I32_GE_S);
+    WI(ge_instr);
     WID(WI_COND_JUMP, 0x01);
 
     forll (AstNode, stmt, for_node->stmt->body, next) {
@@ -612,11 +617,8 @@ COMPILE_FUNC(for, AstFor* for_node) {
 
     if (it_is_local) {
         WID(WI_LOCAL_GET, it_idx);
-        if (for_node->step == NULL)
-            WID(WI_I32_CONST, 0x01);
-        else
-            compile_expression(mod, &code, for_node->step);
-        WI(WI_I32_ADD);
+        compile_expression(mod, &code, for_node->step);
+        WI(add_instr);
         WID(WI_LOCAL_SET, it_idx);
     } else {
         offset = 0;
@@ -624,11 +626,8 @@ COMPILE_FUNC(for, AstFor* for_node) {
         offset = 0;
         compile_local_location(mod, &code, var, &offset);
         compile_load_instruction(mod, &code, var->type, offset);
-        if (for_node->step == NULL)
-            WID(WI_I32_CONST, 0x01);
-        else
-            compile_expression(mod, &code, for_node->step);
-        WI(WI_I32_ADD);
+        compile_expression(mod, &code, for_node->step);
+        WI(add_instr);
         compile_store_instruction(mod, &code, var->type, type_get_alignment_log2(var->type), offset);
     }
 
@@ -980,7 +979,7 @@ COMPILE_FUNC(expression, AstTyped* expr) {
 
                 if (expr->type->kind != Type_Kind_Array) {
                     compile_load_instruction(mod, &code, expr->type, offset);
-                } else {
+                } else if (offset != 0) {
                     WID(WI_I32_CONST, offset);
                     WI(WI_I32_ADD);
                 }