From: Brendan Hansen Date: Tue, 20 Apr 2021 16:42:05 +0000 (-0500) Subject: started working on lazy iterator library X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=339c2194d5e3138a9716589519caf7e55ed296d2;p=onyx.git started working on lazy iterator library --- diff --git a/bin/onyx b/bin/onyx index 084335c7..2b1992df 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/iter.onyx b/core/iter.onyx new file mode 100644 index 00000000..032fa2e8 --- /dev/null +++ b/core/iter.onyx @@ -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; +} diff --git a/core/std.onyx b/core/std.onyx index 77d6c911..f245a718 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -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 index 00000000..7442341f --- /dev/null +++ b/tests/lazy_iterators @@ -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 index 00000000..58f48a25 --- /dev/null +++ b/tests/lazy_iterators.onyx @@ -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]); +}