diff options
Diffstat (limited to 'pkg/lang/compiler/scope_chain.go')
| -rw-r--r-- | pkg/lang/compiler/scope_chain.go | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/pkg/lang/compiler/scope_chain.go b/pkg/lang/compiler/scope_chain.go index 8d942ea..6b7e693 100644 --- a/pkg/lang/compiler/scope_chain.go +++ b/pkg/lang/compiler/scope_chain.go @@ -9,8 +9,9 @@ type ScopeChain struct { func NewScopeChain() ScopeChain { scopes := make([]Scope, 1) scopes[0] = Scope{ - kind: ScopeKindGlobal, - symbols: make(map[string]Symbol), + kind: ScopeKindGlobal, + nameToSymbol: make(map[string]int), + symbols: make([]Symbol, 0), } return ScopeChain{ @@ -24,8 +25,9 @@ func (sc *ScopeChain) Current() *Scope { func (sc *ScopeChain) Enter(kind ScopeKind) { sc.scopes = append(sc.scopes, Scope{ - kind: kind, - symbols: make(map[string]Symbol), + kind: kind, + nameToSymbol: make(map[string]int), + symbols: make([]Symbol, 0), }) } @@ -34,28 +36,51 @@ func (sc *ScopeChain) Exit() { sc.scopes = sc.scopes[:len(sc.scopes)-1] } -func (sc *ScopeChain) Declare(name string) bool { +func (sc *ScopeChain) Declare(name string) (int, bool) { // Check whether the symbol is already declared in any of the scopes. for _, scope := range sc.scopes { - if _, ok := scope.symbols[name]; ok { - return false + if _, ok := scope.nameToSymbol[name]; ok { + return 0, false } } + current := sc.Current() + index := len(current.symbols) + // Declare the symbol in the current scope. - sc.Current().symbols[name] = Symbol{ + current.symbols = append(current.symbols, Symbol{ kind: SymbolKindVariable, name: name, - localIndex: len(sc.Current().symbols), - } + localIndex: index, + }) + + current.nameToSymbol[name] = index + + return index, true +} + +func (sc *ScopeChain) DeclareAnonymous() int { + current := sc.Current() + index := len(current.symbols) + + // Declare the symbol in the current scope. + current.symbols = append(current.symbols, Symbol{ + kind: SymbolKindVariable, + name: "", + localIndex: index, + }) + + return index +} - return true +func (sc *ScopeChain) DeclareTemporary() int { + return len(sc.Current().symbols) } func (sc *ScopeChain) Lookup(name string) (Symbol, bool) { for i := len(sc.scopes) - 1; i >= 0; i-- { - if symbol, ok := sc.scopes[i].symbols[name]; ok { - return symbol, true + if symbol, ok := sc.scopes[i].nameToSymbol[name]; ok { + return sc.scopes[i].symbols[symbol], true } } @@ -71,6 +96,7 @@ const ( ) type Scope struct { - kind ScopeKind - symbols map[string]Symbol + kind ScopeKind + nameToSymbol map[string]int + symbols []Symbol } |
