slowly making the core libraries more consistent
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 7 Nov 2022 04:49:57 +0000 (22:49 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 7 Nov 2022 04:49:57 +0000 (22:49 -0600)
core/builtin.onyx
core/container/iter.onyx
core/container/list.onyx
core/container/map.onyx
core/container/set.onyx
tests/aoc-2021/day12.onyx
tests/aoc-2021/day18.onyx
tests/interfaces.onyx
tests/lazy_iterators.onyx

index 6f8b6a07c5f59c2e6fba01a0fe5bb6cd64b62164..892e7117a06874bcd7edeeff24ca4a0e38e5c264 100644 (file)
@@ -176,6 +176,10 @@ cfree   :: (ptr: rawptr) do raw_free(context.allocator, ptr);
         }
     }
 
+    new_temp :: macro (T: type_expr) => {
+        return new(T, allocator=context.temp_allocator);
+    }
+
     make :: #match {
         macro ($T: type_expr, allocator := context.allocator) => {
             return __make_overload(cast(^T) null, allocator=allocator);
@@ -186,6 +190,10 @@ cfree   :: (ptr: rawptr) do raw_free(context.allocator, ptr);
         },
     }
 
+    make_temp :: macro (T: type_expr) => {
+        return make(T, allocator=context.temp_allocator);
+    }
+
     //
     // This is a rather unique way of using the type matching system
     // to select an overload. What is desired here is that when you say:
index b9684fbd0dd26be899d155a89eabfa065b50c32c..4141f1ff00a7c71d60cb9454313bc8697ba6ae49 100644 (file)
@@ -455,33 +455,18 @@ enumerate :: (it: Iterator($T), start_index: i32 = 0) -> Iterator(Enumeration_Va
 
 #overload
 as_iterator :: from_array
-from_array :: (arr: [] $T) -> Iterator(^T) {
-    Context :: struct (T: type_expr) {
-        data: ^T;
-        count: u32;
-        current: u32;
-    }
+from_array :: (arr: [] $T) => generator(
+    ^.{ data = arr.data, count = arr.count, current = 0 },
 
-    c := make(Context(T), allocator=context.temp_allocator);
-    c.data = arr.data;
-    c.count = arr.count;
-    c.current = 0;
-
-    next :: (use _: ^Context($T)) -> (^T, bool) {
+    (use ctx: ^$T) -> (typeof ctx.data, bool) {
         if current < count {
             defer current += 1;
             return ^data[current], true;
-
-        } else {
-            return null, false;
         }
-    }
 
-    return .{
-        data  = c,
-        next  = #solidify next { T = T },
-    };
-}
+        return null, false;
+    }
+);
 
 #overload
 as_iterator :: (x: ^[..] $T) -> Iterator(T) {
index fb1a4c95a0bccd3ae4f65dfacd19d66eb0373549..59db247b2f3767ce703c62513bccdc2d1cffc829 100644 (file)
@@ -13,6 +13,9 @@ List :: struct (Elem_Type: type_expr) {
     last:  ^ListElem(Elem_Type) = null;
 
     // "Method" like things
+}
+
+#inject List {
     free         :: free
     push_end     :: push_end
     push_begin   :: push_begin
@@ -23,7 +26,7 @@ List :: struct (Elem_Type: type_expr) {
     contains     :: contains
     fold         :: fold
     map          :: map
-    get_iterator :: get_iterator
+    as_iter      :: as_iter
 }
 
 make :: ($T: type_expr, allocator := context.allocator) -> List(T) {
@@ -145,8 +148,8 @@ map :: #match #local {}
     }
 }
 
-#match core.iter.as_iterator get_iterator
-get_iterator :: (list: ^List($T)) -> Iterator(T) {
+#match core.iter.as_iterator as_iter
+as_iter :: (list: ^List($T)) -> Iterator(T) {
     iterator_next :: (list_iter: ^ListIterator($T)) -> (T, bool) {
         if list_iter.current == null do return .{}, false;
 
@@ -158,13 +161,12 @@ get_iterator :: (list: ^List($T)) -> Iterator(T) {
         current: ^ListElem(T);
     }
 
-    list_iterator := new(ListIterator(T));
+    list_iterator := new_temp(ListIterator(T));
     list_iterator.current = list.first;
 
     return .{
         data = list_iterator,
         next = #solidify iterator_next { T = T },
-        close = cfree,
     };
 }
 
index 7e7ddceb93b55a83c8b3b6c6a91a39c83d6761ab..c5986139a57f20d3b445593a40c4b9227f8e8992 100644 (file)
@@ -34,10 +34,6 @@ Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Ty
 }
 
 #inject Map {
-    //
-    // These need to have aliases because some of them like
-    // 'delete', collide with the global 'delete', which
-    // causes it to map to the wrong function.
     init    :: init
     has     :: has
     get     :: get
index 8bf9d3e6accfa7757e5378203859259d2db267d2..066733febbba6c58377bb26be77cbf75d8d2ee58 100644 (file)
@@ -20,7 +20,9 @@ Set :: struct (Elem_Type: type_expr) where SetValue(Elem_Type) {
         hash  : u32;
         value : T;
     }
+}
 
+#inject Set {
     init     :: init
     free     :: free
     has      :: has
@@ -30,7 +32,7 @@ Set :: struct (Elem_Type: type_expr) where SetValue(Elem_Type) {
     remove   :: remove
     clear    :: clear
     empty    :: empty
-    iterator :: iterator
+    as_iter  :: as_iter
 }
 
 make :: ($T: type_expr, default := T.{}, allocator := context.allocator) -> Set(T) {
@@ -116,33 +118,20 @@ empty :: (use set: ^Set) -> bool {
     return entries.count == 0;
 }
 
-#match core.iter.as_iterator iterator
-iterator :: (set: ^Set($T)) -> Iterator(T) {
-    Context :: struct (T: type_expr) {
-        set: ^Set(T);
-        position: i32;
-    }
-
-    context := new(Context(T));
-    context.set = set;
-    context.position = 0;
+#overload core.iter.as_iterator as_iter
 
-    next :: (use context: ^Context($T)) -> (T, bool) {
-        if position < set.entries.count {
-            defer position += 1;
-            return set.entries[position].value, true;
+as_iter :: (s: ^Set) =>
+    core.iter.generator(
+        ^.{ s = s, i = 0 },
 
-        } else {
-            return .{}, false;
-        }
-    }
+        (ctx) => {
+            if ctx.i >= ctx.s.entries.count {
+                return (typeof ^ctx.s.entries.data.value).{}, false;
+            }
 
-    return .{
-        data = context,
-        next = #solidify next { T = T },
-        close = cfree,
-    };
-}
+            defer ctx.i += 1;
+            return ^ctx.s.entries.data[ctx.i].value, true;
+        });
 
 //
 // Private symbols
index 516e611458d897dfe08f4486c998b0d4bccd5069..2837716a6c289292c3c5670c1687715e95774cde 100644 (file)
@@ -41,16 +41,16 @@ main :: (args) => {
         node_stack << .{ "start", 0, false };
 
         children_of :: (edges: ^$T, name: str) -> Iterator(str) {
-            #persist NAME_HACK: str;
-            NAME_HACK = name;
+            name_copy := make_temp(str);
+            *name_copy = name;
 
             return iter.concat(
                 iter.as_iterator(edges)
-                |> iter.filter((x) => x.a == NAME_HACK)
+                |> iter.filter(name_copy, (x, n) => x.a == *n)
                 |> iter.map((x) => x.b),
 
                 iter.as_iterator(edges)
-                |> iter.filter((x) => x.b == NAME_HACK)
+                |> iter.filter(name_copy, (x, n) => x.b == *n)
                 |> iter.map((x) => x.a)
             );
         }
@@ -62,7 +62,7 @@ main :: (args) => {
 
         edge_map: Map(str, [] str);
         for v: iter.as_iterator(^verticies) {
-            edge_map[v] = children_of(^edges, v) |> iter.to_array();
+            edge_map[*v] = children_of(^edges, *v) |> iter.to_array();
         }
 
         paths_count := 0;
index afd606683f94c23e606aa81a7325b2b25dd07615..77a8a1f1c1f0d9e9bdbfd88f10d28251b54e88be 100644 (file)
@@ -30,7 +30,7 @@ SnailNum :: struct {
     }
 
     clone :: (n: ^SnailNum) -> ^SnailNum {
-        if n == null do return null;
+        if !n do return null;
 
         new_num := SnailNum.make();
         new_num->set_left(SnailNum.clone(n.left));
@@ -42,8 +42,8 @@ SnailNum :: struct {
     }
 
     add :: (a, b: ^SnailNum) => {
-        if a == null do return b;
-        if b == null do return a;
+        if !a do return b;
+        if !b do return a;
 
         new_root := SnailNum.make();
         new_root->set_left(a);
@@ -87,8 +87,8 @@ SnailNum :: struct {
 
         pleft  := n->number_to_left();
         pright := n->number_to_right();
-        if pleft  != null do *pleft += left_val;
-        if pright != null do *pright += right_val;
+        if pleft  do *pleft += left_val;
+        if pright do *pright += right_val;
 
         left_val = 0;
         right_val = 0;
@@ -97,7 +97,7 @@ SnailNum :: struct {
     }
 
     reduce_splits :: (use n: ^SnailNum) -> (reduced_something: bool) {
-        if left != null {
+        if left {
             if left->reduce_splits() {
                 return true;
             }
@@ -109,7 +109,7 @@ SnailNum :: struct {
             return true;
         }
 
-        if right != null {
+        if right {
             if right->reduce_splits() {
                 return true;
             }
@@ -125,34 +125,34 @@ SnailNum :: struct {
 
         split_number :: (n: u32) -> (u32, u32) {
             h := n / 2;
-            return h, h + (0 if n % 2 == 0 else 1);
+            return h, h + (n % 2);
         }
     }
 
     set_left :: (parent, new_left: ^SnailNum) {
         parent.left_val = 0;
         parent.left = new_left;
-        if new_left != null do new_left.parent = parent;
+        if new_left do new_left.parent = parent;
     }
 
     set_right :: (parent, new_right: ^SnailNum) {
         parent.right_val = 0;
         parent.right = new_right;
-        if new_right != null do new_right.parent = parent;
+        if new_right do new_right.parent = parent;
     }
 
     number_to_left :: (n: ^SnailNum) -> ^u32 {
-        while n.parent != null && n.parent.left == n {
+        while n.parent && n.parent.left == n {
             n = n.parent;
         }
 
-        if n.parent == null do return null;
+        if !n.parent do return null;
 
-        if n.parent.left == null do return ^n.parent.left_val;
+        if !n.parent.left do return ^n.parent.left_val;
 
         n = n.parent.left;
 
-        while n.right != null {
+        while n.right {
             n = n.right;
         }
 
@@ -160,17 +160,17 @@ SnailNum :: struct {
     }
 
     number_to_right :: (n: ^SnailNum) -> ^u32 {
-        while n.parent != null && n.parent.right == n {
+        while n.parent && n.parent.right == n {
             n = n.parent;
         }
 
-        if n.parent == null do return null;
+        if !n.parent do return null;
 
-        if n.parent.right == null do return ^n.parent.right_val;
+        if !n.parent.right do return ^n.parent.right_val;
 
         n = n.parent.right;
 
-        while n.left != null {
+        while n.left {
             n = n.left;
         }
 
@@ -178,7 +178,7 @@ SnailNum :: struct {
     }
 
     magnitude :: (use n: ^SnailNum) => {
-        if n == null {
+        if !n {
             return 0;
         }
 
@@ -210,16 +210,16 @@ SnailNum :: struct {
     }
 
     format :: (output: ^conv.Format_Output, s: ^conv.Format, use n: ^SnailNum) {
-        if left == null && right == null {
+        if !left && !right {
             conv.format(output, "[{},{}]", left_val, right_val);
         }
-        elseif left == null && right != null {
+        elseif !left && right {
             conv.format(output, "[{},{*}]", left_val, right);
         }
-        elseif left != null && right == null {
+        elseif left && !right {
             conv.format(output, "[{*},{}]", left, right_val);
         }
-        elseif left != null && right != null {
+        elseif left && right {
             conv.format(output, "[{*},{*}]", left, right);
         }
     }
index 897f903ae7ea59ecdd511e30c97b8752a1220a3f..6e51366ed008b25c9631cf978ab28e8536b3a5ec 100644 (file)
@@ -65,7 +65,7 @@ Complex :: struct {
 #operator + (c1, c2: Complex) => Complex.{ c1.x + c2.x, c1.y + c2.y };
 #operator * (c1, c2: Complex) => Complex.{ c1.x * c2.x - c1.y * c2.y, c1.x * c2.y + c1.y * c2.x };
 
-consume :: macro (x: $T) -> #auto where iter.Iterable(T) {
+consume :: macro (x: $T/iter.Iterable) => {
     // This is a weird limitation of the Onyx type system.
     // In order to be able tell what the iterator produces, you
     // have to pattern match it in a procedure parameter. This means
index 2363483a9aa763b6ad107f2ddad3b71746167af2..ae30bd3e3272f3ff5bdaf4c03a4eb208e85279ea 100644 (file)
@@ -3,34 +3,22 @@
 use package core
 
 count_iterator :: (lo: $T, hi: T, step: T = 1) -> Iterator(T) {
-    next :: (ci: ^CountIterator($T)) -> (T, bool) {
-        if ci.current > ci.high do return 0, false;
-
-        defer ci.current += ci.step;
-        return ci.current, true;
-    }
-
-    close :: (data: rawptr) {
-        println("Closing the count iterator...");
-        cfree(data);
-    }
-
-    CountIterator :: struct (T:type_expr) {
-        low, high, step: T;
-        current: T;
-    }
-
-    count_iterator := new(CountIterator(T));
-    count_iterator.low = lo;
-    count_iterator.high = hi;
-    count_iterator.step = step;
-    count_iterator.current = lo;
-
-    return .{
-        data  = count_iterator,
-        next  = #solidify next {T=T},
-        close = close,
-    };
+    return iter.generator(
+        ^.{ low = lo, high = hi, step = step, current = lo },
+    
+        (ctx) => {
+            if ctx.current <= ctx.high {
+                defer ctx.current += ctx.step;
+                return ctx.current, true;
+            }
+
+            return 0, false;
+        },
+
+        (ctx) => {
+            println("Closing the count iterator...");
+        }
+    );
 }
 
 main :: (args: [] cstr) {