@@ -144,10 +144,39 @@ func CompileAst(Ast ast.Ast, filename string, flags int, dont_inherit bool) *py.
144
144
return code
145
145
}
146
146
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
+
147
175
// State for the compiler
148
176
type compiler struct {
149
177
Code * py.Code // code being built up
150
178
OpCodes Instructions
179
+ loops loopstack
151
180
}
152
181
153
182
// Compiles a python constant
@@ -318,6 +347,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
318
347
endpopblock := new (Label )
319
348
c .Jump (vm .SETUP_LOOP , endpopblock )
320
349
while := c .NewLabel ()
350
+ c .loops .Push (loop {Start : while , End : endpopblock })
321
351
c .Expr (node .Test )
322
352
c .Jump (vm .POP_JUMP_IF_FALSE , endwhile )
323
353
for _ , stmt := range node .Body {
@@ -326,6 +356,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
326
356
c .Jump (vm .JUMP_ABSOLUTE , while )
327
357
c .Label (endwhile )
328
358
c .Op (vm .POP_BLOCK )
359
+ c .loops .Pop ()
329
360
for _ , stmt := range node .Orelse {
330
361
c .Stmt (stmt )
331
362
}
@@ -407,9 +438,22 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
407
438
case * ast.Pass :
408
439
// Do nothing
409
440
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 )
411
446
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
+ }
413
457
default :
414
458
panic (py .ExceptionNewf (py .SyntaxError , "Unknown StmtBase: %v" , stmt ))
415
459
}
0 commit comments