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);
|
|
}
|
|
}
|