Imports #
"cmd/compile/internal/base"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types2"
"fmt"
"go/constant"
"internal/abi"
"os"
"cmd/compile/internal/base"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types2"
"fmt"
"go/constant"
"internal/abi"
"os"
nopos is the zero syntax.Pos.
var nopos syntax.Pos
perLoopStep is part of the encoding of loop-spanning control flow for function range iterators. Each multiple of two encodes a "return false" passing control to an enclosing iterator; a terminal value of 1 encodes "return true" (i.e., local continue) from the body function, and a terminal value of 0 encodes executing the remainder of the body function.
const perLoopStep = 2
runtimePkg is a fake runtime package that contains what we need to refer to in package runtime.
var runtimePkg = *ast.CallExpr
type State int
A branch is a single labeled branch.
type branch struct {
tok syntax.Token
label string
}
A forLoop describes a single range-over-func loop being processed.
type forLoop struct {
nfor *syntax.ForStmt
stateVar *types2.Var
stateVarDecl *syntax.VarDecl
depth int
checkRet bool
checkBreak bool
checkContinue bool
checkBranch []branch
}
A rewriter implements rewriting the range-over-funcs in a given function.
type rewriter struct {
pkg *types2.Package
info *types2.Info
sig *types2.Signature
outer *syntax.FuncType
body *syntax.BlockStmt
any types2.Object
bool types2.Object
int types2.Object
true types2.Object
false types2.Object
branchNext map[branch]int
labelLoop map[string]*syntax.ForStmt
stack []syntax.Node
forStack []*forLoop
rewritten map[*syntax.ForStmt]syntax.Stmt
declStmt *syntax.DeclStmt
nextVar types2.Object
defers types2.Object
stateVarCount int
bodyClosureCount int
rangefuncBodyClosures map[*syntax.FuncLit]bool
}
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
assertReady returns the statement: if #tmpState != abi.RF_READY { runtime.panicrangestate(#tmpState) }
func (r *rewriter) assertReady(start syntax.Pos, tmpState *types2.Var) syntax.Stmt
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 syntax.Pos, end syntax.Pos) *syntax.FuncLit
func (r *rewriter) callPanic(start syntax.Pos, arg syntax.Expr) syntax.Stmt
checkFuncMisuse reports whether to check for misuse of iterator callbacks functions.
func (r *rewriter) checkFuncMisuse() bool
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
computeBranchNext computes the branchNext numbering and determines which labels end up inside which range-over-func loop bodies.
func (r *rewriter) computeBranchNext()
func (r *rewriter) cond(op syntax.Operator, x syntax.Expr, y syntax.Expr) *syntax.Operation
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)
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
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
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
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
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)
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)
func (r *rewriter) generateParamName(results []*syntax.Field, i int)
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
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
intConst returns syntax for an integer literal with the given value.
func (r *rewriter) intConst(c int) *syntax.BasicLit
func (r *rewriter) makeVarName(pos syntax.Pos, name string, typ types2.Type) (*types2.Var, *syntax.Name)
next returns a reference to the #next variable.
func (r *rewriter) next() *syntax.Name
retStmt returns a return statement returning the given return values.
func retStmt(results syntax.Expr) *syntax.ReturnStmt
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)
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)
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
setValueType marks x as a value with type typ.
func setValueType(x syntax.Expr, typ syntax.Type)
startLoop sets up for converting a range-over-func loop.
func (r *rewriter) startLoop(loop *forLoop)
func (r *rewriter) stateConst(s abi.RF_State) *syntax.BasicLit
func (r *rewriter) stateVar(pos syntax.Pos) (*types2.Var, *syntax.VarDecl)
useList is useVar for a list of decls.
func (r *rewriter) useList(vars []types2.Object) syntax.Expr
useObj returns syntax for a reference to decl, which should be its declaration.
func (r *rewriter) useObj(obj types2.Object) *syntax.Name
Generated with Arrow