d517c62380
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
- feat: generic enum support (parser, lowering, codegen — both selfhost + bootstrap)
- enum Result<T,E> { Ok(T), Err(E) } parsing + monomorphization
- tag constant mangling in monomorphized function bodies
- data field access (l-value + r-value) for generated enum instances
- multiple concrete instances in same file
- HIR walker for enum reference mangling (selfhost + bootstrap)
- feat: stdlib Result<T,E> and Option<T> made truly generic
- breaking: explicit type args required (Result<int, String>)
- fix: 'is' operator — lowering to hBinary tag comparison + C backend fallback
- fix: Type_Eq structural comparison (inner types for pointer/slice/tuple)
- fix: hardcoded limit diagnostics (>8 params/variants/captures now emit errors)
- docs: Iter<T> safety warning for dangling pointer
- docs: IMPROVEMENTS.md — comprehensive plan and changelog
- test: generic_enum example added to EXAMPLES
All tests pass (0 FAIL). Selfhost loop deterministic.
238 lines
6.8 KiB
Plaintext
238 lines
6.8 KiB
Plaintext
module Std::Iter {
|
|
|
|
import Std::Array::*;
|
|
|
|
// SAFETY: Iter<T> stores a raw *T pointer to the source array's element buffer.
|
|
// The iterator MUST NOT outlive the source Array<T>. Modifying the source array
|
|
// (e.g. Array_Push which may reallocate the buffer) while an iterator is active
|
|
// will result in a dangling pointer and undefined behavior.
|
|
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 (generic; fat func pointers / closures)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/* 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<U> = Array_New<U>(cap);
|
|
var i: uint = it.pos;
|
|
while i < it.len {
|
|
let mapped: U = f(it.data[i]);
|
|
Array_Push<U>(&out, mapped);
|
|
i = i + 1;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/* 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<T> = Array_New<T>(cap);
|
|
var i: uint = it.pos;
|
|
while i < it.len {
|
|
let v: T = it.data[i];
|
|
if pred(v) {
|
|
Array_Push<T>(&out, v);
|
|
}
|
|
i = i + 1;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/* 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]);
|
|
i = i + 1;
|
|
}
|
|
return acc;
|
|
}
|
|
|
|
/* 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]);
|
|
i = i + 1;
|
|
}
|
|
}
|
|
|
|
/* True if any remaining element satisfies pred */
|
|
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]) {
|
|
return true;
|
|
}
|
|
i = i + 1;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* True if all remaining elements satisfy pred (true if empty) */
|
|
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]) {
|
|
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;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 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);
|
|
}
|
|
|
|
}
|