moved container-like things to core/container
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 21 Apr 2021 13:35:50 +0000 (08:35 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 21 Apr 2021 13:35:50 +0000 (08:35 -0500)
core/array.onyx [deleted file]
core/container/array.onyx [new file with mode: 0644]
core/container/iter.onyx [new file with mode: 0644]
core/container/list.onyx [new file with mode: 0644]
core/container/map.onyx [new file with mode: 0644]
core/iter.onyx [deleted file]
core/list.onyx [deleted file]
core/map.onyx [deleted file]
core/std.onyx

diff --git a/core/array.onyx b/core/array.onyx
deleted file mode 100644 (file)
index 20f5ac3..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-package core.array
-
-// [..] T == Array(T)
-//   where
-// Array :: struct (T: type_expr) {
-//     data      : T;
-//     count     : u32;
-//     capacity  : u32;
-//     allocator : Allocator;
-// }
-
-// ---------------------------------
-//           Dynamic Arrays
-// ---------------------------------
-make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T {
-    arr : [..] T;
-    init(^arr, capacity, allocator);
-    return arr;
-}
-
-init :: (arr: ^[..] $T, capacity := 4, allocator := context.allocator) {
-    arr.count = 0;
-    arr.capacity = capacity;
-    arr.allocator = allocator;
-    arr.data = raw_alloc(allocator, sizeof T * arr.capacity);
-}
-
-free :: (arr: ^[..] $T) {
-    arr.count = 0;
-    arr.capacity = 0;
-
-    raw_free(arr.allocator, arr.data);
-    arr.data = null;
-}
-
-copy :: (arr: ^[..] $T, allocator := context.allocator) -> [..] T {
-    new_arr : [..] T;
-    init(^new_arr, arr.count, allocator);
-    new_arr.count = arr.count;
-
-    for i: 0 .. arr.count do new_arr.data[i] = arr.data[i];
-    return new_arr;
-}
-
-copy_range :: (arr: ^[..] $T, r: range, allocator := context.allocator) -> [..] T {
-    new_arr : [..] T;
-    init(^new_arr, r.high - r.low, allocator);
-    new_arr.count = r.high - r.low;
-
-    for i: r do new_arr.data[i] = arr.data[i];
-    return new_arr;
-}
-
-clear :: (arr: ^[..] $T) {
-    arr.count = 0;
-}
-
-ensure_capacity :: (arr: ^[..] $T, capacity: u32) -> bool {
-    if arr.capacity >= capacity do return true;
-
-    while capacity > arr.capacity do arr.capacity <<= 1;
-    new_data := raw_resize(arr.allocator, arr.data, sizeof T * arr.capacity);
-    if new_data == null do return false;
-    arr.data = new_data;
-    return true;
-}
-
-push :: (arr: ^[..] $T, x: T) -> bool {
-    if !ensure_capacity(arr, arr.count + 1) do return false;
-    arr.data[arr.count] = x;
-    arr.count += 1;
-    return true;
-}
-
-insert :: (arr: ^[..] $T, idx: u32, x: T) -> bool {
-    if !ensure_capacity(arr, arr.count + 1) do return false;
-
-    arr.count += 1;
-    while i := arr.count; i > idx {
-        arr.data[i] = arr.data[i - 1];
-        i -= 1;
-    }
-
-    arr.data[idx] = x;
-    return true;
-}
-
-insert_empty :: (arr: ^[..] $T, idx: u32) -> bool {
-    if !ensure_capacity(arr, arr.count + 1) do return false;
-
-    arr.count += 1;
-    while i := arr.count; i > idx {
-        arr.data[i] = arr.data[i - 1];
-        i -= 1;
-    }
-
-    return true;
-}
-
-remove :: (arr: ^[..] $T, elem: T) {
-    move := 0;
-
-    while i := 0; i < arr.count - move {
-        defer i += 1;
-        
-        if arr.data[i + move] == elem do move += 1;
-        if move != 0 do arr.data[i] = arr.data[i + move];
-    }
-
-    arr.count -= move;
-}
-
-delete :: (arr: ^[..] $T, idx: u32) {
-    if idx >= arr.count do return;
-
-    for i: idx .. arr.count - 1 {
-        arr.data[i] = arr.data[i + 1];
-    }
-
-    arr.count -= 1;
-}
-
-fast_delete :: (arr: ^[..] $T, idx: u32) {
-    if idx >= arr.count do return;
-
-    arr.data[idx] = arr.data[arr.count - 1];
-    arr.count -= 1;
-}
-
-pop :: (arr: ^[..] $T) -> T {
-    arr.count -= 1;
-    return arr.data[arr.count];
-}
-
-// Uses '==' to compare for equality.
-contains :: proc {
-    (arr: ^[..] $T, x: T) -> bool {
-        for it: *arr do if it == x do return true;
-        return false;
-    },
-
-    (arr: [] $T, x: T) -> bool {
-        for it: arr do if it == x do return true;
-        return false;
-    }
-}
-
-// Uses '+' to sum.
-sum :: proc {
-    (arr: ^[..] $T, start: T = 0) -> T {
-        sum := start;
-        for it: *arr do sum += it;
-        return sum;
-    },
-
-    (arr: [] $T, start: T = 0) -> T {
-        sum := start;
-        for it: arr do sum += it;
-        return sum;
-    }
-}
-
-average :: (arr: ^[..] $T) -> T {
-    sum := cast(T) 0;
-    for it: *arr do sum += it;
-
-    return sum / cast(T) arr.count;
-}
-
-to_slice :: (arr: ^[..] $T) -> [] T {
-    return arr.data[0 .. arr.count];
-}
-
-/*
-** Simple insertion sort
-**    cmp should return >0 if left > right
-*/
-sort :: (arr: ^[..] $T, cmp: (T, T) -> i32) {
-    for i: 1 .. arr.count {
-        x := arr.data[i];
-        j := i - 1;
-
-        while j >= 0 && cmp(arr.data[j], x) > 0 {
-            arr.data[j + 1] = arr.data[j];
-            j -= 1;
-        }
-
-        arr.data[j + 1] = x;
-    }
-}
-
-fold :: proc {
-    (arr: ^[..] $T, init: $R, f: (T, R) -> R) -> R {
-        val := init;
-        for it: *arr do val = f(it, val);
-        return val;
-    },
-
-    (arr: [] $T, init: $R, f: (T, R) -> R) -> R {
-        val := init;
-        for it: arr do val = f(it, val);
-        return val;
-    }
-}
-
-map :: proc {
-    (arr: ^[..] $T, f: (^T) -> void)          do for ^it: *arr do f(it);,
-    (arr: ^[..] $T, f: (T) -> T)              do for ^it: *arr do *it = f(*it);,
-    (arr: ^[..] $T, data: $R, f: (T, R) -> T) do for ^it: *arr do *it = f(*it, data);,
-    (arr: [] $T, f: (^T) -> void)             do for ^it:  arr do f(it);,
-    (arr: [] $T, f: (T) -> T)                 do for ^it:  arr do *it = f(*it);,
-    (arr: [] $T, data: $R, f: (T, R) -> T)    do for ^it:  arr do *it = f(*it, data);,
-}
-
-#private_file
-fold_idx_elem :: (arr: ^$T, count: i32, cmp: (T, T) -> bool) -> (i32, T) {
-    idx  := 0;
-    elem := arr[0];
-    
-    for i: 1 .. count {
-        if cmp(arr[i], elem) {
-            idx  = i;
-            elem = arr[i];
-        }
-    }
-    
-    return idx, elem;
-}
-
-#private_file cmp_greater :: (x: $T, y: T) -> bool do return x > y;
-#private_file cmp_less    :: (x: $T, y: T) -> bool do return x < y;
-
-greatest :: proc {
-    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
-    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
-    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_greater); },
-}
-
-least :: proc {
-    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
-    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
-    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_less); },
-}
diff --git a/core/container/array.onyx b/core/container/array.onyx
new file mode 100644 (file)
index 0000000..20f5ac3
--- /dev/null
@@ -0,0 +1,243 @@
+package core.array
+
+// [..] T == Array(T)
+//   where
+// Array :: struct (T: type_expr) {
+//     data      : T;
+//     count     : u32;
+//     capacity  : u32;
+//     allocator : Allocator;
+// }
+
+// ---------------------------------
+//           Dynamic Arrays
+// ---------------------------------
+make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T {
+    arr : [..] T;
+    init(^arr, capacity, allocator);
+    return arr;
+}
+
+init :: (arr: ^[..] $T, capacity := 4, allocator := context.allocator) {
+    arr.count = 0;
+    arr.capacity = capacity;
+    arr.allocator = allocator;
+    arr.data = raw_alloc(allocator, sizeof T * arr.capacity);
+}
+
+free :: (arr: ^[..] $T) {
+    arr.count = 0;
+    arr.capacity = 0;
+
+    raw_free(arr.allocator, arr.data);
+    arr.data = null;
+}
+
+copy :: (arr: ^[..] $T, allocator := context.allocator) -> [..] T {
+    new_arr : [..] T;
+    init(^new_arr, arr.count, allocator);
+    new_arr.count = arr.count;
+
+    for i: 0 .. arr.count do new_arr.data[i] = arr.data[i];
+    return new_arr;
+}
+
+copy_range :: (arr: ^[..] $T, r: range, allocator := context.allocator) -> [..] T {
+    new_arr : [..] T;
+    init(^new_arr, r.high - r.low, allocator);
+    new_arr.count = r.high - r.low;
+
+    for i: r do new_arr.data[i] = arr.data[i];
+    return new_arr;
+}
+
+clear :: (arr: ^[..] $T) {
+    arr.count = 0;
+}
+
+ensure_capacity :: (arr: ^[..] $T, capacity: u32) -> bool {
+    if arr.capacity >= capacity do return true;
+
+    while capacity > arr.capacity do arr.capacity <<= 1;
+    new_data := raw_resize(arr.allocator, arr.data, sizeof T * arr.capacity);
+    if new_data == null do return false;
+    arr.data = new_data;
+    return true;
+}
+
+push :: (arr: ^[..] $T, x: T) -> bool {
+    if !ensure_capacity(arr, arr.count + 1) do return false;
+    arr.data[arr.count] = x;
+    arr.count += 1;
+    return true;
+}
+
+insert :: (arr: ^[..] $T, idx: u32, x: T) -> bool {
+    if !ensure_capacity(arr, arr.count + 1) do return false;
+
+    arr.count += 1;
+    while i := arr.count; i > idx {
+        arr.data[i] = arr.data[i - 1];
+        i -= 1;
+    }
+
+    arr.data[idx] = x;
+    return true;
+}
+
+insert_empty :: (arr: ^[..] $T, idx: u32) -> bool {
+    if !ensure_capacity(arr, arr.count + 1) do return false;
+
+    arr.count += 1;
+    while i := arr.count; i > idx {
+        arr.data[i] = arr.data[i - 1];
+        i -= 1;
+    }
+
+    return true;
+}
+
+remove :: (arr: ^[..] $T, elem: T) {
+    move := 0;
+
+    while i := 0; i < arr.count - move {
+        defer i += 1;
+        
+        if arr.data[i + move] == elem do move += 1;
+        if move != 0 do arr.data[i] = arr.data[i + move];
+    }
+
+    arr.count -= move;
+}
+
+delete :: (arr: ^[..] $T, idx: u32) {
+    if idx >= arr.count do return;
+
+    for i: idx .. arr.count - 1 {
+        arr.data[i] = arr.data[i + 1];
+    }
+
+    arr.count -= 1;
+}
+
+fast_delete :: (arr: ^[..] $T, idx: u32) {
+    if idx >= arr.count do return;
+
+    arr.data[idx] = arr.data[arr.count - 1];
+    arr.count -= 1;
+}
+
+pop :: (arr: ^[..] $T) -> T {
+    arr.count -= 1;
+    return arr.data[arr.count];
+}
+
+// Uses '==' to compare for equality.
+contains :: proc {
+    (arr: ^[..] $T, x: T) -> bool {
+        for it: *arr do if it == x do return true;
+        return false;
+    },
+
+    (arr: [] $T, x: T) -> bool {
+        for it: arr do if it == x do return true;
+        return false;
+    }
+}
+
+// Uses '+' to sum.
+sum :: proc {
+    (arr: ^[..] $T, start: T = 0) -> T {
+        sum := start;
+        for it: *arr do sum += it;
+        return sum;
+    },
+
+    (arr: [] $T, start: T = 0) -> T {
+        sum := start;
+        for it: arr do sum += it;
+        return sum;
+    }
+}
+
+average :: (arr: ^[..] $T) -> T {
+    sum := cast(T) 0;
+    for it: *arr do sum += it;
+
+    return sum / cast(T) arr.count;
+}
+
+to_slice :: (arr: ^[..] $T) -> [] T {
+    return arr.data[0 .. arr.count];
+}
+
+/*
+** Simple insertion sort
+**    cmp should return >0 if left > right
+*/
+sort :: (arr: ^[..] $T, cmp: (T, T) -> i32) {
+    for i: 1 .. arr.count {
+        x := arr.data[i];
+        j := i - 1;
+
+        while j >= 0 && cmp(arr.data[j], x) > 0 {
+            arr.data[j + 1] = arr.data[j];
+            j -= 1;
+        }
+
+        arr.data[j + 1] = x;
+    }
+}
+
+fold :: proc {
+    (arr: ^[..] $T, init: $R, f: (T, R) -> R) -> R {
+        val := init;
+        for it: *arr do val = f(it, val);
+        return val;
+    },
+
+    (arr: [] $T, init: $R, f: (T, R) -> R) -> R {
+        val := init;
+        for it: arr do val = f(it, val);
+        return val;
+    }
+}
+
+map :: proc {
+    (arr: ^[..] $T, f: (^T) -> void)          do for ^it: *arr do f(it);,
+    (arr: ^[..] $T, f: (T) -> T)              do for ^it: *arr do *it = f(*it);,
+    (arr: ^[..] $T, data: $R, f: (T, R) -> T) do for ^it: *arr do *it = f(*it, data);,
+    (arr: [] $T, f: (^T) -> void)             do for ^it:  arr do f(it);,
+    (arr: [] $T, f: (T) -> T)                 do for ^it:  arr do *it = f(*it);,
+    (arr: [] $T, data: $R, f: (T, R) -> T)    do for ^it:  arr do *it = f(*it, data);,
+}
+
+#private_file
+fold_idx_elem :: (arr: ^$T, count: i32, cmp: (T, T) -> bool) -> (i32, T) {
+    idx  := 0;
+    elem := arr[0];
+    
+    for i: 1 .. count {
+        if cmp(arr[i], elem) {
+            idx  = i;
+            elem = arr[i];
+        }
+    }
+    
+    return idx, elem;
+}
+
+#private_file cmp_greater :: (x: $T, y: T) -> bool do return x > y;
+#private_file cmp_less    :: (x: $T, y: T) -> bool do return x < y;
+
+greatest :: proc {
+    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
+    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
+    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_greater); },
+}
+
+least :: proc {
+    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
+    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
+    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_less); },
+}
diff --git a/core/container/iter.onyx b/core/container/iter.onyx
new file mode 100644 (file)
index 0000000..ff8f029
--- /dev/null
@@ -0,0 +1,194 @@
+package core.iter
+
+use package core.intrinsics.onyx { __zero_value }
+
+filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
+    FilterIterator :: struct (T: type_expr) {
+        iterator:  Iterator(T);
+        predicate: (T) -> bool;
+    }
+
+    filter_iterator := new(#type FilterIterator(T));
+    filter_iterator.iterator = it;
+    filter_iterator.predicate = predicate;
+
+    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
+        fi := cast(^FilterIterator(T)) data;
+
+        value, cont := fi.iterator.next(fi.iterator.data);
+        if cont {
+            while !fi.predicate(value) {
+                value, cont = fi.iterator.next(fi.iterator.data);
+                if !cont do return value, false;
+            }
+
+            return value, true;
+        } else {
+            return value, false;
+        }
+    }
+
+    close :: ($T: type_expr, data: rawptr) {
+        fi := cast(^FilterIterator(T)) data;
+        fi.iterator.close(fi.iterator.data);
+        cfree(data);
+    }
+
+    return .{
+        data  = filter_iterator,
+        next  = #solidify next  { T=T },
+        close = #solidify close { T=T },
+    };
+}
+
+map :: (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) {
+    MapIterator :: struct (T: type_expr, R: type_expr) {
+        iterator:  Iterator(T);
+        transform: (T) -> R;
+    }
+
+    map_iterator := new(#type MapIterator(T, R));
+    map_iterator.iterator = it;
+    map_iterator.transform = transform;
+
+    next :: ($T: type_expr, $R: type_expr, data: rawptr) -> (R, bool) {
+        mi := cast(^MapIterator(T, R)) data;
+
+        value, cont := mi.iterator.next(mi.iterator.data);
+        if !cont do return value, false;
+
+        return mi.transform(value), true;
+    }
+
+    close :: ($T: type_expr, $R: type_expr, data: rawptr) {
+        mi := cast(^MapIterator(T, R)) data;
+        mi.iterator.close(mi.iterator.data);
+        cfree(data);
+    }
+
+    return .{
+        data  = map_iterator,
+        next  = #solidify next  { T=T, R=R },
+        close = #solidify close { T=T, R=R },
+    };
+}
+
+take :: (it: Iterator($T), count: u32) -> Iterator(T) {
+    TakeIterator :: struct (T: type_expr) {
+        iterator:  Iterator(T);
+        remaining: u32;
+    }
+
+    take_iterator := new(#type TakeIterator(T));
+    take_iterator.iterator = it;
+    take_iterator.remaining = count;
+
+    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
+        ti := cast(^TakeIterator(T)) data;
+        if ti.remaining == 0 do return __zero_value(T), false;
+
+        ti.remaining -= 1;
+        return ti.iterator.next(ti.iterator.data);
+    }
+
+    close :: ($T: type_expr, data: rawptr) {
+        ti := cast(^TakeIterator(T)) data;
+        ti.iterator.close(ti.iterator.data);
+        cfree(data);
+    }
+
+    return .{
+        data  = take_iterator,
+        next  = #solidify next  { T=T },
+        close = #solidify close { T=T },
+    };
+}
+
+take_while :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
+    TakeIterator :: struct (T: type_expr) {
+        iterator:  Iterator(T);
+        predicate: (T) -> bool;
+    }
+
+    take_iterator := new(#type TakeIterator(T));
+    take_iterator.iterator = it;
+    take_iterator.predicate = predicate;
+
+    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
+        ti := cast(^TakeIterator(T)) data;
+
+        value, cont := ti.iterator.next(ti.iterator.data);
+        if !cont do return value, false;
+
+        return value, ti.predicate(value);
+    }
+
+    close :: ($T: type_expr, data: rawptr) {
+        ti := cast(^TakeIterator(T)) data;
+        ti.iterator.close(ti.iterator.data);
+        cfree(data);
+    }
+
+    return .{
+        data  = take_iterator,
+        next  = #solidify next  { T=T },
+        close = #solidify close { T=T },
+    };
+}
+
+skip :: (it: Iterator($T), count: u32) -> Iterator(T) {
+    SkipIterator :: struct (T: type_expr) {
+        iterator: Iterator(T);
+        to_skip:  i32;
+        skipped:  bool = false;
+    }
+
+    skip_iterator := new(#type SkipIterator(T));
+    skip_iterator.iterator = it;
+    skip_iterator.to_skip = count;
+
+    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
+        si := cast(^SkipIterator(T)) data;
+
+        while !si.skipped && si.to_skip > 0 {
+            si.to_skip -= 1;
+            value, cont := si.iterator.next(si.iterator.data);
+
+            if !cont {
+                si.skipped = true;
+                return value, false;
+            }
+        }
+
+        return si.iterator.next(si.iterator.data);
+    }
+
+    close :: ($T: type_expr, data: rawptr) {
+        si := cast(^SkipIterator(T)) data;
+        si.iterator.close(si.iterator.data);
+        cfree(data);
+    }
+
+    return .{
+        data  = skip_iterator,
+        next  = #solidify next  { T=T },
+        close = #solidify close { T=T },
+    };
+}
+
+fold :: (it: Iterator($T), initial_value: R, combine: (T, $R) -> R) -> R {
+    for value: it {
+        initial_value = combine(value, initial_value);
+    }
+    
+    return initial_value;
+}
+
+to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
+    array :: package core.array
+
+    arr := array.make(T, allocator=allocator);
+    for v: it do array.push(^arr, v);
+
+    return arr;
+}
diff --git a/core/container/list.onyx b/core/container/list.onyx
new file mode 100644 (file)
index 0000000..d4bd065
--- /dev/null
@@ -0,0 +1,106 @@
+package core.list
+
+ListElem :: struct (T: type_expr) {
+    next: ^ListElem(T) = null;
+    prev: ^ListElem(T) = null;
+    data: T;
+}
+
+List :: struct (T: type_expr) {
+    allocator: Allocator;
+
+    first: ^ListElem(T) = null;
+    last:  ^ListElem(T) = null;
+}
+
+make :: ($T: type_expr, allocator := context.allocator) -> List(T) {
+    return .{ allocator = allocator };
+}
+
+push_end :: (list: ^List($T), x: T) { 
+    new_elem := allocate_elem(list);
+    new_elem.data = x;
+
+    new_elem.prev = list.last;
+    list.last.next = new_elem;
+    list.last = new_elem;
+
+    if list.first == null do list.first = new_elem;
+}
+
+push_begin :: (list: ^List($T), x: T) {
+    new_elem := allocate_elem(list);
+    new_elem.data = x;
+
+    new_elem.next = list.first;
+    list.first.prev = new_elem;
+    list.first = new_elem;
+
+    if list.last == null do list.last = new_elem;
+}
+
+pop_end :: (list: ^List($T), default: T = 0) -> T {
+    if list.last == null do return default;
+
+    end := list.last;
+    list.last = list.last.prev;
+    list.last.next = null;
+
+    defer raw_free(list.allocator, end);
+    return end.data;
+}
+
+pop_begin :: (list: ^List($T), default: T = 0) -> T {
+    if list.last == null do return default;
+
+    begin := list.first;
+    list.first = list.first.next;
+    list.first.prev = null;
+
+    defer raw_free(list.allocator, begin);
+    return begin.data;
+}
+
+contains :: (list: ^List($T), x: T) -> bool {
+    elem := list.first;
+    while elem != null {
+        if elem.data == x do return true;
+        elem = elem.next;
+    }
+
+    return false;
+}
+
+get_iterator :: (list: ^List($T)) -> Iterator(T) {
+    iterator_next :: ($T: type_expr, data: rawptr) -> (T, bool) {
+        list_iter := cast(^ListIterator(T)) data;
+
+        use package core.intrinsics.onyx { __zero_value }
+        if list_iter.current == null do return __zero_value(T), false;
+
+        defer list_iter.current = list_iter.current.next;
+        return list_iter.current.data, true;
+    }
+
+    iterator_close :: (data: rawptr) {
+        cfree(data);
+    }
+
+    ListIterator :: struct (T: type_expr) {
+        current: ^ListElem(T);
+    }
+
+    list_iterator := new(#type ListIterator(T));
+    list_iterator.current = list.first;
+
+    return .{
+        data = list_iterator,
+        next = #solidify iterator_next { T = T },
+        close = iterator_close,
+    };
+}
+
+#private_file
+allocate_elem :: (list: ^List($T)) -> ^ListElem(T) {
+    return new(#type ListElem(T), allocator=list.allocator);
+}
diff --git a/core/container/map.onyx b/core/container/map.onyx
new file mode 100644 (file)
index 0000000..1153597
--- /dev/null
@@ -0,0 +1,159 @@
+package core.map
+
+#private_file array  :: package core.array
+#private_file string :: package core.string
+
+Map :: struct (K: type_expr, V: type_expr) {
+    hashes  : [..] i32;
+    entries : [..] Entry(K, V);
+
+    // The value provided by `map.get`, if nothing was found.
+    default_value : V;
+
+    Entry :: struct (K: type_expr, V: type_expr) {
+        next  : i32;
+        key   : K;
+        value : V;
+    }
+}
+
+make :: ($Key: type_expr, $Value: type_expr, default: Value = 0, hash_count: i32 = 16) -> Map(Key, Value) {
+    map : Map(Key, Value);
+    init(^map, default = default, hash_count = hash_count);
+    return map;
+}
+
+init :: (use map: ^Map($K, $V), default: V = ~~0, hash_count: i32 = 16) {
+    array.init(^hashes, hash_count);
+    array.init(^entries, 4);
+
+    default_value = default;
+
+    for i: 0 .. hash_count do array.push(^hashes, -1);
+}
+
+free :: (use map: ^Map($K, $V)) {
+    array.free(^hashes);
+    array.free(^entries);
+}
+
+put :: (use map: ^Map($K, $V), key: K, value: V) {
+    lr := lookup(map, key);
+
+    if lr.entry_index >= 0 {
+        entries[lr.entry_index].value = value;
+        return;
+    }
+
+    entry : Map.Entry(K, V);
+    entry.key = key;
+    entry.value = value;
+    entry.next = hashes[lr.hash_index];
+
+    array.push(^entries, entry);
+
+    hashes[lr.hash_index] = entries.count - 1;
+}
+
+has :: (use map: ^Map($K, $V), key: K) -> bool {
+    lr := lookup(map, key);
+    return lr.entry_index >= 0;
+}
+
+get :: (use map: ^Map($K, $V), key: K) -> V {
+    lr := lookup(map, key);
+    if lr.entry_index >= 0 do return entries[lr.entry_index].value;
+
+    return default_value;
+}
+
+get_ptr :: (use map: ^Map($K, $V), key: K) -> ^V {
+    lr := lookup(map, key);
+    if lr.entry_index >= 0 do return ^entries[lr.entry_index].value;
+
+    return null;
+}
+
+delete :: (use map: ^Map($K, $V), key: K) {
+    lr := lookup(map, key);
+    if lr.entry_index < 0 do return;
+
+    if lr.entry_prev < 0   do hashes[lr.hash_index]       = entries[lr.entry_index].next;
+    else                   do entries[lr.entry_prev].next = entries[lr.entry_index].next;
+
+    if lr.entry_index == entries.count - 1 {
+        array.pop(^entries);
+        return;
+    }
+
+    array.fast_delete(^entries, lr.entry_index);
+    last := lookup(map, entries[lr.entry_index].key);
+    if last.entry_prev >= 0    do entries[last.entry_prev].next = lr.entry_index;
+    else                       do hashes[last.hash_index] = lr.entry_index;
+}
+
+update :: (use map: ^Map($K, $V), key: K, f: (^V) -> void) {
+    lr := lookup(map, key);
+    if lr.entry_index < 0 do return;
+
+    f(^entries[lr.entry_index].value);
+}
+
+clear :: (use map: ^Map($K, $V)) {
+    for i: 0 .. hashes.count do hashes.data[i] = -1;
+    entries.count = 0;
+}
+
+empty :: (use map: ^Map($K, $V)) -> bool {
+    return entries.count == 0;
+}
+
+hash_function :: proc {
+    (key: rawptr) -> u32 { return 0xcbf29ce7 ^ cast(u32) key; },
+    (key: i32)    -> u32 { return 0xcbf29ce7 ^ cast(u32) key; },
+    (key: i64)    -> u32 { return cast(u32) (cast(u64) 0xcbf29ce7 ^ cast(u64) key); },
+    (key: str)    -> u32 {
+        hash: u32 = 5381;
+        for ch: key do hash += (hash << 5) + ~~ch;
+        return hash;
+    },
+}
+
+// CLEANUP: This could be replaced with operator overloading of '=='
+cmp_function :: proc {
+    (a: rawptr, b: rawptr) -> bool { return a == b; },
+    (a: i32, b: i32) -> bool       { return a == b; },
+    (a: i64, b: i64) -> bool       { return a == b; },
+
+    string.equal,
+}
+
+//
+// Private symbols
+//
+
+#private_file
+MapLookupResult :: struct {
+    hash_index  : i32 = -1;
+    entry_index : i32 = -1;
+    entry_prev  : i32 = -1;
+}
+
+#private_file
+lookup :: (use map: ^Map($K, $V), key: K) -> MapLookupResult {
+    lr := MapLookupResult.{};
+
+    hash: u32 = hash_function(key); // You cannot use this type for the key, unless you add an overload.
+
+    lr.hash_index = hash % hashes.count;
+    lr.entry_index = hashes[lr.hash_index];
+
+    while lr.entry_index >= 0 {
+        if cmp_function(entries[lr.entry_index].key, key) do return lr;
+
+        lr.entry_prev = lr.entry_index;
+        lr.entry_index = entries[lr.entry_index].next;
+    }
+
+    return lr;
+}
diff --git a/core/iter.onyx b/core/iter.onyx
deleted file mode 100644 (file)
index ff8f029..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-package core.iter
-
-use package core.intrinsics.onyx { __zero_value }
-
-filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
-    FilterIterator :: struct (T: type_expr) {
-        iterator:  Iterator(T);
-        predicate: (T) -> bool;
-    }
-
-    filter_iterator := new(#type FilterIterator(T));
-    filter_iterator.iterator = it;
-    filter_iterator.predicate = predicate;
-
-    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
-        fi := cast(^FilterIterator(T)) data;
-
-        value, cont := fi.iterator.next(fi.iterator.data);
-        if cont {
-            while !fi.predicate(value) {
-                value, cont = fi.iterator.next(fi.iterator.data);
-                if !cont do return value, false;
-            }
-
-            return value, true;
-        } else {
-            return value, false;
-        }
-    }
-
-    close :: ($T: type_expr, data: rawptr) {
-        fi := cast(^FilterIterator(T)) data;
-        fi.iterator.close(fi.iterator.data);
-        cfree(data);
-    }
-
-    return .{
-        data  = filter_iterator,
-        next  = #solidify next  { T=T },
-        close = #solidify close { T=T },
-    };
-}
-
-map :: (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) {
-    MapIterator :: struct (T: type_expr, R: type_expr) {
-        iterator:  Iterator(T);
-        transform: (T) -> R;
-    }
-
-    map_iterator := new(#type MapIterator(T, R));
-    map_iterator.iterator = it;
-    map_iterator.transform = transform;
-
-    next :: ($T: type_expr, $R: type_expr, data: rawptr) -> (R, bool) {
-        mi := cast(^MapIterator(T, R)) data;
-
-        value, cont := mi.iterator.next(mi.iterator.data);
-        if !cont do return value, false;
-
-        return mi.transform(value), true;
-    }
-
-    close :: ($T: type_expr, $R: type_expr, data: rawptr) {
-        mi := cast(^MapIterator(T, R)) data;
-        mi.iterator.close(mi.iterator.data);
-        cfree(data);
-    }
-
-    return .{
-        data  = map_iterator,
-        next  = #solidify next  { T=T, R=R },
-        close = #solidify close { T=T, R=R },
-    };
-}
-
-take :: (it: Iterator($T), count: u32) -> Iterator(T) {
-    TakeIterator :: struct (T: type_expr) {
-        iterator:  Iterator(T);
-        remaining: u32;
-    }
-
-    take_iterator := new(#type TakeIterator(T));
-    take_iterator.iterator = it;
-    take_iterator.remaining = count;
-
-    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
-        ti := cast(^TakeIterator(T)) data;
-        if ti.remaining == 0 do return __zero_value(T), false;
-
-        ti.remaining -= 1;
-        return ti.iterator.next(ti.iterator.data);
-    }
-
-    close :: ($T: type_expr, data: rawptr) {
-        ti := cast(^TakeIterator(T)) data;
-        ti.iterator.close(ti.iterator.data);
-        cfree(data);
-    }
-
-    return .{
-        data  = take_iterator,
-        next  = #solidify next  { T=T },
-        close = #solidify close { T=T },
-    };
-}
-
-take_while :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
-    TakeIterator :: struct (T: type_expr) {
-        iterator:  Iterator(T);
-        predicate: (T) -> bool;
-    }
-
-    take_iterator := new(#type TakeIterator(T));
-    take_iterator.iterator = it;
-    take_iterator.predicate = predicate;
-
-    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
-        ti := cast(^TakeIterator(T)) data;
-
-        value, cont := ti.iterator.next(ti.iterator.data);
-        if !cont do return value, false;
-
-        return value, ti.predicate(value);
-    }
-
-    close :: ($T: type_expr, data: rawptr) {
-        ti := cast(^TakeIterator(T)) data;
-        ti.iterator.close(ti.iterator.data);
-        cfree(data);
-    }
-
-    return .{
-        data  = take_iterator,
-        next  = #solidify next  { T=T },
-        close = #solidify close { T=T },
-    };
-}
-
-skip :: (it: Iterator($T), count: u32) -> Iterator(T) {
-    SkipIterator :: struct (T: type_expr) {
-        iterator: Iterator(T);
-        to_skip:  i32;
-        skipped:  bool = false;
-    }
-
-    skip_iterator := new(#type SkipIterator(T));
-    skip_iterator.iterator = it;
-    skip_iterator.to_skip = count;
-
-    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
-        si := cast(^SkipIterator(T)) data;
-
-        while !si.skipped && si.to_skip > 0 {
-            si.to_skip -= 1;
-            value, cont := si.iterator.next(si.iterator.data);
-
-            if !cont {
-                si.skipped = true;
-                return value, false;
-            }
-        }
-
-        return si.iterator.next(si.iterator.data);
-    }
-
-    close :: ($T: type_expr, data: rawptr) {
-        si := cast(^SkipIterator(T)) data;
-        si.iterator.close(si.iterator.data);
-        cfree(data);
-    }
-
-    return .{
-        data  = skip_iterator,
-        next  = #solidify next  { T=T },
-        close = #solidify close { T=T },
-    };
-}
-
-fold :: (it: Iterator($T), initial_value: R, combine: (T, $R) -> R) -> R {
-    for value: it {
-        initial_value = combine(value, initial_value);
-    }
-    
-    return initial_value;
-}
-
-to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
-    array :: package core.array
-
-    arr := array.make(T, allocator=allocator);
-    for v: it do array.push(^arr, v);
-
-    return arr;
-}
diff --git a/core/list.onyx b/core/list.onyx
deleted file mode 100644 (file)
index d4bd065..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-package core.list
-
-ListElem :: struct (T: type_expr) {
-    next: ^ListElem(T) = null;
-    prev: ^ListElem(T) = null;
-    data: T;
-}
-
-List :: struct (T: type_expr) {
-    allocator: Allocator;
-
-    first: ^ListElem(T) = null;
-    last:  ^ListElem(T) = null;
-}
-
-make :: ($T: type_expr, allocator := context.allocator) -> List(T) {
-    return .{ allocator = allocator };
-}
-
-push_end :: (list: ^List($T), x: T) { 
-    new_elem := allocate_elem(list);
-    new_elem.data = x;
-
-    new_elem.prev = list.last;
-    list.last.next = new_elem;
-    list.last = new_elem;
-
-    if list.first == null do list.first = new_elem;
-}
-
-push_begin :: (list: ^List($T), x: T) {
-    new_elem := allocate_elem(list);
-    new_elem.data = x;
-
-    new_elem.next = list.first;
-    list.first.prev = new_elem;
-    list.first = new_elem;
-
-    if list.last == null do list.last = new_elem;
-}
-
-pop_end :: (list: ^List($T), default: T = 0) -> T {
-    if list.last == null do return default;
-
-    end := list.last;
-    list.last = list.last.prev;
-    list.last.next = null;
-
-    defer raw_free(list.allocator, end);
-    return end.data;
-}
-
-pop_begin :: (list: ^List($T), default: T = 0) -> T {
-    if list.last == null do return default;
-
-    begin := list.first;
-    list.first = list.first.next;
-    list.first.prev = null;
-
-    defer raw_free(list.allocator, begin);
-    return begin.data;
-}
-
-contains :: (list: ^List($T), x: T) -> bool {
-    elem := list.first;
-    while elem != null {
-        if elem.data == x do return true;
-        elem = elem.next;
-    }
-
-    return false;
-}
-
-get_iterator :: (list: ^List($T)) -> Iterator(T) {
-    iterator_next :: ($T: type_expr, data: rawptr) -> (T, bool) {
-        list_iter := cast(^ListIterator(T)) data;
-
-        use package core.intrinsics.onyx { __zero_value }
-        if list_iter.current == null do return __zero_value(T), false;
-
-        defer list_iter.current = list_iter.current.next;
-        return list_iter.current.data, true;
-    }
-
-    iterator_close :: (data: rawptr) {
-        cfree(data);
-    }
-
-    ListIterator :: struct (T: type_expr) {
-        current: ^ListElem(T);
-    }
-
-    list_iterator := new(#type ListIterator(T));
-    list_iterator.current = list.first;
-
-    return .{
-        data = list_iterator,
-        next = #solidify iterator_next { T = T },
-        close = iterator_close,
-    };
-}
-
-#private_file
-allocate_elem :: (list: ^List($T)) -> ^ListElem(T) {
-    return new(#type ListElem(T), allocator=list.allocator);
-}
diff --git a/core/map.onyx b/core/map.onyx
deleted file mode 100644 (file)
index 1153597..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-package core.map
-
-#private_file array  :: package core.array
-#private_file string :: package core.string
-
-Map :: struct (K: type_expr, V: type_expr) {
-    hashes  : [..] i32;
-    entries : [..] Entry(K, V);
-
-    // The value provided by `map.get`, if nothing was found.
-    default_value : V;
-
-    Entry :: struct (K: type_expr, V: type_expr) {
-        next  : i32;
-        key   : K;
-        value : V;
-    }
-}
-
-make :: ($Key: type_expr, $Value: type_expr, default: Value = 0, hash_count: i32 = 16) -> Map(Key, Value) {
-    map : Map(Key, Value);
-    init(^map, default = default, hash_count = hash_count);
-    return map;
-}
-
-init :: (use map: ^Map($K, $V), default: V = ~~0, hash_count: i32 = 16) {
-    array.init(^hashes, hash_count);
-    array.init(^entries, 4);
-
-    default_value = default;
-
-    for i: 0 .. hash_count do array.push(^hashes, -1);
-}
-
-free :: (use map: ^Map($K, $V)) {
-    array.free(^hashes);
-    array.free(^entries);
-}
-
-put :: (use map: ^Map($K, $V), key: K, value: V) {
-    lr := lookup(map, key);
-
-    if lr.entry_index >= 0 {
-        entries[lr.entry_index].value = value;
-        return;
-    }
-
-    entry : Map.Entry(K, V);
-    entry.key = key;
-    entry.value = value;
-    entry.next = hashes[lr.hash_index];
-
-    array.push(^entries, entry);
-
-    hashes[lr.hash_index] = entries.count - 1;
-}
-
-has :: (use map: ^Map($K, $V), key: K) -> bool {
-    lr := lookup(map, key);
-    return lr.entry_index >= 0;
-}
-
-get :: (use map: ^Map($K, $V), key: K) -> V {
-    lr := lookup(map, key);
-    if lr.entry_index >= 0 do return entries[lr.entry_index].value;
-
-    return default_value;
-}
-
-get_ptr :: (use map: ^Map($K, $V), key: K) -> ^V {
-    lr := lookup(map, key);
-    if lr.entry_index >= 0 do return ^entries[lr.entry_index].value;
-
-    return null;
-}
-
-delete :: (use map: ^Map($K, $V), key: K) {
-    lr := lookup(map, key);
-    if lr.entry_index < 0 do return;
-
-    if lr.entry_prev < 0   do hashes[lr.hash_index]       = entries[lr.entry_index].next;
-    else                   do entries[lr.entry_prev].next = entries[lr.entry_index].next;
-
-    if lr.entry_index == entries.count - 1 {
-        array.pop(^entries);
-        return;
-    }
-
-    array.fast_delete(^entries, lr.entry_index);
-    last := lookup(map, entries[lr.entry_index].key);
-    if last.entry_prev >= 0    do entries[last.entry_prev].next = lr.entry_index;
-    else                       do hashes[last.hash_index] = lr.entry_index;
-}
-
-update :: (use map: ^Map($K, $V), key: K, f: (^V) -> void) {
-    lr := lookup(map, key);
-    if lr.entry_index < 0 do return;
-
-    f(^entries[lr.entry_index].value);
-}
-
-clear :: (use map: ^Map($K, $V)) {
-    for i: 0 .. hashes.count do hashes.data[i] = -1;
-    entries.count = 0;
-}
-
-empty :: (use map: ^Map($K, $V)) -> bool {
-    return entries.count == 0;
-}
-
-hash_function :: proc {
-    (key: rawptr) -> u32 { return 0xcbf29ce7 ^ cast(u32) key; },
-    (key: i32)    -> u32 { return 0xcbf29ce7 ^ cast(u32) key; },
-    (key: i64)    -> u32 { return cast(u32) (cast(u64) 0xcbf29ce7 ^ cast(u64) key); },
-    (key: str)    -> u32 {
-        hash: u32 = 5381;
-        for ch: key do hash += (hash << 5) + ~~ch;
-        return hash;
-    },
-}
-
-// CLEANUP: This could be replaced with operator overloading of '=='
-cmp_function :: proc {
-    (a: rawptr, b: rawptr) -> bool { return a == b; },
-    (a: i32, b: i32) -> bool       { return a == b; },
-    (a: i64, b: i64) -> bool       { return a == b; },
-
-    string.equal,
-}
-
-//
-// Private symbols
-//
-
-#private_file
-MapLookupResult :: struct {
-    hash_index  : i32 = -1;
-    entry_index : i32 = -1;
-    entry_prev  : i32 = -1;
-}
-
-#private_file
-lookup :: (use map: ^Map($K, $V), key: K) -> MapLookupResult {
-    lr := MapLookupResult.{};
-
-    hash: u32 = hash_function(key); // You cannot use this type for the key, unless you add an overload.
-
-    lr.hash_index = hash % hashes.count;
-    lr.entry_index = hashes[lr.hash_index];
-
-    while lr.entry_index >= 0 {
-        if cmp_function(entries[lr.entry_index].key, key) do return lr;
-
-        lr.entry_prev = lr.entry_index;
-        lr.entry_index = entries[lr.entry_index].next;
-    }
-
-    return lr;
-}
index f245a718275b7a4463402e93b17e0a258593d639..677d0e65faa622abf78dd3ab6fa463bd2a6e75e0 100644 (file)
@@ -4,10 +4,10 @@ package core
 #load "core/alloc"
 #load "core/memory"
 
-#load "core/array"
-#load "core/map"
-#load "core/list"
-#load "core/iter"
+#load "core/container/array"
+#load "core/container/map"
+#load "core/container/list"
+#load "core/container/iter"
 
 #load "core/conv"
 #load "core/math"