f1896183f5
Add int-specialized higher-order Iter helpers that accept fat function pointers, plus an example using named funcs and capturing closures. Fix selfhost C backend pointer field access and Array Push indexing.
206 lines
4.9 KiB
Plaintext
206 lines
4.9 KiB
Plaintext
module Std::Iter {
|
|
|
|
import Std::Array::*;
|
|
|
|
struct Iter<T> {
|
|
data: *T,
|
|
len: uint,
|
|
pos: uint,
|
|
}
|
|
|
|
/* Create an iterator from an Array */
|
|
func Array_Iter<T>(arr: *Array<T>) -> Iter<T> {
|
|
return Iter<T> { data: arr.data, len: arr.len, pos: 0 };
|
|
}
|
|
|
|
/* Check if there are more elements */
|
|
func Iter_HasNext<T>(it: *Iter<T>) -> bool {
|
|
return it.pos < it.len;
|
|
}
|
|
|
|
/* Get the next element and advance (undefined if HasNext is false) */
|
|
func Iter_Next<T>(it: *Iter<T>) -> 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<T>(it: *Iter<T>) -> T {
|
|
return it.data[it.pos];
|
|
}
|
|
|
|
/* Reset iterator to the beginning */
|
|
func Iter_Reset<T>(it: *Iter<T>) {
|
|
it.pos = 0;
|
|
}
|
|
|
|
/* Current position */
|
|
func Iter_Pos<T>(it: *Iter<T>) -> uint {
|
|
return it.pos;
|
|
}
|
|
|
|
/* Remaining length */
|
|
func Iter_Len<T>(it: *Iter<T>) -> uint {
|
|
return it.len;
|
|
}
|
|
|
|
/* Count remaining elements */
|
|
func Iter_Count<T>(it: *Iter<T>) -> uint {
|
|
return it.len - it.pos;
|
|
}
|
|
|
|
/* Skip N elements */
|
|
func Iter_Skip<T>(it: *Iter<T>, 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<T>(it: *Iter<T>, n: uint) -> Iter<T> {
|
|
var endPos: uint = it.pos + n;
|
|
if endPos > it.len {
|
|
endPos = it.len;
|
|
}
|
|
return Iter<T> { data: it.data, len: endPos, pos: it.pos };
|
|
}
|
|
|
|
/* True if any remaining element equals value */
|
|
func Iter_AnyEq<T>(it: *Iter<T>, 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<T>(it: *Iter<T>, 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<T>(it: *Iter<T>) -> Array<T> {
|
|
let remaining: uint = it.len - it.pos;
|
|
var cap: uint = remaining;
|
|
if cap == 0 {
|
|
cap = 1;
|
|
}
|
|
var arr: Array<T> = Array_New<T>(cap);
|
|
var i: uint = it.pos;
|
|
while i < it.len {
|
|
Array_Push<T>(&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<int>, f: func(int) -> int) -> Array<int> {
|
|
let remaining: uint = it.len - it.pos;
|
|
var cap: uint = remaining;
|
|
if cap == 0 {
|
|
cap = 1;
|
|
}
|
|
var out: Array<int> = Array_New<int>(cap);
|
|
var i: uint = it.pos;
|
|
while i < it.len {
|
|
let mapped: int = f(it.data[i]);
|
|
Array_Push<int>(&out, mapped);
|
|
i = i + 1;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/* Keep remaining ints for which pred returns true */
|
|
func Iter_FilterInt(it: *Iter<int>, pred: func(int) -> bool) -> Array<int> {
|
|
let remaining: uint = it.len - it.pos;
|
|
var cap: uint = remaining;
|
|
if cap == 0 {
|
|
cap = 1;
|
|
}
|
|
var out: Array<int> = Array_New<int>(cap);
|
|
var i: uint = it.pos;
|
|
while i < it.len {
|
|
let v: int = it.data[i];
|
|
if pred(v) {
|
|
Array_Push<int>(&out, v);
|
|
}
|
|
i = i + 1;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/* Left-fold remaining ints: f(f(...f(init, x0), x1), ...) */
|
|
func Iter_FoldInt(it: *Iter<int>, 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<int>, 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<int>, 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<int>, 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>) -> int {
|
|
var total: int = 0;
|
|
var i: uint = it.pos;
|
|
while i < it.len {
|
|
total = total + it.data[i];
|
|
i = i + 1;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
}
|