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-06-20 00:37:01 +0200
committerMel <einebeere@gmail.com>2022-06-20 00:37:01 +0200
commit621f624f50a7bef16eeed02113b470e79e790cd9 (patch)
tree058767579a4c542b173ee001cc7e89a853d79e25 /pkg/lang/compiler/scope_chain.go
parent9a847f9ec4a0030bf2194005bc9a79cd609cd48a (diff)
downloadjinx-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.go76
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
+}