diff options
Diffstat (limited to 'pkg/lang')
| -rw-r--r-- | pkg/lang/compiler/compiler.go | 33 | ||||
| -rw-r--r-- | pkg/lang/compiler/scope/scope_chain.go (renamed from pkg/lang/compiler/scope_chain.go) | 129 | ||||
| -rw-r--r-- | pkg/lang/compiler/scope/scopes.go | 50 | ||||
| -rw-r--r-- | pkg/lang/compiler/scope/symbol.go (renamed from pkg/lang/compiler/symbol.go) | 28 |
4 files changed, 127 insertions, 113 deletions
diff --git a/pkg/lang/compiler/compiler.go b/pkg/lang/compiler/compiler.go index 728dec1..ad37ded 100644 --- a/pkg/lang/compiler/compiler.go +++ b/pkg/lang/compiler/compiler.go @@ -3,6 +3,7 @@ package compiler import ( "fmt" "jinx/pkg/lang/ast" + "jinx/pkg/lang/compiler/scope" "jinx/pkg/lang/vm/code" ) @@ -11,14 +12,14 @@ type Compiler struct { funcs []*code.Builder - scopes ScopeChain + scopes scope.ScopeChain } func New(ast ast.Program) *Compiler { return &Compiler{ ast: ast, funcs: make([]*code.Builder, 0), - scopes: NewScopeChain(), + scopes: scope.NewScopeChain(), } } @@ -114,7 +115,7 @@ func (comp *Compiler) compileFnDeclStmt(t *code.Builder, fnDeclStmt ast.StmtFnDe symbol := comp.scopes.GetFunction(symbolID) - marker = symbol.data.marker + marker = symbol.Data().Marker() } else { return fmt.Errorf("function %s already declared", fnDeclStmt.Name.Value) } @@ -382,8 +383,8 @@ func (comp *Compiler) compileForInStmt(t *code.Builder, forInStmt ast.StmtForIn) func (comp *Compiler) compileReturnStmt(t *code.Builder, returnStmt ast.StmtReturn) error { // Check that we are in fact in a function functionScope := comp.scopes.CurrentFunction() - if functionScope.data.(ScopeFunction).IsRootScope() { - return fmt.Errorf("can't return when not inside a function" + functionScope.data.(ScopeFunction).unit.String()) + if functionScope.IsRootScope() { + return fmt.Errorf("can't return when not inside a function") } if returnStmt.Value.IsEmpty() { @@ -491,8 +492,8 @@ func (comp *Compiler) compileAssignExpr(t *code.Builder, expr ast.ExprBinary) er return fmt.Errorf("variable %s not declared", name) } - if symbolId.symbolKind != SymbolKindVariable { - return fmt.Errorf("can't assign to a %v", symbolId.symbolKind) + if symbolId.SymbolKind() != scope.SymbolKindVariable { + return fmt.Errorf("can't assign to a %v", symbolId.SymbolKind()) } symbol := comp.scopes.GetVariable(symbolId) @@ -502,7 +503,7 @@ func (comp *Compiler) compileAssignExpr(t *code.Builder, expr ast.ExprBinary) er } t.AppendOp(code.OpSetLocal) - t.AppendInt(int64(symbol.data.localIndex)) + t.AppendInt(int64(symbol.Data().LocalIndex())) return nil } @@ -587,24 +588,24 @@ func (comp *Compiler) compileIdentExpr(t *code.Builder, expr ast.ExprIdent) erro } // TODO: Add other ways how the symbol should be fetched. (local, env, global, etc.) - switch symbolId.symbolKind { - case SymbolKindVariable: + switch symbolId.SymbolKind() { + case scope.SymbolKindVariable: symbol := comp.scopes.GetVariable(symbolId) t.AppendOp(code.OpGetLocal) - t.AppendInt(int64(symbol.data.localIndex)) - case SymbolKindFunction: + t.AppendInt(int64(symbol.Data().LocalIndex())) + case scope.SymbolKindFunction: symbol := comp.scopes.GetFunction(symbolId) t.AppendOp(code.OpPushFunction) - t.AppendMarkerReference(symbol.data.marker) + t.AppendMarkerReference(symbol.Data().Marker()) - if symbol.data.args != 0 { + if symbol.Data().Args() != 0 { t.AppendOp(code.OpSetArgCount) - t.AppendInt(int64(symbol.data.args)) + t.AppendInt(int64(symbol.Data().Args())) } default: - panic(fmt.Errorf("unknown symbol kind: %v", symbolId.symbolKind)) + panic(fmt.Errorf("unknown symbol kind: %v", symbolId.SymbolKind())) } return nil diff --git a/pkg/lang/compiler/scope_chain.go b/pkg/lang/compiler/scope/scope_chain.go index 6705852..683d53a 100644 --- a/pkg/lang/compiler/scope_chain.go +++ b/pkg/lang/compiler/scope/scope_chain.go @@ -1,57 +1,63 @@ -package compiler +package scope import ( "fmt" "jinx/pkg/lang/vm/code" ) -type ScopeID int - type ScopeChain struct { nameToSymbol map[string]SymbolID - scopes []Scope + + symbolScopes []SymbolScope // All other scopes are bound to this by ID. + functionScopes []FunctionScope } func NewScopeChain() ScopeChain { - scopes := make([]Scope, 1) - scopes[0] = NewFunctionScope(0, "") // Top-most scope is a function scope, so it can have sub-units + symbolScopes := make([]SymbolScope, 1) + symbolScopes[0] = NewSymbolScope() + + functionScopes := make([]FunctionScope, 1) + functionScopes[0] = NewFunctionScope(0, "") // Root function to house top-scope sub units return ScopeChain{ nameToSymbol: make(map[string]SymbolID), - scopes: scopes, + + symbolScopes: symbolScopes, + functionScopes: functionScopes, } } func (sc *ScopeChain) CurrentScopeID() ScopeID { - return ScopeID(len(sc.scopes) - 1) + return ScopeID(len(sc.symbolScopes) - 1) } func (sc *ScopeChain) IsRootScope() bool { return sc.CurrentScopeID() == ScopeID(0) } -func (sc *ScopeChain) Current() *Scope { - return &sc.scopes[sc.CurrentScopeID()] +func (sc *ScopeChain) Current() *SymbolScope { + if len(sc.functionScopes) == 0 { + panic("root scope is missing") + } + + return &sc.symbolScopes[sc.CurrentScopeID()] } -func (sc *ScopeChain) CurrentFunction() *Scope { - // TODO: Probably should make this lookup constant by making a seperate array of function scopes - for i := len(sc.scopes) - 1; i >= 0; i++ { - if sc.scopes[i].kind == ScopeKindFunction { - return &sc.scopes[i] - } +func (sc *ScopeChain) CurrentFunction() *FunctionScope { + if len(sc.functionScopes) == 0 { + panic("root function scope is missing") } - panic("top scope should always be a function scope") + return &sc.functionScopes[len(sc.functionScopes)-1] } func (sc *ScopeChain) Enter() { - sc.scopes = append(sc.scopes, NewNormalScope()) + sc.symbolScopes = append(sc.symbolScopes, NewSymbolScope()) } func (sc *ScopeChain) EnterFunction(unit code.Marker) { - id := sc.CurrentScopeID() + 1 - sc.scopes = append(sc.scopes, NewFunctionScope(id, unit)) + sc.Enter() + sc.functionScopes = append(sc.functionScopes, NewFunctionScope(sc.CurrentScopeID(), unit)) } func (sc *ScopeChain) Exit() { @@ -59,8 +65,8 @@ func (sc *ScopeChain) Exit() { return } - sc.scopes[sc.CurrentScopeID()] = Scope{} - sc.scopes = sc.scopes[:sc.CurrentScopeID()] + sc.symbolScopes[sc.CurrentScopeID()] = SymbolScope{} + sc.symbolScopes = sc.symbolScopes[:sc.CurrentScopeID()] } func (sc *ScopeChain) Declare(name string) (int, bool) { @@ -140,21 +146,17 @@ func (sc *ScopeChain) DeclareTemporary() int { func (sc *ScopeChain) CreateAnonymousFunctionSubUnit() code.Marker { fnScope := sc.CurrentFunction() - data := fnScope.data.(ScopeFunction) - index := data.subUnitCount - data.subUnitCount++ - - fnScope.data = data + index := fnScope.subUnitCount + fnScope.subUnitCount++ return sc.CreateFunctionSubUnit(fmt.Sprintf("anon_%d", index)) } func (sc *ScopeChain) CreateFunctionSubUnit(subUnitName string) code.Marker { fnScope := sc.CurrentFunction() - data := fnScope.data.(ScopeFunction) - name := data.unit + name := fnScope.unit if name == "" { name = code.Marker(subUnitName) } else { @@ -177,7 +179,7 @@ func (sc *ScopeChain) GetVariable(id SymbolID) Symbol[SymbolVariable] { panic("incorrect symbol id kind given") } - return sc.scopes[id.scopeID].variableSymbols[id.indexInScope] + return sc.symbolScopes[id.scopeID].variableSymbols[id.indexInScope] } func (sc *ScopeChain) GetFunction(id SymbolID) Symbol[SymbolFunction] { @@ -185,70 +187,5 @@ func (sc *ScopeChain) GetFunction(id SymbolID) Symbol[SymbolFunction] { panic("incorrect symbol id kind given") } - return sc.scopes[id.scopeID].functionSymbols[id.indexInScope] -} - -type SymbolID struct { - symbolKind SymbolKind - scopeID ScopeID - indexInScope int -} - -type ScopeKind int - -const ( - ScopeKindNormal ScopeKind = iota - ScopeKindFunction - ScopeKindLoop -) - -type Scope struct { - variableSymbols []Symbol[SymbolVariable] - functionSymbols []Symbol[SymbolFunction] - - kind ScopeKind - data any -} - -func NewNormalScope() Scope { - return Scope{ - variableSymbols: make([]Symbol[SymbolVariable], 0), - functionSymbols: make([]Symbol[SymbolFunction], 0), - kind: ScopeKindNormal, - data: ScopeNormal{}, - } -} - -func NewFunctionScope(id ScopeID, unit code.Marker) Scope { - return Scope{ - variableSymbols: make([]Symbol[SymbolVariable], 0), - functionSymbols: make([]Symbol[SymbolFunction], 0), - kind: ScopeKindFunction, - data: ScopeFunction{ - id: id, - unit: unit, - subUnitCount: 0, - }, - } -} - -type ScopeNormal struct{} - -type ScopeFunction struct { - id ScopeID - unit code.Marker - subUnitCount int -} - -func (sf ScopeFunction) ID() ScopeID { - return sf.id -} - -func (sf ScopeFunction) IsRootScope() bool { - return sf.ID() == ScopeID(0) -} - -type ScopeLoop struct { - breakMarker code.Marker - continueMarker code.Marker + return sc.symbolScopes[id.scopeID].functionSymbols[id.indexInScope] } diff --git a/pkg/lang/compiler/scope/scopes.go b/pkg/lang/compiler/scope/scopes.go new file mode 100644 index 0000000..39e48ef --- /dev/null +++ b/pkg/lang/compiler/scope/scopes.go @@ -0,0 +1,50 @@ +package scope + +import "jinx/pkg/lang/vm/code" + +type ScopeID int + +type ScopeKind int + +const ( + ScopeKindNormal ScopeKind = iota + ScopeKindFunction +) + +type SymbolScope struct { + variableSymbols []Symbol[SymbolVariable] + functionSymbols []Symbol[SymbolFunction] +} + +func NewSymbolScope() SymbolScope { + return SymbolScope{ + variableSymbols: make([]Symbol[SymbolVariable], 0), + functionSymbols: make([]Symbol[SymbolFunction], 0), + } +} + +type FunctionScope struct { + id ScopeID + unit code.Marker + subUnitCount int +} + +func NewFunctionScope(id ScopeID, unit code.Marker) FunctionScope { + return FunctionScope{ + id: id, + unit: unit, + subUnitCount: 0, + } +} + +func (sf FunctionScope) ID() ScopeID { + return sf.id +} + +func (sf FunctionScope) Unit() code.Marker { + return sf.unit +} + +func (sf FunctionScope) IsRootScope() bool { + return sf.ID() == ScopeID(0) +} diff --git a/pkg/lang/compiler/symbol.go b/pkg/lang/compiler/scope/symbol.go index 453cb2b..df91899 100644 --- a/pkg/lang/compiler/symbol.go +++ b/pkg/lang/compiler/scope/symbol.go @@ -1,7 +1,17 @@ -package compiler +package scope import "jinx/pkg/lang/vm/code" +type SymbolID struct { + symbolKind SymbolKind + scopeID ScopeID + indexInScope int +} + +func (id SymbolID) SymbolKind() SymbolKind { + return id.symbolKind +} + type SymbolKind int const ( @@ -25,6 +35,10 @@ type Symbol[D SymbolData] struct { data D } +func (s Symbol[D]) Data() D { + return s.data +} + type SymbolData interface { SymbolVariable | SymbolFunction } @@ -33,7 +47,19 @@ type SymbolVariable struct { localIndex int } +func (sv SymbolVariable) LocalIndex() int { + return sv.localIndex +} + type SymbolFunction struct { marker code.Marker args uint } + +func (sf SymbolFunction) Marker() code.Marker { + return sf.marker +} + +func (sf SymbolFunction) Args() uint { + return sf.args +} |
