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.
5.6 KiB
Bux Language Roadmap — New Constructs
Updated: 2026-06-08 | Status: In Progress
This document tracks planned language constructs beyond Phase 8 strategy.
✅ Done
1. defer Statement
Status: ✅ Implemented in both bootstrap and selfhost.
Syntax:
func ReadFile(path: String) -> String {
let fd: int = Open(path);
defer Close(fd); // runs on any exit from scope
defer PrintLine("done"); // LIFO order
let data: String = ReadAll(fd);
return data; // both defers run before return
}
2. Native switch / case
Status: ✅ Implemented in both bootstrap and selfhost. Desugars to if-else chain.
Syntax:
switch statusCode {
case 200: PrintLine("OK");
case 404: PrintLine("Not Found");
case 500: PrintLine("Server Error");
default: PrintLine("Unknown");
}
3. Operator Overloading
Status: ✅ Implemented in bootstrap. Selfhost has no method-table yet (not needed for selfhost-loop parity).
Supported operators:
func Vec2_operator_add(self: *Vec2, other: Vec2) -> Vec2 { ... }
func Vec2_operator_sub(self: *Vec2, other: Vec2) -> Vec2 { ... }
func Vec2_operator_eq(self: *Vec2, other: Vec2) -> bool { ... }
func Vec2_operator_lt(self: *Vec2, other: Vec2) -> bool { ... }
func MyArray_operator_index_get(self: *MyArray, idx: int) -> int { ... }
func MyArray_operator_index_set(self: *MyArray, idx: int, value: int) { ... }
Notes:
- Works via method-table lookup in sema + hir_lower.
- Generic method instantiation supported.
- Short-circuit operators (
&&,||) remain builtin.
P0 — Critical (Unlocks Major Use Cases)
4. String Interpolation
Why: Fmt_Fmt1("hello {0}", name) is verbose.
Syntax:
let name: String = "Bux";
let msg: String = "Hello, {name}!";
let num: int = 42;
let msg2: String = "Count: {num}";
Implementation Steps:
- Lexer: detect
{inside string literals, parse interpolation expressions - Parser: create string concatenation AST node
- Desugar to
String_Concatcalls orFmt_FmtN
Complexity: Low — lexer/parser changes only.
5. Named / Default Parameters ✅ DONE
Why: API ergonomics.
Syntax:
func HttpResponse(code: int = 200, body: String = "") -> Response { ... }
let r: Response = HttpResponse(body: "hello"); // code=200
let s = HttpResponse(404, body: "err"); // positional + named mixed
Status: Implemented in both bootstrap and selfhost.
- Bootstrap parser already parsed defaults; added named-arg parsing and sema injection.
- Selfhost parser now parses
= defaultExprin params andname: valueat call sites. - Sema injects default expressions and reorders named args into param order.
- HIR lowerer unchanged — desugaring happens in sema.
6. Closures / Anonymous Functions
Why: Callbacks, iterators, functional APIs. Currently only named functions exist.
Syntax:
let add: func(int, int) -> int = |a, b| { return a + b; };
let nums: Array<int> = Array_New<int>();
Array_Filter(nums, |x| { return x > 10; });
Implementation Steps:
- New AST node:
ClosureExprwithparams,body,captures - Parser: parse
|param1, param2| -> Type { body } - Type system: closure type as
func(Args) -> Ret+ implicit capture struct - C backend: generate struct with captured vars + function pointer
- Lifetime: ensure captures outlive closure usage
Complexity: High — touches parser, sema, type system, C backend.
7. for x in collection Iterator Loops
Why: Currently only for i in 0..10 works. No way to iterate arrays/channels/maps.
Syntax:
for item in arr {
PrintLine(item);
}
for msg in channel {
Process(msg);
}
Implementation Steps:
- Parser: extend
forto acceptfor <ident> in <expr> { ... } - Desugar to while loop using
Iter_HasNext/Iter_Nextor trait-based iterator - C backend: generate standard while loop with iterator state
Complexity: Medium — needs either trait system enhancement or hardcoded desugaring.
P1 — High Impact
8. Destructors / Drop Trait
Why: own T exists but nothing cleans up automatically. Complements defer.
Syntax:
extend Array<T> {
func Drop(self: own Array<T>) {
Array_Free(self);
}
}
Implementation Steps:
- Define
Dropinterface in stdlib - C backend: emit
Drop(value)before variable goes out of scope - Respect move semantics — don't drop moved values
Complexity: High — needs ownership tracking + move semantics.
P2 — Nice to Have
9. Trait System Enhancement
Why: Currently have interface + extend (basic). Need trait bounds, associated types.
Syntax:
func Sort<T: Comparable>(arr: &mut Array<T>) { ... }
10. CTFE (Compile-Time Function Execution)
Why: Precomputed tables for embedded / kernel dev.
Syntax:
const func Fib(n: int) -> int { ... }
const TABLE_SIZE = Fib(20);
11. Concurrency
Why: Go-style goroutines + channels, but without GC.
Syntax:
let (tx, rx) = Channel::New<int>();
Task::Spawn(Worker, rx);
Recommended Order
- ✅
defer— Done - ✅
switch/case— Done - ✅ Operator overloading — Done (bootstrap)
- String interpolation — Low complexity, big ergonomics win. ← NEXT
- Named/default parameters — Medium complexity, improves stdlib APIs.
- Closures — High complexity, unlocks iterators and functional style.
for x in collection— Depends on closures or trait system.- Destructors / Drop — High complexity, needs ownership + move semantics.