module Std::Iter { import Std::Array::*; struct Iter { data: *T, len: uint, pos: uint, } /* Create an iterator from an Array */ func Array_Iter(arr: *Array) -> Iter { return Iter { data: arr.data, len: arr.len, pos: 0 }; } /* Check if there are more elements */ func Iter_HasNext(it: *Iter) -> bool { return it.pos < it.len; } /* Get the next element and advance (undefined if HasNext is false) */ func Iter_Next(it: *Iter) -> T { let val: T = it.data[it.pos]; it.pos = it.pos + 1; return val; } /* Peek current element without advancing (undefined if HasNext is false) */ func Iter_Peek(it: *Iter) -> T { return it.data[it.pos]; } /* Reset iterator to the beginning */ func Iter_Reset(it: *Iter) { it.pos = 0; } /* Current position */ func Iter_Pos(it: *Iter) -> uint { return it.pos; } /* Remaining length */ func Iter_Len(it: *Iter) -> uint { return it.len; } /* Count remaining elements */ func Iter_Count(it: *Iter) -> uint { return it.len - it.pos; } /* Skip N elements */ func Iter_Skip(it: *Iter, n: uint) { it.pos = it.pos + n; if it.pos > it.len { it.pos = it.len; } } /* Take first N elements (by limiting len) */ func Iter_Take(it: *Iter, n: uint) -> Iter { var endPos: uint = it.pos + n; if endPos > it.len { endPos = it.len; } return Iter { data: it.data, len: endPos, pos: it.pos }; } /* True if any remaining element equals value */ func Iter_AnyEq(it: *Iter, value: T) -> bool { var i: uint = it.pos; while i < it.len { if it.data[i] == value { return true; } i = i + 1; } return false; } /* True if every remaining element equals value (true if empty) */ func Iter_AllEq(it: *Iter, value: T) -> bool { var i: uint = it.pos; while i < it.len { if it.data[i] != value { return false; } i = i + 1; } return true; } /* Collect remaining elements into a new Array */ func Iter_Collect(it: *Iter) -> Array { let remaining: uint = it.len - it.pos; var cap: uint = remaining; if cap == 0 { cap = 1; } var arr: Array = Array_New(cap); var i: uint = it.pos; while i < it.len { Array_Push(&arr, it.data[i]); i = i + 1; } return arr; } // --------------------------------------------------------------------------- // Higher-order helpers (int-specialized; take fat func pointers / closures) // --------------------------------------------------------------------------- /* Map each remaining int through f, collect into a new Array */ func Iter_MapInt(it: *Iter, f: func(int) -> int) -> Array { let remaining: uint = it.len - it.pos; var cap: uint = remaining; if cap == 0 { cap = 1; } var out: Array = Array_New(cap); var i: uint = it.pos; while i < it.len { let mapped: int = f(it.data[i]); Array_Push(&out, mapped); i = i + 1; } return out; } /* Keep remaining ints for which pred returns true */ func Iter_FilterInt(it: *Iter, pred: func(int) -> bool) -> Array { let remaining: uint = it.len - it.pos; var cap: uint = remaining; if cap == 0 { cap = 1; } var out: Array = Array_New(cap); var i: uint = it.pos; while i < it.len { let v: int = it.data[i]; if pred(v) { Array_Push(&out, v); } i = i + 1; } return out; } /* Left-fold remaining ints: f(f(...f(init, x0), x1), ...) */ func Iter_FoldInt(it: *Iter, init: int, f: func(int, int) -> int) -> int { var acc: int = init; var i: uint = it.pos; while i < it.len { acc = f(acc, it.data[i]); i = i + 1; } return acc; } /* Call f for each remaining int (side effects; f's return is ignored) */ func Iter_ForEachInt(it: *Iter, f: func(int) -> int) { var i: uint = it.pos; while i < it.len { let _ignored: int = f(it.data[i]); i = i + 1; } } /* True if any remaining element satisfies pred */ func Iter_AnyInt(it: *Iter, pred: func(int) -> bool) -> bool { var i: uint = it.pos; while i < it.len { if pred(it.data[i]) { return true; } i = i + 1; } return false; } /* True if all remaining elements satisfy pred (true if empty) */ func Iter_AllInt(it: *Iter, pred: func(int) -> bool) -> bool { var i: uint = it.pos; while i < it.len { if !pred(it.data[i]) { return false; } i = i + 1; } return true; } /* Sum remaining ints (specialized fold) */ func Iter_SumInt(it: *Iter) -> int { var total: int = 0; var i: uint = it.pos; while i < it.len { total = total + it.data[i]; i = i + 1; } return total; } }