it.close(it.data);
}
-filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
+filter :: #match {}
+#match filter (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
FilterIterator :: struct (T: type_expr) {
iterator: Iterator(T);
predicate: (T) -> bool;
};
}
-map :: (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) {
+#match filter (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool) -> Iterator(T) {
+ FilterIterator :: struct (T: type_expr, Ctx: type_expr) {
+ iterator: Iterator(T);
+ predicate: (T, Ctx) -> bool;
+ ctx: Ctx;
+ }
+
+ filter_iterator := new(FilterIterator(T, Ctx));
+ filter_iterator.iterator = it;
+ filter_iterator.predicate = predicate;
+ filter_iterator.ctx = ctx;
+
+ next :: (fi: ^FilterIterator($T, $_)) -> (T, bool) {
+ value, cont := fi.iterator.next(fi.iterator.data);
+ if cont {
+ while !fi.predicate(value, fi.ctx) {
+ value, cont = fi.iterator.next(fi.iterator.data);
+ if !cont do return value, false;
+ }
+
+ return value, true;
+ } else {
+ return value, false;
+ }
+ }
+
+ close :: (fi: ^FilterIterator($T, $_)) {
+ if fi.iterator.close != null_proc do fi.iterator.close(fi.iterator.data);
+ cfree(fi);
+ }
+
+ return .{
+ data = filter_iterator,
+ next = #solidify next { T=T, _=Ctx },
+ close = #solidify close { T=T, _=Ctx },
+ };
+}
+
+map :: #match {}
+#match map (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) {
MapIterator :: struct (T: type_expr, R: type_expr) {
iterator: Iterator(T);
transform: (T) -> R;
};
}
+#match map (it: Iterator($T), ctx: $Ctx, transform: (T, Ctx) -> $R) -> Iterator(R) {
+ MapIterator :: struct (T: type_expr, R: type_expr, Ctx: type_expr) {
+ iterator: Iterator(T);
+ transform: (T, Ctx) -> R;
+ ctx: Ctx;
+ }
+
+ map_iterator := new(MapIterator(T, R, Ctx));
+ map_iterator.iterator = it;
+ map_iterator.transform = transform;
+ map_iterator.ctx = ctx;
+
+ next :: (mi: ^MapIterator($T, $R, $Ctx)) -> (R, bool) {
+ value, cont := mi.iterator.next(mi.iterator.data);
+ if !cont do return __zero_value(R), false;
+
+ return mi.transform(value, mi.ctx), true;
+ }
+
+ close :: (mi: ^MapIterator($T, $R, $Ctx)) {
+ if mi.iterator.close != null_proc do mi.iterator.close(mi.iterator.data);
+ cfree(mi);
+ }
+
+ return .{
+ data = map_iterator,
+ next = #solidify next { T=T, R=R, Ctx=Ctx },
+ close = #solidify close { T=T, R=R, Ctx=Ctx },
+ };
+}
+
take_one :: (it: Iterator($T), no_close := false) -> (T, bool) {
ret, cont := it.next(it.data);
if !cont && !no_close do it.close(it.data);