From: Brendan Hansen Date: Mon, 3 Apr 2023 02:44:42 +0000 (-0500) Subject: bugfix: numerous symbol related core library bugs X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ab6f0726c0c7fd7c0b7d2eac049c17218259d03d;p=onyx.git bugfix: numerous symbol related core library bugs --- diff --git a/core/alloc/alloc.onyx b/core/alloc/alloc.onyx index f08b3058..e6147409 100644 --- a/core/alloc/alloc.onyx +++ b/core/alloc/alloc.onyx @@ -45,6 +45,8 @@ array_from_stack :: macro ($T: type_expr, size: u32) -> [] T { } """ on_heap :: macro (v: $V) -> &V { + use core + out := cast(&V) raw_alloc(context.allocator, sizeof V); core.memory.set(out, 0, sizeof V); *out = v; @@ -55,6 +57,8 @@ on_heap :: macro (v: $V) -> &V { Like `alloc.on_heap`, but allocates on the temporary allocator. """ on_temp :: macro (v: $V) -> &V { + use core + out := cast(&V) raw_alloc(context.temp_allocator, sizeof V); core.memory.set(out, 0, sizeof V); *out = v; diff --git a/core/alloc/gc.onyx b/core/alloc/gc.onyx index 293222b8..01ad229f 100644 --- a/core/alloc/gc.onyx +++ b/core/alloc/gc.onyx @@ -16,7 +16,7 @@ package core.alloc.gc // // Every allocation here will automatically be freed // } -use core +use core {package, *} GCState :: struct { backing_allocator: Allocator; @@ -60,11 +60,11 @@ make_allocator :: (hs: &GCState) -> Allocator { auto :: #match { macro () { - use core.alloc {gc} + use core.alloc {package, gc} gcs := gc.make(); old_allocator := context.allocator; - context.allocator = core.alloc.as_allocator(&gcs); + context.allocator = alloc.as_allocator(&gcs); defer { gc.clear(&gcs); context.allocator = old_allocator; diff --git a/core/builtin.onyx b/core/builtin.onyx index 0b90dcd1..abe73849 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -448,23 +448,6 @@ any :: struct { Code :: struct {_:i32;} -#doc """ - Define aliases for common datastructures in the core library, if the core library is available. - I'm on the fence about keeping this, as the programmer may want to use these names for their own - structures, but for the moment I don't see any harm. I'm also thinking about removing the '[..]' - syntax for dynamic arrays and just make them like Map's and Set's, i.e. Array(T). This would - remove some confusion around the 3 different array types as dynamic arrays would clearly just be - normal structures. With the recent addition of macros and iterators, there really wouldn't be much - difference anyway. -""" -#if #defined(core.map.Map) { - Map :: core.map.Map; -} - -#if #defined(core.set.Set) { - Set :: core.set.Set; -} - #doc """ This procedure is a special compiler generated procedure that initializes all the data segments diff --git a/core/container/array.onyx b/core/container/array.onyx index fd19385b..1613b5f5 100644 --- a/core/container/array.onyx +++ b/core/container/array.onyx @@ -14,8 +14,16 @@ use core // --------------------------------- // Dynamic Arrays // --------------------------------- + +#doc """ + Creates a new dynamic array. +""" make :: #match #local {} +#doc """ + Creates a dynamic array of type `T` with an initial capacity of `capacity`, + from the `allocator`. +""" #overload make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T { arr : [..] T; @@ -23,6 +31,9 @@ make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T return arr; } +#doc """ + Creates a new dynamic array as a *copy* of the provided array. +""" #overload make :: (base: [] $T, allocator := context.allocator) -> [..] T { arr: [..] T; @@ -41,6 +52,7 @@ __make_overload :: macro (_: &[..] $T, capacity: u32, allocator := context.alloc return #this_package.make(T, capacity, allocator); } +#doc "Initializes a dynamic array." init :: (arr: &[..] $T, capacity := 4, allocator := context.allocator) { arr.count = 0; arr.capacity = capacity; @@ -48,6 +60,7 @@ init :: (arr: &[..] $T, capacity := 4, allocator := context.allocator) { arr.data = raw_alloc(allocator, sizeof T * arr.capacity); } +#doc "Frees a dynamic array." free :: (arr: &[..] $T) { arr.count = 0; arr.capacity = 0; @@ -78,6 +91,13 @@ copy :: #match #locked { } } +#doc """ + Copies a sub-array of a dynamic-array. + + arr := array.make(.[ 2, 3, 5, 7, 11 ]); + sub := array.copy_range(&arr, 2 .. 5); + println(sub); // 5, 7, 11 +""" copy_range :: (arr: &[..] $T, r: range, allocator := context.allocator) -> [..] T { new_arr : [..] T; init(&new_arr, r.high - r.low, allocator); @@ -87,10 +107,20 @@ copy_range :: (arr: &[..] $T, r: range, allocator := context.allocator) -> [..] return new_arr; } +#doc """ + Clears a dynamic array. + + Note: This does not clear or free the memory for the dynamic array. +""" clear :: (arr: &[..] $T) { arr.count = 0; } +#doc """ + Resizes a dynamic array if it does not have enough capacity. + + If this procedure returns `true`, `arr.capacity` will be greater than or equal to `capacity`. +""" ensure_capacity :: (arr: &[..] $T, capacity: u32) -> bool { if arr.capacity >= capacity do return true; if arr.data == null do init(arr); @@ -102,12 +132,18 @@ ensure_capacity :: (arr: &[..] $T, capacity: u32) -> bool { return true; } +#doc """ + Appends a zeroed-element to the end of the array, and returns a pointer to it. +""" alloc_one :: (arr: &[..] $T) -> &T { if !ensure_capacity(arr, arr.count + 1) do return null; arr.count += 1; return &arr.data[arr.count - 1]; } +#doc """ + Appends `x` to the end of the array. +""" push :: (arr: &[..] $T, x: T) -> bool { if !ensure_capacity(arr, arr.count + 1) do return false; arr.data[arr.count] = x; @@ -118,6 +154,12 @@ push :: (arr: &[..] $T, x: T) -> bool { // Semi-useful shortcut for adding something to an array. #operator << macro (arr: [..] $T, v: T) do #this_package.push(&arr, v); + +#doc """ + Inserts element(s) into the middle of the array at `idx`. + + If `idx >= arr.count`, nothing happens. +""" insert :: #match #local {} #overload @@ -152,7 +194,11 @@ insert :: (arr: &[..] $T, idx: u32, new_arr: [] T) -> bool { return true; } +#doc """ + Inserts a zeroed-element at `idx`. +""" insert_empty :: (arr: &[..] $T, idx: u32) -> bool { + if idx >= arr.count do return false; if !ensure_capacity(arr, arr.count + 1) do return false; arr.count += 1; @@ -164,6 +210,11 @@ insert_empty :: (arr: &[..] $T, idx: u32) -> bool { return true; } +#doc """ + Removes all instances of `elem` from the array. + + Uses `==` to test for equality. +""" remove :: (arr: &[..] $T, elem: T) { move := 0; @@ -177,6 +228,11 @@ remove :: (arr: &[..] $T, elem: T) { arr.count -= move; } +#doc """ + Removes the element at index `idx` from the array and returns it. + + Maintains order of the array. +""" delete :: (arr: &[..] $T, idx: u32) -> T { if idx >= arr.count do return .{}; @@ -189,6 +245,11 @@ delete :: (arr: &[..] $T, idx: u32) -> T { return to_return; } +#doc """ + Removes the element at index `idx` from the array and returns it. + + Order is not guaranteed to be preserved. +""" fast_delete :: (arr: &[..] $T, idx: u32) -> T { if idx >= arr.count do return .{}; @@ -199,6 +260,11 @@ fast_delete :: (arr: &[..] $T, idx: u32) -> T { return to_return; } +#doc """ + Removes `n` elements from the end of the array. + + `n` by default is 1. +""" pop :: (arr: &[..] $T, n := 1) -> T { if arr.count == 0 do return .{}; @@ -207,6 +273,10 @@ pop :: (arr: &[..] $T, n := 1) -> T { return arr.data[arr.count]; } + +#doc """ + Appends elements from another array or iterator to the end of the array. +""" concat :: #match #local {} #overload @@ -224,6 +294,15 @@ concat :: (arr: &[..] $T, other: Iterator(T)) { } } +#doc """ + Removes all elements for which the given predicate does not hold. + + Use `it` to refer to the current element being tested. + + arr := array.make(.[ 1, 2, 3, 4, 5 ]); + array.filter(&arr, #(it % 2 == 0)); + println(arr); // 2, 4 +""" filter :: macro (arr: &[..] $T, body: Code) { move := 0; diff --git a/core/container/map.onyx b/core/container/map.onyx index 9edcaa30..afaece43 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -58,6 +58,10 @@ Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Ty as_iter :: as_iter } +#inject builtin { + Map :: Map; +} + #doc """ Allows for creation of a Map using make(). diff --git a/core/container/set.onyx b/core/container/set.onyx index 71f41fc8..942ddd57 100644 --- a/core/container/set.onyx +++ b/core/container/set.onyx @@ -42,6 +42,10 @@ Set :: struct (Elem_Type: type_expr) where SetValue(Elem_Type) { as_iter :: as_iter } +#inject builtin { + Set :: Set; +} + make :: ($T: type_expr, default := T.{}, allocator := context.allocator) -> Set(T) { set : Set(T); init(&set, default=default, allocator=allocator); diff --git a/core/misc/method_ops.onyx b/core/misc/method_ops.onyx index 1e347dec..48e2fd53 100644 --- a/core/misc/method_ops.onyx +++ b/core/misc/method_ops.onyx @@ -1,5 +1,7 @@ package core +use runtime + // // This file defines an optional language feature called method operators. // Instead of defining an operator overload using the #operator directive,