From e06aeb7fa2fcb9046b8861ed3c23417555e823f5 Mon Sep 17 00:00:00 2001 From: Mel Date: Tue, 12 Jul 2022 01:31:27 +0200 Subject: Compile continue and break statements --- pkg/lang/compiler/scope/scope_chain.go | 24 ++++++++++++++++++++++++ pkg/lang/compiler/scope/scopes.go | 27 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) (limited to 'pkg/lang/compiler/scope') diff --git a/pkg/lang/compiler/scope/scope_chain.go b/pkg/lang/compiler/scope/scope_chain.go index 683d53a..4d5bbcf 100644 --- a/pkg/lang/compiler/scope/scope_chain.go +++ b/pkg/lang/compiler/scope/scope_chain.go @@ -10,6 +10,7 @@ type ScopeChain struct { symbolScopes []SymbolScope // All other scopes are bound to this by ID. functionScopes []FunctionScope + loopScopes []LoopScope } func NewScopeChain() ScopeChain { @@ -19,11 +20,14 @@ func NewScopeChain() ScopeChain { functionScopes := make([]FunctionScope, 1) functionScopes[0] = NewFunctionScope(0, "") // Root function to house top-scope sub units + loopScopes := make([]LoopScope, 0) + return ScopeChain{ nameToSymbol: make(map[string]SymbolID), symbolScopes: symbolScopes, functionScopes: functionScopes, + loopScopes: loopScopes, } } @@ -51,6 +55,14 @@ func (sc *ScopeChain) CurrentFunction() *FunctionScope { return &sc.functionScopes[len(sc.functionScopes)-1] } +func (sc *ScopeChain) CurrentLoop() *LoopScope { + if len(sc.loopScopes) == 0 { + return nil + } + + return &sc.loopScopes[len(sc.loopScopes)-1] +} + func (sc *ScopeChain) Enter() { sc.symbolScopes = append(sc.symbolScopes, NewSymbolScope()) } @@ -60,6 +72,18 @@ func (sc *ScopeChain) EnterFunction(unit code.Marker) { sc.functionScopes = append(sc.functionScopes, NewFunctionScope(sc.CurrentScopeID(), unit)) } +func (sc *ScopeChain) EnterLoop() (code.Marker, code.Marker) { + parentMarker := sc.CreateAnonymousFunctionSubUnit() + + breakMarker := parentMarker.SubMarker("end") + continueMarker := parentMarker.SubMarker("start") + + sc.Enter() + sc.loopScopes = append(sc.loopScopes, NewLoopScope(sc.CurrentScopeID(), breakMarker, continueMarker)) + + return breakMarker, continueMarker +} + func (sc *ScopeChain) Exit() { if sc.CurrentScopeID() == 0 { return diff --git a/pkg/lang/compiler/scope/scopes.go b/pkg/lang/compiler/scope/scopes.go index 39e48ef..5cfcd5d 100644 --- a/pkg/lang/compiler/scope/scopes.go +++ b/pkg/lang/compiler/scope/scopes.go @@ -9,6 +9,7 @@ type ScopeKind int const ( ScopeKindNormal ScopeKind = iota ScopeKindFunction + ScopeKindLoop ) type SymbolScope struct { @@ -48,3 +49,29 @@ func (sf FunctionScope) Unit() code.Marker { func (sf FunctionScope) IsRootScope() bool { return sf.ID() == ScopeID(0) } + +type LoopScope struct { + id ScopeID + breakMarker code.Marker + continueMarker code.Marker +} + +func NewLoopScope(id ScopeID, breakMarker code.Marker, continueMarker code.Marker) LoopScope { + return LoopScope{ + id: id, + breakMarker: breakMarker, + continueMarker: continueMarker, + } +} + +func (sl LoopScope) ID() ScopeID { + return sl.id +} + +func (sl LoopScope) BreakMarker() code.Marker { + return sl.breakMarker +} + +func (sl LoopScope) ContinueMarker() code.Marker { + return sl.continueMarker +} -- cgit 1.4.1