feat(stdlib): generic Iter_Map/Filter/Fold with func monomorphization

Add Iter_Map<T,U>, Filter, Fold, Any, All, ForEach over fat function
pointers; keep Iter_MapInt and friends as thin aliases.

Compiler fixes required for non-int returns and capturing closures:
- bootstrap: resolve fat-func call return type under mono typeSubst
- bootstrap: type-check args of Foo<T>(...) so closures capture correctly
- selfhost: substitute type params inside tekFunc (BuxFn_U_T → concrete)
- selfhost: emit cstr fat typedefs with #ifndef redefinition guards

Example: examples/iter_generic.bux (int↔String map, fold, closures).
Selfhost-loop remains binary-identical.
This commit is contained in:
2026-07-18 01:07:41 +03:00
parent 26631252c0
commit eac78f28c1
9 changed files with 267 additions and 87 deletions
+46 -18
View File
@@ -108,48 +108,48 @@ func Iter_Collect<T>(it: *Iter<T>) -> Array<T> {
}
// ---------------------------------------------------------------------------
// Higher-order helpers (int-specialized; take fat func pointers / closures)
// Higher-order helpers (generic; 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> {
/* Map each remaining element through f: T → U, collect into Array<U> */
func Iter_Map<T, U>(it: *Iter<T>, f: func(T) -> U) -> Array<U> {
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 out: Array<U> = Array_New<U>(cap);
var i: uint = it.pos;
while i < it.len {
let mapped: int = f(it.data[i]);
Array_Push<int>(&out, mapped);
let mapped: U = f(it.data[i]);
Array_Push<U>(&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> {
/* Keep remaining elements for which pred returns true */
func Iter_Filter<T>(it: *Iter<T>, pred: func(T) -> bool) -> Array<T> {
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 out: Array<T> = Array_New<T>(cap);
var i: uint = it.pos;
while i < it.len {
let v: int = it.data[i];
let v: T = it.data[i];
if pred(v) {
Array_Push<int>(&out, v);
Array_Push<T>(&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;
/* Left-fold: f(f(...f(init, x0), x1), ...) */
func Iter_Fold<T, Acc>(it: *Iter<T>, init: Acc, f: func(Acc, T) -> Acc) -> Acc {
var acc: Acc = init;
var i: uint = it.pos;
while i < it.len {
acc = f(acc, it.data[i]);
@@ -158,8 +158,8 @@ func Iter_FoldInt(it: *Iter<int>, init: int, f: func(int, int) -> int) -> int {
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) {
/* Call f for each remaining element (return value of f is ignored) */
func Iter_ForEach<T>(it: *Iter<T>, f: func(T) -> int) {
var i: uint = it.pos;
while i < it.len {
let _ignored: int = f(it.data[i]);
@@ -168,7 +168,7 @@ func Iter_ForEachInt(it: *Iter<int>, f: func(int) -> int) {
}
/* True if any remaining element satisfies pred */
func Iter_AnyInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
func Iter_Any<T>(it: *Iter<T>, pred: func(T) -> bool) -> bool {
var i: uint = it.pos;
while i < it.len {
if pred(it.data[i]) {
@@ -180,7 +180,7 @@ func Iter_AnyInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
}
/* True if all remaining elements satisfy pred (true if empty) */
func Iter_AllInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
func Iter_All<T>(it: *Iter<T>, pred: func(T) -> bool) -> bool {
var i: uint = it.pos;
while i < it.len {
if !pred(it.data[i]) {
@@ -202,4 +202,32 @@ func Iter_SumInt(it: *Iter<int>) -> int {
return total;
}
// ---------------------------------------------------------------------------
// Int-specialized aliases (backward compatible with earlier examples)
// ---------------------------------------------------------------------------
func Iter_MapInt(it: *Iter<int>, f: func(int) -> int) -> Array<int> {
return Iter_Map<int, int>(it, f);
}
func Iter_FilterInt(it: *Iter<int>, pred: func(int) -> bool) -> Array<int> {
return Iter_Filter<int>(it, pred);
}
func Iter_FoldInt(it: *Iter<int>, init: int, f: func(int, int) -> int) -> int {
return Iter_Fold<int, int>(it, init, f);
}
func Iter_ForEachInt(it: *Iter<int>, f: func(int) -> int) {
Iter_ForEach<int>(it, f);
}
func Iter_AnyInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
return Iter_Any<int>(it, pred);
}
func Iter_AllInt(it: *Iter<int>, pred: func(int) -> bool) -> bool {
return Iter_All<int>(it, pred);
}
}