var nopos … type rewriter … type branch … type forLoop … type State … // Rewrite rewrites all the range-over-funcs in the files. // It returns the set of function literals generated from rangefunc loop bodies. // This allows for rangefunc loop bodies to be distinguished by debuggers. func Rewrite(pkg *types2.Package, info *types2.Info, files []*syntax.File) map[*syntax.FuncLit]bool { … } // rewriteFunc rewrites all the range-over-funcs in a single function (a top-level func or a func literal). // The typ and body are the function's type and body. func rewriteFunc(pkg *types2.Package, info *types2.Info, typ *syntax.FuncType, body *syntax.BlockStmt, sig *types2.Signature, ri map[*syntax.FuncLit]bool) { … } // checkFuncMisuse reports whether to check for misuse of iterator callbacks functions. func (r *rewriter) checkFuncMisuse() bool { … } // inspect is a callback for syntax.Inspect that drives the actual rewriting. // If it sees a func literal, it kicks off a separate rewrite for that literal. // Otherwise, it maintains a stack of range-over-func loops and // converts each in turn. func (r *rewriter) inspect(n syntax.Node) bool { … } // startLoop sets up for converting a range-over-func loop. func (r *rewriter) startLoop(loop *forLoop) { … } // editStmt returns the replacement for the statement x, // or x itself if it should be left alone. // This includes the for loops we are converting, // as left in x.rewritten by r.endLoop. func (r *rewriter) editStmt(x syntax.Stmt) syntax.Stmt { … } // editDefer returns the replacement for the defer statement x. // See the "Defers" section in the package doc comment above for more context. func (r *rewriter) editDefer(x *syntax.CallStmt) syntax.Stmt { … } func (r *rewriter) stateVar(pos syntax.Pos) (*types2.Var, *syntax.VarDecl) { … } // editReturn returns the replacement for the return statement x. // See the "Return" section in the package doc comment above for more context. func (r *rewriter) editReturn(x *syntax.ReturnStmt) syntax.Stmt { … } const perLoopStep … // editBranch returns the replacement for the branch statement x, // or x itself if it should be left alone. // See the package doc comment above for more context. func (r *rewriter) editBranch(x *syntax.BranchStmt) syntax.Stmt { … } // computeBranchNext computes the branchNext numbering // and determines which labels end up inside which range-over-func loop bodies. func (r *rewriter) computeBranchNext() { … } // endLoop finishes the conversion of a range-over-func loop. // We have inspected and rewritten the body of the loop and can now // construct the body function and rewrite the for loop into a call // bracketed by any declarations and checks it requires. func (r *rewriter) endLoop(loop *forLoop) { … } func (r *rewriter) cond(op syntax.Operator, x, y syntax.Expr) *syntax.Operation { … } func (r *rewriter) setState(val abi.RF_State, pos syntax.Pos) *syntax.AssignStmt { … } func (r *rewriter) setStateAt(index int, stateVal abi.RF_State) *syntax.AssignStmt { … } // bodyFunc converts the loop body (control flow has already been updated) // to a func literal that can be passed to the range function. // // vars is the range variables from the range statement. // def indicates whether this is a := range statement. // ftyp is the type of the function we are creating // start and end are the syntax positions to use for new nodes // that should be at the start or end of the loop. func (r *rewriter) bodyFunc(body []syntax.Stmt, lhs []syntax.Expr, def bool, ftyp *types2.Signature, start, end syntax.Pos) *syntax.FuncLit { … } // checks returns the post-call checks that need to be done for the given loop. func (r *rewriter) checks(loop *forLoop, pos syntax.Pos) []syntax.Stmt { … } // retStmt returns a return statement returning the given return values. func retStmt(results syntax.Expr) *syntax.ReturnStmt { … } // ifNext returns the statement: // // if #next op c { [#next = 0;] thens... } func (r *rewriter) ifNext(op syntax.Operator, c int, zeroNext bool, thens ...syntax.Stmt) syntax.Stmt { … } // setValueType marks x as a value with type typ. func setValueType(x syntax.Expr, typ syntax.Type) { … } // assertReady returns the statement: // // if #stateK != abi.RF_READY { runtime.panicrangestate(#stateK) } // // where #stateK is the state variable for loop. func (r *rewriter) assertReady(start syntax.Pos, loop *forLoop) syntax.Stmt { … } func (r *rewriter) callPanic(start syntax.Pos, arg syntax.Expr) syntax.Stmt { … } // next returns a reference to the #next variable. func (r *rewriter) next() *syntax.Name { … } // forRangeFunc checks whether n is a range-over-func. // If so, it returns n.(*syntax.ForStmt), true. // Otherwise it returns nil, false. func forRangeFunc(n syntax.Node) (*syntax.ForStmt, bool) { … } // intConst returns syntax for an integer literal with the given value. func (r *rewriter) intConst(c int) *syntax.BasicLit { … } func (r *rewriter) stateConst(s abi.RF_State) *syntax.BasicLit { … } // useObj returns syntax for a reference to decl, which should be its declaration. func (r *rewriter) useObj(obj types2.Object) *syntax.Name { … } // useList is useVar for a list of decls. func (r *rewriter) useList(vars []types2.Object) syntax.Expr { … } func (r *rewriter) makeVarName(pos syntax.Pos, name string, typ types2.Type) (*types2.Var, *syntax.Name) { … } func (r *rewriter) generateParamName(results []*syntax.Field, i int) { … } // 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 { … } // 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) { … } var runtimePkg … // runtimeSym returns a reference to a symbol in the fake runtime package. func runtimeSym(info *types2.Info, name string) *syntax.Name { … } // setPos walks the top structure of x that has no position assigned // and assigns it all to have position pos. // When setPos encounters a syntax node with a position assigned, // setPos does not look inside that node. // setPos only needs to handle syntax we create in this package; // all other syntax should have positions assigned already. func setPos(x syntax.Node, pos syntax.Pos) { … }