started working on lazy iterator library
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 20 Apr 2021 16:42:05 +0000 (11:42 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 20 Apr 2021 16:42:05 +0000 (11:42 -0500)
bin/onyx
core/iter.onyx [new file with mode: 0644]
core/std.onyx
tests/lazy_iterators [new file with mode: 0644]
tests/lazy_iterators.onyx [new file with mode: 0644]

index 084335c70c369ccb3bef3e0f215c66972f7617d2..2b1992dfce0cf8c6ac843d75f47e347ea154b742 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
diff --git a/core/iter.onyx b/core/iter.onyx
new file mode 100644 (file)
index 0000000..032fa2e
--- /dev/null
@@ -0,0 +1,88 @@
+package core.iter
+
+use package core.intrinsics.onyx { __zero_value }
+
+filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
+    FoldIterator :: struct (T: type_expr) {
+        iterator:  Iterator(T);
+        predicate: (T) -> bool;
+    }
+
+    fold_iterator := new(#type FoldIterator(T));
+    fold_iterator.iterator = it;
+    fold_iterator.predicate = predicate;
+
+    next :: ($T: type_expr, data: rawptr) -> (T, bool) {
+        fi := cast(^FoldIterator(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(^FoldIterator(T)) data;
+        fi.iterator.close(fi.iterator.data);
+        cfree(data);
+    }
+
+    return .{
+        data  = fold_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 },
+    };
+}
+
+fold :: (it: Iterator($T), initial_value: R = __zero_value(R), combine: (T, $R) -> R) -> R {
+    assert(false, "Not implemented yet");
+    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;
+}
index 77d6c911d61c6e3a0d5f4ac80ba40a694c6aff3e..f245a718275b7a4463402e93b17e0a258593d639 100644 (file)
@@ -7,6 +7,7 @@ package core
 #load "core/array"
 #load "core/map"
 #load "core/list"
+#load "core/iter"
 
 #load "core/conv"
 #load "core/math"
diff --git a/tests/lazy_iterators b/tests/lazy_iterators
new file mode 100644 (file)
index 0000000..7442341
--- /dev/null
@@ -0,0 +1,9 @@
+Starting the iteration...
+54
+56
+58
+60
+62
+Closing the count iterator...
+Closing the count iterator...
+58
diff --git a/tests/lazy_iterators.onyx b/tests/lazy_iterators.onyx
new file mode 100644 (file)
index 0000000..58f48a2
--- /dev/null
@@ -0,0 +1,56 @@
+#load "core/std"
+
+use package core
+
+count_iterator :: (lo: i32, hi: i32, step := 1) -> Iterator(i32) {
+    next :: (data: rawptr) -> (i32, bool) {
+        ci := cast(^CountIterator) data;
+        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 {
+        low, high, step: i32;
+        current: i32;
+    }
+
+    count_iterator := new(CountIterator);
+    count_iterator.low = lo;
+    count_iterator.high = hi;
+    count_iterator.step = step;
+    count_iterator.current = lo;
+
+    return .{
+        data = count_iterator,
+        next = next,
+        close = close,
+    };
+}
+
+main :: (args: [] cstr) {
+
+    iterator := count_iterator(1, 10)
+                |> iter.map((x: i32) -> i32 do return x * 2;)
+                |> iter.filter((x: i32) -> bool do return x > 10;)
+                |> iter.map((x: i32) -> i32 do return x + 42;);
+
+    println("Starting the iteration...");
+    for i: iterator {
+        println(i);
+    }
+
+    arr := count_iterator(1, 10)
+                |> iter.map((x: i32) -> i32 do return x * 2;)
+                |> iter.filter((x: i32) -> bool do return x > 10;)
+                |> iter.map((x: i32) -> i32 do return x + 42;)
+                |> iter.to_array();
+
+    println(arr[2]);
+}