diff options
| author | Mel <einebeere@gmail.com> | 2022-07-12 01:31:27 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-07-12 01:31:27 +0200 |
| commit | e06aeb7fa2fcb9046b8861ed3c23417555e823f5 (patch) | |
| tree | 3edbaa3a329e0c545c0e8334aeefc77f2bb994d6 /pkg/lang/compiler/compiler.go | |
| parent | c61e995b316ba3382798492b03ab7d5a60002237 (diff) | |
| download | jinx-e06aeb7fa2fcb9046b8861ed3c23417555e823f5.tar.zst jinx-e06aeb7fa2fcb9046b8861ed3c23417555e823f5.zip | |
Compile continue and break statements
Diffstat (limited to 'pkg/lang/compiler/compiler.go')
| -rw-r--r-- | pkg/lang/compiler/compiler.go | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/pkg/lang/compiler/compiler.go b/pkg/lang/compiler/compiler.go index ad37ded..4167088 100644 --- a/pkg/lang/compiler/compiler.go +++ b/pkg/lang/compiler/compiler.go @@ -88,9 +88,11 @@ func (comp *Compiler) compileStmt(t *code.Builder, stmt ast.Stmt) error { returnStmt := stmt.Value.(ast.StmtReturn) err = comp.compileReturnStmt(t, returnStmt) case ast.StmtKindContinue: - panic("continue statements not implemented") + continueStmt := stmt.Value.(ast.StmtContinue) + err = comp.compileContinueStmt(t, continueStmt) case ast.StmtKindBreak: - panic("break statements not implemented") + breakStmt := stmt.Value.(ast.StmtBreak) + err = comp.compileBreakStmt(t, breakStmt) case ast.StmtKindThrow: panic("throw statements not implemented") case ast.StmtKindExpr: @@ -234,12 +236,9 @@ func (comp *Compiler) compileForCondStmt(t *code.Builder, forCondStmt ast.StmtFo // 3. Do block: Does something // 4. Repeat jump: Jumps back to start - parentMarker := comp.scopes.CreateAnonymousFunctionSubUnit() - - startMarker := parentMarker.SubMarker("start") - endMarker := parentMarker.SubMarker("end") + endMarker, repeatMarker := comp.scopes.EnterLoop() - t.PutMarker(startMarker) + t.PutMarker(repeatMarker) if !forCondStmt.Cond.IsEmpty() { // Condition check @@ -259,10 +258,12 @@ func (comp *Compiler) compileForCondStmt(t *code.Builder, forCondStmt ast.StmtFo // Repeat jump t.AppendOp(code.OpJmp) - t.AppendMarkerReference(startMarker) + t.AppendMarkerReference(repeatMarker) t.PutMarker(endMarker) + comp.scopes.Exit() + return nil } @@ -301,10 +302,7 @@ func (comp *Compiler) compileForInStmt(t *code.Builder, forInStmt ast.StmtForIn) // @end: // halt - parentMarker := comp.scopes.CreateAnonymousFunctionSubUnit() - - checkMarker := parentMarker.SubUnit("check") - endMarker := parentMarker.SubUnit("end") + endMarker, repeatMarker := comp.scopes.EnterLoop() // Preparation if err := comp.compileExpr(t, forInStmt.Collection); err != nil { @@ -323,7 +321,7 @@ func (comp *Compiler) compileForInStmt(t *code.Builder, forInStmt ast.StmtForIn) } // Condition check - t.PutMarker(checkMarker) + t.PutMarker(repeatMarker) t.AppendOp(code.OpGetLocal) t.AppendInt(int64(iLocal)) @@ -373,10 +371,12 @@ func (comp *Compiler) compileForInStmt(t *code.Builder, forInStmt ast.StmtForIn) // Repeat jump t.AppendOp(code.OpJmp) - t.AppendMarkerReference(checkMarker) + t.AppendMarkerReference(repeatMarker) t.PutMarker(endMarker) + comp.scopes.Exit() + return nil } @@ -400,6 +400,30 @@ func (comp *Compiler) compileReturnStmt(t *code.Builder, returnStmt ast.StmtRetu return nil } +func (comp *Compiler) compileContinueStmt(t *code.Builder, continueStmt ast.StmtContinue) error { + loopScope := comp.scopes.CurrentLoop() + if loopScope == nil { + return fmt.Errorf("can't continue when not inside a loop") + } + + t.AppendOp(code.OpJmp) + t.AppendMarkerReference(loopScope.ContinueMarker()) + + return nil +} + +func (comp *Compiler) compileBreakStmt(t *code.Builder, breakStmt ast.StmtBreak) error { + loopScope := comp.scopes.CurrentLoop() + if loopScope == nil { + return fmt.Errorf("can't break when not inside a loop") + } + + t.AppendOp(code.OpJmp) + t.AppendMarkerReference(loopScope.BreakMarker()) + + return nil +} + func (comp *Compiler) compileExpr(t *code.Builder, expr ast.Expr) error { switch expr.Kind { case ast.ExprKindBinary: |
