rewritten map[*syntax.ForStmt]syntax.Stmt
// Declared variables in generated code for outermost loop.
- declStmt *syntax.DeclStmt
- nextVar types2.Object
- retVars []types2.Object
- defers types2.Object
- stateVarCount int // stateVars are referenced from their respective loops
+ declStmt *syntax.DeclStmt
+ nextVar types2.Object
+ defers types2.Object
+ stateVarCount int // stateVars are referenced from their respective loops
+ bodyClosureCount int // to help the debugger, the closures generated for loop bodies get names
rangefuncBodyClosures map[*syntax.FuncLit]bool
}
tv := syntax.TypeAndValue{Type: r.any.Type()}
tv.SetIsValue()
init.SetTypeInfo(tv)
- r.defers = r.declVar("#defers", r.any.Type(), init)
+ r.defers = r.declOuterVar("#defers", r.any.Type(), init)
}
// Attach the token as an "extra" argument to the defer.
base.Fatalf("invalid typecheck of range func")
}
+ // Give the closure generated for the body a name, to help the debugger connect it to its frame, if active.
+ r.bodyClosureCount++
+ clo := r.bodyFunc(nfor.Body.List, syntax.UnpackListExpr(rclause.Lhs), rclause.Def, ftyp, start, end)
+ cloDecl, cloVar := r.declSingleVar(fmt.Sprintf("#yield%d", r.bodyClosureCount), clo.GetTypeInfo().Type, clo)
+ setPos(cloDecl, start)
+
// Build X(bodyFunc)
call := &syntax.ExprStmt{
X: &syntax.CallExpr{
Fun: rclause.X,
ArgList: []syntax.Expr{
- r.bodyFunc(nfor.Body.List, syntax.UnpackListExpr(rclause.Lhs), rclause.Def, ftyp, start, end),
+ r.useObj(cloVar),
},
},
}
}
// iteratorFunc(bodyFunc)
- block.List = append(block.List, call)
+ block.List = append(block.List, cloDecl, call)
if r.checkFuncMisuse() {
// iteratorFunc has exited, check for swallowed panic, and set body state to abi.RF_EXHAUSTED
if len(r.forStack) == 1 { // ending an outermost loop
r.declStmt = nil
r.nextVar = nil
- r.retVars = nil
r.defers = nil
}
// next returns a reference to the #next variable.
func (r *rewriter) next() *syntax.Name {
if r.nextVar == nil {
- r.nextVar = r.declVar("#next", r.int.Type(), nil)
+ r.nextVar = r.declOuterVar("#next", r.int.Type(), nil)
}
return r.useObj(r.nextVar)
}
r.info.Defs[n] = obj
}
-// declVar declares a variable with a given name type and initializer value.
-func (r *rewriter) declVar(name string, typ types2.Type, init syntax.Expr) *types2.Var {
+// declOuterVar declares a variable with a given name, type, and initializer value,
+// in the same scope as the outermost loop in a loop nest.
+func (r *rewriter) declOuterVar(name string, typ types2.Type, init syntax.Expr) *types2.Var {
if r.declStmt == nil {
r.declStmt = &syntax.DeclStmt{}
}
return obj
}
+// declSingleVar declares a variable with a given name, type, and initializer value,
+// and returns both the declaration and variable, so that the declaration can be placed
+// in a specific scope.
+func (r *rewriter) declSingleVar(name string, typ types2.Type, init syntax.Expr) (*syntax.DeclStmt, *types2.Var) {
+ stmt := &syntax.DeclStmt{}
+ obj, n := r.makeVarName(stmt.Pos(), name, typ)
+ stmt.DeclList = append(stmt.DeclList, &syntax.VarDecl{
+ NameList: []*syntax.Name{n},
+ // Note: Type is ignored
+ Values: init,
+ })
+ return stmt, obj
+}
+
// runtimePkg is a fake runtime package that contains what we need to refer to in package runtime.
var runtimePkg = func() *types2.Package {
var nopos syntax.Pos