Skip to content

Commit

Permalink
fix: continue statement was not applied correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and traefiker committed Jan 10, 2020
1 parent f1cde2b commit 5381ee6
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 21 deletions.
18 changes: 18 additions & 0 deletions _test/for8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

func main() {
for i := 0; i < 4; i++ {
for {
break
}
if i == 1 {
continue
}
println(i)
}
}

// Output:
// 0
// 2
// 3
26 changes: 26 additions & 0 deletions _test/primes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

func Primes(n int) int {
var xs []int
for i := 2; len(xs) < n; i++ {
ok := true
for _, x := range xs {
if i%x == 0 {
ok = false
break
}
}
if !ok {
continue
}
xs = append(xs, i)
}
return xs[n-1]
}

func main() {
println(Primes(3))
}

// Output:
// 5
20 changes: 5 additions & 15 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ var identifier = regexp.MustCompile(`([\pL_][\pL_\d]*)$`)
// Following this pass, the CFG is ready to run
func (interp *Interpreter) cfg(root *node) ([]*node, error) {
sc, pkgName := interp.initScopePkg(root)
var loop, loopRestart *node
var initNodes []*node
var iotaValue int
var err error
Expand Down Expand Up @@ -236,12 +235,12 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
}

case forStmt0, forRangeStmt:
loop, loopRestart = n, n.child[0]
sc = sc.pushBloc()
sc.loop, sc.loopRestart = n, n.child[0]

case forStmt1, forStmt2, forStmt3, forStmt3a, forStmt4:
loop, loopRestart = n, n.lastChild()
sc = sc.pushBloc()
sc.loop, sc.loopRestart = n, n.lastChild()

case funcLit:
n.typ = nil // to force nodeType to recompute the type
Expand Down Expand Up @@ -313,7 +312,7 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
c[i], c[l] = c[l], c[i]
}
sc = sc.pushBloc()
loop = n
sc.loop = n

case importSpec:
var name, ipath string
Expand Down Expand Up @@ -698,14 +697,14 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
if len(n.child) > 0 {
gotoLabel(n.sym)
} else {
n.tnext = loop
n.tnext = sc.loop
}

case continueStmt:
if len(n.child) > 0 {
gotoLabel(n.sym)
} else {
n.tnext = loopRestart
n.tnext = sc.loopRestart
}

case gotoStmt:
Expand Down Expand Up @@ -829,7 +828,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
body := n.child[0]
n.start = body.start
body.tnext = n.start
loop, loopRestart = nil, nil
sc = sc.pop()

case forStmt1: // for cond {}
Expand All @@ -841,7 +839,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
cond.tnext = body.start
cond.fnext = n
body.tnext = cond.start
loop, loopRestart = nil, nil
sc = sc.pop()

case forStmt2: // for init; cond; {}
Expand All @@ -854,7 +851,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
cond.tnext = body.start
cond.fnext = n
body.tnext = cond.start
loop, loopRestart = nil, nil
sc = sc.pop()

case forStmt3: // for ; cond; post {}
Expand All @@ -867,7 +863,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
cond.fnext = n
body.tnext = post.start
post.tnext = cond.start
loop, loopRestart = nil, nil
sc = sc.pop()

case forStmt3a: // for int; ; post {}
Expand All @@ -876,7 +871,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
init.tnext = body.start
body.tnext = post.start
post.tnext = body.start
loop, loopRestart = nil, nil
sc = sc.pop()

case forStmt4: // for init; cond; post {}
Expand All @@ -890,11 +884,9 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
cond.fnext = n
body.tnext = post.start
post.tnext = cond.start
loop, loopRestart = nil, nil
sc = sc.pop()

case forRangeStmt:
loop, loopRestart = nil, nil
n.start = n.child[0].start
n.child[0].fnext = n
sc = sc.pop()
Expand Down Expand Up @@ -1320,7 +1312,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
n.start = sbn.start
}
sc = sc.pop()
loop = nil

case switchIfStmt: // like an if-else chain
sbn := n.lastChild() // switch block node
Expand Down Expand Up @@ -1357,7 +1348,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
n.start = sbn.start
}
sc = sc.pop()
loop = nil

case typeAssertExpr:
if len(n.child) > 1 {
Expand Down
16 changes: 10 additions & 6 deletions interp/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ type symbol struct {
// execution to the index in frame, created exactly from the types layout.
//
type scope struct {
anc *scope // Ancestor upper scope
def *node // function definition node this scope belongs to, or nil
types []reflect.Type // Frame layout, may be shared by same level scopes
level int // Frame level: number of frame indirections to access var during execution
sym map[string]*symbol // Map of symbols defined in this current scope
global bool // true if scope refers to global space (single frame for universe and package level scopes)
anc *scope // Ancestor upper scope
def *node // function definition node this scope belongs to, or nil
loop *node // loop exit node for break statement
loopRestart *node // loop restart node for continue statement
types []reflect.Type // Frame layout, may be shared by same level scopes
level int // Frame level: number of frame indirections to access var during execution
sym map[string]*symbol // Map of symbols defined in this current scope
global bool // true if scope refers to global space (single frame for universe and package level scopes)
}

// push creates a new scope and chain it to the current one
Expand All @@ -95,6 +97,8 @@ func (s *scope) push(indirect bool) *scope {
sc.global = s.global
sc.level = s.level
}
// inherit loop state from ancestor
sc.loop, sc.loopRestart = s.loop, s.loopRestart
return &sc
}

Expand Down

0 comments on commit 5381ee6

Please sign in to comment.