diff --git a/_test/for16.go b/_test/for16.go new file mode 100644 index 00000000..57dbba0a --- /dev/null +++ b/_test/for16.go @@ -0,0 +1,16 @@ +package main + +func main() { + max := 1 + for ; ; max-- { + if max == 0 { + break + } + println("in for") + } + println("bye") +} + +// Output: +// in for +// bye diff --git a/interp/ast.go b/interp/ast.go index e19e722f..502a0461 100644 --- a/interp/ast.go +++ b/interp/ast.go @@ -51,13 +51,14 @@ const ( fieldList fileStmt forStmt0 // for {} - forStmt0a // for init; ; {} - forStmt1 // for cond {} - forStmt2 // for init; cond; {} - forStmt3 // for ; cond; post {} - forStmt3a // for init; ; post {} - forStmt4 // for init; cond; post {} - forRangeStmt // for range + forStmt1 // for init; ; {} + forStmt2 // for cond {} + forStmt3 // for init; cond; {} + forStmt4 // for ; ; post {} + forStmt5 // for ; cond; post {} + forStmt6 // for init; ; post {} + forStmt7 // for init; cond; post {} + forRangeStmt // for range {} funcDecl funcLit funcType @@ -132,12 +133,13 @@ var kinds = [...]string{ fieldList: "fieldList", fileStmt: "fileStmt", forStmt0: "forStmt0", - forStmt0a: "forStmt0a", forStmt1: "forStmt1", forStmt2: "forStmt2", forStmt3: "forStmt3", - forStmt3a: "forStmt3a", forStmt4: "forStmt4", + forStmt5: "forStmt5", + forStmt6: "forStmt6", + forStmt7: "forStmt7", forRangeStmt: "forRangeStmt", funcDecl: "funcDecl", funcType: "funcType", @@ -656,27 +658,23 @@ func (interp *Interpreter) ast(src, name string, inc bool) (string, *node, error case *ast.ForStmt: // Disambiguate variants of FOR statements with a node kind per variant var kind nkind - if a.Cond == nil { - if a.Init != nil { - if a.Post != nil { - kind = forStmt3a - } else { - kind = forStmt0a - } - } else { - kind = forStmt0 - } - } else { - switch { - case a.Init == nil && a.Post == nil: - kind = forStmt1 - case a.Init != nil && a.Post == nil: - kind = forStmt2 - case a.Init == nil && a.Post != nil: - kind = forStmt3 - default: - kind = forStmt4 - } + switch { + case a.Cond == nil && a.Init == nil && a.Post == nil: + kind = forStmt0 + case a.Cond == nil && a.Init != nil && a.Post == nil: + kind = forStmt1 + case a.Cond != nil && a.Init == nil && a.Post == nil: + kind = forStmt2 + case a.Cond != nil && a.Init != nil && a.Post == nil: + kind = forStmt3 + case a.Cond == nil && a.Init == nil && a.Post != nil: + kind = forStmt4 + case a.Cond != nil && a.Init == nil && a.Post != nil: + kind = forStmt5 + case a.Cond == nil && a.Init != nil && a.Post != nil: + kind = forStmt6 + case a.Cond != nil && a.Init != nil && a.Post != nil: + kind = forStmt7 } st.push(addChild(&root, anc, pos, kind, aNop), nod) diff --git a/interp/cfg.go b/interp/cfg.go index 1c8e9d66..b8dbd29a 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -320,11 +320,7 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) { } } - case forStmt0, forRangeStmt: - sc = sc.pushBloc() - sc.loop, sc.loopRestart = n, n.child[0] - - case forStmt0a, forStmt1, forStmt2, forStmt3, forStmt3a, forStmt4: + case forStmt0, forStmt1, forStmt2, forStmt3, forStmt4, forStmt5, forStmt6, forStmt7, forRangeStmt: sc = sc.pushBloc() sc.loop, sc.loopRestart = n, n.lastChild() @@ -1050,14 +1046,14 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) { body.tnext = n.start sc = sc.pop() - case forStmt0a: // for init; ; {} + case forStmt1: // for init; ; {} init, body := n.child[0], n.child[1] n.start = init.start init.tnext = body.start body.tnext = n.start sc = sc.pop() - case forStmt1: // for cond {} + case forStmt2: // for cond {} cond, body := n.child[0], n.child[1] if !isBool(cond.typ) { err = cond.cfgErrorf("non-bool used as for condition") @@ -1076,7 +1072,7 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) { setFNext(cond, n) sc = sc.pop() - case forStmt2: // for init; cond; {} + case forStmt3: // for init; cond; {} init, cond, body := n.child[0], n.child[1], n.child[2] if !isBool(cond.typ) { err = cond.cfgErrorf("non-bool used as for condition") @@ -1098,7 +1094,14 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) { setFNext(cond, n) sc = sc.pop() - case forStmt3: // for ; cond; post {} + case forStmt4: // for ; ; post {} + post, body := n.child[0], n.child[1] + n.start = body.start + post.tnext = body.start + body.tnext = post.start + sc = sc.pop() + + case forStmt5: // for ; cond; post {} cond, post, body := n.child[0], n.child[1], n.child[2] if !isBool(cond.typ) { err = cond.cfgErrorf("non-bool used as for condition") @@ -1118,7 +1121,7 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) { body.tnext = post.start sc = sc.pop() - case forStmt3a: // for init; ; post {} + case forStmt6: // for init; ; post {} init, post, body := n.child[0], n.child[1], n.child[2] n.start = init.start init.tnext = body.start @@ -1126,7 +1129,7 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) { post.tnext = body.start sc = sc.pop() - case forStmt4: // for init; cond; post {} + case forStmt7: // for init; cond; post {} init, cond, post, body := n.child[0], n.child[1], n.child[2], n.child[3] if !isBool(cond.typ) { err = cond.cfgErrorf("non-bool used as for condition")