updated io.stream to use multiple return values; small mrv bug fixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 12 Jan 2021 21:06:23 +0000 (15:06 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 12 Jan 2021 21:06:23 +0000 (15:06 -0600)
bin/onyx
core/io/reader.onyx
core/io/stream.onyx
onyx.exe
src/onyxtypes.c
src/onyxwasm.c
tests/string_stream_test [new file with mode: 0644]
tests/string_stream_test.onyx [new file with mode: 0644]

index dddbe4b52469d33867956c997987a174d9096cc2..c7649f401ecd16b611485336879e01b5844687f1 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 336c782a28e6028969634d1316932e4653fc23b4..14508eb590014b8805401485950aa9785a26c1cd 100644 (file)
@@ -15,15 +15,15 @@ read_u32 :: proc (use reader: ^Reader) -> u32 {
 
     skip_whitespace(reader);
 
-    curr  := cast(u8) 0;
-    stream_peek_byte(stream, ^curr);
+    err, curr := stream_peek_byte(stream);
     while curr >= #char "0" && curr <= #char "9" {
-        stream_read_byte(stream, ^curr);
+        err, curr = stream_read_byte(stream);
 
         n *= 10;
         n += cast(u32) (curr - #char "0"); 
 
-        if stream_peek_byte(stream, ^curr) == Error.EOF do break;
+        err, curr = stream_peek_byte(stream);
+        if err == Error.EOF do break;
     }
 
     return n;
@@ -34,15 +34,15 @@ read_u64 :: proc (use reader: ^Reader) -> u64 {
 
     skip_whitespace(reader);
 
-    curr  := cast(u8) 0;
-    stream_peek_byte(stream, ^curr);
+    err, curr := stream_peek_byte(stream);
     while curr >= #char "0" && curr <= #char "9" {
-        stream_read_byte(stream, ^curr);
+        err, curr = stream_read_byte(stream);
 
         n *= 10;
         n += cast(u64) (curr - #char "0"); 
 
-        if stream_peek_byte(stream, ^curr) == Error.EOF do break;
+        err, curr = stream_peek_byte(stream);
+        if err == Error.EOF do break;
     }
 
     return n;
@@ -53,11 +53,12 @@ read_line :: proc (use reader: ^Reader, allocator := context.allocator) -> str {
     stream_tell(stream, ^curr_pos);
 
     count := 0;
-    curr  := cast(u8) 0;
-    stream_read_byte(stream, ^curr);
+    err, curr := stream_read_byte(stream);
     while curr != #char "\n" {
         count += 1;
-        if stream_read_byte(stream, ^curr) != Error.None do break;
+
+        err, curr = stream_read_byte(stream);
+        if err != Error.None do break;
     }
 
     stream_seek(stream, curr_pos, SeekFrom.Start);
@@ -78,8 +79,7 @@ read_word :: proc (use reader: ^Reader, allocator := context.allocator) -> str {
     stream_tell(stream, ^curr_pos);
 
     count := 0;
-    curr  := cast(u8) 0;
-    stream_read_byte(stream, ^curr);
+    err, curr := stream_read_byte(stream);
 
     while true {
         if     (curr >= #char "a" && curr <= #char "z")
@@ -90,7 +90,8 @@ read_word :: proc (use reader: ^Reader, allocator := context.allocator) -> str {
             break;
         }
 
-        if stream_read_byte(stream, ^curr) != Error.None do break;
+        err, curr = stream_read_byte(stream);
+        if err != Error.None do break;
     }
 
     stream_seek(stream, curr_pos, SeekFrom.Start);
@@ -105,23 +106,25 @@ read_word :: proc (use reader: ^Reader, allocator := context.allocator) -> str {
 }
 
 advance_line :: proc (use reader: ^Reader) {
-    curr := cast(u8) 0;
-    if stream_read_byte(stream, ^curr) != Error.None do return;
+    err, curr := stream_read_byte(stream);
+    if err != Error.None do return;
+    
     while curr != #char "\n" {
-        if stream_read_byte(stream, ^curr) != Error.None do return;
+        err, curr = stream_read_byte(stream);
+        if err != Error.None do return;
     }
 
-    stream_read_byte(stream, ^curr);
+    err, curr = stream_read_byte(stream);
 }
 
 skip_whitespace :: proc (use reader: ^Reader) {
     while true {
-        byte := cast(u8) 0;
-        if stream_peek_byte(stream, ^byte) == Error.EOF do break;
+        err, byte := stream_peek_byte(stream);
+        if err == Error.EOF do break;
 
         switch byte {
             case #char " ", #char "\t", #char "\n", #char "\r" {
-                stream_read_byte(stream, ^byte);
+                err, byte = stream_read_byte(stream);
             }
 
             case #default do return;
index d76d09e54bf3392a6e50660f23a90620636a8af4..2dc30240890d0652312393347e7972dcfd6c90c5 100644 (file)
@@ -11,13 +11,13 @@ Stream_Vtable :: struct {
     seek         : proc (s: ^Stream, to: i32, whence: SeekFrom) -> Error;
     tell         : proc (s: ^Stream, out: ^i32) -> Error;
 
-    read         : proc (s: ^Stream, buffer: [] u8, number_read: ^u32) -> Error;
-    read_at      : proc (s: ^Stream, at: u32, buffer: [] u8, number_read: ^u32) -> Error;
-    read_byte    : proc (s: ^Stream, out: ^u8) -> Error;
+    read         : proc (s: ^Stream, buffer: [] u8) -> (Error, u32);
+    read_at      : proc (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32);
+    read_byte    : proc (s: ^Stream) -> (Error, u8);
     unread_byte  : proc (s: ^Stream) -> Error;
 
-    write        : proc (s: ^Stream, buffer: [] u8, number_written: ^u32) -> Error;
-    write_at     : proc (s: ^Stream, at: u32, buffer: [] u8, number_written: ^u32) -> Error;
+    write        : proc (s: ^Stream, buffer: [] u8) -> (Error, u32);
+    write_at     : proc (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32);
     write_byte   : proc (s: ^Stream, byte: u8) -> Error;
 
     close        : proc (s: ^Stream) -> Error;
@@ -46,25 +46,25 @@ stream_tell :: proc (use s: ^Stream, out: ^i32) -> Error {
     return vtable.tell(s, out);
 }
 
-stream_read :: proc (use s: ^Stream, buffer: [] u8, number_read: ^u32 = null) -> Error {
-    if vtable == null do return Error.NoVtable;
-    if vtable.read == null_proc do return Error.NotImplemented;
+stream_read :: proc (use s: ^Stream, buffer: [] u8) -> (Error, u32) {
+    if vtable == null do return Error.NoVtable, 0;
+    if vtable.read == null_proc do return Error.NotImplemented, 0;
     
-    return vtable.read(s, buffer, number_read);
+    return vtable.read(s, buffer);
 }
 
-stream_read_at :: proc (use s: ^Stream, at: u32, buffer: [] u8, number_read: ^u32 = null) -> Error {
-    if vtable == null do return Error.NoVtable;
-    if vtable.read_at == null_proc do return Error.NotImplemented;
+stream_read_at :: proc (use s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
+    if vtable == null do return Error.NoVtable, 0;
+    if vtable.read_at == null_proc do return Error.NotImplemented, 0;
     
-    return vtable.read_at(s, at, buffer, number_read);
+    return vtable.read_at(s, at, buffer);
 }
 
-stream_read_byte :: proc (use s: ^Stream, out: ^u8) -> Error {
-    if vtable == null do return Error.NoVtable;
-    if vtable.read_byte == null_proc do return Error.NotImplemented;
+stream_read_byte :: proc (use s: ^Stream) -> (Error, u8) {
+    if vtable == null do return Error.NoVtable, cast(u8) 0;
+    if vtable.read_byte == null_proc do return Error.NotImplemented, cast(u8) 0;
     
-    return vtable.read_byte(s, out);
+    return vtable.read_byte(s);
 }
 
 stream_unread_byte :: proc (use s: ^Stream) -> Error {
@@ -74,18 +74,18 @@ stream_unread_byte :: proc (use s: ^Stream) -> Error {
     return vtable.unread_byte(s);
 }
 
-stream_write :: proc (use s: ^Stream, buffer: [] u8, number_written: ^u32 = null) -> Error {
-    if vtable == null do return Error.NoVtable;
-    if vtable.write == null_proc do return Error.NotImplemented;
+stream_write :: proc (use s: ^Stream, buffer: [] u8) -> (Error, u32) {
+    if vtable == null do return Error.NoVtable, 0;
+    if vtable.write == null_proc do return Error.NotImplemented, 0;
     
-    return vtable.write(s, buffer, number_written);
+    return vtable.write(s, buffer);
 }
 
-stream_write_at :: proc (use s: ^Stream, at: u32, buffer: [] u8, number_written: ^u32 = null) -> Error {
-    if vtable == null do return Error.NoVtable;
-    if vtable.write_at == null_proc do return Error.NotImplemented;
+stream_write_at :: proc (use s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
+    if vtable == null do return Error.NoVtable, 0;
+    if vtable.write_at == null_proc do return Error.NotImplemented, 0;
     
-    return vtable.write_at(s, at, buffer, number_written);
+    return vtable.write_at(s, at, buffer);
 }
 
 stream_write_byte :: proc (use s: ^Stream, byte: u8) -> Error {
@@ -116,10 +116,17 @@ stream_size :: proc (use s: ^Stream) -> i32 {
     return vtable.size(s);
 }
 
-stream_peek_byte :: proc (use s: ^Stream, out: ^u8) -> Error {
-    if err := stream_read_byte(s, out); err != Error.None do return err;
-    if err := stream_unread_byte(s);    err != Error.None do return err;
-    return Error.None;
+stream_peek_byte :: proc (use s: ^Stream) -> (Error, u8) {
+    out : u8;
+    err : io.Error;
+
+    err, out = stream_read_byte(s);
+    if err != Error.None do return err, cast(u8) 0;
+
+    err = stream_unread_byte(s);
+    if err != Error.None do return err, cast(u8) 0;
+
+    return Error.None, out;
 }
 
 
@@ -170,43 +177,39 @@ string_stream_vtable := Stream_Vtable.{
         return Error.None;
     },
 
-    read = proc (s: ^Stream, buffer: [] u8, number_read: ^u32) -> Error {
+    read = proc (s: ^Stream, buffer: [] u8) -> (Error, u32) {
         ss : ^StringStream = ~~s;
         use ss;
 
-        if curr_pos >= data.count do return Error.EOF;
+        if curr_pos >= data.count do return Error.EOF, 0;
 
         bytes_to_read := math.min(buffer.count, data.count - curr_pos);
         memory.copy(buffer.data, ^data.data[curr_pos], bytes_to_read);
         curr_pos += bytes_to_read;
 
-        if number_read != null do *number_read = bytes_to_read;
-        return Error.None;
+        return Error.None, bytes_to_read;
     },
 
-    read_at = proc (s: ^Stream, at: u32, buffer: [] u8, number_read: ^u32) -> Error {
+    read_at = proc (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
         ss : ^StringStream = ~~s;
         use ss;
 
-        if at >= data.count do return Error.EOF;
+        if at >= data.count do return Error.EOF, 0;
 
         bytes_to_read := math.min(buffer.count, data.count - at);
         memory.copy(buffer.data, ^data.data[at], bytes_to_read);
 
-        if number_read != null do *number_read = bytes_to_read;
-        return Error.None;
+        return Error.None, bytes_to_read;
     },
 
-    read_byte = proc (s: ^Stream, out: ^u8) -> Error {
+    read_byte = proc (s: ^Stream) -> (Error, u8) #export "DEBUG ME" {
         ss : ^StringStream = ~~s;
         use ss;
 
-        if curr_pos >= data.count do return Error.EOF;
-
-        if out != null do *out = data[curr_pos];
+        if curr_pos >= data.count do return Error.EOF, cast(u8) 0;
 
-        curr_pos += 1;
-        return Error.None;
+        defer curr_pos += 1;
+        return Error.None, data[curr_pos];
     },
 
     unread_byte = proc (s: ^Stream) -> Error {
@@ -219,31 +222,29 @@ string_stream_vtable := Stream_Vtable.{
         return Error.None;
     },
 
-    write = proc (s: ^Stream, buffer: [] u8, number_written: ^u32) -> Error {
+    write = proc (s: ^Stream, buffer: [] u8) -> (Error, u32) {
         ss : ^StringStream = ~~s;
         use ss;
 
-        if curr_pos >= data.count do return Error.EOF;
+        if curr_pos >= data.count do return Error.EOF, 0;
 
         bytes_to_write := math.min(buffer.count, data.count - curr_pos);
         memory.copy(^data.data[curr_pos], buffer.data, bytes_to_write);
         curr_pos += bytes_to_write;
 
-        if number_written != null do *number_written = bytes_to_write;
-        return Error.None;
+        return Error.None, bytes_to_write;
     },
 
-    write_at = proc (s: ^Stream, at: u32, buffer: [] u8, number_written: ^u32) -> Error {
+    write_at = proc (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
         ss : ^StringStream = ~~s;
         use ss;
 
-        if at >= data.count do return Error.EOF;
+        if at >= data.count do return Error.EOF, 0;
 
         bytes_to_write := math.min(buffer.count, data.count - at);
         memory.copy(^data.data[at], buffer.data, bytes_to_write);
 
-        if number_written != null do *number_written = bytes_to_write;
-        return Error.None;
+        return Error.None, bytes_to_write;
     },
 
     write_byte = proc (s: ^Stream, byte: u8) -> Error {
@@ -332,43 +333,39 @@ dynamic_string_stream_vtable := Stream_Vtable.{
         return Error.None;
     },
 
-    read = proc (s: ^Stream, buffer: [] u8, number_read: ^u32) -> Error {
+    read = proc (s: ^Stream, buffer: [] u8) -> (Error, u32) {
         dss : ^DynamicStringStream = ~~s;
         use dss;
 
-        if curr_pos >= data.count do return Error.EOF;
+        if curr_pos >= data.count do return Error.EOF, 0;
 
         bytes_to_read := math.min(buffer.count, data.count - curr_pos);
         memory.copy(buffer.data, ^data.data[curr_pos], bytes_to_read);
         curr_pos += bytes_to_read;
 
-        if number_read != null do *number_read = bytes_to_read;
-        return Error.None;
+        return Error.None, bytes_to_read;
     },
 
-    read_at = proc (s: ^Stream, at: u32, buffer: [] u8, number_read: ^u32) -> Error {
+    read_at = proc (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
         dss : ^DynamicStringStream = ~~s;
         use dss;
 
-        if at >= data.count do return Error.EOF;
+        if at >= data.count do return Error.EOF, 0;
 
         bytes_to_read := math.min(buffer.count, data.count - at);
         memory.copy(buffer.data, ^data.data[at], bytes_to_read);
 
-        if number_read != null do *number_read = bytes_to_read;
-        return Error.None;
+        return Error.None, bytes_to_read;
     },
 
-    read_byte = proc (s: ^Stream, out: ^u8) -> Error {
+    read_byte = proc (s: ^Stream) -> (Error, u8) {
         dss : ^DynamicStringStream = ~~s;
         use dss;
 
-        if curr_pos >= data.count do return Error.EOF;
-
-        if out != null do *out = data[curr_pos];
+        if curr_pos >= data.count do return Error.EOF, cast(u8) 0;
 
-        curr_pos += 1;
-        return Error.None;
+        defer curr_pos += 1;
+        return Error.None, data[curr_pos];
     },
 
     unread_byte = proc (s: ^Stream) -> Error {
@@ -381,14 +378,14 @@ dynamic_string_stream_vtable := Stream_Vtable.{
         return Error.None;
     },
 
-    write = proc (s: ^Stream, buffer: [] u8, number_written: ^u32) -> Error {
+    write = proc (s: ^Stream, buffer: [] u8) -> (Error, u32) {
         dss : ^DynamicStringStream = ~~s;
         use dss;
 
         if curr_pos + buffer.count >= data.capacity {
             #context_scope {
                 context.allocator = alloc;
-                if !array.ensure_capacity(^data, curr_pos + buffer.count) do return Error.EOF;
+                if !array.ensure_capacity(^data, curr_pos + buffer.count) do return Error.EOF, 0;
             }
         }
 
@@ -396,26 +393,24 @@ dynamic_string_stream_vtable := Stream_Vtable.{
         curr_pos   += buffer.count;
         data.count += buffer.count;
 
-        if number_written != null do *number_written = buffer.count;
-        return Error.None;
+        return Error.None, buffer.count;
     },
 
-    write_at = proc (s: ^Stream, at: u32, buffer: [] u8, number_written: ^u32) -> Error {
+    write_at = proc (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
         dss : ^DynamicStringStream = ~~s;
         use dss;
 
         if at + buffer.count >= data.capacity {
             #context_scope {
                 context.allocator = alloc;
-                if !array.ensure_capacity(^data, at + buffer.count) do return Error.EOF;
+                if !array.ensure_capacity(^data, at + buffer.count) do return Error.EOF, 0;
             }
         }
 
         memory.copy(^data.data[at], buffer.data, buffer.count);
         data.count = math.max(data.count, at + buffer.count);
 
-        if number_written != null do *number_written = buffer.count;
-        return Error.None;
+        return Error.None, buffer.count;
     },
 
     write_byte = proc (s: ^Stream, byte: u8) -> Error {
index 2e658aab068e6c9f72a5f94943a006748fc9c403..d2fe583915c0dc725b09cd180c3801b0dfa5d763 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 718d8942d2349b57af2fccb0ee9817e7120557b4..a6fb6817ccc43806f874a8e6f40d76ba676dad84 100644 (file)
@@ -541,6 +541,8 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                 comp_type->Compound.size += type_size_of(comp_type->Compound.types[i]);
             }
 
+            bh_align(comp_type->Compound.size, 8);
+
             return comp_type;
         }
 
@@ -590,6 +592,8 @@ Type* type_build_compound_type(bh_allocator alloc, AstCompound* compound) {
         comp_type->Compound.size += type_size_of(compound->exprs[i]->type);
         comp_type->Compound.types[i] = compound->exprs[i]->type;
     }
+    
+    bh_align(comp_type->Compound.size, 8);
 
     return comp_type;
 }
index 8b7c6c4721f60dab4601c4a2bf2bf7a997780d85..7ae928703c3baf5f2935d4ee1bf48455e1321d19 100644 (file)
@@ -512,7 +512,7 @@ EMIT_FUNC(store_instruction, Type* type, u32 offset) {
         u32 placement = offset + type_size_of(type);
         forir (i, type->Compound.count - 1, 0) {
             Type* curr_type = type->Compound.types[i];
-            placement -= type_size_of(curr_type);
+            placement -= bh_max(type_size_of(curr_type), 4);
 
             if (type_is_compound(curr_type)) {
                 if (bh_arr_last(code).type == WI_LOCAL_SET && (u64) bh_arr_last(code).data.l == loc_tmp) {
@@ -606,7 +606,7 @@ EMIT_FUNC(load_instruction, Type* type, u32 offset) {
             if (i != 0) WIL(WI_LOCAL_GET, loc_tmp);
 
             emit_load_instruction(mod, &code, type->Compound.types[i], accum_offset);
-            accum_offset += type_size_of(type->Compound.types[i]);
+            accum_offset += bh_max(type_size_of(type->Compound.types[i]), 4);
         }
 
         local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
diff --git a/tests/string_stream_test b/tests/string_stream_test
new file mode 100644 (file)
index 0000000..0d2d756
--- /dev/null
@@ -0,0 +1,6 @@
+This
+is
+ a test string that can be read.
+1234
+4567
+5801
diff --git a/tests/string_stream_test.onyx b/tests/string_stream_test.onyx
new file mode 100644 (file)
index 0000000..0da2510
--- /dev/null
@@ -0,0 +1,24 @@
+#load "core/std/js"
+
+use package core
+
+main :: proc (args: [] cstr) {
+    some_string := "This is a test string that can be read.\n\n\n\n\n\n1234 4567";
+
+    sstream := io.string_stream_make(some_string);
+    sreader := io.reader_make(^sstream);
+
+    for i: 0 .. 2 {
+        word := io.read_word(^sreader, context.temp_allocator);
+        println(word);
+    }
+
+    println(io.read_line(^sreader, context.temp_allocator));
+
+    a := io.read_u32(^sreader);
+    b := io.read_u32(^sreader);
+
+    println(a);
+    println(b);
+    println(a + b);
+}
\ No newline at end of file