cb256397bd
buxc (Nim bootstrap) successfully compiles buxc2 (Bux self-hosted compiler)
into a working 88KB ELF x86-64 binary.
Compiler fixes (Nim):
- duplicate symbol: user funcs shadow stdlib funcs via mergeDecls()
- forward declarations: func without body + definition (both orderings)
- extern func dedup: same extern in multiple files
- discard keyword: new language keyword, lowered to expr stmt or no-op
- parser: keywords as field names + advance-on-error safeguard
- parser: var without initializer (zero-init)
- parser: multi-line || && continuation expressions
- parser: else-if chain newline handling
- C backend: const declarations emitted as #define
- C backend: load(field_ptr) → base.field optimization (fixes lvalue errors)
Source fixes (src_bux/*.bux):
- types.bux: tk* → ty* prefix for type kind constants (avoid token conflict)
- sema.bux: remaining tk* → ty* references, StringMap → *void workaround
- hir_lower.bux: ekReturn removed, Lcx_LowerParam helper, *f dereference
- c_backend.bux: &mod.funcs[i] for pointer passing
- cli.bux: ReadFile/WriteFile → bux_read_file/bux_write_file wrappers
- parser.bux: pathStr.len → String_Len(pathStr)
- types.bux: "*" + x → String_Concat("*", x)
Build system:
- Makefile: added 4 missing examples + selfhost target
- PLAN.md: updated with actual project state, Phase 7.9 marked complete
All 18 examples pass, all unit tests pass.
94 lines
2.2 KiB
Plaintext
94 lines
2.2 KiB
Plaintext
// scope.bux — Symbol table with parent-chain lookup
|
|
module Scope {
|
|
|
|
// Symbol kinds
|
|
const skVar: int = 0;
|
|
const skFunc: int = 1;
|
|
const skType: int = 2;
|
|
const skConst: int = 3;
|
|
const skModule: int = 4;
|
|
|
|
// Maximum symbols per scope
|
|
const maxSymbols: int = 256;
|
|
|
|
struct Symbol {
|
|
kind: int,
|
|
name: String,
|
|
typeKind: int,
|
|
typeName: String,
|
|
isMutable: bool,
|
|
isPublic: bool,
|
|
}
|
|
|
|
struct Scope {
|
|
symbols: *Symbol,
|
|
count: int,
|
|
parent: *Scope,
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Scope operations
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Scope_New() -> Scope {
|
|
let sz: uint = maxSymbols as uint * sizeof(Symbol);
|
|
let data: *Symbol = bux_alloc(sz) as *Symbol;
|
|
return Scope { symbols: data, count: 0, parent: null as *Scope };
|
|
}
|
|
|
|
func Scope_NewChild(parent: *Scope) -> Scope {
|
|
let sz: uint = maxSymbols as uint * sizeof(Symbol);
|
|
let data: *Symbol = bux_alloc(sz) as *Symbol;
|
|
return Scope { symbols: data, count: 0, parent: parent };
|
|
}
|
|
|
|
func Scope_Define(scope: *Scope, sym: Symbol) -> bool {
|
|
// Check local scope for duplicates
|
|
var i: int = 0;
|
|
while i < scope.count {
|
|
if String_Eq(scope.symbols[i].name, sym.name) {
|
|
return false;
|
|
}
|
|
i = i + 1;
|
|
}
|
|
if scope.count < maxSymbols {
|
|
scope.symbols[scope.count] = sym;
|
|
scope.count = scope.count + 1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
func Scope_Lookup(scope: *Scope, name: String) -> Symbol {
|
|
var cur: *Scope = scope;
|
|
while cur != null as *Scope {
|
|
var i: int = 0;
|
|
while i < cur.count {
|
|
if String_Eq(cur.symbols[i].name, name) {
|
|
return cur.symbols[i];
|
|
}
|
|
i = i + 1;
|
|
}
|
|
cur = cur.parent;
|
|
}
|
|
var empty: Symbol;
|
|
return empty;
|
|
}
|
|
|
|
func Scope_LookupLocal(scope: *Scope, name: String) -> Symbol {
|
|
var i: int = 0;
|
|
while i < scope.count {
|
|
if String_Eq(scope.symbols[i].name, name) {
|
|
return scope.symbols[i];
|
|
}
|
|
i = i + 1;
|
|
}
|
|
var empty: Symbol;
|
|
return empty;
|
|
}
|
|
|
|
func Scope_Free(scope: *Scope) {
|
|
bux_free(scope.symbols as *void);
|
|
}
|
|
}
|