package scope import "jinx/pkg/lang/vm/code" type ScopeID int type ScopeKind int const ( ScopeKindNormal ScopeKind = iota ScopeKindFunction ScopeKindLoop ) type SymbolScope struct { nameToSymbol map[string]SymbolID variableSymbols []Symbol[SymbolVariable] globalSymbols []Symbol[SymbolGlobal] } func NewSymbolScope() SymbolScope { return SymbolScope{ nameToSymbol: make(map[string]SymbolID), variableSymbols: make([]Symbol[SymbolVariable], 0), globalSymbols: make([]Symbol[SymbolGlobal], 0), } } type FunctionScope struct { id ScopeID unit code.Marker subUnitCount int outsideSymbolsInEnv []SymbolID isMethod bool methodLocal int // -1 if in env 0 } func NewFunctionScope(id ScopeID, unit code.Marker) FunctionScope { return FunctionScope{ id: id, unit: unit, subUnitCount: 0, outsideSymbolsInEnv: make([]SymbolID, 0), } } func NewMethodFunctionScope(id ScopeID, unit code.Marker, methodLocal int) FunctionScope { return FunctionScope{ id: id, unit: unit, subUnitCount: 0, outsideSymbolsInEnv: make([]SymbolID, 0), isMethod: true, methodLocal: methodLocal, } } func (sf FunctionScope) ID() ScopeID { return sf.id } func (sf FunctionScope) Unit() code.Marker { return sf.unit } func (sf FunctionScope) OutsideSymbolsInEnv() []SymbolID { return sf.outsideSymbolsInEnv } func (sf FunctionScope) IsRootScope() bool { return sf.ID() == ScopeID(0) } func (sf FunctionScope) IsMethod() bool { return sf.isMethod } func (sf FunctionScope) ThisLocal() (bool, int) { if !sf.isMethod { return false, 0 } if sf.methodLocal == -1 { return false, 0 } return true, sf.methodLocal } 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 }