From: Brendan Hansen Date: Mon, 10 Aug 2020 02:06:14 +0000 (-0500) Subject: random improvements X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=12994409cbd0f0604dfcc6b5189781089149ff36;p=onyx.git random improvements --- diff --git a/.vimspector.json b/.vimspector.json index 343544d8..41b49cb7 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -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": [], diff --git a/Makefile b/Makefile index 6a575b28..0e514db6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -RELEASE=0 +RELEASE=1 OBJ_FILES=\ build/onyxlex.o \ diff --git a/docs/plan b/docs/plan index 94de23d3..7c5ac2ca 100644 --- 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 diff --git a/include/bh.h b/include/bh.h index 3760fda2..5d498f84 100644 --- a/include/bh.h +++ b/include/bh.h @@ -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 }; diff --git a/misc/onyx.sublime-syntax b/misc/onyx.sublime-syntax index c728bf37..e60ade04 100644 --- a/misc/onyx.sublime-syntax +++ b/misc/onyx.sublime-syntax @@ -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 376fff4d..ec5938bd 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/alloc.onyx b/progs/alloc.onyx index b432d769..ec753e5e 100644 --- a/progs/alloc.onyx +++ b/progs/alloc.onyx @@ -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); diff --git a/progs/alloc_test.onyx b/progs/alloc_test.onyx index c8accc5b..7e6156ad 100644 --- a/progs/alloc_test.onyx +++ b/progs/alloc_test.onyx @@ -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); diff --git a/progs/print_funcs.onyx b/progs/print_funcs.onyx index d368c5f7..aa668d04 100644 --- a/progs/print_funcs.onyx +++ b/progs/print_funcs.onyx @@ -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, diff --git a/progs/stack_based.onyx b/progs/stack_based.onyx index e1b2b6ee..1abc86d2 100644 --- a/progs/stack_based.onyx +++ b/progs/stack_based.onyx @@ -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 diff --git a/src/onyxchecker.c b/src/onyxchecker.c index e5aace0b..73c26260 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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; diff --git a/src/onyxparser.c b/src/onyxparser.c index 2a7b53c4..5b0c3ffc 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 0320cab4..116eb158 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index caff5d93..7033abef 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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); }