about summary refs log tree commit diff
path: root/pkg/lang/compiler/scope
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-07-19 02:27:19 +0200
committerMel <einebeere@gmail.com>2022-07-19 02:27:19 +0200
commitb6fa4bc82398b09307f2e6b75e27422d1d1ecb33 (patch)
treee5b7aec7eb7f72f1c2f55e4b2a78d331bd81485e /pkg/lang/compiler/scope
parente06aeb7fa2fcb9046b8861ed3c23417555e823f5 (diff)
downloadjinx-b6fa4bc82398b09307f2e6b75e27422d1d1ecb33.tar.zst
jinx-b6fa4bc82398b09307f2e6b75e27422d1d1ecb33.zip
Implement stack hygiene
Diffstat (limited to 'pkg/lang/compiler/scope')
-rw-r--r--pkg/lang/compiler/scope/scope_chain.go24
1 files changed, 20 insertions, 4 deletions
diff --git a/pkg/lang/compiler/scope/scope_chain.go b/pkg/lang/compiler/scope/scope_chain.go
index 4d5bbcf..d0108ee 100644
--- a/pkg/lang/compiler/scope/scope_chain.go
+++ b/pkg/lang/compiler/scope/scope_chain.go
@@ -84,13 +84,29 @@ func (sc *ScopeChain) EnterLoop() (code.Marker, code.Marker) {
 	return breakMarker, continueMarker
 }
 
-func (sc *ScopeChain) Exit() {
+func (sc *ScopeChain) Exit() int {
 	if sc.CurrentScopeID() == 0 {
-		return
+		return 0
 	}
+	id := sc.CurrentScopeID()
+	stackSpace := len(sc.symbolScopes[id].variableSymbols)
 
-	sc.symbolScopes[sc.CurrentScopeID()] = SymbolScope{}
-	sc.symbolScopes = sc.symbolScopes[:sc.CurrentScopeID()]
+	sc.symbolScopes[id] = SymbolScope{}
+	sc.symbolScopes = sc.symbolScopes[:id]
+
+	if sc.CurrentLoop() != nil && sc.CurrentLoop().id == id {
+		lastLoopScope := len(sc.loopScopes) - 1
+		sc.loopScopes[lastLoopScope] = LoopScope{}
+		sc.loopScopes = sc.loopScopes[:lastLoopScope]
+	}
+
+	if sc.CurrentFunction().id == id {
+		lastFunctionScope := len(sc.functionScopes) - 1
+		sc.functionScopes[lastFunctionScope] = FunctionScope{}
+		sc.functionScopes = sc.functionScopes[:lastFunctionScope]
+	}
+
+	return stackSpace
 }
 
 func (sc *ScopeChain) Declare(name string) (int, bool) {