fix(hir_lower): generic monomorphization for cross-module generic calls

The old findGenericCalls second-pass only looked in non-generic functions
and generated unresolved instances like Array_Get_T when generic funcs
called other generic funcs. Removed it entirely.

lowerExpr for ekCall now invokes generateMethodInstance directly for
both explicit (ekGenericCall) and inferred generic calls. This ensures
concrete instantiations are generated on-demand with correct typeSubst.

Also added guard in resolveTypeExpr/substituteType to skip emitting C
struct definitions for unresolved type parameters (e.g. Array<T> inside
a generic function body before monomorphization).

feat(std): add Std::Iter module
- Array_Iter, Iter_Next, Iter_HasNext, Iter_Peek, Iter_Reset
- Iter_Pos, Iter_Len, Iter_Count, Iter_Skip, Iter_Take

docs: document Std::Iter in Stdlib.md
examples: add iter.bux example
tests: add _test_array regression test
This commit is contained in:
2026-06-05 23:39:41 +03:00
parent 846c29c6dd
commit 7b32cad3e9
7 changed files with 224 additions and 184 deletions
+70
View File
@@ -0,0 +1,70 @@
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 };
}
}