diff options
| author | Mel <einebeere@gmail.com> | 2022-06-20 00:37:01 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-06-20 00:37:01 +0200 |
| commit | 621f624f50a7bef16eeed02113b470e79e790cd9 (patch) | |
| tree | 058767579a4c542b173ee001cc7e89a853d79e25 /pkg/lang/compiler/scope_chain.go | |
| parent | 9a847f9ec4a0030bf2194005bc9a79cd609cd48a (diff) | |
| download | jinx-621f624f50a7bef16eeed02113b470e79e790cd9.tar.zst jinx-621f624f50a7bef16eeed02113b470e79e790cd9.zip | |
Compile rudimetary variables
Diffstat (limited to 'pkg/lang/compiler/scope_chain.go')
| -rw-r--r-- | pkg/lang/compiler/scope_chain.go | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/pkg/lang/compiler/scope_chain.go b/pkg/lang/compiler/scope_chain.go new file mode 100644 index 0000000..8d942ea --- /dev/null +++ b/pkg/lang/compiler/scope_chain.go @@ -0,0 +1,76 @@ +package compiler + +type ScopeID int + +type ScopeChain struct { + scopes []Scope +} + +func NewScopeChain() ScopeChain { + scopes := make([]Scope, 1) + scopes[0] = Scope{ + kind: ScopeKindGlobal, + symbols: make(map[string]Symbol), + } + + return ScopeChain{ + scopes: scopes, + } +} + +func (sc *ScopeChain) Current() *Scope { + return &sc.scopes[len(sc.scopes)-1] +} + +func (sc *ScopeChain) Enter(kind ScopeKind) { + sc.scopes = append(sc.scopes, Scope{ + kind: kind, + symbols: make(map[string]Symbol), + }) +} + +func (sc *ScopeChain) Exit() { + sc.scopes[len(sc.scopes)-1] = Scope{} + sc.scopes = sc.scopes[:len(sc.scopes)-1] +} + +func (sc *ScopeChain) Declare(name string) 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 + } + } + + // Declare the symbol in the current scope. + sc.Current().symbols[name] = Symbol{ + kind: SymbolKindVariable, + name: name, + localIndex: len(sc.Current().symbols), + } + + return true +} + +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 + } + } + + return Symbol{}, false +} + +type ScopeKind int + +const ( + ScopeKindGlobal ScopeKind = iota + ScopeKindFunction + ScopeKindBlock +) + +type Scope struct { + kind ScopeKind + symbols map[string]Symbol +} |
