Skip to content

Commit 50cdc44

Browse files
committed
compler: break, continue and framework for testing exceptions
1 parent 1cfd200 commit 50cdc44

File tree

4 files changed

+251
-112
lines changed

4 files changed

+251
-112
lines changed

compile/compile.go

+46-2
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,39 @@ func CompileAst(Ast ast.Ast, filename string, flags int, dont_inherit bool) *py.
144144
return code
145145
}
146146

147+
// Loop
148+
type loop struct {
149+
Start *Label
150+
End *Label
151+
IsForLoop bool
152+
}
153+
154+
// Loopstack
155+
type loopstack []loop
156+
157+
// Push a loop
158+
func (ls *loopstack) Push(l loop) {
159+
*ls = append(*ls, l)
160+
}
161+
162+
// Pop a loop
163+
func (ls *loopstack) Pop() {
164+
*ls = (*ls)[:len(*ls)-1]
165+
}
166+
167+
// Return current loop or nil for none
168+
func (ls loopstack) Top() *loop {
169+
if len(ls) == 0 {
170+
return nil
171+
}
172+
return &ls[len(ls)-1]
173+
}
174+
147175
// State for the compiler
148176
type compiler struct {
149177
Code *py.Code // code being built up
150178
OpCodes Instructions
179+
loops loopstack
151180
}
152181

153182
// Compiles a python constant
@@ -318,6 +347,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
318347
endpopblock := new(Label)
319348
c.Jump(vm.SETUP_LOOP, endpopblock)
320349
while := c.NewLabel()
350+
c.loops.Push(loop{Start: while, End: endpopblock})
321351
c.Expr(node.Test)
322352
c.Jump(vm.POP_JUMP_IF_FALSE, endwhile)
323353
for _, stmt := range node.Body {
@@ -326,6 +356,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
326356
c.Jump(vm.JUMP_ABSOLUTE, while)
327357
c.Label(endwhile)
328358
c.Op(vm.POP_BLOCK)
359+
c.loops.Pop()
329360
for _, stmt := range node.Orelse {
330361
c.Stmt(stmt)
331362
}
@@ -407,9 +438,22 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
407438
case *ast.Pass:
408439
// Do nothing
409440
case *ast.Break:
410-
panic("FIXME compile: Break not implemented")
441+
l := c.loops.Top()
442+
if l == nil {
443+
panic(py.ExceptionNewf(py.SyntaxError, "'break' outside loop"))
444+
}
445+
c.Op(vm.BREAK_LOOP)
411446
case *ast.Continue:
412-
panic("FIXME compile: Continue not implemented")
447+
l := c.loops.Top()
448+
if l == nil {
449+
panic(py.ExceptionNewf(py.SyntaxError, "'continue' not properly in loop"))
450+
}
451+
if l.IsForLoop {
452+
panic(py.ExceptionNewf(py.SyntaxError, "FIXME continue in for loop not implemented", stmt))
453+
c.OpArg(vm.CONTINUE_LOOP, 0)
454+
} else {
455+
c.Jump(vm.JUMP_ABSOLUTE, l.Start)
456+
}
413457
default:
414458
panic(py.ExceptionNewf(py.SyntaxError, "Unknown StmtBase: %v", stmt))
415459
}

0 commit comments

Comments
 (0)