about summary refs log tree commit diff
path: root/pkg/lang/compiler/scope_chain.go
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-07-05 23:39:18 +0200
committerMel <einebeere@gmail.com>2022-07-06 14:05:28 +0200
commit3a31347d38ae9a4c04c52304330b50f95a54a826 (patch)
treee5ddbe398ede58f45c4a8e79c66018c5e37b06d8 /pkg/lang/compiler/scope_chain.go
parentbb1f61f938be3cc209dacf97b0395336631319bb (diff)
downloadjinx-3a31347d38ae9a4c04c52304330b50f95a54a826.tar.zst
jinx-3a31347d38ae9a4c04c52304330b50f95a54a826.zip
Implement ForIn statement compilation
Diffstat (limited to 'pkg/lang/compiler/scope_chain.go')
-rw-r--r--pkg/lang/compiler/scope_chain.go56
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
 }