bugfixes in compiler and core libraries
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 8 Sep 2021 03:19:02 +0000 (22:19 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 8 Sep 2021 03:19:02 +0000 (22:19 -0500)
.vimspector.json.old [new file with mode: 0644]
bin/onyx
core/alloc/heap.onyx
core/random.onyx
examples/11_map.onyx
include/onyxutils.h
modules/bmfont/position.onyx
modules/ui/ui.onyx
src/onyxchecker.c
src/onyxutils.c

diff --git a/.vimspector.json.old b/.vimspector.json.old
new file mode 100644 (file)
index 0000000..b892307
--- /dev/null
@@ -0,0 +1,24 @@
+{ "configurations": {
+        "cpptools-run": {
+            "adapter": "vscode-cpptools",
+            "configuration": {
+                "type": "cppdbg",
+                "request": "launch",
+                "program": "/home/brendan/dev/c/onyx/bin/onyx-debug",
+                "args": ["-VVV", "-I", "/home/brendan/dev/c/onyx", "-o", "site/analyzer.wasm", "-r", "js", "--no-colors", "src/build.onyx", "--doc", "doc/source_reference" ],
+                "stopAtEntry": true,
+                "cwd": "/home/brendan/dev/onyx/wasm_analyzer",
+                "environment": [],
+                "externalConsole": false,
+                "MIMode": "gdb",
+                "setupCommands": [
+                    {
+                        "description": "Enable pretty-printing for gdb",
+                        "text": "-enable-pretty-printing",
+                        "ignoreFailures": true
+                    }
+                ]
+            }
+        }
+    }
+}
index 122314bb0ef4dc366ba45d8e150944a0f1793f77..8a4f175d476239d8bd10574cb4c3c6bb654a2f53 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 33722d0b4be7abba2eaf465d1b1aff26550e14b0..09645b8e3bf3504c7f5e3f1f6e3f3febf9b9fcd3 100644 (file)
@@ -13,92 +13,118 @@ Enable_Debug :: false
 
 #load "core/intrinsics/wasm"
 
-uintptr :: #type u32
+init :: () {
+    heap_state.free_list = null;
+    heap_state.next_alloc = cast(rawptr) (cast(uintptr) __heap_start + 8);
+    heap_state.remaining_space = (memory_size() << 16) - cast(u32) __heap_start;
 
-use package core.intrinsics.wasm {
-    memory_size, memory_grow,
-    memory_copy, memory_fill,
-}
-#private_file memory :: package core.memory
-#private_file math   :: package core.math
-
-// The global heap state
-#private_file
-heap_state : struct {
-    free_list       : ^heap_freed_block;
-    next_alloc      : rawptr;
-    remaining_space : u32;
+    use package core.alloc { heap_allocator }
+    heap_allocator.data = ^heap_state;
+    heap_allocator.func = heap_alloc_proc;
 }
 
-#private_file
-heap_block :: struct {
-    size         : u32;
-    magic_number : u32;
-}
+get_watermark :: () => cast(u32) heap_state.next_alloc;
 
-#private_file
-heap_freed_block :: struct {
-    use base: heap_block;
-    next : ^heap_freed_block;
-    prev : ^heap_freed_block;
-}
+#private_file {
+    use package core.intrinsics.wasm {
+        memory_size, memory_grow,
+        memory_copy, memory_fill,
+    }
 
-#private_file
-heap_allocated_block :: struct {
-    use base: heap_block;
-}
+    memory :: package core.memory
+    math   :: package core.math
 
-#private_file Allocated_Flag          :: 0x1
-#private_file Free_Block_Magic_Number :: 0xdeadbeef
-#private_file Block_Split_Size        :: 512
-
-// FIX: This does not respect the choice of alignment
-#private_file
-heap_alloc :: (size_: u32, align: u32) -> rawptr {
-    if size_ == 0 do return null;
-
-    size := size_ + sizeof heap_block;
-    size = math.max(size, sizeof heap_freed_block);
-    memory.align(~~^size, ~~align);
-
-    prev := ^heap_state.free_list;
-    hb := heap_state.free_list;
-    while hb != null {
-        if hb.size >= size {
-            #if Enable_Debug {
-                assert(hb.size & Allocated_Flag == 0, "Allocated block in free list.");
-                assert(hb.magic_number == Free_Block_Magic_Number, "Malformed free block in free list.");
-            }
+    uintptr :: #type u32
 
-            if hb.size - size >= Block_Split_Size {
-                hb.size = size;
+    // The global heap state
+    heap_state : struct {
+        free_list       : ^heap_freed_block;
+        next_alloc      : rawptr;
+        remaining_space : u32;
+    }
 
-                new_block := cast(^heap_freed_block) (cast(uintptr) hb + size);
-                new_block.size = hb.size - size;
-                new_block.next = hb.next;
-                new_block.prev = hb.prev;
-                new_block.magic_number = Free_Block_Magic_Number;
+    heap_block :: struct {
+        size         : u32;
+        magic_number : u32;
+    }
+
+    heap_freed_block :: struct {
+        use base: heap_block;
+        next : ^heap_freed_block;
+        prev : ^heap_freed_block;
+    }
 
-                if hb.next != null do hb.next.prev = new_block;
-                *prev = new_block;
+    heap_allocated_block :: struct {
+        use base: heap_block;
+    }
 
-            } else {
-                if hb.next != null do hb.next.prev = hb.prev;
-                *prev = hb.next;
+    Allocated_Flag          :: 0x1
+    Free_Block_Magic_Number :: 0xdeadbeef
+    Block_Split_Size        :: 512
+
+    // FIX: This does not respect the choice of alignment
+    heap_alloc :: (size_: u32, align: u32) -> rawptr {
+        if size_ == 0 do return null;
+
+        size := size_ + sizeof heap_block;
+        size = math.max(size, sizeof heap_freed_block);
+        memory.align(~~^size, ~~align);
+
+        prev := ^heap_state.free_list;
+        hb := heap_state.free_list;
+        while hb != null {
+            if hb.size >= size {
+                #if Enable_Debug {
+                    assert(hb.size & Allocated_Flag == 0, "Allocated block in free list.");
+                    assert(hb.magic_number == Free_Block_Magic_Number, "Malformed free block in free list.");
+                }
+
+                if hb.size - size >= Block_Split_Size {
+                    hb.size = size;
+
+                    new_block := cast(^heap_freed_block) (cast(uintptr) hb + size);
+                    new_block.size = hb.size - size;
+                    new_block.next = hb.next;
+                    new_block.prev = hb.prev;
+                    new_block.magic_number = Free_Block_Magic_Number;
+
+                    if hb.next != null do hb.next.prev = new_block;
+                    *prev = new_block;
+
+                } else {
+                    if hb.next != null do hb.next.prev = hb.prev;
+                    *prev = hb.next;
+                }
+
+                hb.next = null;
+                hb.prev = null;
+                hb.magic_number = 0;
+                hb.size |= Allocated_Flag;
+                return cast(rawptr) (cast(uintptr) hb + sizeof heap_allocated_block);
             }
 
-            hb.next = null;
-            hb.prev = null;
-            hb.magic_number = 0;
-            hb.size |= Allocated_Flag;
-            return cast(rawptr) (cast(uintptr) hb + sizeof heap_allocated_block);
+            prev = ^hb.next;
+            hb = hb.next;
         }
 
-        prev = ^hb.next;
-        hb = hb.next;
-    }
+        if size < heap_state.remaining_space {
+            ret := cast(^heap_allocated_block) heap_state.next_alloc;
+            ret.size = size;
+            ret.size |= Allocated_Flag;
+
+            heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size);
+            heap_state.remaining_space -= size;
+
+            return cast(rawptr) (cast(uintptr) ret + sizeof heap_allocated_block);
+        }
+
+        new_pages := ((size - heap_state.remaining_space) >> 16) + 1;
+        if memory_grow(new_pages) == -1 {
+            // out of memory
+            return null;
+        }
+        heap_state.remaining_space += new_pages << 16;
 
-    if size < heap_state.remaining_space {
         ret := cast(^heap_allocated_block) heap_state.next_alloc;
         ret.size = size;
         ret.size |= Allocated_Flag;
@@ -109,128 +135,98 @@ heap_alloc :: (size_: u32, align: u32) -> rawptr {
         return cast(rawptr) (cast(uintptr) ret + sizeof heap_allocated_block);
     }
 
-    new_pages := ((size - heap_state.remaining_space) >> 16) + 1;
-    if memory_grow(new_pages) == -1 {
-        // out of memory
-        return null;
-    }
-    heap_state.remaining_space += new_pages << 16;
-
-    ret := cast(^heap_allocated_block) heap_state.next_alloc;
-    ret.size = size;
-    ret.size |= Allocated_Flag;
+    heap_free :: (ptr: rawptr) {
+        #if Enable_Debug do assert(ptr != null, "Trying to free a null pointer.");
 
-    heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size);
-    heap_state.remaining_space -= size;
+        hb_ptr := cast(^heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
+        #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it.");
 
-    return cast(rawptr) (cast(uintptr) ret + sizeof heap_allocated_block);
-}
-
-#private_file
-heap_free :: (ptr: rawptr) {
-    #if Enable_Debug do assert(ptr != null, "Trying to free a null pointer.");
-
-    hb_ptr := cast(^heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
-    #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it.");
-
-    hb_ptr.size &= ~Allocated_Flag;
-    orig_size := hb_ptr.size - sizeof heap_allocated_block;
+        hb_ptr.size &= ~Allocated_Flag;
+        orig_size := hb_ptr.size - sizeof heap_allocated_block;
 
-    #if Enable_Debug do memory_fill(ptr, ~~0xcc, orig_size);
+        #if Enable_Debug do memory_fill(ptr, ~~0xcc, orig_size);
 
-    // CLEANUP: This is not complete. This only checks if the block after the freed block is also free.
-    // There are three other cases related to the block before this one that need to be handled for
-    // the best efficiency and minimal fragmentation.
-    if cast(uintptr) hb_ptr + hb_ptr.size < cast(uintptr) heap_state.next_alloc {
-        next_block := cast(^heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size);
+        // CLEANUP: This is not complete. This only checks if the block after the freed block is also free.
+        // There are three other cases related to the block before this one that need to be handled for
+        // the best efficiency and minimal fragmentation.
+        if cast(uintptr) hb_ptr + hb_ptr.size < cast(uintptr) heap_state.next_alloc {
+            next_block := cast(^heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size);
 
-        if next_block.size & Allocated_Flag == 0 && next_block.magic_number == Free_Block_Magic_Number {
-            hb_ptr.size += next_block.size;
+            if next_block.size & Allocated_Flag == 0 && next_block.magic_number == Free_Block_Magic_Number {
+                hb_ptr.size += next_block.size;
 
-            if next_block.next != null do next_block.next.prev = next_block.prev;
-            if next_block.prev != null do next_block.prev.next = next_block.next;
-            else                       do heap_state.free_list = next_block.next;
+                if next_block.next != null do next_block.next.prev = next_block.prev;
+                if next_block.prev != null do next_block.prev.next = next_block.next;
+                else                       do heap_state.free_list = next_block.next;
 
-            next_block.next = null;
-            next_block.prev = null;
+                next_block.next = null;
+                next_block.prev = null;
+            }
         }
-    }
-
-    hb_ptr.magic_number = Free_Block_Magic_Number;
-    hb_ptr.prev = null;
-    hb_ptr.next = heap_state.free_list;
 
-    if heap_state.free_list != null do heap_state.free_list.prev = hb_ptr;
-    heap_state.free_list = hb_ptr;
-}
+        hb_ptr.magic_number = Free_Block_Magic_Number;
+        hb_ptr.prev = null;
+        hb_ptr.next = heap_state.free_list;
 
-#private_file
-heap_resize :: (ptr: rawptr, new_size_: u32, align: u32) -> rawptr {
-    if ptr == null do return null;
+        if heap_state.free_list != null do heap_state.free_list.prev = hb_ptr;
+        heap_state.free_list = hb_ptr;
+    }
 
-    new_size := new_size_ + sizeof heap_block;
-    new_size = math.max(new_size, sizeof heap_freed_block);
-    new_size = ~~memory.align(cast(u64) new_size, ~~align);
-    
-    hb_ptr := cast(^heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
-    #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on resize.");
-    hb_ptr.size &= ~Allocated_Flag;
+    heap_resize :: (ptr: rawptr, new_size_: u32, align: u32) -> rawptr {
+        if ptr == null do return null;
 
-    old_size := hb_ptr.size;
+        new_size := new_size_ + sizeof heap_block;
+        new_size = math.max(new_size, sizeof heap_freed_block);
+        new_size = ~~memory.align(cast(u64) new_size, ~~align);
+        
+        hb_ptr := cast(^heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
+        #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on resize.");
+        hb_ptr.size &= ~Allocated_Flag;
 
-    // If there is already enough space in the current allocated block,
-    // just return the block that already exists and has the memory in it.
-    if old_size >= new_size {
-        hb_ptr.size |= Allocated_Flag;
-        return ptr;
-    }
+        old_size := hb_ptr.size;
 
-    // If we are at the end of the allocation space, just extend it
-    if cast(uintptr) hb_ptr + hb_ptr.size >= cast(uintptr) heap_state.next_alloc {
-        needed_size := cast(u32) memory.align(cast(u64) (new_size - old_size), 16);
+        // If there is already enough space in the current allocated block,
+        // just return the block that already exists and has the memory in it.
+        if old_size >= new_size {
+            hb_ptr.size |= Allocated_Flag;
+            return ptr;
+        }
 
-        if needed_size >= heap_state.remaining_space {
-            new_pages := ((needed_size - heap_state.remaining_space) >> 16) + 1;
-            if memory_grow(new_pages) == -1 {
-                // out of memory
-                return null;
+        // If we are at the end of the allocation space, just extend it
+        if cast(uintptr) hb_ptr + hb_ptr.size >= cast(uintptr) heap_state.next_alloc {
+            needed_size := cast(u32) memory.align(cast(u64) (new_size - old_size), 16);
+
+            if needed_size >= heap_state.remaining_space {
+                new_pages := ((needed_size - heap_state.remaining_space) >> 16) + 1;
+                if memory_grow(new_pages) == -1 {
+                    // out of memory
+                    return null;
+                }
+                heap_state.remaining_space += new_pages << 16;
             }
-            heap_state.remaining_space += new_pages << 16;
+
+            hb_ptr.size = new_size;
+            hb_ptr.size |= Allocated_Flag;
+            heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + needed_size);
+            heap_state.remaining_space -= needed_size;
+            return ptr;
         }
 
-        hb_ptr.size = new_size;
         hb_ptr.size |= Allocated_Flag;
-        heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + needed_size);
-        heap_state.remaining_space -= needed_size;
-        return ptr;
+        new_ptr := heap_alloc(new_size_, align);
+        memory_copy(new_ptr, ptr, old_size - sizeof heap_block);
+        heap_free(ptr);
+        return new_ptr;
     }
 
-    hb_ptr.size |= Allocated_Flag;
-    new_ptr := heap_alloc(new_size_, align);
-    memory_copy(new_ptr, ptr, old_size - sizeof heap_block);
-    heap_free(ptr);
-    return new_ptr;
-}
+    heap_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
+        switch aa {
+            case .Alloc  do return heap_alloc(size, align);
+            case .Resize do return heap_resize(oldptr, size, align);
+            case .Free   do heap_free(oldptr);
+        }
 
-#private_file
-heap_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
-    switch aa {
-        case .Alloc  do return heap_alloc(size, align);
-        case .Resize do return heap_resize(oldptr, size, align);
-        case .Free   do heap_free(oldptr);
+        return null;
     }
-
-    return null;
-}
-
-init :: () {
-    heap_state.free_list = null;
-    heap_state.next_alloc = cast(rawptr) (cast(uintptr) __heap_start + 8);
-    heap_state.remaining_space = (memory_size() << 16) - cast(u32) __heap_start;
-
-    use package core.alloc { heap_allocator }
-    heap_allocator.data = ^heap_state;
-    heap_allocator.func = heap_alloc_proc;
 }
 
-get_watermark :: () => cast(u32) heap_state.next_alloc;
\ No newline at end of file
index 979948082c0af34591c47f5b135d6c9a7f3557da..85ba22c0688c57533c59ac7048cdfb89815f214e 100644 (file)
@@ -1,16 +1,19 @@
 package core.random
 
-#private_file seed : i32 = 8675309
+#private_file seed : i64 = 867530932187
 
-#private_file RANDOM_MULTIPLIER :: 1664525
-#private_file RANDOM_INCREMENT  :: 1013904223
+#private_file RANDOM_MULTIPLIER :: 25214903917
+#private_file RANDOM_INCREMENT  :: cast(i64) 11
 // #private_file RANDOM_MODULUS    :: 1 << 32
 
-set_seed :: (s: u32) do seed = s;
+set_seed :: #match {
+    (s: u32) do seed = ~~s; ,
+    (s: u64) do seed =   s; ,
+}
 
 int :: (s := ^seed) -> u32 {
     *s = *s * RANDOM_MULTIPLIER + RANDOM_INCREMENT;
-    return *s;
+    return cast(u32) ((*s >> 16) & ~~0xffffffff);
 }
 
 between :: (lo: i32, hi: i32) -> i32 do return int () % (hi + 1 - lo) + lo;
index bba7b9e43ca97a61d3a2ccb4aad81a8cec04dd92..5cab4dac9fc217f03080aa442d833ca9959172e9 100644 (file)
@@ -8,7 +8,7 @@ main :: (args: [] cstr) {
     // provide an 'any-to-any' hash map in it's core libraries.
 
     // To use it, simply create one like so:
-    ages : map.Map(str, u32);
+    ages : Map(str, u32);
     map.init(^ages, default=0, hash_count=16);
     defer map.free(^ages);
 
@@ -29,7 +29,7 @@ main :: (args: [] cstr) {
     map.put(^ages, "Pam", 24);
 
     // To retrieve an entry's value, use the map.get procedure.
-    print_age :: (ages: ^map.Map(str, u32), name: str) {
+    print_age :: (ages: ^Map(str, u32), name: str) {
         age := map.get(ages, name);
         printf("{}'s age is {}.\n", name, age);
     }
index cd72671171fdabb7e3c6e08ce0bfde0bfc29d126..96957887210647042c9f5657674d5a5b1db37c5f 100644 (file)
@@ -39,4 +39,4 @@ i32 string_process_escape_seqs(char* dest, char* src, i32 len);
 // :RelativeFiles This should lookup for the file relative to "relative_to"
 char* lookup_included_file(char* filename, char* relative_to, b32 add_onyx_suffix, b32 search_included_folders);
 
-extern AstNode node_that_signals_a_yield;
\ No newline at end of file
+extern AstTyped node_that_signals_a_yield;
index 857953849f7cad08d09129658f46024475f56030..6cd6025550eee43a9b98d56f81a133ab172340bd 100644 (file)
@@ -1,32 +1,34 @@
 package bmfont
 
-#private_file math :: package core.math
+#private_file {
+    math :: package core.math
 
-#private_file Renderable_Glyph :: struct {
-    pos_x, pos_y : f32;
-    pos_w, pos_h : f32;
+    renderable_glyph: Renderable_Glyph;
+    Renderable_Glyph :: struct {
+        pos_x, pos_y : f32;
+        pos_w, pos_h : f32;
 
-    tex_x, tex_y : f32;
-    tex_w, tex_h : f32;
+        tex_x, tex_y : f32;
+        tex_w, tex_h : f32;
 
-    x_advance : f32;
-}
-#private_file renderable_glyph: Renderable_Glyph;
+        x_advance : f32;
+    }
 
-#private_file Rendering_Context :: struct {
-    font : ^BMFont;
-    size : f32;
+    rendering_context: Rendering_Context;
+    Rendering_Context :: struct {
+        font : ^BMFont;
+        size : f32;
 
-    x, y : f32;
+        x, y : f32;
 
-    original_x  : f32;
-    baseline    : f32;
-    line_height : f32;
+        original_x  : f32;
+        baseline    : f32;
+        line_height : f32;
 
-    text : str;
-    text_position : u32;
+        text : str;
+        text_position : u32;
+    }
 }
-#private_file rendering_context: Rendering_Context;
 
 @FontSizing // Currently, `size` is just a multipler for the baked font size. This should be changed to be height in pixels, or 'em's.
 @Rename
@@ -99,4 +101,4 @@ get_character_positions :: (font: ^BMFont, size: f32, text: str, x: f32, y: f32)
         close = close,
         data = ^rendering_context,
     };
-}
\ No newline at end of file
+}
index da3cc025806298a504d0e94fb5e6af6a70ca945b..980cc8c75a24b1ebf065ff2748856adac26c7474 100644 (file)
@@ -5,14 +5,15 @@ use package core
 @Temporary
 DEFAULT_TEXT_SIZE :: 1.0f
 
-
 UI_Id :: #type u32
 
-#private hot_item    : UI_Id = 0
-#private active_item : UI_Id = 0
-#private hot_item_was_set := false
+#private {
+    hot_item    : UI_Id = 0
+    active_item : UI_Id = 0
+    hot_item_was_set := false
 
-#private current_font : ^Font;
+    current_font : ^Font;
+}
 
 init_ui :: () {
     map.init(^font_registry, hash_count=4);
index 3ec91cf568f35ca1adfccc02d45f8dc796a56f0f..e2edab7a8499efda118e0e5843a9906624b6b13d 100644 (file)
@@ -223,6 +223,8 @@ CheckStatus check_for(AstFor* fornode) {
     resolve_expression_type(fornode->iter);
 
     Type* iter_type = fornode->iter->type;
+    if (iter_type == NULL) YIELD(fornode->token->pos, "Waiting for iteration expression type to be known.");
+
     fornode->loop_type = For_Loop_Invalid;
     if (types_are_compatible(iter_type, &basic_types[Basic_Kind_I32])) {
         if (fornode->by_pointer) {
index 5c35c5fdb4c122e76d14ef883382251a305c7ca9..e53256ceab95e7481ff2f44814a749f05b8221b4 100644 (file)
@@ -249,7 +249,7 @@ void scope_clear(Scope* scope) {
 // HACK HACK HACK nocheckin
 static b32 flag_to_yield = 0;
 
-AstNode node_that_signals_a_yield = { 0 };
+AstTyped node_that_signals_a_yield = { Ast_Kind_Function, 0 };
 
 static void ensure_polyproc_cache_is_created(AstPolyProc* pp) {
     if (pp->concrete_funcs == NULL) {