- cli: buxc2 build now delegates to Cli_BuildProject for src/Main.bux,
enabling stdlib merging (Array_Iter, Iter_HasNext, etc. available)
- sema: set expr.refType on ekCall from function return type
(needed for for-loop type extraction from MakeArr()-style expressions)
- hir_lower: remove ekIdent restriction on collection-based for loops
- supports arbitrary expressions: for x in MakeArr() { ... }
- creates temp variable __tmp_coll_N for non-identifier iterators
- generates proper Array_T struct instances for temp variables
- Test: for x in MakeArr() sums [10,20,30] → 60
- Selfhost loop: C output IDENTICAL
- parser: extend-for only linked first 2 methods; now uses lastMethod pointer
- sema: trait bounds checking was after indirect-call early return (tyFunc path),
so Max<Circle>(...) skipped bounds check when callee had tekFunc refType.
Moved bounds check before both indirect/direct call returns.
- Negative test: Circle without Comparable impl now correctly errors.
- Selfhost loop: C output IDENTICAL.
- Fix Fmt_Format name conflict between lib/Fmt.bux and src/fmt.bux
by renaming selfhost formatter function to Fmt_FormatSource.
- Fix collection-based for-in loops to handle already-monomorphized
types like Array_int and Iter_string (typeArgCount=0 cases).
- Fix ekSizeOf and ekCast in HIR lowering to apply Lcx_SubstituteType
during generic monomorphization, so sizeof(T) and *T casts emit
correct concrete types in C output.
- Fix sema to infer stmt.refStmtType from initializer expression
when no explicit type annotation is given, ensuring C backend
emits correct pointer types for let data = ... as *T.
- Fix nested Lcx_GenerateStructInstance overwriting parent slot by
incrementing structCount BEFORE field processing
- Fix Lcx_LowerModule to skip generic structs from hm.structs (was missing
continue due to bootstrap compiler codegen limitation)
- Fix C backend to forward-declare ALL structs at top, removing second
generic-only forward declaration section that came too late
- Add empty-name guard in CBE_EmitStructDef
- Import system: parser supports ::* glob imports, sema two-pass resolution
- Parser: add parseRange for selfhost (.. / ..=)
- Sema: determine loop variable type from range bounds
- HIR Lower: desugar range for-in to while loop with counter
- Bootstrap sema: fix range-based for variable type (was unknown)
- Selfhost loop remains deterministic
Implement MVP closures — anonymous functions without captures.
Syntax:
|a: int, b: int| -> int { return a + b; }
Changes:
- ast.bux + ast.nim: add ekClosure AST node
- parser.bux + parser.nim: parse |params| -> Ret { body }
- sema.bux + sema.nim: type-check closure params/body, return tyFunc
- hir_lower.bux + hir_lower.nim: generate __closure_N function + hAddrOf
- lir_c_backend.nim: fix function-pointer variable declaration (cParamDecl)
- C backend: closures compile to global functions with unique names
Test: _test_closure/src/Main.bux
- Closure as variable
- Closure passed to higher-order function
- Address of named function as function pointer
Both bootstrap and selfhost compilers build and pass the test.
- Add inline movedName0..7 fields to Sema (avoids dynamic allocation issues)
- Sema_AddMoved: track variable moves from let/var init expressions
- Sema_IsMoved: check if variable was moved before use
- Sema_RemoveMoved: clear moved status on reinitialization (x = value)
- Report 'use of moved value' error for moved variable access
Detect when the same variable is passed as &mut argument twice
in a single function call (e.g. Swap(&x, &x)) inside checked functions.
Matches bootstrap sema.nim behavior (lines 1078-1089).
- Add isChecked field to Decl struct (ast.bux)
- Parse @[Checked] attribute in parserParseDecl (parser.bux)
- Add checkedFunc flag and movedVars to Sema struct (sema.bux)
- Enable borrow checking per-function in Sema_Analyze
- Reject assignment through raw pointer (*T) in @[Checked] functions
- Skip newlines between @[Checked] attribute and the declaration keyword
to avoid parser seeing the attribute and function as separate decls
- Create child scope in Sema_CheckBlock for every block, matching
bootstrap sema.nim behavior (newScope for ekBlock).
- Fixes "var scoping bug in selfhost sema" where variables declared
with var inside if/while blocks shared parent function scope, causing
duplicate-definition errors between sibling if/else blocks, and C
scoping mismatch between user variables and compiled output.
- Remove stale workaround comments from lib/Json.bux (let instead of
var inside if blocks — no longer needed).
- Update sema.bux TODO comment for type table.
- Replace Decl's 256 inline struct fields with dynamic fields: *StructField
array to avoid parser field limit truncation and name shifts.
- Update parser.bux and hir_lower.bux to use decl.fields[i].
- Fix uninitialized Symbol.refType in three stack-allocated Symbol sites:
loopSym (for-loop iterator), vSym (enum variants), and HIR param sym.
Garbage refType values (e.g. 0xFF) were leaking into scope tables,
later copied to expr->refType, causing SIGSEGV in Lcx_LowerExpr.
- Add tekFunc AST node and TypeExprList linked list for params
- Parse func(T, U) -> R syntax in parser.bux
- Resolve tekFunc to tyFunc in sema.bux
- Track original TypeExpr via Symbol.refType for params/lets/consts/funcs
- Build C function-pointer type names in hir_lower.bux (Ret (*)(Params))
- Lower indirect calls through function-typed values as hCallIndirect
- Add CBE_CParamDecl helper in c_backend.bux to embed name inside (*)
- Emit hCallIndirect and function-pointer variable declarations
- _test_funcptr now builds and runs with selfhost buxc2
Bootstrap compiler:
- ast.nim: add exprCallArgNames to ekCall for named arg tracking
- parser.nim: detect name: value syntax in call args
- sema.nim: add resolveCallArgs helper that injects default values
for missing params and reorders named args into param order.
Parser already parsed default param values; sema now uses them.
Selfhost compiler:
- ast.bux: add defaultExpr to Param, argName to ExprList
- parser.bux: parse = defaultExpr in param list, detect name: value
syntax in call arguments
- sema.bux: add Sema_ResolveCallArgs with same logic as bootstrap
Tests:
- _test_named_params verifies defaults, named args, mixed positional+named,
and named args with defaults in both compilers.
All verifications pass: build, selfhost-loop, test-examples, test-golden.
The selfhost parser did not skip tkNewLine tokens inside expression parsing,
causing multi-line expressions (e.g. if conditions spanning lines with ||)
to be truncated. When parserParseBinaryPrec hit a newline it treated it as
an invalid primary, returning a malformed literal and leaving p.pos at the
newline. parserParseBlock then failed to find '{' and its depth-counter
fallback consumed far too many tokens, causing subsequent function bodies
to be parsed into the wrong AST nodes.
Fix: add newline skipping in parserParsePrimary, parserParseUnary, and
parserParseBinaryPrec, matching the bootstrap parser's skipNewlines() calls
in parseAnd/parseOr.
Also complete the variant cap raise from 8->9 in src/sema.bux (was already
done in ast.bux, parser.bux, hir_lower.bux).
- Makefile: new targets `test-golden` and `selfhost-loop`
- selfhost-loop verifies C codegen determinism (2-pass bootstrap)
- test-golden compares C output against expected.c golden files
- Updated clean-all to clean new build dirs
- tests/golden/hello/: first golden test (hello world)
- src/sema.bux:
- Fix: import stubs only registered if symbol doesn't already exist
- Improve: error message now includes identifier name
- ast.bux: Decl expanded with field0..field255, variant0..7, param0..8
- parser.bux: add parserParseUnary for correct unary precedence; handle tkDiscard statements; allow var without initializer (matching bootstrap); add diagCount bounds check in parserEmitDiag
- hir.bux: HirParam changed to pointers
- hir_lower.bux: full field chains for struct lowering
- c_backend.bux: hardened -> vs . field access; null checks in CBE_GetExprTypeName
- cli.bux: add -lcrypto to linker
- Fix lirValToC crash on lvkInt in hStore raw C emission
- Add hAlloca handling to lowerExpr (returns &name, avoids unhandled fallback)
- Fix nested comment syntax in unhandled expr fallback
- Rewrite buildLval to handle hIndexPtr and nested hFieldPtr/hArrowField
so assignments like arr[i].field = val emit direct C lvalues
- Make &&/|| temporaries unique (__and_tmp_N/__or_tmp_N) to avoid
duplicate declarations in the same function
- Selfhost null-deref fix in sema.bux (unchained nested conditions)