bugfixes; starting work on wasm module
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 2 Jul 2021 03:47:20 +0000 (22:47 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 2 Jul 2021 03:47:20 +0000 (22:47 -0500)
bin/onyx
core/conv.onyx
core/io/reader.onyx
modules/js_events/js_events.onyx
modules/wasm_utils/module.onyx [new file with mode: 0644]
modules/wasm_utils/types.onyx [new file with mode: 0644]
modules/wasm_utils/utils.onyx [new file with mode: 0644]
src/onyxtypes.c
tests/new_printf
tests/new_printf.onyx

index 018c527e86e83b881220b65689209e054c44cecf..592017b57df7b408a5510425bbbf8403a581c85e 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index cd020b69f2c577266972e855f54d6b3979428604..842407d363fedc00f5dba7e5f8b4a7dc28aa2bf0 100644 (file)
@@ -186,7 +186,7 @@ f64_to_str :: (f: f64, buf: [] u8) -> str {
 
 // This is better than the above version, but still relies on converting the integer
 // part of the float to an integer, which could overflow.
-f64_to_str :: (f: f64, buf: [] u8) -> str {
+f64_to_str :: (f: f64, buf: [] u8, digits_after_decimal := 4) -> str {
     math :: package core.math
 
     len := 0;
@@ -208,15 +208,14 @@ f64_to_str :: (f: f64, buf: [] u8) -> str {
 
     digits := "0123456789";
 
-    decimals :: 4;
-    for i: decimals {
+    for i: digits_after_decimal {
         dec_part *= 10;
         v := math.trunc(dec_part);
         dec_part -= v;
 
         buf.data[len + i] = digits[cast(i32) v];
     }
-    len += decimals;
+    len += digits_after_decimal;
 
     return str.{ buf.data, len };
 }
@@ -226,7 +225,6 @@ str_format :: (format: str, buffer: [] u8, va: ..any) -> str {
 }
 
 str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
-    @Cleanup
     Output :: struct {
         data: ^u8;
         count: u32;
@@ -241,7 +239,12 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
             },
 
             (use output: ^Output, s: str) {
-                for c: s do output->write(c);
+                for c: s {
+                    if count >= capacity do return;
+
+                    data[count] = c;
+                    count += 1;
+                }
             }
         }
     }
@@ -251,7 +254,6 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
     Format :: struct {
         digits_after_decimal := cast(u32) 4;
     }
-    formatting := Format.{};
 
     vararg_index := 0;
 
@@ -259,6 +261,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
         defer i += 1;
 
         ch := format[i];
+        formatting := Format.{};
 
         if ch == #char "{" {
             if format[i + 1] == #char "{" {
@@ -267,8 +270,8 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                 continue;
             }
 
+            i += 1;
             while true {
-                i += 1;
                 ch = format[i];
 
                 switch ch {
@@ -282,6 +285,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                             i += 1;
                         }
 
+                        ch = format[i];
                         formatting.digits_after_decimal = digits;
                     }
 
@@ -299,7 +303,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
 
             arg := va[vararg_index];
             vararg_index += 1;
-            print_any(^output, arg);
+            print_any(^output, formatting, arg);
 
             continue;
         }
@@ -309,7 +313,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
 
     return .{ output.data, output.count };
 
-    print_any :: (output: ^Output, v: any) {
+    print_any :: (output: ^Output, formatting: Format, v: any) {
         use package builtin.type_info
         array :: package core.array
 
@@ -320,6 +324,19 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                 else     do output->write("false");
             }
 
+            case u8 {
+                value := *(cast(^u8) v.data);
+
+                if value > 31 {
+                    output->write(value);
+
+                } else {
+                    ibuf : [128] u8;
+                    istr := i64_to_str(~~value, 16, ~~ibuf);
+                    output->write(istr);
+                }
+            }
+
             case i32, u32 {
                 value := *(cast(^i32) v.data);
 
@@ -340,7 +357,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                 value := *(cast(^f32) v.data);
 
                 fbuf : [128] u8;
-                fstr := f64_to_str(~~value, ~~fbuf);
+                fstr := f64_to_str(~~value, ~~fbuf, formatting.digits_after_decimal);
                 output->write(fstr);
             }
 
@@ -348,7 +365,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                 value := *(cast(^f64) v.data);
 
                 fbuf : [128] u8;
-                fstr := f64_to_str(~~value, ~~fbuf);
+                fstr := f64_to_str(~~value, ~~fbuf, formatting.digits_after_decimal);
                 output->write(fstr);
             }
 
@@ -377,13 +394,23 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                         output->write(member.name);
                         output->write(" = ");
 
-                        print_any(output, .{ ~~(cast(^u8) v.data + member.offset), member.type });
+                        print_any(output, formatting, .{ ~~(cast(^u8) v.data + member.offset), member.type });
                     }
 
                     output->write(" }");
                 }
 
-                if info.kind == .Function do output->write("<function>");
+                if info.kind == .Function {
+                    output->write("func[");
+
+                    value := *(cast(^i32) v.data);
+
+                    ibuf : [128] u8;
+                    istr := i64_to_str(~~value, 10, ~~ibuf);
+                    output->write(istr);
+
+                    output->write("]");
+                }
 
                 if info.kind == .Pointer {
                     value := *(cast(^rawptr) v.data);
@@ -405,7 +432,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                     for i: count {
                         if i != 0 do output->write(", ");
 
-                        print_any(output, .{ ~~(cast(^u8) data + get_type_info(a.of).size * i), a.of });
+                        print_any(output, formatting, .{ ~~(cast(^u8) data + get_type_info(a.of).size * i), a.of });
                     }
                     
                     output->write(" ]");
@@ -420,7 +447,7 @@ str_format_va :: (format: str, buffer: [] u8, va: [] any) -> str {
                     for i: a.count {
                         if i != 0 do output->write(", ");
 
-                        print_any(output, .{ ~~(cast(^u8) data + get_type_info(a.of).size * i), a.of });
+                        print_any(output, formatting, .{ ~~(cast(^u8) data + get_type_info(a.of).size * i), a.of });
                     }
 
                     output->write(" ]");
index 943d360ba59fb49656146b6d5f4d50f034f789c7..4367566e0fde5eb09dc3dfa419fe83ab5ea6465e 100644 (file)
@@ -24,10 +24,17 @@ read_byte :: (use reader: ^Reader) -> u8 {
     return byte;
 }
 
-read_bytes :: (use reader: ^Reader, bytes := 1, allocator := context.allocator) -> str {
-    buffer := memory.make_slice(u8, bytes, allocator);
-    stream_read(stream, buffer);
-    return buffer;
+read_bytes :: #match {
+    (use reader: ^Reader, bytes := 1, allocator := context.allocator) -> str {
+        buffer := memory.make_slice(u8, bytes, allocator);
+        stream_read(stream, buffer);
+        return buffer;
+    },
+
+    (use reader: ^Reader, bytes: [] u8) -> str {
+        err, bytes_read := stream_read(stream, bytes);
+        return bytes;
+    }
 }
 
 read_u32 :: (use reader: ^Reader) -> u32 {
@@ -192,4 +199,4 @@ skip_whitespace :: (use reader: ^Reader) {
 
 skip_bytes :: (use reader: ^Reader, bytes: u32) {
     for _: bytes do stream_read_byte(stream);
-}
\ No newline at end of file
+}
index ec441cb8245948e3ea4e0db4feda98013e65ed13..ae73ff9b3a30f1903ae8bb22e5e71fd5af99e324 100644 (file)
@@ -95,20 +95,20 @@ init :: () {
     event_setup(^event_storage, sizeof Event);
 }
 
-consume :: () -> Iterator(Event) {
-    next :: (_: rawptr) -> (Event, bool) {
-        use package core.intrinsics.onyx { __zero_value }
-        if event_storage.event_count == 0 do return __zero_value(Event), false;
+#private_file processing_event: Event
+consume :: () -> Iterator(^Event) {
+    next :: (_: rawptr) -> (^Event, bool) {
+        if event_storage.event_count == 0 do return null, false;
 
         @CodeGeneration // This instruction (and all instructions involving Event) generate a TON of instructions because Event is a union.
-        event := event_storage.event_buffer[0];
+        processing_event := event_storage.event_buffer[0];
 
         for i: 0 .. Num_Buffered_Events - 2 {
             event_storage.event_buffer[i] = event_storage.event_buffer[i + 1];
         }
         event_storage.event_count -= 1;
         
-        return event, true;
+        return ^processing_event, true;
     }
 
     return .{ null, next };
diff --git a/modules/wasm_utils/module.onyx b/modules/wasm_utils/module.onyx
new file mode 100644 (file)
index 0000000..7d8a471
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+
+WebAssembly 32-bit disassembly and decompiler utils
+
+*/
+
+package wasm_utils
+
+#load "./types"
+#load "./utils"
+
+#private map  :: package core.map
+#private io   :: package core.io
+#private hash :: package core.hash
diff --git a/modules/wasm_utils/types.onyx b/modules/wasm_utils/types.onyx
new file mode 100644 (file)
index 0000000..e4b5f74
--- /dev/null
@@ -0,0 +1,91 @@
+package wasm_utils
+
+WasmSection :: enum {
+    Custom    :: 0x00;
+    Type      :: 0x01;
+    Import    :: 0x02;
+    Function  :: 0x03;
+    Table     :: 0x04;
+    Memory    :: 0x05;
+    Global    :: 0x06;
+    Export    :: 0x07;
+    Start     :: 0x08;
+    Element   :: 0x09;
+    Code      :: 0x0a;
+    Data      :: 0x0b;
+    DataCount :: 0x0c;
+}
+
+#add_match hash.to_u32, (w: WasmSection) -> u32 {
+    return hash.to_u32(cast(u32) w);
+}
+
+WasmBinary :: struct {
+    data: [] u8;
+
+    // Section number -> Offset into data
+    // This does not work for custom sections, as they all have the same section number
+    section_locations : map.Map(WasmSection, i32);
+
+    // So there is a custom section location that maps the name of the custom section
+    // to the offset into the file. The backing-store for the keys is just the data
+    // itself, as the names are in the data for the binary.
+    custom_section_locations : map.Map(str, i32);
+}
+
+load :: (data: [] u8, allocator := context.allocator) -> WasmBinary {
+    binary: WasmBinary;
+    binary.data = data;
+    
+    #context_scope {
+        context.allocator = allocator;
+        map.init(^binary.section_locations, -1);
+        map.init(^binary.custom_section_locations, -1);
+    }
+
+    assert(parse_section_locations(^binary), "Failed to parse WASM binary");
+
+    return binary;
+}
+
+
+#private_file
+parse_section_locations :: (use bin: ^WasmBinary) -> bool {
+    stream := io.string_stream_make(data);
+    reader := io.reader_make(^stream);
+
+    {
+        // Checking the magic string
+        magic_buffer: [4] u8; 
+
+        if !(io.read_bytes(^reader, cast([] u8) magic_buffer) == ~~u8.[ 0, #char "a", #char "s", #char "m" ]) do return false;
+        if !(io.read_bytes(^reader, cast([] u8) magic_buffer) == ~~u8.[ 1, 0, 0, 0 ]) do return false; // This may not be necessary
+    }
+    while !io.stream_end_of_file(^stream) {
+        section_number := cast(WasmSection) io.read_byte(^reader);
+        section_size   := read_uleb128(^reader);
+        _, pos := io.stream_tell(^stream);
+
+        switch section_number {
+            @Incomplete
+            case .Custom ---
+
+            case .Type, .Import, .Function, .Table, .Memory, .Global,
+                .Export, .Start, .Element, .Code, .Data, .DataCount  {
+                map.put(^section_locations, section_number, pos);
+            }
+
+            case #default {
+                buffer: [128] u8;
+                conv :: package core.conv
+                assert(false, conv.str_format("Bad section number {}", ~~buffer, cast(i32) section_number));
+            }
+        }
+
+        err := io.stream_seek(^stream, pos + ~~section_size, .Start);
+        if err == .OutOfBounds do break;
+    }
+
+    return true;
+}
diff --git a/modules/wasm_utils/utils.onyx b/modules/wasm_utils/utils.onyx
new file mode 100644 (file)
index 0000000..326da06
--- /dev/null
@@ -0,0 +1,39 @@
+package wasm_utils
+
+#private_file io :: package core.io
+
+#private
+read_uleb128 :: (use reader: ^io.Reader) -> u64 {
+    result: u64 = 0;
+    shift := 0;
+    byte: u8;
+
+    while true {
+        byte = io.read_byte(reader);
+        result |= ~~((byte & 127) << ~~shift);
+        if (byte & 128) == 0 do break;
+
+        shift += 7;
+    }
+
+    return result;
+}
+
+#private
+read_sleb128 :: (use reader: ^io.Reader, size := 4) -> i64 {
+    result: i64 = 0;
+    shift := 0;
+    byte: u8 = 128;
+
+    while (byte & 128) != 0 {
+        byte = io.read_byte(reader);
+        result |= ~~((byte & 127) << ~~shift);
+        shift += 7;
+    }
+
+    if (shift < size) && (byte & 64) > 0 {
+        result |= 0xFFFFFFFFFFFFFFFF << ~~shift;
+    }
+
+    return result;
+}
index 36fc57bf9f38cf2db3cb4669e8f459f758ee4b36..58734c65b7db927b8a1813bbe70e4b686129b566 100644 (file)
@@ -484,6 +484,9 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             AstPolyCallType* pc_type = (AstPolyCallType *) type_node;
 
             if (!(pc_type->callee && pc_type->callee->kind == Ast_Kind_Poly_Struct_Type)) {
+                // If it is an unresolved field access, just return because an error will be printed elsewhere.
+                if (pc_type->callee->kind == Ast_Kind_Field_Access) return NULL;
+
                 onyx_report_error(pc_type->token->pos, "Cannot instantiate a concrete type off of a non-polymorphic type.");
                 return NULL;
             }
index 3442358f08db89b9c3b1d73cfbf4a762816cec3a..08594c7822c7084fbc9eec43cdbe6b3c38c12755 100644 (file)
@@ -1 +1 @@
-123 Test { } false 0x4E8
+123 Test {} false 12.3 12.34567
index c53077ad3fdbb146b97e8da26d7a5632a0d01752..cf188d5451fa1bb77795780625cb9b330467356c 100644 (file)
@@ -3,5 +3,5 @@
 use package core
 
 main :: (args: [] cstr) {
-    printf("{} {} {{ }} {} {}\n", 123, "Test", false, ^stdio.print_writer);
+    printf("{} {} {{}} {} {.1} {.5}\n", 123, "Test", false, 12.34, 12.3456789);
 }