refactoring the standup code to be more modular
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 2 Apr 2021 04:01:43 +0000 (23:01 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 2 Apr 2021 04:01:43 +0000 (23:01 -0500)
23 files changed:
bin/onyx
bin/test
core/build_opts.onyx [deleted file]
core/builtin.onyx
core/env.onyx
core/intrinsics/onyx.onyx [new file with mode: 0644]
core/intrinsics/wasm.onyx
core/io/file.onyx
core/js/webgl.onyx
core/map.onyx
core/runtime/build_opts.onyx [new file with mode: 0644]
core/runtime/common.onyx [new file with mode: 0644]
core/runtime/js.onyx [new file with mode: 0644]
core/runtime/wasi.onyx [new file with mode: 0644]
core/std.onyx
core/stdio.onyx
core/string.onyx
core/string/reader.onyx
core/sys/js.onyx [deleted file]
core/sys/wasi.onyx [deleted file]
include/bh.h
progs/poly_solidify.onyx
src/onyxbuiltins.c

index 2cd9c3488783a3389a5f4c0c9f89f50d4aff95d0..a733f4b9ce3a68cabb61d2577f856de8f62869ea 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 98aae8253623b4423a1c266b5ca6bdb49944dc33..4b485717f6fc9d24e0593ec4702ad3563ed6607b 100755 (executable)
--- 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 (file)
index 11f1cf9..0000000
+++ /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
index ccb573251a9ad036d0dd00f8348418b7b19d5ed7..b15509f51fa08b1e21ff39421d95bef73a14003b 100644 (file)
@@ -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;
index 660c158d2cce96076301f5a982a3da15be3e4092..e1b2770cbd7fa5b3ce2995739ce79fc17c03e9bf 100644 (file)
@@ -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 (file)
index 0000000..e77a2dd
--- /dev/null
@@ -0,0 +1,3 @@
+package core.intrinsics.onyx
+
+__initialize :: (val: ^$T) -> void #intrinsic ---
index fd7174e47a100a675c3c72124434f22e223378a4..0d2d115d6e701a76d137db36d919555ac7f39479 100644 (file)
@@ -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 ---
index 99c1759c0c6eab6e55c546027531d38dc63e5c10..757be624c7c9a1e9be51193b6015a988695fa6a3 100644 (file)
@@ -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."
 }
 
index 8ebabfd26682315c3fb04871a00c39309dae1f4d..b0befbef181ef5087263185491f7f12a4164bef9 100644 (file)
@@ -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."
 }
 
index cbdb47b9bb9b1fa6df5b67024e42e90219704f52..e8ac3db8939643f966a990ce7bc8f792a192317c 100644 (file)
@@ -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 (file)
index 0000000..5b60b13
--- /dev/null
@@ -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 (file)
index 0000000..917a97f
--- /dev/null
@@ -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 (file)
index 0000000..2907569
--- /dev/null
@@ -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 (file)
index 0000000..3fdb336
--- /dev/null
@@ -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();
+}
index 58428eb4e7a1744d4a6af414c740046df0b01136..d10f13e1edf6376b48ddb36ebcad561c1f826b77 100644 (file)
@@ -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"
 }
index 47ac620bd91d904f5827708b30480b007c093b51..81a983699dd95e9cfc405aca92cc440e2f2294eb 100644 (file)
@@ -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();
 }
index 18a2e75e5fb80ea38d0c41029ecb0bb1ad27cf47..76d8696307d40a5636351cdf8168a7b75cd5da73 100644 (file)
@@ -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] {
index 2b46d0333ce037a8204029563600f3cec0aedaac..c950227dae48131be4420b044539425ad306548a 100644 (file)
@@ -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 (file)
index 727eddc..0000000
+++ /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 (file)
index 2805a21..0000000
+++ /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();
-}
index 127e74ad9aabd027bc02e75fcc891400bedcc685..c3dcdb32d94df6d654f65d5e3ed063de0008dac3 100644 (file)
@@ -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) {
index 29c6219cfd936c111aa87d8c8c86800831767b2a..931c5e7e90b9f9967a407cc755ffe98075c9b735 100644 (file)
@@ -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;
index 0d8a9b4cd356e57100a9c257d9b139f7fa64eaac..f4c0ca28ad2ade16da5325e2ab28fd7e107789a5 100644 (file)
@@ -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);