rangefunc

Imports

Imports #

"cmd/compile/internal/base"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types2"
"fmt"
"go/constant"
"internal/abi"
"os"

Constants & Variables

nopos var #

nopos is the zero syntax.Pos.

var nopos syntax.Pos

perLoopStep const #

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 var #

runtimePkg is a fake runtime package that contains what we need to refer to in package runtime.

var runtimePkg = *ast.CallExpr

Type Aliases

State type #

type State int

Structs

branch struct #

A branch is a single labeled branch.

type branch struct {
tok syntax.Token
label string
}

forLoop struct #

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
}

rewriter struct #

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
}

Functions

Rewrite function #

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 method #

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 method #

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

callPanic method #

func (r *rewriter) callPanic(start syntax.Pos, arg syntax.Expr) syntax.Stmt

checkFuncMisuse method #

checkFuncMisuse reports whether to check for misuse of iterator callbacks functions.

func (r *rewriter) checkFuncMisuse() bool

checks method #

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 method #

computeBranchNext computes the branchNext numbering and determines which labels end up inside which range-over-func loop bodies.

func (r *rewriter) computeBranchNext()

cond method #

func (r *rewriter) cond(op syntax.Operator, x syntax.Expr, y syntax.Expr) *syntax.Operation

declOuterVar method #

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 method #

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 method #

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 method #

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 method #

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 method #

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 method #

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 function #

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)

generateParamName method #

func (r *rewriter) generateParamName(results []*syntax.Field, i int)

ifNext method #

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 method #

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 method #

intConst returns syntax for an integer literal with the given value.

func (r *rewriter) intConst(c int) *syntax.BasicLit

makeVarName method #

func (r *rewriter) makeVarName(pos syntax.Pos, name string, typ types2.Type) (*types2.Var, *syntax.Name)

next method #

next returns a reference to the #next variable.

func (r *rewriter) next() *syntax.Name

retStmt function #

retStmt returns a return statement returning the given return values.

func retStmt(results syntax.Expr) *syntax.ReturnStmt

rewriteFunc function #

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 function #

runtimeSym returns a reference to a symbol in the fake runtime package.

func runtimeSym(info *types2.Info, name string) *syntax.Name

setPos function #

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)

setState method #

func (r *rewriter) setState(val abi.RF_State, pos syntax.Pos) *syntax.AssignStmt

setStateAt method #

func (r *rewriter) setStateAt(index int, stateVal abi.RF_State) *syntax.AssignStmt

setValueType function #

setValueType marks x as a value with type typ.

func setValueType(x syntax.Expr, typ syntax.Type)

startLoop method #

startLoop sets up for converting a range-over-func loop.

func (r *rewriter) startLoop(loop *forLoop)

stateConst method #

func (r *rewriter) stateConst(s abi.RF_State) *syntax.BasicLit

stateVar method #

func (r *rewriter) stateVar(pos syntax.Pos) (*types2.Var, *syntax.VarDecl)

useList method #

useList is useVar for a list of decls.

func (r *rewriter) useList(vars []types2.Object) syntax.Expr

useObj method #

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