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