diff options
| author | Mel <einebeere@gmail.com> | 2022-07-12 00:29:56 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-07-12 00:29:56 +0200 |
| commit | e5ae4ea1288a555c4019dad43ee27e960eec46b9 (patch) | |
| tree | b0c92bae8bd7d58be9c5b42dc0b06081f4a1d780 /pkg/lang/compiler/scope_chain.go | |
| parent | 74dd678dfd1aae9e655fd13cb65278ea9ba307e2 (diff) | |
| download | jinx-e5ae4ea1288a555c4019dad43ee27e960eec46b9.tar.zst jinx-e5ae4ea1288a555c4019dad43ee27e960eec46b9.zip | |
Extract scopes and scope chain from compiler
Diffstat (limited to 'pkg/lang/compiler/scope_chain.go')
| -rw-r--r-- | pkg/lang/compiler/scope_chain.go | 254 |
1 files changed, 0 insertions, 254 deletions
diff --git a/pkg/lang/compiler/scope_chain.go b/pkg/lang/compiler/scope_chain.go deleted file mode 100644 index 6705852..0000000 --- a/pkg/lang/compiler/scope_chain.go +++ /dev/null @@ -1,254 +0,0 @@ -package compiler - -import ( - "fmt" - "jinx/pkg/lang/vm/code" -) - -type ScopeID int - -type ScopeChain struct { - nameToSymbol map[string]SymbolID - scopes []Scope -} - -func NewScopeChain() ScopeChain { - scopes := make([]Scope, 1) - scopes[0] = NewFunctionScope(0, "") // Top-most scope is a function scope, so it can have sub-units - - return ScopeChain{ - nameToSymbol: make(map[string]SymbolID), - scopes: scopes, - } -} - -func (sc *ScopeChain) CurrentScopeID() ScopeID { - return ScopeID(len(sc.scopes) - 1) -} - -func (sc *ScopeChain) IsRootScope() bool { - return sc.CurrentScopeID() == ScopeID(0) -} - -func (sc *ScopeChain) Current() *Scope { - return &sc.scopes[sc.CurrentScopeID()] -} - -func (sc *ScopeChain) CurrentFunction() *Scope { - // TODO: Probably should make this lookup constant by making a seperate array of function scopes - for i := len(sc.scopes) - 1; i >= 0; i++ { - if sc.scopes[i].kind == ScopeKindFunction { - return &sc.scopes[i] - } - } - - panic("top scope should always be a function scope") -} - -func (sc *ScopeChain) Enter() { - sc.scopes = append(sc.scopes, NewNormalScope()) -} - -func (sc *ScopeChain) EnterFunction(unit code.Marker) { - id := sc.CurrentScopeID() + 1 - sc.scopes = append(sc.scopes, NewFunctionScope(id, unit)) -} - -func (sc *ScopeChain) Exit() { - if sc.CurrentScopeID() == 0 { - return - } - - sc.scopes[sc.CurrentScopeID()] = Scope{} - sc.scopes = sc.scopes[:sc.CurrentScopeID()] -} - -func (sc *ScopeChain) Declare(name string) (int, bool) { - // Check whether the symbol is already declared in any of the scopes. - if _, ok := sc.nameToSymbol[name]; ok { - return 0, false - } - - current := sc.Current() - indexInScope := len(current.variableSymbols) - - symbolID := SymbolID{ - symbolKind: SymbolKindVariable, - scopeID: sc.CurrentScopeID(), - indexInScope: indexInScope, - } - - // Declare the symbol in the current scope. - current.variableSymbols = append(current.variableSymbols, Symbol[SymbolVariable]{ - name: name, - data: SymbolVariable{ - localIndex: indexInScope, - }, - }) - - sc.nameToSymbol[name] = symbolID - - return indexInScope, true -} - -func (sc *ScopeChain) DeclareFunction(name string, args uint) (code.Marker, bool) { - if _, ok := sc.nameToSymbol[name]; ok { - return "", false - } - - current := sc.Current() - index := len(current.functionSymbols) - - symbolID := SymbolID{ - symbolKind: SymbolKindFunction, - scopeID: sc.CurrentScopeID(), - indexInScope: index, - } - - unitName := sc.CreateFunctionSubUnit(name) - - current.functionSymbols = append(current.functionSymbols, Symbol[SymbolFunction]{ - name: name, - data: SymbolFunction{ - marker: unitName, - args: args, - }, - }) - - sc.nameToSymbol[name] = symbolID - - return unitName, true -} - -func (sc *ScopeChain) DeclareAnonymous() int { - current := sc.Current() - index := len(current.variableSymbols) - - current.variableSymbols = append(current.variableSymbols, Symbol[SymbolVariable]{ - name: "", // An anonymous symbol has no name. - data: SymbolVariable{ - localIndex: index, - }, - }) - - return index -} - -func (sc *ScopeChain) DeclareTemporary() int { - return len(sc.Current().variableSymbols) // :) -} - -func (sc *ScopeChain) CreateAnonymousFunctionSubUnit() code.Marker { - fnScope := sc.CurrentFunction() - data := fnScope.data.(ScopeFunction) - - index := data.subUnitCount - data.subUnitCount++ - - fnScope.data = data - - return sc.CreateFunctionSubUnit(fmt.Sprintf("anon_%d", index)) -} - -func (sc *ScopeChain) CreateFunctionSubUnit(subUnitName string) code.Marker { - fnScope := sc.CurrentFunction() - data := fnScope.data.(ScopeFunction) - - name := data.unit - if name == "" { - name = code.Marker(subUnitName) - } else { - name = name.SubUnit(subUnitName) - } - - return name -} - -func (sc *ScopeChain) Lookup(name string) (SymbolID, bool) { - if id, ok := sc.nameToSymbol[name]; ok { - return id, true - } - - return SymbolID{}, false -} - -func (sc *ScopeChain) GetVariable(id SymbolID) Symbol[SymbolVariable] { - if id.symbolKind != SymbolKindVariable { - panic("incorrect symbol id kind given") - } - - return sc.scopes[id.scopeID].variableSymbols[id.indexInScope] -} - -func (sc *ScopeChain) GetFunction(id SymbolID) Symbol[SymbolFunction] { - if id.symbolKind != SymbolKindFunction { - panic("incorrect symbol id kind given") - } - - return sc.scopes[id.scopeID].functionSymbols[id.indexInScope] -} - -type SymbolID struct { - symbolKind SymbolKind - scopeID ScopeID - indexInScope int -} - -type ScopeKind int - -const ( - ScopeKindNormal ScopeKind = iota - ScopeKindFunction - ScopeKindLoop -) - -type Scope struct { - variableSymbols []Symbol[SymbolVariable] - functionSymbols []Symbol[SymbolFunction] - - kind ScopeKind - data any -} - -func NewNormalScope() Scope { - return Scope{ - variableSymbols: make([]Symbol[SymbolVariable], 0), - functionSymbols: make([]Symbol[SymbolFunction], 0), - kind: ScopeKindNormal, - data: ScopeNormal{}, - } -} - -func NewFunctionScope(id ScopeID, unit code.Marker) Scope { - return Scope{ - variableSymbols: make([]Symbol[SymbolVariable], 0), - functionSymbols: make([]Symbol[SymbolFunction], 0), - kind: ScopeKindFunction, - data: ScopeFunction{ - id: id, - unit: unit, - subUnitCount: 0, - }, - } -} - -type ScopeNormal struct{} - -type ScopeFunction struct { - id ScopeID - unit code.Marker - subUnitCount int -} - -func (sf ScopeFunction) ID() ScopeID { - return sf.id -} - -func (sf ScopeFunction) IsRootScope() bool { - return sf.ID() == ScopeID(0) -} - -type ScopeLoop struct { - breakMarker code.Marker - continueMarker code.Marker -} |
