From: Brendan Hansen Date: Fri, 2 Apr 2021 04:01:43 +0000 (-0500) Subject: refactoring the standup code to be more modular X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=677c31f50d5e677ff6c3b569b14b89db4b4465d6;p=onyx.git refactoring the standup code to be more modular --- diff --git a/bin/onyx b/bin/onyx index 2cd9c348..a733f4b9 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/bin/test b/bin/test index 98aae825..4b485717 100755 --- a/bin/test +++ b/bin/test @@ -17,19 +17,19 @@ for test_file in $(find tests/ -name '*.onyx'); do print_check "$name" if ! ./bin/onyx -r js --use-post-mvp-features "$test_file" -o "./tests/$name.wasm" >/dev/null; then - print "\n❌ Failed to compile $name.onyx.\n" + printf "\n❌ Failed to compile $name.onyx.\n" failed=1 continue fi if ! ./bin/onyx-js "./tests/$name.wasm" > ./tmpoutput; then - print "\n❌ Failed to run $name.onyx.\n" + printf "\n❌ Failed to run $name.onyx.\n" failed=1 continue fi if ! diff ./tmpoutput "$dirname/$name" >/dev/null; then - print "\n❌ Test output did not match.\n" + printf "\n❌ Test output did not match.\n" diff ./tmpoutput "$dirname/$name" # failed=0 continue diff --git a/core/build_opts.onyx b/core/build_opts.onyx deleted file mode 100644 index 11f1cf95..00000000 --- a/core/build_opts.onyx +++ /dev/null @@ -1,21 +0,0 @@ -// This following sybmols are not meant to be included in any compilation. -// Instead, all of the commented out symbols are defined automatically by the compiler -// and can be used in compile time #if statements. - -// Runtime :: Runtime_Wasi OR Runtime_Js OR Runtime_Custom - - - - - -package build_opts - - -// At some point, these will become an enum. The problem at the moment is that -// compile-time if statements are not well integrated into other language features -// such as enums. They can only really handle compile time number math and boolean -// logic. - brendanfh 2020/02/08 - -Runtime_Wasi :: 1 -Runtime_Js :: 2 -Runtime_Custom :: 3 diff --git a/core/builtin.onyx b/core/builtin.onyx index ccb57325..b15509f5 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -1,5 +1,9 @@ package builtin -use package build_opts as build_opts + +// CLEANUP: Should builtin.onyx really be including other files in the compilation? +// Does that complicate things too much? +#load "core/runtime/build_opts" +use package runtime as runtime str :: #type []u8; cstr :: #type ^u8; @@ -31,7 +35,7 @@ vararg_get :: proc { ret := *cast(^T) va.data; va.data = cast(rawptr) (cast(^u8) va.data + sizeof T); va.count -= 1; - return res; + return ret; } } @@ -53,7 +57,7 @@ OnyxContext :: struct { assert_handler : (msg: str, file: str) -> void; } -#if build_opts.Runtime != build_opts.Runtime_Custom { +#if runtime.Runtime != runtime.Runtime_Custom { #private_file default_logger :: (data: rawptr, msg: str) { use package core println(msg); @@ -132,14 +136,14 @@ calloc :: (size: u32) -> rawptr do return raw_alloc(context.allocator, size); cresize :: (ptr: rawptr, size: u32) -> rawptr do return raw_resize(context.allocator, ptr, size); cfree :: (ptr: rawptr) do raw_free(context.allocator, ptr); -#if build_opts.Runtime != build_opts.Runtime_Custom { +#if runtime.Runtime != runtime.Runtime_Custom { new :: ($T: type_expr, allocator := context.allocator, initialize := true) -> ^T { res := cast(^T) raw_alloc(allocator, sizeof T); // @Robustness: This should be a '#if' when those are added in procedures because // otherwise the __initialize intrinsic is going to be generated no matter what. // This could be a problem if the type is not something that can be initialized. - use package core.intrinsics.wasm { __initialize } + use package core.intrinsics.onyx { __initialize } if initialize do __initialize(res); return res; diff --git a/core/env.onyx b/core/env.onyx index 660c158d..e1b2770c 100644 --- a/core/env.onyx +++ b/core/env.onyx @@ -1,7 +1,7 @@ package core.env -use package build_opts as build_opts -#if build_opts.Runtime != build_opts.Runtime_Wasi { +use package runtime as runtime +#if runtime.Runtime != runtime.Runtime_Wasi { #error "'core.env' is only available with the 'wasi' runtime."; } diff --git a/core/intrinsics/onyx.onyx b/core/intrinsics/onyx.onyx new file mode 100644 index 00000000..e77a2ddd --- /dev/null +++ b/core/intrinsics/onyx.onyx @@ -0,0 +1,3 @@ +package core.intrinsics.onyx + +__initialize :: (val: ^$T) -> void #intrinsic --- diff --git a/core/intrinsics/wasm.onyx b/core/intrinsics/wasm.onyx index fd7174e4..0d2d115d 100644 --- a/core/intrinsics/wasm.onyx +++ b/core/intrinsics/wasm.onyx @@ -5,8 +5,6 @@ memory_grow :: (val: i32) -> i32 #intrinsic --- memory_copy :: (dst: rawptr, src: rawptr, count: i32) -> void #intrinsic --- memory_fill :: (dst: rawptr, byte: u8, count: i32) -> void #intrinsic --- -__initialize :: (val: ^$T) -> void #intrinsic --- - clz_i32 :: (val: i32) -> i32 #intrinsic --- ctz_i32 :: (val: i32) -> i32 #intrinsic --- popcnt_i32 :: (val: i32) -> i32 #intrinsic --- diff --git a/core/io/file.onyx b/core/io/file.onyx index 99c1759c..757be624 100644 --- a/core/io/file.onyx +++ b/core/io/file.onyx @@ -1,7 +1,7 @@ package core.io -use package build_opts as build_opts -#if build_opts.Runtime != build_opts.Runtime_Wasi { +use package runtime as runtime +#if runtime.Runtime != runtime.Runtime_Wasi { #error "The file system library is currently only available on the WASI runtime, and should only be included if that is the chosen runtime." } diff --git a/core/js/webgl.onyx b/core/js/webgl.onyx index 8ebabfd2..b0befbef 100644 --- a/core/js/webgl.onyx +++ b/core/js/webgl.onyx @@ -3,8 +3,8 @@ package gl // To be used with the corresponding gl.js // There are many things that are missing but this suffices for me. -use package build_opts as build_opts -#if build_opts.Runtime != build_opts.Runtime_Js { +use package runtime as runtime +#if runtime.Runtime != runtime.Runtime_Js { #error "'webgl' can only be used with the 'js' runtime." } diff --git a/core/map.onyx b/core/map.onyx index cbdb47b9..e8ac3db8 100644 --- a/core/map.onyx +++ b/core/map.onyx @@ -1,6 +1,5 @@ package core.map -use package core { printf } use package core.array as array use package core.string as string diff --git a/core/runtime/build_opts.onyx b/core/runtime/build_opts.onyx new file mode 100644 index 00000000..5b60b137 --- /dev/null +++ b/core/runtime/build_opts.onyx @@ -0,0 +1,21 @@ +// This following sybmols are not meant to be included in any compilation. +// Instead, all of the commented out symbols are defined automatically by the compiler +// and can be used in compile time #if statements. + +// Runtime :: Runtime_Wasi OR Runtime_Js OR Runtime_Custom + + + + + +package runtime + + +// At some point, these will become an enum. The problem at the moment is that +// compile-time if statements are not well integrated into other language features +// such as enums. They can only really handle compile time number math and boolean +// logic. - brendanfh 2020/02/08 + +Runtime_Wasi :: 1 +Runtime_Js :: 2 +Runtime_Custom :: 3 diff --git a/core/runtime/common.onyx b/core/runtime/common.onyx new file mode 100644 index 00000000..917a97fa --- /dev/null +++ b/core/runtime/common.onyx @@ -0,0 +1,34 @@ +package runtime + +use package core +use package core.intrinsics.onyx { __initialize } + +// The default assert handler. This assumes that __output_string +// and __exit are defined in the 'runtime' package. +__assert_handler :: (msg: str, file: str) { + __output_string("Assert failed: "); + __output_string(msg); + + if file.data != null { + __output_string(" in "); + __output_string(file); + } + + __output_string("\n"); + + __exit(1); +} + +// Use this procedure to initialize everything needed in the +// standard library when you are dropped directly into a function. +__runtime_initialize :: () { + alloc.init(); + + __initialize(^context); + context.allocator = alloc.heap_allocator; + context.temp_allocator = alloc.temp_allocator; + context.assert_handler = __assert_handler; + + __stdio_init(); +} + diff --git a/core/runtime/js.onyx b/core/runtime/js.onyx new file mode 100644 index 00000000..2907569c --- /dev/null +++ b/core/runtime/js.onyx @@ -0,0 +1,20 @@ +package runtime + +#load "core/runtime/common" + +use package core +use package main as main + +__output_string :: (s: str) -> u32 #foreign "host" "print_str" --- +__exit :: (status: i32) -> void #foreign "host" "exit" --- + +// The builtin _start proc. +// Sets up everything needed for execution. +proc () #export "_start" { + __runtime_initialize(); + + args: [] cstr = .{ null, 0 }; + main.main(args); + + __flush_stdio(); +} diff --git a/core/runtime/wasi.onyx b/core/runtime/wasi.onyx new file mode 100644 index 00000000..3fdb3365 --- /dev/null +++ b/core/runtime/wasi.onyx @@ -0,0 +1,52 @@ +package runtime + +#load "core/wasi" +#load "core/runtime/common" + +use package wasi +use package core +use package main as main + +__output_string :: (s: str) -> u32 { + STDOUT_FILENO :: 1 + + vec := IOVec.{ buf = cast(u32) s.data, len = s.count }; + tmp : Size; + fd_write(STDOUT_FILENO, IOVecArray.{ cast(u32) ^vec, 1 }, ^tmp); + fd_datasync(STDOUT_FILENO); + return tmp; +} + +__exit :: (status: i32) do proc_exit(status); + +// The builtin _start proc. +// Sets up everything needed for execution. +proc () #export "_start" { + __runtime_initialize(); + + args : [] cstr; + argv_buf_size : Size; + args_sizes_get(^args.count, ^argv_buf_size); + + args = memory.make_slice(cstr, args.count); + argv_buf := cast(cstr) calloc(argv_buf_size); + args_get(args.data, argv_buf); + + + // This post processing of the argv array needs to happen if the target is using + // 32-bit pointers, instead of 64-bits. Right now, Onyx pointers take up 64-bits, + // but in most circumstances, only the lower 32-bits are used. When webassembly + // standardizes the 64-bit address space, it will be an easy conversion over. + // But for right now, WASI will give the argv array 32-bit pointers, instead of + // 64-bit pointers. This loops expands the 32-bit pointers into 64-bit pointers + // while not clobbering any of them. + while i := cast(i32) (args.count - 1); i >= 0 { + defer i -= 1; + + args[i] = cast(cstr) (cast(^u32) args.data)[i]; + } + + main.main(args); + + __flush_stdio(); +} diff --git a/core/std.onyx b/core/std.onyx index 58428eb4..d10f13e1 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -1,8 +1,6 @@ package core -#load "core/build_opts" - #load "core/alloc" #load "core/memory" @@ -17,6 +15,7 @@ package core #load "core/string/builder" #load "core/string/reader" +#load "core/intrinsics/onyx" #load "core/intrinsics/wasm" #load "core/io/io" @@ -25,18 +24,21 @@ package core #load "core/io/writer" #load "core/io/binary" -use package build_opts as build_opts -#if build_opts.Runtime == build_opts.Runtime_Wasi { - #load "core/sys/wasi" +#load "core/runtime/build_opts" +#load "core/runtime/common" + +use package runtime as runtime +#if runtime.Runtime == runtime.Runtime_Wasi { + #load "core/runtime/wasi" #load "core/wasi" #load "core/io/file" #load "core/env" } -#if build_opts.Runtime == build_opts.Runtime_Js { - #load "core/sys/js" +#if runtime.Runtime == runtime.Runtime_Js { + #load "core/runtime/js" } -#if build_opts.Runtime != build_opts.Runtime_Custom { +#if runtime.Runtime != runtime.Runtime_Custom { #load "core/stdio" } diff --git a/core/stdio.onyx b/core/stdio.onyx index 47ac620b..81a98369 100644 --- a/core/stdio.onyx +++ b/core/stdio.onyx @@ -10,25 +10,15 @@ package core // It is expected that a file will be included that will be part // of the system package -use package build_opts as build_opts -#if build_opts.Runtime != build_opts.Runtime_Custom { - use package system as system -} else { +use package runtime as runtime +#if runtime.Runtime == runtime.Runtime_Custom { #error "'stdio' can only be included in the 'wasi' or 'js' runtime." } -#private_file print_stream : io.DynamicStringStream; -#private_file print_writer : io.Writer; - -stdio_init :: () { - print_stream = io.dynamic_string_stream_make(2048, context.allocator); - print_writer = io.writer_make(^print_stream); -} - print :: proc { (x: str) { io.write(^print_writer, x); - if x[x.count - 1] == #char "\n" do print_stream_flush(); + if x[x.count - 1] == #char "\n" do __flush_stdio(); }, (x: $T) { io.write(^print_writer, x); }, @@ -66,12 +56,26 @@ print_array :: proc { } } -print_stream_flush :: () { + +// +// Private and internal things +// + +#private_file print_stream : io.DynamicStringStream; +#private_file print_writer : io.Writer; + +__stdio_init :: () { + print_stream = io.dynamic_string_stream_make(2048, context.allocator); + print_writer = io.writer_make(^print_stream); +} + + +__flush_stdio :: () { if print_stream.data.count == 0 do return; ^print_stream |> io.dynamic_string_stream_to_str() - |> system.output_str(); + |> runtime.__output_string(); ^print_stream |> io.stream_flush(); } diff --git a/core/string.onyx b/core/string.onyx index 18a2e75e..76d86963 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -41,20 +41,24 @@ length :: proc { }, } -// trim_start :: (s: str, ch := #char " ") -> str -// trim_start :: (s: ^str, ch := #char " ") -// trim_end :: (s: str, ch := #char " ") -> str -// trim_end :: (s: ^str, ch := #char " ") +concat :: proc { + (s1: str, s2: str, allocator := context.allocator) -> str { + len1 := length(s1); + len2 := length(s2); -concat :: (s1: str, s2: str, allocator := context.allocator) -> str { - len1 := length(s1); - len2 := length(s2); + data := cast(^u8) raw_alloc(allocator, len1 + len2); + memory.copy(data, s1.data, len1); + memory.copy(data + len1, s2.data, len2); - data := cast(^u8) raw_alloc(allocator, len1 + len2); - memory.copy(data, s1.data, len1); - memory.copy(data + len1, s2.data, len2); + return str.{ data, len1 + len2 }; + }, - return str.{ data, len1 + len2 }; + (into: ^[..] u8, s: str) -> str { + array.ensure_capacity(into, into.count + s.count); + memory.copy(into.data, s.data, into.count); + into.count += s.count; + return .{ into.data, into.count }; + } } split :: (s: str, delim: u8, allocator := context.allocator) -> []str { @@ -85,7 +89,7 @@ contains :: proc { return false; }, - (s: str, substr: str) -> bool #export "ASDFASDFASDF" { + (s: str, substr: str) -> bool { while i := 0; i < s.count { while j := 0; j < substr.count { if s[i + j] != substr[j] { diff --git a/core/string/reader.onyx b/core/string/reader.onyx index 2b46d033..c950227d 100644 --- a/core/string/reader.onyx +++ b/core/string/reader.onyx @@ -1,7 +1,5 @@ package core.string.reader -use package core { printf } - StringReader :: struct { // Think of this as `use s : str`; data : ^u8; diff --git a/core/sys/js.onyx b/core/sys/js.onyx deleted file mode 100644 index 727eddc9..00000000 --- a/core/sys/js.onyx +++ /dev/null @@ -1,43 +0,0 @@ -package system - -use package core -use package main as main -use package core.intrinsics.wasm { __initialize } - -output_str :: (s: str) -> u32 #foreign "host" "print_str" --- - -assert_handler :: (msg: str, file: str) { - output_str("Assert failed: "); - output_str(msg); - - if file.data != null { - output_str(" in "); - output_str(file); - } - - output_str("\n"); - - process_exit :: proc (status: i32) #foreign "host" "exit" --- - process_exit(1); -} - -// The builtin _start proc. -// Sets up everything needed for execution. -proc () #export "_start" { - alloc.init(); - - __initialize(^context); - context.allocator = alloc.heap_allocator; - context.temp_allocator = alloc.temp_allocator; - context.assert_handler = assert_handler; - - args : [] cstr; - args.data = null; - args.count = 0; - - stdio_init(); - - main.main(args); - - print_stream_flush(); -} diff --git a/core/sys/wasi.onyx b/core/sys/wasi.onyx deleted file mode 100644 index 2805a217..00000000 --- a/core/sys/wasi.onyx +++ /dev/null @@ -1,82 +0,0 @@ -package system - -#load "core/wasi" - -use package wasi -use package core -use package main as main -use package core.intrinsics.wasm { __initialize } - -STDOUT_FILENO :: 1 - -output_str :: (s: str) -> u32 { - vec := IOVec.{ buf = cast(u32) s.data, len = s.count }; - tmp : Size; - fd_write(STDOUT_FILENO, IOVecArray.{ cast(u32) ^vec, 1 }, ^tmp); - fd_datasync(STDOUT_FILENO); - return tmp; -} - -assert_handler :: (msg: str, file: str) { - output_str("Assert failed: "); - output_str(msg); - - if file.data != null { - output_str(" in "); - output_str(file); - } - - output_str("\n"); - - proc_exit(1); -} - -proc () #export "_initialize" { - alloc.init(); - - __initialize(^context); - context.allocator = alloc.heap_allocator; - context.temp_allocator = alloc.temp_allocator; - context.assert_handler = assert_handler; - - stdio_init(); -} - -// The builtin _start proc. -// Sets up everything needed for execution. -proc () #export "_start" { - alloc.init(); - - __initialize(^context); - context.allocator = alloc.heap_allocator; - context.temp_allocator = alloc.temp_allocator; - context.assert_handler = assert_handler; - - stdio_init(); - - args : [] cstr; - argv_buf_size : Size; - args_sizes_get(^args.count, ^argv_buf_size); - - args = memory.make_slice(cstr, args.count); - argv_buf := cast(cstr) calloc(argv_buf_size); - args_get(args.data, argv_buf); - - - // This post processing of the argv array needs to happen if the target is using - // 32-bit pointers, instead of 64-bits. Right now, Onyx pointers take up 64-bits, - // but in most circumstances, only the lower 32-bits are used. When webassembly - // standardizes the 64-bit address space, it will be an easy conversion over. - // But for right now, WASI will give the argv array 32-bit pointers, instead of - // 64-bit pointers. This loops expands the 32-bit pointers into 64-bit pointers - // while not clobbering any of them. - while i := cast(i32) (args.count - 1); i >= 0 { - defer i -= 1; - - args[i] = cast(cstr) (cast(^u32) args.data)[i]; - } - - main.main(args); - - print_stream_flush(); -} diff --git a/include/bh.h b/include/bh.h index 127e74ad..c3dcdb32 100644 --- a/include/bh.h +++ b/include/bh.h @@ -1221,7 +1221,7 @@ b32 bh_str_ends_with(char* str, char* end) { while (*e == *s && e != end && s != str) e--, s--; - return e == end; + return *e == *s; } char* bh_strdup(bh_allocator a, char* str) { diff --git a/progs/poly_solidify.onyx b/progs/poly_solidify.onyx index 29c6219c..931c5e7e 100644 --- a/progs/poly_solidify.onyx +++ b/progs/poly_solidify.onyx @@ -11,7 +11,7 @@ specific_compose_1 :: #solidify specific_compose_0 { A = f32 }; specific_compose_2 :: #solidify specific_compose_1 { C = f64 }; main :: proc (args: [] cstr) { - use package build_opts + use package runtime println(Runtime); println("=================================================="); @@ -78,4 +78,4 @@ array_map :: proc (arr: [..] $T, f: proc (T) -> T) { } } -double :: proc (v: $V) -> V do return v * 2; \ No newline at end of file +double :: proc (v: $V) -> V do return v * 2; diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index 0d8a9b4c..f4c0ca28 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -383,7 +383,7 @@ void initialize_builtins(bh_allocator a) { } void introduce_build_options(bh_allocator a) { - Package* p = package_lookup_or_create("build_opts", context.global_scope, a); + Package* p = package_lookup_or_create("runtime", context.global_scope, a); AstNumLit* runtime_type = make_int_literal(a, context.options->runtime); symbol_builtin_introduce(p->scope, "Runtime", (AstNode *) runtime_type);