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
+7 -1
View File
@@ -548,9 +548,15 @@ proc resolveExprType(ctx: var LowerCtx, expr: Expr): Type =
return makeUnknown()
else: return ctx.resolveExprType(expr.exprUnaryOperand)
of ekCall:
# Local / param fat-func values (after monomorphization typeSubst) — e.g. f: func(T)->U
# Must run before the global-only lookup so generic HOFs get the correct return type.
if expr.exprCallCallee.kind in {ekIdent, ekPath}:
let calType = ctx.resolveExprType(expr.exprCallCallee)
if calType != nil and calType.kind == tkFunc and calType.inner.len > 0:
return calType.inner[^1]
if expr.exprCallCallee.kind == ekIdent:
let sym = ctx.globalScope.lookup(expr.exprCallCallee.exprIdent)
if sym != nil and sym.typ != nil and sym.typ.kind == tkFunc:
if sym != nil and sym.typ != nil and sym.typ.kind == tkFunc and sym.typ.inner.len > 0:
return sym.typ.inner[^1]
if expr.exprCallCallee.kind == ekField:
let recvType = ctx.resolveExprType(expr.exprCallCallee.exprFieldObj)