github.com/goplus/gogen@v1.16.0/codebuild.go (about)

     1  /*
     2   Copyright 2021 The GoPlus Authors (goplus.org)
     3   Licensed under the Apache License, Version 2.0 (the "License");
     4   you may not use this file except in compliance with the License.
     5   You may obtain a copy of the License at
     6       http://www.apache.org/licenses/LICENSE-2.0
     7   Unless required by applicable law or agreed to in writing, software
     8   distributed under the License is distributed on an "AS IS" BASIS,
     9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10   See the License for the specific language governing permissions and
    11   limitations under the License.
    12  */
    13  
    14  package gogen
    15  
    16  import (
    17  	"errors"
    18  	"fmt"
    19  	"go/ast"
    20  	"go/constant"
    21  	"go/token"
    22  	"go/types"
    23  	"log"
    24  	"math/big"
    25  	"reflect"
    26  	"strconv"
    27  	"strings"
    28  	"syscall"
    29  
    30  	"github.com/goplus/gogen/internal"
    31  	xtoken "github.com/goplus/gogen/token"
    32  	"golang.org/x/tools/go/types/typeutil"
    33  )
    34  
    35  func getSrc(node []ast.Node) ast.Node {
    36  	if node != nil {
    37  		return node[0]
    38  	}
    39  	return nil
    40  }
    41  
    42  func getSrcPos(node ast.Node) token.Pos {
    43  	if node != nil {
    44  		return node.Pos()
    45  	}
    46  	return token.NoPos
    47  }
    48  
    49  func getPos(src []ast.Node) token.Pos {
    50  	if src == nil {
    51  		return token.NoPos
    52  	}
    53  	return getSrcPos(src[0])
    54  }
    55  
    56  // ----------------------------------------------------------------------------
    57  
    58  type posNode struct {
    59  	pos, end token.Pos
    60  }
    61  
    62  func NewPosNode(pos token.Pos, end ...token.Pos) ast.Node {
    63  	ret := &posNode{pos: pos, end: pos}
    64  	if end != nil {
    65  		ret.end = end[0]
    66  	}
    67  	return ret
    68  }
    69  
    70  func (p *posNode) Pos() token.Pos { return p.pos }
    71  func (p *posNode) End() token.Pos { return p.end }
    72  
    73  // ----------------------------------------------------------------------------
    74  
    75  type codeBlock interface {
    76  	End(cb *CodeBuilder, src ast.Node)
    77  }
    78  
    79  type vblockCtx struct {
    80  	codeBlock
    81  	scope *types.Scope
    82  }
    83  
    84  type codeBlockCtx struct {
    85  	codeBlock
    86  	scope *types.Scope
    87  	base  int
    88  	stmts []ast.Stmt
    89  	label *ast.LabeledStmt
    90  	flows int // flow flags
    91  }
    92  
    93  const (
    94  	flowFlagBreak = 1 << iota
    95  	flowFlagContinue
    96  	flowFlagReturn
    97  	flowFlagGoto
    98  	flowFlagWithLabel
    99  )
   100  
   101  type Label struct {
   102  	types.Label
   103  	used bool
   104  }
   105  
   106  type funcBodyCtx struct {
   107  	codeBlockCtx
   108  	fn     *Func
   109  	labels map[string]*Label
   110  }
   111  
   112  func (p *funcBodyCtx) checkLabels(cb *CodeBuilder) {
   113  	for name, l := range p.labels {
   114  		if !l.used {
   115  			cb.handleCodeErrorf(l.Pos(), "label %s defined and not used", name)
   116  		}
   117  	}
   118  }
   119  
   120  type CodeError struct {
   121  	Fset dbgPositioner
   122  	Pos  token.Pos
   123  	Msg  string
   124  }
   125  
   126  func (p *CodeError) Error() string {
   127  	pos := p.Fset.Position(p.Pos)
   128  	return fmt.Sprintf("%v: %s", pos, p.Msg)
   129  }
   130  
   131  // CodeBuilder type
   132  type CodeBuilder struct {
   133  	stk       internal.Stack
   134  	current   funcBodyCtx
   135  	fset      dbgPositioner
   136  	comments  *ast.CommentGroup
   137  	pkg       *Package
   138  	btiMap    *typeutil.Map
   139  	valDecl   *ValueDecl
   140  	ctxt      *typesContext
   141  	interp    NodeInterpreter
   142  	rec       Recorder
   143  	loadNamed LoadNamedFunc
   144  	handleErr func(err error)
   145  	closureParamInsts
   146  	iotav       int
   147  	commentOnce bool
   148  	noSkipConst bool
   149  }
   150  
   151  func (p *CodeBuilder) init(pkg *Package) {
   152  	conf := pkg.conf
   153  	p.pkg = pkg
   154  	p.fset = conf.DbgPositioner
   155  	if p.fset == nil {
   156  		p.fset = conf.Fset
   157  	}
   158  	p.noSkipConst = conf.NoSkipConstant
   159  	p.handleErr = conf.HandleErr
   160  	if p.handleErr == nil {
   161  		p.handleErr = defaultHandleErr
   162  	}
   163  	p.rec = conf.Recorder
   164  	p.interp = conf.NodeInterpreter
   165  	if p.interp == nil {
   166  		p.interp = nodeInterp{}
   167  	}
   168  	p.ctxt = newTypesContext()
   169  	p.loadNamed = conf.LoadNamed
   170  	if p.loadNamed == nil {
   171  		p.loadNamed = defaultLoadNamed
   172  	}
   173  	p.current.scope = pkg.Types.Scope()
   174  	p.stk.Init()
   175  	p.closureParamInsts.init()
   176  }
   177  
   178  func defaultLoadNamed(at *Package, t *types.Named) {
   179  	// no delay-loaded named types
   180  }
   181  
   182  func defaultHandleErr(err error) {
   183  	panic(err)
   184  }
   185  
   186  type nodeInterp struct{}
   187  
   188  func (p nodeInterp) LoadExpr(expr ast.Node) string {
   189  	return ""
   190  }
   191  
   192  func getFunExpr(fn *internal.Elem) (caller string, pos token.Pos) {
   193  	if fn == nil {
   194  		return "the closure call", token.NoPos
   195  	}
   196  	caller = types.ExprString(fn.Val)
   197  	pos = getSrcPos(fn.Src)
   198  	return
   199  }
   200  
   201  func getCaller(expr *internal.Elem) string {
   202  	if ce, ok := expr.Val.(*ast.CallExpr); ok {
   203  		return types.ExprString(ce.Fun)
   204  	}
   205  	return "the function call"
   206  }
   207  
   208  func (p *CodeBuilder) loadExpr(expr ast.Node) (string, token.Pos) {
   209  	if expr == nil {
   210  		return "", token.NoPos
   211  	}
   212  	return p.interp.LoadExpr(expr), expr.Pos()
   213  }
   214  
   215  func (p *CodeBuilder) newCodeError(pos token.Pos, msg string) *CodeError {
   216  	return &CodeError{Msg: msg, Pos: pos, Fset: p.fset}
   217  }
   218  
   219  func (p *CodeBuilder) newCodeErrorf(pos token.Pos, format string, args ...interface{}) *CodeError {
   220  	return p.newCodeError(pos, fmt.Sprintf(format, args...))
   221  }
   222  
   223  func (p *CodeBuilder) handleCodeError(pos token.Pos, msg string) {
   224  	p.handleErr(p.newCodeError(pos, msg))
   225  }
   226  
   227  func (p *CodeBuilder) handleCodeErrorf(pos token.Pos, format string, args ...interface{}) {
   228  	p.handleErr(p.newCodeError(pos, fmt.Sprintf(format, args...)))
   229  }
   230  
   231  func (p *CodeBuilder) panicCodeError(pos token.Pos, msg string) {
   232  	panic(p.newCodeError(pos, msg))
   233  }
   234  
   235  func (p *CodeBuilder) panicCodeErrorf(pos token.Pos, format string, args ...interface{}) {
   236  	panic(p.newCodeError(pos, fmt.Sprintf(format, args...)))
   237  }
   238  
   239  // Scope returns current scope.
   240  func (p *CodeBuilder) Scope() *types.Scope {
   241  	return p.current.scope
   242  }
   243  
   244  // Func returns current func (nil means in global scope).
   245  func (p *CodeBuilder) Func() *Func {
   246  	return p.current.fn
   247  }
   248  
   249  // Pkg returns the package instance.
   250  func (p *CodeBuilder) Pkg() *Package {
   251  	return p.pkg
   252  }
   253  
   254  func (p *CodeBuilder) startFuncBody(fn *Func, src []ast.Node, old *funcBodyCtx) *CodeBuilder {
   255  	p.current.fn, old.fn = fn, p.current.fn
   256  	p.current.labels, old.labels = nil, p.current.labels
   257  	p.startBlockStmt(fn, src, "func "+fn.Name(), &old.codeBlockCtx)
   258  	scope := p.current.scope
   259  	sig := fn.Type().(*types.Signature)
   260  	insertParams(scope, sig.Params())
   261  	insertParams(scope, sig.Results())
   262  	if recv := sig.Recv(); recv != nil {
   263  		scope.Insert(recv)
   264  	}
   265  	return p
   266  }
   267  
   268  func insertParams(scope *types.Scope, params *types.Tuple) {
   269  	for i, n := 0, params.Len(); i < n; i++ {
   270  		v := params.At(i)
   271  		if name := v.Name(); name != "" && name != "_" {
   272  			scope.Insert(v)
   273  		}
   274  	}
   275  }
   276  
   277  func (p *CodeBuilder) endFuncBody(old funcBodyCtx) []ast.Stmt {
   278  	p.current.checkLabels(p)
   279  	p.current.fn = old.fn
   280  	p.current.labels = old.labels
   281  	stmts, _ := p.endBlockStmt(&old.codeBlockCtx)
   282  	return stmts
   283  }
   284  
   285  func (p *CodeBuilder) startBlockStmt(current codeBlock, src []ast.Node, comment string, old *codeBlockCtx) *CodeBuilder {
   286  	var start, end token.Pos
   287  	if src != nil {
   288  		start, end = src[0].Pos(), src[0].End()
   289  	}
   290  	scope := types.NewScope(p.current.scope, start, end, comment)
   291  	p.current.codeBlockCtx, *old = codeBlockCtx{current, scope, p.stk.Len(), nil, nil, 0}, p.current.codeBlockCtx
   292  	return p
   293  }
   294  
   295  func (p *CodeBuilder) endBlockStmt(old *codeBlockCtx) ([]ast.Stmt, int) {
   296  	flows := p.current.flows
   297  	if p.current.label != nil {
   298  		p.emitStmt(&ast.EmptyStmt{})
   299  	}
   300  	stmts := p.current.stmts
   301  	p.stk.SetLen(p.current.base)
   302  	p.current.codeBlockCtx = *old
   303  	return stmts, flows
   304  }
   305  
   306  func (p *CodeBuilder) clearBlockStmt() []ast.Stmt {
   307  	stmts := p.current.stmts
   308  	p.current.stmts = nil
   309  	return stmts
   310  }
   311  
   312  func (p *CodeBuilder) startVBlockStmt(current codeBlock, comment string, old *vblockCtx) *CodeBuilder {
   313  	*old = vblockCtx{codeBlock: p.current.codeBlock, scope: p.current.scope}
   314  	scope := types.NewScope(p.current.scope, token.NoPos, token.NoPos, comment)
   315  	p.current.codeBlock, p.current.scope = current, scope
   316  	return p
   317  }
   318  
   319  func (p *CodeBuilder) endVBlockStmt(old *vblockCtx) {
   320  	p.current.codeBlock, p.current.scope = old.codeBlock, old.scope
   321  }
   322  
   323  func (p *CodeBuilder) popStmt() ast.Stmt {
   324  	stmts := p.current.stmts
   325  	n := len(stmts) - 1
   326  	stmt := stmts[n]
   327  	p.current.stmts = stmts[:n]
   328  	return stmt
   329  }
   330  
   331  func (p *CodeBuilder) startStmtAt(stmt ast.Stmt) int {
   332  	idx := len(p.current.stmts)
   333  	p.emitStmt(stmt)
   334  	return idx
   335  }
   336  
   337  // Usage:
   338  //
   339  //	idx := cb.startStmtAt(stmt)
   340  //	...
   341  //	cb.commitStmt(idx)
   342  func (p *CodeBuilder) commitStmt(idx int) {
   343  	stmts := p.current.stmts
   344  	n := len(stmts) - 1
   345  	if n > idx {
   346  		stmt := stmts[idx]
   347  		copy(stmts[idx:], stmts[idx+1:])
   348  		stmts[n] = stmt
   349  	}
   350  }
   351  
   352  func (p *CodeBuilder) emitStmt(stmt ast.Stmt) {
   353  	if p.comments != nil {
   354  		p.pkg.setStmtComments(stmt, p.comments)
   355  		if p.commentOnce {
   356  			p.comments = nil
   357  		}
   358  	}
   359  	if p.current.label != nil {
   360  		p.current.label.Stmt = stmt
   361  		stmt, p.current.label = p.current.label, nil
   362  	}
   363  	p.current.stmts = append(p.current.stmts, stmt)
   364  }
   365  
   366  func (p *CodeBuilder) startInitExpr(current codeBlock) (old codeBlock) {
   367  	p.current.codeBlock, old = current, p.current.codeBlock
   368  	return
   369  }
   370  
   371  func (p *CodeBuilder) endInitExpr(old codeBlock) {
   372  	p.current.codeBlock = old
   373  }
   374  
   375  // Comments returns the comments of next statement.
   376  func (p *CodeBuilder) Comments() *ast.CommentGroup {
   377  	return p.comments
   378  }
   379  
   380  func (p *CodeBuilder) BackupComments() (*ast.CommentGroup, bool) {
   381  	return p.comments, p.commentOnce
   382  }
   383  
   384  // SetComments sets comments to next statement.
   385  func (p *CodeBuilder) SetComments(comments *ast.CommentGroup, once bool) *CodeBuilder {
   386  	if debugComments && comments != nil {
   387  		for i, c := range comments.List {
   388  			log.Println("SetComments", i, c.Text)
   389  		}
   390  	}
   391  	p.comments, p.commentOnce = comments, once
   392  	return p
   393  }
   394  
   395  // ReturnErr func
   396  func (p *CodeBuilder) ReturnErr(outer bool) *CodeBuilder {
   397  	if debugInstr {
   398  		log.Println("ReturnErr", outer)
   399  	}
   400  	fn := p.current.fn
   401  	if outer {
   402  		if !fn.isInline() {
   403  			panic("only support ReturnOuterErr in an inline call")
   404  		}
   405  		fn = fn.old.fn
   406  	}
   407  	results := fn.Type().(*types.Signature).Results()
   408  	n := results.Len()
   409  	if n > 0 {
   410  		last := results.At(n - 1)
   411  		if last.Type() == TyError { // last result is error
   412  			err := p.stk.Pop()
   413  			for i := 0; i < n-1; i++ {
   414  				p.doZeroLit(results.At(i).Type(), false)
   415  			}
   416  			p.stk.Push(err)
   417  			p.returnResults(n)
   418  			p.current.flows |= flowFlagReturn
   419  			return p
   420  		}
   421  	}
   422  	panic("TODO: last result type isn't an error")
   423  }
   424  
   425  func (p *CodeBuilder) returnResults(n int) {
   426  	var rets []ast.Expr
   427  	if n > 0 {
   428  		args := p.stk.GetArgs(n)
   429  		rets = make([]ast.Expr, n)
   430  		for i := 0; i < n; i++ {
   431  			rets[i] = args[i].Val
   432  		}
   433  		p.stk.PopN(n)
   434  	}
   435  	p.emitStmt(&ast.ReturnStmt{Results: rets})
   436  }
   437  
   438  // Return func
   439  func (p *CodeBuilder) Return(n int, src ...ast.Node) *CodeBuilder {
   440  	if debugInstr {
   441  		log.Println("Return", n)
   442  	}
   443  	fn := p.current.fn
   444  	results := fn.Type().(*types.Signature).Results()
   445  	checkFuncResults(p.pkg, p.stk.GetArgs(n), results, getSrc(src))
   446  	if fn.isInline() {
   447  		for i := n - 1; i >= 0; i-- {
   448  			key := closureParamInst{fn, results.At(i)}
   449  			elem := p.stk.Pop()
   450  			p.doVarRef(p.paramInsts[key], nil, false)
   451  			p.stk.Push(elem)
   452  			p.doAssignWith(1, 1, nil)
   453  		}
   454  		p.Goto(p.getEndingLabel(fn))
   455  	} else {
   456  		p.current.flows |= flowFlagReturn
   457  		p.returnResults(n)
   458  	}
   459  	return p
   460  }
   461  
   462  // Call func
   463  func (p *CodeBuilder) Call(n int, ellipsis ...bool) *CodeBuilder {
   464  	var flags InstrFlags
   465  	if ellipsis != nil && ellipsis[0] {
   466  		flags = InstrFlagEllipsis
   467  	}
   468  	return p.CallWith(n, flags)
   469  }
   470  
   471  // CallWith always panics on error, while CallWithEx returns err if match function call failed.
   472  func (p *CodeBuilder) CallWith(n int, flags InstrFlags, src ...ast.Node) *CodeBuilder {
   473  	if err := p.CallWithEx(n, flags, src...); err != nil {
   474  		panic(err)
   475  	}
   476  	return p
   477  }
   478  
   479  // CallWith always panics on error, while CallWithEx returns err if match function call failed.
   480  // If an error ocurs, CallWithEx pops all function arguments from the CodeBuilder stack.
   481  // In most case, you should call CallWith instead of CallWithEx.
   482  func (p *CodeBuilder) CallWithEx(n int, flags InstrFlags, src ...ast.Node) error {
   483  	fn := p.stk.Get(-(n + 1))
   484  	if t, ok := fn.Type.(*btiMethodType); ok {
   485  		n++
   486  		fn.Type = t.Type
   487  		fn = p.stk.Get(-(n + 1))
   488  		if t.eargs != nil {
   489  			for _, arg := range t.eargs {
   490  				p.Val(arg)
   491  			}
   492  			n += len(t.eargs)
   493  		}
   494  	}
   495  	args := p.stk.GetArgs(n)
   496  	if debugInstr {
   497  		log.Println("Call", n, int(flags), "//", fn.Type)
   498  	}
   499  	s := getSrc(src)
   500  	fn.Src = s
   501  	ret, err := matchFuncCall(p.pkg, fn, args, flags)
   502  	if err != nil {
   503  		p.stk.PopN(n)
   504  		return err
   505  	}
   506  	ret.Src = s
   507  	p.stk.Ret(n+1, ret)
   508  	return nil
   509  }
   510  
   511  type closureParamInst struct {
   512  	inst  *Func
   513  	param *types.Var
   514  }
   515  
   516  type closureParamInsts struct {
   517  	paramInsts map[closureParamInst]*types.Var
   518  }
   519  
   520  func (p *closureParamInsts) init() {
   521  	p.paramInsts = make(map[closureParamInst]*types.Var)
   522  }
   523  
   524  func (p *CodeBuilder) getEndingLabel(fn *Func) *Label {
   525  	key := closureParamInst{fn, nil}
   526  	if v, ok := p.paramInsts[key]; ok {
   527  		return p.current.labels[v.Name()]
   528  	}
   529  	ending := p.pkg.autoName()
   530  	p.paramInsts[key] = types.NewParam(token.NoPos, nil, ending, nil)
   531  	return p.NewLabel(token.NoPos, ending)
   532  }
   533  
   534  func (p *CodeBuilder) needEndingLabel(fn *Func) (*Label, bool) {
   535  	key := closureParamInst{fn, nil}
   536  	if v, ok := p.paramInsts[key]; ok {
   537  		return p.current.labels[v.Name()], true
   538  	}
   539  	return nil, false
   540  }
   541  
   542  func (p *Func) inlineClosureEnd(cb *CodeBuilder) {
   543  	if ending, ok := cb.needEndingLabel(p); ok {
   544  		cb.Label(ending)
   545  	}
   546  	sig := p.Type().(*types.Signature)
   547  	cb.emitStmt(&ast.BlockStmt{List: cb.endFuncBody(p.old)})
   548  	cb.stk.PopN(p.getInlineCallArity())
   549  	results := sig.Results()
   550  	for i, n := 0, results.Len(); i < n; i++ { // return results & clean env
   551  		key := closureParamInst{p, results.At(i)}
   552  		cb.pushVal(cb.paramInsts[key], nil)
   553  		delete(cb.paramInsts, key)
   554  	}
   555  	for i, n := 0, getParamLen(sig); i < n; i++ { // clean env
   556  		key := closureParamInst{p, getParam(sig, i)}
   557  		delete(cb.paramInsts, key)
   558  	}
   559  }
   560  
   561  // CallInlineClosureStart func
   562  func (p *CodeBuilder) CallInlineClosureStart(sig *types.Signature, arity int, ellipsis bool) *CodeBuilder {
   563  	if debugInstr {
   564  		log.Println("CallInlineClosureStart", arity, ellipsis)
   565  	}
   566  	pkg := p.pkg
   567  	closure := pkg.newInlineClosure(sig, arity)
   568  	results := sig.Results()
   569  	for i, n := 0, results.Len(); i < n; i++ {
   570  		p.emitVar(pkg, closure, results.At(i), false)
   571  	}
   572  	p.startFuncBody(closure, nil, &closure.old)
   573  	args := p.stk.GetArgs(arity)
   574  	var flags InstrFlags
   575  	if ellipsis {
   576  		flags = InstrFlagEllipsis
   577  	}
   578  	if err := matchFuncType(pkg, args, flags, sig, nil); err != nil {
   579  		panic(err)
   580  	}
   581  	n1 := getParamLen(sig) - 1
   582  	if sig.Variadic() && !ellipsis {
   583  		p.SliceLit(getParam(sig, n1).Type().(*types.Slice), arity-n1)
   584  	}
   585  	for i := n1; i >= 0; i-- {
   586  		p.emitVar(pkg, closure, getParam(sig, i), true)
   587  	}
   588  	return p
   589  }
   590  
   591  func (p *CodeBuilder) emitVar(pkg *Package, closure *Func, param *types.Var, withInit bool) {
   592  	name := pkg.autoName()
   593  	if withInit {
   594  		p.NewVarStart(param.Type(), name).EndInit(1)
   595  	} else {
   596  		p.NewVar(param.Type(), name)
   597  	}
   598  	key := closureParamInst{closure, param}
   599  	p.paramInsts[key] = p.current.scope.Lookup(name).(*types.Var)
   600  }
   601  
   602  // NewClosure func
   603  func (p *CodeBuilder) NewClosure(params, results *Tuple, variadic bool) *Func {
   604  	sig := types.NewSignatureType(nil, nil, nil, params, results, variadic)
   605  	return p.NewClosureWith(sig)
   606  }
   607  
   608  // NewClosureWith func
   609  func (p *CodeBuilder) NewClosureWith(sig *types.Signature) *Func {
   610  	if debugInstr {
   611  		t := sig.Params()
   612  		for i, n := 0, t.Len(); i < n; i++ {
   613  			v := t.At(i)
   614  			if _, ok := v.Type().(*unboundType); ok {
   615  				panic("can't use unbound type in func parameters")
   616  			}
   617  		}
   618  	}
   619  	return p.pkg.newClosure(sig)
   620  }
   621  
   622  // NewType func
   623  func (p *CodeBuilder) NewType(name string, src ...ast.Node) *TypeDecl {
   624  	return p.NewTypeDefs().NewType(name, src...)
   625  }
   626  
   627  // AliasType func
   628  func (p *CodeBuilder) AliasType(name string, typ types.Type, src ...ast.Node) *types.Named {
   629  	decl := p.NewTypeDefs().AliasType(name, typ, src...)
   630  	return decl.typ
   631  }
   632  
   633  // NewConstStart func
   634  func (p *CodeBuilder) NewConstStart(typ types.Type, names ...string) *CodeBuilder {
   635  	if debugInstr {
   636  		log.Println("NewConstStart", names)
   637  	}
   638  	defs := p.valueDefs(token.CONST)
   639  	return p.pkg.newValueDecl(defs.NewPos(), defs.scope, token.NoPos, token.CONST, typ, names...).InitStart(p.pkg)
   640  }
   641  
   642  // NewVar func
   643  func (p *CodeBuilder) NewVar(typ types.Type, names ...string) *CodeBuilder {
   644  	if debugInstr {
   645  		log.Println("NewVar", names)
   646  	}
   647  	defs := p.valueDefs(token.VAR)
   648  	p.pkg.newValueDecl(defs.NewPos(), defs.scope, token.NoPos, token.VAR, typ, names...)
   649  	return p
   650  }
   651  
   652  // NewVarStart func
   653  func (p *CodeBuilder) NewVarStart(typ types.Type, names ...string) *CodeBuilder {
   654  	if debugInstr {
   655  		log.Println("NewVarStart", names)
   656  	}
   657  	defs := p.valueDefs(token.VAR)
   658  	return p.pkg.newValueDecl(defs.NewPos(), defs.scope, token.NoPos, token.VAR, typ, names...).InitStart(p.pkg)
   659  }
   660  
   661  // DefineVarStart func
   662  func (p *CodeBuilder) DefineVarStart(pos token.Pos, names ...string) *CodeBuilder {
   663  	if debugInstr {
   664  		log.Println("DefineVarStart", names)
   665  	}
   666  	return p.pkg.newValueDecl(
   667  		ValueAt{}, p.current.scope, pos, token.DEFINE, nil, names...).InitStart(p.pkg)
   668  }
   669  
   670  // NewAutoVar func
   671  func (p *CodeBuilder) NewAutoVar(pos token.Pos, name string, pv **types.Var) *CodeBuilder {
   672  	spec := &ast.ValueSpec{Names: []*ast.Ident{ident(name)}}
   673  	decl := &ast.GenDecl{Tok: token.VAR, Specs: []ast.Spec{spec}}
   674  	stmt := &ast.DeclStmt{
   675  		Decl: decl,
   676  	}
   677  	if debugInstr {
   678  		log.Println("NewAutoVar", name)
   679  	}
   680  	p.emitStmt(stmt)
   681  	typ := &unboundType{ptypes: []*ast.Expr{&spec.Type}}
   682  	*pv = types.NewVar(pos, p.pkg.Types, name, typ)
   683  	if old := p.current.scope.Insert(*pv); old != nil {
   684  		oldPos := p.fset.Position(old.Pos())
   685  		p.panicCodeErrorf(
   686  			pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldPos)
   687  	}
   688  	return p
   689  }
   690  
   691  // VarRef func: p.VarRef(nil) means underscore (_)
   692  func (p *CodeBuilder) VarRef(ref interface{}, src ...ast.Node) *CodeBuilder {
   693  	return p.doVarRef(ref, getSrc(src), true)
   694  }
   695  
   696  func (p *CodeBuilder) doVarRef(ref interface{}, src ast.Node, allowDebug bool) *CodeBuilder {
   697  	if ref == nil {
   698  		if allowDebug && debugInstr {
   699  			log.Println("VarRef _")
   700  		}
   701  		p.stk.Push(&internal.Elem{
   702  			Val: underscore, // _
   703  		})
   704  	} else {
   705  		if v, ok := ref.(string); ok {
   706  			_, ref = p.Scope().LookupParent(v, token.NoPos)
   707  		}
   708  		if v, ok := ref.(*types.Var); ok {
   709  			if allowDebug && debugInstr {
   710  				log.Println("VarRef", v.Name(), v.Type())
   711  			}
   712  			fn := p.current.fn
   713  			if fn != nil && fn.isInline() { // is in an inline call
   714  				key := closureParamInst{fn, v}
   715  				if arg, ok := p.paramInsts[key]; ok { // replace param with arg
   716  					v = arg
   717  				}
   718  			}
   719  			p.stk.Push(&internal.Elem{
   720  				Val: toObjectExpr(p.pkg, v), Type: &refType{typ: v.Type()}, Src: src,
   721  			})
   722  		} else {
   723  			code, pos := p.loadExpr(src)
   724  			p.panicCodeErrorf(pos, "%s is not a variable", code)
   725  		}
   726  	}
   727  	return p
   728  }
   729  
   730  var (
   731  	elemNone = &internal.Elem{}
   732  )
   733  
   734  // None func
   735  func (p *CodeBuilder) None() *CodeBuilder {
   736  	if debugInstr {
   737  		log.Println("None")
   738  	}
   739  	p.stk.Push(elemNone)
   740  	return p
   741  }
   742  
   743  // ZeroLit func
   744  func (p *CodeBuilder) ZeroLit(typ types.Type) *CodeBuilder {
   745  	return p.doZeroLit(typ, true)
   746  }
   747  
   748  func (p *CodeBuilder) doZeroLit(typ types.Type, allowDebug bool) *CodeBuilder {
   749  	typ0 := typ
   750  	if allowDebug && debugInstr {
   751  		log.Println("ZeroLit //", typ)
   752  	}
   753  retry:
   754  	switch t := typ.(type) {
   755  	case *types.Basic:
   756  		switch kind := t.Kind(); kind {
   757  		case types.Bool:
   758  			return p.Val(false)
   759  		case types.String:
   760  			return p.Val("")
   761  		case types.UnsafePointer:
   762  			return p.Val(nil)
   763  		default:
   764  			return p.Val(0)
   765  		}
   766  	case *types.Interface, *types.Map, *types.Slice, *types.Pointer, *types.Signature, *types.Chan:
   767  		return p.Val(nil)
   768  	case *types.Named:
   769  		typ = p.getUnderlying(t)
   770  		goto retry
   771  	}
   772  	ret := &ast.CompositeLit{}
   773  	switch t := typ.(type) {
   774  	case *unboundType:
   775  		if t.tBound == nil {
   776  			t.ptypes = append(t.ptypes, &ret.Type)
   777  		} else {
   778  			typ = t.tBound
   779  			typ0 = typ
   780  			ret.Type = toType(p.pkg, typ)
   781  		}
   782  	default:
   783  		ret.Type = toType(p.pkg, typ)
   784  	}
   785  	p.stk.Push(&internal.Elem{Type: typ0, Val: ret})
   786  	return p
   787  }
   788  
   789  // MapLit func
   790  func (p *CodeBuilder) MapLit(typ types.Type, arity int, src ...ast.Node) *CodeBuilder {
   791  	if err := p.MapLitEx(typ, arity, src...); err != nil {
   792  		panic(err)
   793  	}
   794  	return p
   795  }
   796  
   797  // MapLit func
   798  func (p *CodeBuilder) MapLitEx(typ types.Type, arity int, src ...ast.Node) error {
   799  	if debugInstr {
   800  		log.Println("MapLit", typ, arity)
   801  	}
   802  	var t *types.Map
   803  	var typExpr ast.Expr
   804  	var pkg = p.pkg
   805  	if typ != nil {
   806  		var ok bool
   807  		switch tt := typ.(type) {
   808  		case *types.Named:
   809  			typExpr = toNamedType(pkg, tt)
   810  			t, ok = p.getUnderlying(tt).(*types.Map)
   811  		case *types.Map:
   812  			typExpr = toMapType(pkg, tt)
   813  			t, ok = tt, true
   814  		}
   815  		if !ok {
   816  			return p.newCodeErrorf(getPos(src), "type %v isn't a map", typ)
   817  		}
   818  	}
   819  	if arity == 0 {
   820  		if t == nil {
   821  			t = types.NewMap(types.Typ[types.String], TyEmptyInterface)
   822  			typ = t
   823  			typExpr = toMapType(pkg, t)
   824  		}
   825  		ret := &ast.CompositeLit{Type: typExpr}
   826  		p.stk.Push(&internal.Elem{Type: typ, Val: ret, Src: getSrc(src)})
   827  		return nil
   828  	}
   829  	if (arity & 1) != 0 {
   830  		return p.newCodeErrorf(getPos(src), "MapLit: invalid arity, can't be odd - %d", arity)
   831  	}
   832  	var key, val types.Type
   833  	var args = p.stk.GetArgs(arity)
   834  	var check = (t != nil)
   835  	if check {
   836  		key, val = t.Key(), t.Elem()
   837  	} else {
   838  		key = boundElementType(pkg, args, 0, arity, 2)
   839  		val = boundElementType(pkg, args, 1, arity, 2)
   840  		t = types.NewMap(Default(pkg, key), Default(pkg, val))
   841  		typ = t
   842  		typExpr = toMapType(pkg, t)
   843  	}
   844  	elts := make([]ast.Expr, arity>>1)
   845  	for i := 0; i < arity; i += 2 {
   846  		elts[i>>1] = &ast.KeyValueExpr{Key: args[i].Val, Value: args[i+1].Val}
   847  		if check {
   848  			if !AssignableTo(pkg, args[i].Type, key) {
   849  				src, pos := p.loadExpr(args[i].Src)
   850  				return p.newCodeErrorf(
   851  					pos, "cannot use %s (type %v) as type %v in map key", src, args[i].Type, key)
   852  			} else if !AssignableTo(pkg, args[i+1].Type, val) {
   853  				src, pos := p.loadExpr(args[i+1].Src)
   854  				return p.newCodeErrorf(
   855  					pos, "cannot use %s (type %v) as type %v in map value", src, args[i+1].Type, val)
   856  			}
   857  		}
   858  	}
   859  	p.stk.Ret(arity, &internal.Elem{
   860  		Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src),
   861  	})
   862  	return nil
   863  }
   864  
   865  func (p *CodeBuilder) toBoundArrayLen(elts []*internal.Elem, arity, limit int) int {
   866  	n := -1
   867  	max := -1
   868  	for i := 0; i < arity; i += 2 {
   869  		if elts[i].Val != nil {
   870  			n = p.toIntVal(elts[i], "index which must be non-negative integer constant")
   871  		} else {
   872  			n++
   873  		}
   874  		if limit >= 0 && n >= limit { // error message
   875  			if elts[i].Src == nil {
   876  				pos := getSrcPos(elts[i+1].Src)
   877  				p.panicCodeErrorf(pos, "array index %d out of bounds [0:%d]", n, limit)
   878  			}
   879  			src, pos := p.loadExpr(elts[i].Src)
   880  			p.panicCodeErrorf(pos, "array index %s (value %d) out of bounds [0:%d]", src, n, limit)
   881  		}
   882  		if max < n {
   883  			max = n
   884  		}
   885  	}
   886  	return max + 1
   887  }
   888  
   889  func (p *CodeBuilder) toIntVal(v *internal.Elem, msg string) int {
   890  	if cval := v.CVal; cval != nil && cval.Kind() == constant.Int {
   891  		if v, ok := constant.Int64Val(cval); ok {
   892  			return int(v)
   893  		}
   894  	}
   895  	code, pos := p.loadExpr(v.Src)
   896  	p.panicCodeErrorf(pos, "cannot use %s as %s", code, msg)
   897  	return 0
   898  }
   899  
   900  func (p *CodeBuilder) indexElemExpr(args []*internal.Elem, i int) ast.Expr {
   901  	key := args[i].Val
   902  	if key == nil { // none
   903  		return args[i+1].Val
   904  	}
   905  	p.toIntVal(args[i], "index which must be non-negative integer constant")
   906  	return &ast.KeyValueExpr{Key: key, Value: args[i+1].Val}
   907  }
   908  
   909  // SliceLit func
   910  func (p *CodeBuilder) SliceLit(typ types.Type, arity int, keyVal ...bool) *CodeBuilder {
   911  	var keyValMode = (keyVal != nil && keyVal[0])
   912  	return p.SliceLitEx(typ, arity, keyValMode)
   913  }
   914  
   915  // SliceLitEx func
   916  func (p *CodeBuilder) SliceLitEx(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder {
   917  	var elts []ast.Expr
   918  	if debugInstr {
   919  		log.Println("SliceLit", typ, arity, keyVal)
   920  	}
   921  	var t *types.Slice
   922  	var typExpr ast.Expr
   923  	var pkg = p.pkg
   924  	if typ != nil {
   925  		switch tt := typ.(type) {
   926  		case *types.Named:
   927  			typExpr = toNamedType(pkg, tt)
   928  			t = p.getUnderlying(tt).(*types.Slice)
   929  		case *types.Slice:
   930  			typExpr = toSliceType(pkg, tt)
   931  			t = tt
   932  		default:
   933  			log.Panicln("SliceLit: typ isn't a slice type -", reflect.TypeOf(typ))
   934  		}
   935  	}
   936  	if keyVal { // in keyVal mode
   937  		if (arity & 1) != 0 {
   938  			log.Panicln("SliceLit: invalid arity, can't be odd in keyVal mode -", arity)
   939  		}
   940  		args := p.stk.GetArgs(arity)
   941  		val := t.Elem()
   942  		n := arity >> 1
   943  		elts = make([]ast.Expr, n)
   944  		for i := 0; i < arity; i += 2 {
   945  			arg := args[i+1]
   946  			if !AssignableConv(pkg, arg.Type, val, arg) {
   947  				src, pos := p.loadExpr(args[i+1].Src)
   948  				p.panicCodeErrorf(
   949  					pos, "cannot use %s (type %v) as type %v in slice literal", src, args[i+1].Type, val)
   950  			}
   951  			elts[i>>1] = p.indexElemExpr(args, i)
   952  		}
   953  	} else {
   954  		if arity == 0 {
   955  			if t == nil {
   956  				t = types.NewSlice(TyEmptyInterface)
   957  				typ = t
   958  				typExpr = toSliceType(pkg, t)
   959  			}
   960  			p.stk.Push(&internal.Elem{
   961  				Type: typ, Val: &ast.CompositeLit{Type: typExpr}, Src: getSrc(src),
   962  			})
   963  			return p
   964  		}
   965  		var val types.Type
   966  		var args = p.stk.GetArgs(arity)
   967  		var check = (t != nil)
   968  		if check {
   969  			val = t.Elem()
   970  		} else {
   971  			val = boundElementType(pkg, args, 0, arity, 1)
   972  			t = types.NewSlice(Default(pkg, val))
   973  			typ = t
   974  			typExpr = toSliceType(pkg, t)
   975  		}
   976  		elts = make([]ast.Expr, arity)
   977  		for i, arg := range args {
   978  			elts[i] = arg.Val
   979  			if check {
   980  				if !AssignableConv(pkg, arg.Type, val, arg) {
   981  					src, pos := p.loadExpr(arg.Src)
   982  					p.panicCodeErrorf(
   983  						pos, "cannot use %s (type %v) as type %v in slice literal", src, arg.Type, val)
   984  				}
   985  			}
   986  		}
   987  	}
   988  	p.stk.Ret(arity, &internal.Elem{
   989  		Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src),
   990  	})
   991  	return p
   992  }
   993  
   994  // ArrayLit func
   995  func (p *CodeBuilder) ArrayLit(typ types.Type, arity int, keyVal ...bool) *CodeBuilder {
   996  	var keyValMode = (keyVal != nil && keyVal[0])
   997  	return p.ArrayLitEx(typ, arity, keyValMode)
   998  }
   999  
  1000  // ArrayLitEx func
  1001  func (p *CodeBuilder) ArrayLitEx(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder {
  1002  	var elts []ast.Expr
  1003  	if debugInstr {
  1004  		log.Println("ArrayLit", typ, arity, keyVal)
  1005  	}
  1006  	var t *types.Array
  1007  	var typExpr ast.Expr
  1008  	var pkg = p.pkg
  1009  	switch tt := typ.(type) {
  1010  	case *types.Named:
  1011  		typExpr = toNamedType(pkg, tt)
  1012  		t = p.getUnderlying(tt).(*types.Array)
  1013  	case *types.Array:
  1014  		typExpr = toArrayType(pkg, tt)
  1015  		t = tt
  1016  	default:
  1017  		log.Panicln("ArrayLit: typ isn't a array type -", reflect.TypeOf(typ))
  1018  	}
  1019  	if keyVal { // in keyVal mode
  1020  		if (arity & 1) != 0 {
  1021  			log.Panicln("ArrayLit: invalid arity, can't be odd in keyVal mode -", arity)
  1022  		}
  1023  		n := int(t.Len())
  1024  		args := p.stk.GetArgs(arity)
  1025  		max := p.toBoundArrayLen(args, arity, n)
  1026  		val := t.Elem()
  1027  		if n < 0 {
  1028  			t = types.NewArray(val, int64(max))
  1029  			typ = t
  1030  		}
  1031  		elts = make([]ast.Expr, arity>>1)
  1032  		for i := 0; i < arity; i += 2 {
  1033  			if !AssignableTo(pkg, args[i+1].Type, val) {
  1034  				src, pos := p.loadExpr(args[i+1].Src)
  1035  				p.panicCodeErrorf(
  1036  					pos, "cannot use %s (type %v) as type %v in array literal", src, args[i+1].Type, val)
  1037  			}
  1038  			elts[i>>1] = p.indexElemExpr(args, i)
  1039  		}
  1040  	} else {
  1041  		args := p.stk.GetArgs(arity)
  1042  		val := t.Elem()
  1043  		if n := t.Len(); n < 0 {
  1044  			t = types.NewArray(val, int64(arity))
  1045  			typ = t
  1046  		} else if int(n) < arity {
  1047  			pos := getSrcPos(args[n].Src)
  1048  			p.panicCodeErrorf(pos, "array index %d out of bounds [0:%d]", n, n)
  1049  		}
  1050  		elts = make([]ast.Expr, arity)
  1051  		for i, arg := range args {
  1052  			elts[i] = arg.Val
  1053  			if !AssignableConv(pkg, arg.Type, val, arg) {
  1054  				src, pos := p.loadExpr(arg.Src)
  1055  				p.panicCodeErrorf(
  1056  					pos, "cannot use %s (type %v) as type %v in array literal", src, arg.Type, val)
  1057  			}
  1058  		}
  1059  	}
  1060  	p.stk.Ret(arity, &internal.Elem{
  1061  		Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src),
  1062  	})
  1063  	return p
  1064  }
  1065  
  1066  // StructLit func
  1067  func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder {
  1068  	if debugInstr {
  1069  		log.Println("StructLit", typ, arity, keyVal)
  1070  	}
  1071  	var t *types.Struct
  1072  	var typExpr ast.Expr
  1073  	var pkg = p.pkg
  1074  	switch tt := typ.(type) {
  1075  	case *types.Named:
  1076  		typExpr = toNamedType(pkg, tt)
  1077  		t = p.getUnderlying(tt).(*types.Struct)
  1078  	case *types.Struct:
  1079  		typExpr = toStructType(pkg, tt)
  1080  		t = tt
  1081  	default:
  1082  		log.Panicln("StructLit: typ isn't a struct type -", reflect.TypeOf(typ))
  1083  	}
  1084  	var elts []ast.Expr
  1085  	var n = t.NumFields()
  1086  	var args = p.stk.GetArgs(arity)
  1087  	if keyVal {
  1088  		if (arity & 1) != 0 {
  1089  			log.Panicln("StructLit: invalid arity, can't be odd in keyVal mode -", arity)
  1090  		}
  1091  		elts = make([]ast.Expr, arity>>1)
  1092  		for i := 0; i < arity; i += 2 {
  1093  			idx := p.toIntVal(args[i], "field which must be non-negative integer constant")
  1094  			if idx >= n {
  1095  				panic("invalid struct field index")
  1096  			}
  1097  			elt := t.Field(idx)
  1098  			eltTy, eltName := elt.Type(), elt.Name()
  1099  			if !AssignableTo(pkg, args[i+1].Type, eltTy) {
  1100  				src, pos := p.loadExpr(args[i+1].Src)
  1101  				p.panicCodeErrorf(
  1102  					pos, "cannot use %s (type %v) as type %v in value of field %s",
  1103  					src, args[i+1].Type, eltTy, eltName)
  1104  			}
  1105  			elts[i>>1] = &ast.KeyValueExpr{Key: ident(eltName), Value: args[i+1].Val}
  1106  		}
  1107  	} else if arity != n {
  1108  		if arity != 0 {
  1109  			fewOrMany := "few"
  1110  			if arity > n {
  1111  				fewOrMany = "many"
  1112  			}
  1113  			pos := getSrcPos(args[arity-1].Src)
  1114  			p.panicCodeErrorf(pos, "too %s values in %v{...}", fewOrMany, typ)
  1115  		}
  1116  	} else {
  1117  		elts = make([]ast.Expr, arity)
  1118  		for i, arg := range args {
  1119  			elts[i] = arg.Val
  1120  			eltTy := t.Field(i).Type()
  1121  			if !AssignableTo(pkg, arg.Type, eltTy) {
  1122  				src, pos := p.loadExpr(arg.Src)
  1123  				p.panicCodeErrorf(
  1124  					pos, "cannot use %s (type %v) as type %v in value of field %s",
  1125  					src, arg.Type, eltTy, t.Field(i).Name())
  1126  			}
  1127  		}
  1128  	}
  1129  	p.stk.Ret(arity, &internal.Elem{
  1130  		Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src),
  1131  	})
  1132  	return p
  1133  }
  1134  
  1135  // Slice func
  1136  func (p *CodeBuilder) Slice(slice3 bool, src ...ast.Node) *CodeBuilder { // a[i:j:k]
  1137  	if debugInstr {
  1138  		log.Println("Slice", slice3)
  1139  	}
  1140  	n := 3
  1141  	if slice3 {
  1142  		n++
  1143  	}
  1144  	srcExpr := getSrc(src)
  1145  	args := p.stk.GetArgs(n)
  1146  	x := args[0]
  1147  	typ := x.Type
  1148  	switch t := typ.(type) {
  1149  	case *types.Slice:
  1150  		// nothing to do
  1151  	case *types.Basic:
  1152  		if t.Kind() == types.String || t.Kind() == types.UntypedString {
  1153  			if slice3 {
  1154  				code, pos := p.loadExpr(srcExpr)
  1155  				p.panicCodeErrorf(pos, "invalid operation %s (3-index slice of string)", code)
  1156  			}
  1157  		} else {
  1158  			code, pos := p.loadExpr(x.Src)
  1159  			p.panicCodeErrorf(pos, "cannot slice %s (type %v)", code, typ)
  1160  		}
  1161  	case *types.Array:
  1162  		typ = types.NewSlice(t.Elem())
  1163  	case *types.Pointer:
  1164  		if tt, ok := t.Elem().(*types.Array); ok {
  1165  			typ = types.NewSlice(tt.Elem())
  1166  		} else {
  1167  			code, pos := p.loadExpr(x.Src)
  1168  			p.panicCodeErrorf(pos, "cannot slice %s (type %v)", code, typ)
  1169  		}
  1170  	}
  1171  	var exprMax ast.Expr
  1172  	if slice3 {
  1173  		exprMax = args[3].Val
  1174  	}
  1175  	// TODO: check type
  1176  	elem := &internal.Elem{
  1177  		Val: &ast.SliceExpr{
  1178  			X: x.Val, Low: args[1].Val, High: args[2].Val, Max: exprMax, Slice3: slice3,
  1179  		},
  1180  		Type: typ, Src: srcExpr,
  1181  	}
  1182  	p.stk.Ret(n, elem)
  1183  	return p
  1184  }
  1185  
  1186  // Index func:
  1187  //   - a[i]
  1188  //   - fn[T1, T2, ..., Tn]
  1189  //   - G[T1, T2, ..., Tn]
  1190  func (p *CodeBuilder) Index(nidx int, twoValue bool, src ...ast.Node) *CodeBuilder {
  1191  	if debugInstr {
  1192  		log.Println("Index", nidx, twoValue)
  1193  	}
  1194  	args := p.stk.GetArgs(nidx + 1)
  1195  	if nidx > 0 {
  1196  		if _, ok := args[1].Type.(*TypeType); ok {
  1197  			return p.instantiate(nidx, args, src...)
  1198  		}
  1199  	}
  1200  	if nidx != 1 {
  1201  		panic("Index doesn't support a[i, j...] yet")
  1202  	}
  1203  	srcExpr := getSrc(src)
  1204  	typs, allowTwoValue := p.getIdxValTypes(args[0].Type, false, srcExpr)
  1205  	var tyRet types.Type
  1206  	if twoValue { // elem, ok = a[key]
  1207  		if !allowTwoValue {
  1208  			pos := getSrcPos(srcExpr)
  1209  			p.panicCodeError(pos, "assignment mismatch: 2 variables but 1 values")
  1210  		}
  1211  		pkg := p.pkg
  1212  		tyRet = types.NewTuple(
  1213  			pkg.NewParam(token.NoPos, "", typs[1]),
  1214  			pkg.NewParam(token.NoPos, "", types.Typ[types.Bool]))
  1215  	} else { // elem = a[key]
  1216  		tyRet = typs[1]
  1217  	}
  1218  	elem := &internal.Elem{
  1219  		Val: &ast.IndexExpr{X: args[0].Val, Index: args[1].Val}, Type: tyRet, Src: srcExpr,
  1220  	}
  1221  	// TODO: check index type
  1222  	p.stk.Ret(2, elem)
  1223  	return p
  1224  }
  1225  
  1226  // IndexRef func
  1227  func (p *CodeBuilder) IndexRef(nidx int, src ...ast.Node) *CodeBuilder {
  1228  	if debugInstr {
  1229  		log.Println("IndexRef", nidx)
  1230  	}
  1231  	if nidx != 1 {
  1232  		panic("IndexRef doesn't support a[i, j...] = val yet")
  1233  	}
  1234  	args := p.stk.GetArgs(2)
  1235  	typ := args[0].Type
  1236  	elemRef := &internal.Elem{
  1237  		Val: &ast.IndexExpr{X: args[0].Val, Index: args[1].Val},
  1238  		Src: getSrc(src),
  1239  	}
  1240  	if t, ok := typ.(*unboundType); ok {
  1241  		tyMapElem := &unboundMapElemType{key: args[1].Type, typ: t}
  1242  		elemRef.Type = &refType{typ: tyMapElem}
  1243  	} else {
  1244  		typs, _ := p.getIdxValTypes(typ, true, elemRef.Src)
  1245  		elemRef.Type = &refType{typ: typs[1]}
  1246  		// TODO: check index type
  1247  	}
  1248  	p.stk.Ret(2, elemRef)
  1249  	return p
  1250  }
  1251  
  1252  func (p *CodeBuilder) getIdxValTypes(typ types.Type, ref bool, idxSrc ast.Node) ([]types.Type, bool) {
  1253  retry:
  1254  	switch t := typ.(type) {
  1255  	case *types.Slice:
  1256  		return []types.Type{tyInt, t.Elem()}, false
  1257  	case *types.Map:
  1258  		return []types.Type{t.Key(), t.Elem()}, true
  1259  	case *types.Array:
  1260  		return []types.Type{tyInt, t.Elem()}, false
  1261  	case *types.Pointer:
  1262  		elem := t.Elem()
  1263  		if named, ok := elem.(*types.Named); ok {
  1264  			elem = p.getUnderlying(named)
  1265  		}
  1266  		if e, ok := elem.(*types.Array); ok {
  1267  			return []types.Type{tyInt, e.Elem()}, false
  1268  		}
  1269  	case *types.Basic:
  1270  		if (t.Info() & types.IsString) != 0 {
  1271  			if ref {
  1272  				src, pos := p.loadExpr(idxSrc)
  1273  				p.panicCodeErrorf(pos, "cannot assign to %s (strings are immutable)", src)
  1274  			}
  1275  			return []types.Type{tyInt, TyByte}, false
  1276  		}
  1277  	case *types.Named:
  1278  		typ = p.getUnderlying(t)
  1279  		goto retry
  1280  	}
  1281  	src, pos := p.loadExpr(idxSrc)
  1282  	p.panicCodeErrorf(pos, "invalid operation: %s (type %v does not support indexing)", src, typ)
  1283  	return nil, false
  1284  }
  1285  
  1286  var (
  1287  	tyInt = types.Typ[types.Int]
  1288  )
  1289  
  1290  // Typ func
  1291  func (p *CodeBuilder) Typ(typ types.Type, src ...ast.Node) *CodeBuilder {
  1292  	if debugInstr {
  1293  		log.Println("Typ", typ)
  1294  	}
  1295  	p.stk.Push(&internal.Elem{
  1296  		Val:  toType(p.pkg, typ),
  1297  		Type: NewTypeType(typ),
  1298  		Src:  getSrc(src),
  1299  	})
  1300  	return p
  1301  }
  1302  
  1303  // UntypedBigInt func
  1304  func (p *CodeBuilder) UntypedBigInt(v *big.Int, src ...ast.Node) *CodeBuilder {
  1305  	pkg := p.pkg
  1306  	bigPkg := pkg.big()
  1307  	if v.IsInt64() {
  1308  		val := &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(v.Int64(), 10)}
  1309  		p.Val(bigPkg.Ref("NewInt")).Val(val).Call(1)
  1310  	} else {
  1311  		/*
  1312  			func() *typ {
  1313  				v, _ := new(typ).SetString(strVal, 10)
  1314  				return v
  1315  			}()
  1316  		*/
  1317  		typ := bigPkg.Ref("Int").Type()
  1318  		retTyp := types.NewPointer(typ)
  1319  		ret := pkg.NewParam(token.NoPos, "", retTyp)
  1320  		p.NewClosure(nil, types.NewTuple(ret), false).BodyStart(pkg).
  1321  			DefineVarStart(token.NoPos, "v", "_").
  1322  			Val(pkg.builtin.Ref("new")).Typ(typ).Call(1).
  1323  			MemberVal("SetString").Val(v.String()).Val(10).Call(2).EndInit(1).
  1324  			Val(p.Scope().Lookup("v")).Return(1).
  1325  			End().Call(0)
  1326  	}
  1327  	ret := p.stk.Get(-1)
  1328  	ret.Type, ret.CVal, ret.Src = pkg.utBigInt, constant.Make(v), getSrc(src)
  1329  	return p
  1330  }
  1331  
  1332  // UntypedBigRat func
  1333  func (p *CodeBuilder) UntypedBigRat(v *big.Rat, src ...ast.Node) *CodeBuilder {
  1334  	pkg := p.pkg
  1335  	bigPkg := pkg.big()
  1336  	a, b := v.Num(), v.Denom()
  1337  	if a.IsInt64() && b.IsInt64() {
  1338  		va := &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(a.Int64(), 10)}
  1339  		vb := &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(b.Int64(), 10)}
  1340  		p.Val(bigPkg.Ref("NewRat")).Val(va).Val(vb).Call(2)
  1341  	} else {
  1342  		// new(big.Rat).SetFrac(a, b)
  1343  		p.Val(p.pkg.builtin.Ref("new")).Typ(bigPkg.Ref("Rat").Type()).Call(1).
  1344  			MemberVal("SetFrac").UntypedBigInt(a).UntypedBigInt(b).Call(2)
  1345  	}
  1346  	ret := p.stk.Get(-1)
  1347  	ret.Type, ret.CVal, ret.Src = pkg.utBigRat, constant.Make(v), getSrc(src)
  1348  	return p
  1349  }
  1350  
  1351  func (p *CodeBuilder) VarVal(name string, src ...ast.Node) *CodeBuilder {
  1352  	_, o := p.Scope().LookupParent(name, token.NoPos)
  1353  	if o == nil {
  1354  		log.Panicf("VarVal: variable `%v` not found\n", name)
  1355  	}
  1356  	return p.Val(o, src...)
  1357  }
  1358  
  1359  // Val func
  1360  func (p *CodeBuilder) Val(v interface{}, src ...ast.Node) *CodeBuilder {
  1361  	if debugInstr {
  1362  		if o, ok := v.(types.Object); ok {
  1363  			log.Println("Val", o.Name(), o.Type())
  1364  		} else {
  1365  			log.Println("Val", v, reflect.TypeOf(v))
  1366  		}
  1367  	}
  1368  	fn := p.current.fn
  1369  	if fn != nil && fn.isInline() { // is in an inline call
  1370  		if param, ok := v.(*types.Var); ok {
  1371  			key := closureParamInst{fn, param}
  1372  			if arg, ok := p.paramInsts[key]; ok { // replace param with arg
  1373  				v = arg
  1374  			}
  1375  		}
  1376  	}
  1377  	return p.pushVal(v, getSrc(src))
  1378  }
  1379  
  1380  func (p *CodeBuilder) pushVal(v interface{}, src ast.Node) *CodeBuilder {
  1381  	p.stk.Push(toExpr(p.pkg, v, src))
  1382  	return p
  1383  }
  1384  
  1385  // Star func
  1386  func (p *CodeBuilder) Star(src ...ast.Node) *CodeBuilder {
  1387  	if debugInstr {
  1388  		log.Println("Star")
  1389  	}
  1390  	arg := p.stk.Get(-1)
  1391  	ret := &internal.Elem{Val: &ast.StarExpr{X: arg.Val}, Src: getSrc(src)}
  1392  	argType := arg.Type
  1393  retry:
  1394  	switch t := argType.(type) {
  1395  	case *TypeType:
  1396  		ret.Type = t.Pointer()
  1397  	case *types.Pointer:
  1398  		ret.Type = t.Elem()
  1399  	case *types.Named:
  1400  		argType = p.getUnderlying(t)
  1401  		goto retry
  1402  	default:
  1403  		code, pos := p.loadExpr(arg.Src)
  1404  		p.panicCodeErrorf(pos, "invalid indirect of %s (type %v)", code, t)
  1405  	}
  1406  	p.stk.Ret(1, ret)
  1407  	return p
  1408  }
  1409  
  1410  // Elem func
  1411  func (p *CodeBuilder) Elem(src ...ast.Node) *CodeBuilder {
  1412  	if debugInstr {
  1413  		log.Println("Elem")
  1414  	}
  1415  	arg := p.stk.Get(-1)
  1416  	t, ok := arg.Type.(*types.Pointer)
  1417  	if !ok {
  1418  		code, pos := p.loadExpr(arg.Src)
  1419  		p.panicCodeErrorf(pos, "invalid indirect of %s (type %v)", code, arg.Type)
  1420  	}
  1421  	p.stk.Ret(1, &internal.Elem{Val: &ast.StarExpr{X: arg.Val}, Type: t.Elem(), Src: getSrc(src)})
  1422  	return p
  1423  }
  1424  
  1425  // ElemRef func
  1426  func (p *CodeBuilder) ElemRef(src ...ast.Node) *CodeBuilder {
  1427  	if debugInstr {
  1428  		log.Println("ElemRef")
  1429  	}
  1430  	arg := p.stk.Get(-1)
  1431  	t, ok := arg.Type.(*types.Pointer)
  1432  	if !ok {
  1433  		code, pos := p.loadExpr(arg.Src)
  1434  		p.panicCodeErrorf(pos, "invalid indirect of %s (type %v)", code, arg.Type)
  1435  	}
  1436  	p.stk.Ret(1, &internal.Elem{
  1437  		Val: &ast.StarExpr{X: arg.Val}, Type: &refType{typ: t.Elem()}, Src: getSrc(src),
  1438  	})
  1439  	return p
  1440  }
  1441  
  1442  // MemberVal func
  1443  func (p *CodeBuilder) MemberVal(name string, src ...ast.Node) *CodeBuilder {
  1444  	_, err := p.Member(name, MemberFlagVal, src...)
  1445  	if err != nil {
  1446  		panic(err)
  1447  	}
  1448  	return p
  1449  }
  1450  
  1451  // MemberRef func
  1452  func (p *CodeBuilder) MemberRef(name string, src ...ast.Node) *CodeBuilder {
  1453  	_, err := p.Member(name, MemberFlagRef, src...)
  1454  	if err != nil {
  1455  		panic(err)
  1456  	}
  1457  	return p
  1458  }
  1459  
  1460  func (p *CodeBuilder) refMember(typ types.Type, name string, argVal ast.Expr, src ast.Node) MemberKind {
  1461  	switch o := indirect(typ).(type) {
  1462  	case *types.Named:
  1463  		if struc, ok := p.getUnderlying(o).(*types.Struct); ok {
  1464  			if p.fieldRef(argVal, struc, name, src) {
  1465  				return MemberField
  1466  			}
  1467  		}
  1468  	case *types.Struct:
  1469  		if p.fieldRef(argVal, o, name, src) {
  1470  			return MemberField
  1471  		}
  1472  	}
  1473  	return MemberInvalid
  1474  }
  1475  
  1476  func (p *CodeBuilder) fieldRef(x ast.Expr, o *types.Struct, name string, src ast.Node) bool {
  1477  	for i, n := 0, o.NumFields(); i < n; i++ {
  1478  		fld := o.Field(i)
  1479  		if fld.Name() == name {
  1480  			if p.rec != nil {
  1481  				p.rec.Member(src, fld)
  1482  			}
  1483  			p.stk.Ret(1, &internal.Elem{
  1484  				Val:  &ast.SelectorExpr{X: x, Sel: ident(name)},
  1485  				Type: &refType{typ: fld.Type()},
  1486  			})
  1487  			return true
  1488  		} else if fld.Embedded() {
  1489  			fldt := fld.Type()
  1490  			if o, ok := fldt.(*types.Pointer); ok {
  1491  				fldt = o.Elem()
  1492  			}
  1493  			if t, ok := fldt.(*types.Named); ok {
  1494  				u := p.getUnderlying(t)
  1495  				if struc, ok := u.(*types.Struct); ok {
  1496  					if p.fieldRef(x, struc, name, src) {
  1497  						return true
  1498  					}
  1499  				}
  1500  			}
  1501  		}
  1502  	}
  1503  	return false
  1504  }
  1505  
  1506  type (
  1507  	MemberKind int
  1508  	MemberFlag int
  1509  )
  1510  
  1511  const (
  1512  	MemberInvalid MemberKind = iota
  1513  	MemberMethod
  1514  	MemberAutoProperty
  1515  	MemberField
  1516  	memberBad MemberKind = -1
  1517  )
  1518  
  1519  const (
  1520  	MemberFlagVal MemberFlag = iota
  1521  	MemberFlagMethodAlias
  1522  	MemberFlagAutoProperty
  1523  	MemberFlagRef MemberFlag = -1
  1524  
  1525  	// private state
  1526  	memberFlagMethodToFunc MemberFlag = 0x80
  1527  )
  1528  
  1529  func aliasNameOf(name string, flag MemberFlag) (string, MemberFlag) {
  1530  	// flag > 0 means:
  1531  	//   flag == MemberFlagMethodAlias ||
  1532  	//   flag == MemberFlagAutoProperty ||
  1533  	//   flag == memberFlagMethodToFunc
  1534  	if flag > 0 && name != "" {
  1535  		if c := name[0]; c >= 'a' && c <= 'z' {
  1536  			return string(rune(c)+('A'-'a')) + name[1:], flag
  1537  		}
  1538  		if flag != memberFlagMethodToFunc {
  1539  			flag = MemberFlagVal
  1540  		}
  1541  	}
  1542  	return "", flag
  1543  }
  1544  
  1545  // Member access member by its name.
  1546  // src should point to the full source node `x.sel`
  1547  func (p *CodeBuilder) Member(name string, flag MemberFlag, src ...ast.Node) (kind MemberKind, err error) {
  1548  	srcExpr := getSrc(src)
  1549  	arg := p.stk.Get(-1)
  1550  	if debugInstr {
  1551  		log.Println("Member", name, flag, "//", arg.Type)
  1552  	}
  1553  	switch arg.Type {
  1554  	case p.pkg.utBigInt, p.pkg.utBigRat, p.pkg.utBigFlt:
  1555  		arg.Type = DefaultConv(p.pkg, arg.Type, arg)
  1556  	}
  1557  	at := arg.Type
  1558  	if flag == MemberFlagRef {
  1559  		kind = p.refMember(at, name, arg.Val, srcExpr)
  1560  	} else {
  1561  		var aliasName string
  1562  		var t, isType = at.(*TypeType)
  1563  		if isType { // (T).method or (*T).method
  1564  			at = t.Type()
  1565  			flag = memberFlagMethodToFunc
  1566  		}
  1567  		aliasName, flag = aliasNameOf(name, flag)
  1568  		kind = p.findMember(at, name, aliasName, flag, arg, srcExpr)
  1569  		if isType && kind != MemberMethod {
  1570  			code, pos := p.loadExpr(srcExpr)
  1571  			return MemberInvalid, p.newCodeError(
  1572  				pos, fmt.Sprintf("%s undefined (type %v has no method %s)", code, at, name))
  1573  		}
  1574  	}
  1575  	if kind > 0 {
  1576  		return
  1577  	}
  1578  	code, pos := p.loadExpr(srcExpr)
  1579  	return MemberInvalid, p.newCodeError(
  1580  		pos, fmt.Sprintf("%s undefined (type %v has no field or method %s)", code, arg.Type, name))
  1581  }
  1582  
  1583  func (p *CodeBuilder) getUnderlying(t *types.Named) types.Type {
  1584  	u := t.Underlying()
  1585  	if u == nil {
  1586  		p.loadNamed(p.pkg, t)
  1587  		u = t.Underlying()
  1588  	}
  1589  	return u
  1590  }
  1591  
  1592  func (p *CodeBuilder) ensureLoaded(typ types.Type) {
  1593  	if t, ok := typ.(*types.Pointer); ok {
  1594  		typ = t.Elem()
  1595  	}
  1596  	if t, ok := typ.(*types.Named); ok && (t.NumMethods() == 0 || t.Underlying() == nil) {
  1597  		if debugMatch {
  1598  			log.Println("==> EnsureLoaded", typ)
  1599  		}
  1600  		p.loadNamed(p.pkg, t)
  1601  	}
  1602  }
  1603  
  1604  func getUnderlying(pkg *Package, typ types.Type) types.Type {
  1605  	u := typ.Underlying()
  1606  	if u == nil {
  1607  		if t, ok := typ.(*types.Named); ok {
  1608  			pkg.cb.loadNamed(pkg, t)
  1609  			u = t.Underlying()
  1610  		}
  1611  	}
  1612  	return u
  1613  }
  1614  
  1615  func (p *CodeBuilder) findMember(
  1616  	typ types.Type, name, aliasName string, flag MemberFlag, arg *Element, srcExpr ast.Node) MemberKind {
  1617  	var named *types.Named
  1618  retry:
  1619  	switch o := typ.(type) {
  1620  	case *types.Pointer:
  1621  		switch t := o.Elem().(type) {
  1622  		case *types.Named:
  1623  			u := p.getUnderlying(t) // may cause to loadNamed (delay-loaded)
  1624  			struc, fstruc := u.(*types.Struct)
  1625  			if fstruc {
  1626  				if kind := p.normalField(struc, name, arg, srcExpr); kind != MemberInvalid {
  1627  					return kind
  1628  				}
  1629  			}
  1630  			if kind := p.method(t, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid {
  1631  				return kind
  1632  			}
  1633  			if fstruc {
  1634  				return p.embeddedField(struc, name, aliasName, flag, arg, srcExpr)
  1635  			}
  1636  		case *types.Struct:
  1637  			if kind := p.field(t, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid {
  1638  				return kind
  1639  			}
  1640  		}
  1641  	case *types.Named:
  1642  		named, typ = o, p.getUnderlying(o) // may cause to loadNamed (delay-loaded)
  1643  		if kind := p.method(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid {
  1644  			return kind
  1645  		}
  1646  		goto retry
  1647  	case *types.Struct:
  1648  		if kind := p.field(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid {
  1649  			return kind
  1650  		}
  1651  		if named != nil {
  1652  			return MemberInvalid
  1653  		}
  1654  	case *types.Interface:
  1655  		o.Complete()
  1656  		if kind := p.method(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid {
  1657  			return kind
  1658  		}
  1659  	case *types.Basic, *types.Slice, *types.Map, *types.Chan:
  1660  		return p.btiMethod(p.getBuiltinTI(o), name, aliasName, flag, srcExpr)
  1661  	}
  1662  	return MemberInvalid
  1663  }
  1664  
  1665  type methodList interface {
  1666  	NumMethods() int
  1667  	Method(i int) *types.Func
  1668  }
  1669  
  1670  func selector(arg *Element, name string) *ast.SelectorExpr {
  1671  	denoted := &ast.Object{Data: arg}
  1672  	return &ast.SelectorExpr{X: arg.Val, Sel: &ast.Ident{Name: name, Obj: denoted}}
  1673  }
  1674  
  1675  func denoteRecv(v *ast.SelectorExpr) *Element {
  1676  	if o := v.Sel.Obj; o != nil {
  1677  		if e, ok := o.Data.(*Element); ok {
  1678  			return e
  1679  		}
  1680  	}
  1681  	return nil
  1682  }
  1683  
  1684  func getDenoted(expr ast.Expr) *ast.Object {
  1685  	switch v := expr.(type) {
  1686  	case *ast.SelectorExpr:
  1687  		return v.Sel.Obj
  1688  	case *ast.Ident:
  1689  		return v.Obj
  1690  	default:
  1691  		return nil
  1692  	}
  1693  }
  1694  
  1695  func setDenoted(expr ast.Expr, denoted *ast.Object) {
  1696  	switch v := expr.(type) {
  1697  	case *ast.SelectorExpr:
  1698  		v.Sel.Obj = denoted
  1699  	case *ast.Ident:
  1700  		v.Obj = denoted
  1701  	}
  1702  }
  1703  
  1704  func (p *CodeBuilder) allowAccess(pkg *types.Package, name string) bool {
  1705  	if !ast.IsExported(name) && pkg != nil && pkg.Path() != p.pkg.Path() {
  1706  		return false
  1707  	}
  1708  	return true
  1709  }
  1710  
  1711  func (p *CodeBuilder) method(
  1712  	o methodList, name, aliasName string, flag MemberFlag, arg *Element, src ast.Node) (kind MemberKind) {
  1713  	var found *types.Func
  1714  	var exact bool
  1715  	for i, n := 0, o.NumMethods(); i < n; i++ {
  1716  		method := o.Method(i)
  1717  		v := method.Name()
  1718  		if !p.allowAccess(method.Pkg(), v) {
  1719  			continue
  1720  		}
  1721  		if v == name {
  1722  			found, exact = method, true
  1723  			break
  1724  		} else if flag > 0 && v == aliasName {
  1725  			found = method
  1726  			if method.Pkg() != p.pkg.Types {
  1727  				break
  1728  			}
  1729  		}
  1730  	}
  1731  	if found != nil {
  1732  		autoprop := !exact && flag == MemberFlagAutoProperty
  1733  		typ := found.Type()
  1734  		if autoprop && !methodHasAutoProperty(typ, 0) {
  1735  			return memberBad
  1736  		}
  1737  
  1738  		sel := selector(arg, found.Name())
  1739  		ret := &internal.Elem{Val: sel, Src: src}
  1740  		if t, set := p.methodSigOf(typ, flag, arg, ret); set {
  1741  			ret.Type = t
  1742  		}
  1743  		p.stk.Ret(1, ret)
  1744  
  1745  		if p.rec != nil {
  1746  			p.rec.Member(src, found)
  1747  		}
  1748  		if autoprop {
  1749  			p.CallWith(0, 0, src)
  1750  			return MemberAutoProperty
  1751  		}
  1752  		return MemberMethod
  1753  	}
  1754  	if t, ok := o.(*types.Named); ok {
  1755  		kind = p.btiMethod(p.getBuiltinTI(t), name, aliasName, flag, src)
  1756  	}
  1757  	return
  1758  }
  1759  
  1760  func isTypeConvert(otyp, typ types.Type) (string, bool) {
  1761  	if otyp != typ {
  1762  		if t, ok := typ.Underlying().(*types.Basic); ok &&
  1763  			(t.Info()&types.IsUntyped) == 0 {
  1764  			return t.Name(), true
  1765  		}
  1766  	}
  1767  	return "", false
  1768  }
  1769  
  1770  func (p *CodeBuilder) btiMethod(
  1771  	o *builtinTI, name, aliasName string, flag MemberFlag, src ast.Node) MemberKind {
  1772  	if o != nil {
  1773  		for i, n := 0, o.NumMethods(); i < n; i++ {
  1774  			method := o.Method(i)
  1775  			v := method.name
  1776  			if v == name || (flag > 0 && v == aliasName) {
  1777  				autoprop := flag == MemberFlagAutoProperty && v == aliasName
  1778  				this := p.stk.Pop()
  1779  				if fn, ok := isTypeConvert(o.typ, this.Type); ok {
  1780  					this.Val = &ast.CallExpr{
  1781  						Fun:  ast.NewIdent(fn),
  1782  						Args: []ast.Expr{this.Val},
  1783  					}
  1784  					this.Type = &btiMethodType{Type: o.typ, eargs: method.eargs}
  1785  				} else {
  1786  					this.Type = &btiMethodType{Type: this.Type, eargs: method.eargs}
  1787  				}
  1788  				p.Val(method.fn, src)
  1789  				p.stk.Push(this)
  1790  				if p.rec != nil {
  1791  					p.rec.Member(src, method.fn)
  1792  				}
  1793  				if autoprop {
  1794  					p.CallWith(0, 0, src)
  1795  					return MemberAutoProperty
  1796  				}
  1797  				return MemberMethod
  1798  			}
  1799  		}
  1800  	}
  1801  	return MemberInvalid
  1802  }
  1803  
  1804  func (p *CodeBuilder) normalField(
  1805  	o *types.Struct, name string, arg *Element, src ast.Node) MemberKind {
  1806  	for i, n := 0, o.NumFields(); i < n; i++ {
  1807  		fld := o.Field(i)
  1808  		v := fld.Name()
  1809  		if !p.allowAccess(fld.Pkg(), v) {
  1810  			continue
  1811  		}
  1812  		if v == name {
  1813  			p.stk.Ret(1, &internal.Elem{
  1814  				Val:  selector(arg, name),
  1815  				Type: fld.Type(),
  1816  				Src:  src,
  1817  			})
  1818  			if p.rec != nil {
  1819  				p.rec.Member(src, fld)
  1820  			}
  1821  			return MemberField
  1822  		}
  1823  	}
  1824  	return MemberInvalid
  1825  }
  1826  
  1827  func (p *CodeBuilder) embeddedField(
  1828  	o *types.Struct, name, aliasName string, flag MemberFlag, arg *Element, src ast.Node) MemberKind {
  1829  	for i, n := 0, o.NumFields(); i < n; i++ {
  1830  		if fld := o.Field(i); fld.Embedded() {
  1831  			if kind := p.findMember(fld.Type(), name, aliasName, flag, arg, src); kind != MemberInvalid {
  1832  				return kind
  1833  			}
  1834  		}
  1835  	}
  1836  	return MemberInvalid
  1837  }
  1838  
  1839  func (p *CodeBuilder) field(
  1840  	o *types.Struct, name, aliasName string, flag MemberFlag, arg *Element, src ast.Node) MemberKind {
  1841  	if kind := p.normalField(o, name, arg, src); kind != MemberInvalid {
  1842  		return kind
  1843  	}
  1844  	return p.embeddedField(o, name, aliasName, flag, arg, src)
  1845  }
  1846  
  1847  func toFuncSig(sig *types.Signature, recv *types.Var) *types.Signature {
  1848  	sp := sig.Params()
  1849  	spLen := sp.Len()
  1850  	vars := make([]*types.Var, spLen+1)
  1851  	vars[0] = recv
  1852  	for i := 0; i < spLen; i++ {
  1853  		vars[i+1] = sp.At(i)
  1854  	}
  1855  	return types.NewSignatureType(nil, nil, nil, types.NewTuple(vars...), sig.Results(), sig.Variadic())
  1856  }
  1857  
  1858  func methodToFuncSig(pkg *Package, o types.Object, fn *Element) *types.Signature {
  1859  	sig := o.Type().(*types.Signature)
  1860  	recv := sig.Recv()
  1861  	if recv == nil { // special signature
  1862  		fn.Val = toObjectExpr(pkg, o)
  1863  		return sig
  1864  	}
  1865  
  1866  	sel := fn.Val.(*ast.SelectorExpr)
  1867  	sel.Sel = ident(o.Name())
  1868  	sel.X = &ast.ParenExpr{X: sel.X}
  1869  	return toFuncSig(sig, recv)
  1870  }
  1871  
  1872  func (p *CodeBuilder) methodSigOf(typ types.Type, flag MemberFlag, arg, ret *Element) (types.Type, bool) {
  1873  	if flag != memberFlagMethodToFunc {
  1874  		return methodCallSig(typ), true
  1875  	}
  1876  
  1877  	sig := typ.(*types.Signature)
  1878  	if t, ok := CheckFuncEx(sig); ok {
  1879  		switch ext := t.(type) {
  1880  		case *TyStaticMethod:
  1881  			return p.funcExSigOf(ext.Func, ret)
  1882  		case *TyTemplateRecvMethod:
  1883  			return p.funcExSigOf(ext.Func, ret)
  1884  		}
  1885  		// TODO: We should take `methodSigOf` more seriously
  1886  		return typ, true
  1887  	}
  1888  
  1889  	sel := ret.Val.(*ast.SelectorExpr)
  1890  	at := arg.Type.(*TypeType).typ
  1891  	recv := sig.Recv().Type()
  1892  	_, isPtr := recv.(*types.Pointer) // recv is a pointer
  1893  	if t, ok := at.(*types.Pointer); ok {
  1894  		if !isPtr {
  1895  			if _, ok := recv.Underlying().(*types.Interface); !ok { // and recv isn't a interface
  1896  				log.Panicf("recv of method %v.%s isn't a pointer\n", t.Elem(), sel.Sel.Name)
  1897  			}
  1898  		}
  1899  	} else if isPtr { // use *T
  1900  		at = types.NewPointer(at)
  1901  		sel.X = &ast.StarExpr{X: sel.X}
  1902  	}
  1903  	sel.X = &ast.ParenExpr{X: sel.X}
  1904  
  1905  	return toFuncSig(sig, types.NewVar(token.NoPos, nil, "", at)), true
  1906  }
  1907  
  1908  func (p *CodeBuilder) funcExSigOf(o types.Object, ret *Element) (types.Type, bool) {
  1909  	ret.Val = toObjectExpr(p.pkg, o)
  1910  	ret.Type = o.Type()
  1911  	return nil, false
  1912  }
  1913  
  1914  func methodCallSig(typ types.Type) types.Type {
  1915  	sig := typ.(*types.Signature)
  1916  	if _, ok := CheckFuncEx(sig); ok {
  1917  		// TODO: We should take `methodSigOf` more seriously
  1918  		return typ
  1919  	}
  1920  	return types.NewSignatureType(nil, nil, nil, sig.Params(), sig.Results(), sig.Variadic())
  1921  }
  1922  
  1923  func indirect(typ types.Type) types.Type {
  1924  	if t, ok := typ.(*types.Pointer); ok {
  1925  		typ = t.Elem()
  1926  	}
  1927  	return typ
  1928  }
  1929  
  1930  // IncDec func
  1931  func (p *CodeBuilder) IncDec(op token.Token, src ...ast.Node) *CodeBuilder {
  1932  	name := goxPrefix + incdecOps[op]
  1933  	if debugInstr {
  1934  		log.Println("IncDec", op)
  1935  	}
  1936  	pkg := p.pkg
  1937  	arg := p.stk.Pop()
  1938  	if t, ok := arg.Type.(*refType).typ.(*types.Named); ok {
  1939  		op := lookupMethod(t, name)
  1940  		if op != nil {
  1941  			fn := &internal.Elem{
  1942  				Val:  &ast.SelectorExpr{X: arg.Val, Sel: ident(name)},
  1943  				Type: realType(op.Type()),
  1944  			}
  1945  			ret := toFuncCall(pkg, fn, []*Element{arg}, 0)
  1946  			if ret.Type != nil {
  1947  				p.shouldNoResults(name, src)
  1948  			}
  1949  			p.emitStmt(&ast.ExprStmt{X: ret.Val})
  1950  			return p
  1951  		}
  1952  	}
  1953  	fn := pkg.builtin.Ref(name)
  1954  	t := fn.Type().(*TyInstruction)
  1955  	if _, err := t.instr.Call(pkg, []*Element{arg}, 0, nil); err != nil {
  1956  		panic(err)
  1957  	}
  1958  	return p
  1959  }
  1960  
  1961  var (
  1962  	incdecOps = [...]string{
  1963  		token.INC: "Inc",
  1964  		token.DEC: "Dec",
  1965  	}
  1966  )
  1967  
  1968  // AssignOp func
  1969  func (p *CodeBuilder) AssignOp(op token.Token, src ...ast.Node) *CodeBuilder {
  1970  	args := p.stk.GetArgs(2)
  1971  	stmt := callAssignOp(p.pkg, op, args, src)
  1972  	p.emitStmt(stmt)
  1973  	p.stk.PopN(2)
  1974  	return p
  1975  }
  1976  
  1977  func checkDivisionByZero(cb *CodeBuilder, a, b *internal.Elem) {
  1978  	if a.CVal == nil {
  1979  		if isNormalInt(cb, a) {
  1980  			if c := b.CVal; c != nil {
  1981  				switch c.Kind() {
  1982  				case constant.Int, constant.Float, constant.Complex:
  1983  					if constant.Sign(c) == 0 {
  1984  						pos := getSrcPos(b.Src)
  1985  						cb.panicCodeError(pos, "invalid operation: division by zero")
  1986  					}
  1987  				}
  1988  			}
  1989  		}
  1990  	} else if c := b.CVal; c != nil {
  1991  		switch c.Kind() {
  1992  		case constant.Int, constant.Float, constant.Complex:
  1993  			if constant.Sign(c) == 0 {
  1994  				pos := getSrcPos(b.Src)
  1995  				cb.panicCodeError(pos, "invalid operation: division by zero")
  1996  			}
  1997  		}
  1998  	}
  1999  }
  2000  
  2001  func callAssignOp(pkg *Package, tok token.Token, args []*internal.Elem, src []ast.Node) ast.Stmt {
  2002  	name := goxPrefix + assignOps[tok]
  2003  	if debugInstr {
  2004  		log.Println("AssignOp", tok, name)
  2005  	}
  2006  	if t, ok := args[0].Type.(*refType).typ.(*types.Named); ok {
  2007  		op := lookupMethod(t, name)
  2008  		if op != nil {
  2009  			fn := &internal.Elem{
  2010  				Val:  &ast.SelectorExpr{X: args[0].Val, Sel: ident(name)},
  2011  				Type: realType(op.Type()),
  2012  			}
  2013  			ret := toFuncCall(pkg, fn, args, 0)
  2014  			if ret.Type != nil {
  2015  				pkg.cb.shouldNoResults(name, src)
  2016  			}
  2017  			return &ast.ExprStmt{X: ret.Val}
  2018  		}
  2019  	}
  2020  	op := pkg.builtin.Ref(name)
  2021  	if tok == token.QUO_ASSIGN {
  2022  		checkDivisionByZero(&pkg.cb, &internal.Elem{Val: args[0].Val, Type: args[0].Type.(*refType).typ}, args[1])
  2023  	}
  2024  	fn := &internal.Elem{
  2025  		Val: ident(op.Name()), Type: op.Type(),
  2026  	}
  2027  	toFuncCall(pkg, fn, args, 0)
  2028  	return &ast.AssignStmt{
  2029  		Tok: tok,
  2030  		Lhs: []ast.Expr{args[0].Val},
  2031  		Rhs: []ast.Expr{args[1].Val},
  2032  	}
  2033  }
  2034  
  2035  func (p *CodeBuilder) shouldNoResults(name string, src []ast.Node) {
  2036  	pos := token.NoPos
  2037  	if src != nil {
  2038  		pos = src[0].Pos()
  2039  	}
  2040  	p.panicCodeErrorf(pos, "operator %s should return no results\n", name)
  2041  }
  2042  
  2043  var (
  2044  	assignOps = [...]string{
  2045  		token.ADD_ASSIGN: "AddAssign", // +=
  2046  		token.SUB_ASSIGN: "SubAssign", // -=
  2047  		token.MUL_ASSIGN: "MulAssign", // *=
  2048  		token.QUO_ASSIGN: "QuoAssign", // /=
  2049  		token.REM_ASSIGN: "RemAssign", // %=
  2050  
  2051  		token.AND_ASSIGN:     "AndAssign",    // &=
  2052  		token.OR_ASSIGN:      "OrAssign",     // |=
  2053  		token.XOR_ASSIGN:     "XorAssign",    // ^=
  2054  		token.AND_NOT_ASSIGN: "AndNotAssign", // &^=
  2055  		token.SHL_ASSIGN:     "LshAssign",    // <<=
  2056  		token.SHR_ASSIGN:     "RshAssign",    // >>=
  2057  	}
  2058  )
  2059  
  2060  // Assign func
  2061  func (p *CodeBuilder) Assign(lhs int, rhs ...int) *CodeBuilder {
  2062  	var v int
  2063  	if rhs != nil {
  2064  		v = rhs[0]
  2065  	} else {
  2066  		v = lhs
  2067  	}
  2068  	if debugInstr {
  2069  		log.Println("Assign", lhs, v)
  2070  	}
  2071  	return p.doAssignWith(lhs, v, nil)
  2072  }
  2073  
  2074  // AssignWith func
  2075  func (p *CodeBuilder) AssignWith(lhs, rhs int, src ...ast.Node) *CodeBuilder {
  2076  	if debugInstr {
  2077  		log.Println("Assign", lhs, rhs)
  2078  	}
  2079  	return p.doAssignWith(lhs, rhs, getSrc(src))
  2080  }
  2081  
  2082  func (p *CodeBuilder) doAssignWith(lhs, rhs int, src ast.Node) *CodeBuilder {
  2083  	mkBlockStmt := false
  2084  	args := p.stk.GetArgs(lhs + rhs)
  2085  	stmt := &ast.AssignStmt{
  2086  		Tok: token.ASSIGN,
  2087  		Lhs: make([]ast.Expr, lhs),
  2088  		Rhs: make([]ast.Expr, rhs),
  2089  	}
  2090  	if rhs == 1 {
  2091  		if rhsVals, ok := args[lhs].Type.(*types.Tuple); ok {
  2092  			if lhs != rhsVals.Len() {
  2093  				pos := getSrcPos(src)
  2094  				caller := getCaller(args[lhs])
  2095  				p.panicCodeErrorf(
  2096  					pos, "assignment mismatch: %d variables but %v returns %d values",
  2097  					lhs, caller, rhsVals.Len())
  2098  			}
  2099  			for i := 0; i < lhs; i++ {
  2100  				val := &internal.Elem{Type: rhsVals.At(i).Type()}
  2101  				checkAssignType(p.pkg, args[i].Type, val)
  2102  				stmt.Lhs[i] = args[i].Val
  2103  			}
  2104  			stmt.Rhs[0] = args[lhs].Val
  2105  			goto done
  2106  		}
  2107  	}
  2108  	if lhs == rhs {
  2109  		for i := 0; i < lhs; i++ {
  2110  			lhsType := args[i].Type
  2111  			checkAssignType(p.pkg, lhsType, args[lhs+i])
  2112  			stmt.Lhs[i] = args[i].Val
  2113  			stmt.Rhs[i] = args[lhs+i].Val
  2114  		}
  2115  	} else {
  2116  		pos := getSrcPos(src)
  2117  		p.panicCodeErrorf(
  2118  			pos, "assignment mismatch: %d variables but %d values", lhs, rhs)
  2119  	}
  2120  done:
  2121  	p.emitStmt(stmt)
  2122  	if mkBlockStmt { // }
  2123  		p.End()
  2124  	} else {
  2125  		p.stk.PopN(lhs + rhs)
  2126  	}
  2127  	return p
  2128  }
  2129  
  2130  func lookupMethod(t *types.Named, name string) types.Object {
  2131  	for i, n := 0, t.NumMethods(); i < n; i++ {
  2132  		m := t.Method(i)
  2133  		if m.Name() == name {
  2134  			return m
  2135  		}
  2136  	}
  2137  	return nil
  2138  }
  2139  
  2140  func doUnaryOp(cb *CodeBuilder, op token.Token, args []*internal.Elem, flags InstrFlags) (ret *internal.Elem, err error) {
  2141  	name := goxPrefix + unaryOps[op]
  2142  	pkg := cb.pkg
  2143  	typ := args[0].Type
  2144  retry:
  2145  	switch t := typ.(type) {
  2146  	case *types.Named:
  2147  		lm := lookupMethod(t, name)
  2148  		if lm != nil {
  2149  			fn := &internal.Elem{
  2150  				Val:  &ast.SelectorExpr{X: args[0].Val, Sel: ident(name)},
  2151  				Type: realType(lm.Type()),
  2152  			}
  2153  			return matchFuncCall(pkg, fn, args, flags|instrFlagOpFunc)
  2154  		}
  2155  	case *types.Pointer:
  2156  		typ = t.Elem()
  2157  		goto retry
  2158  	}
  2159  	lm := pkg.builtin.Ref(name)
  2160  	return matchFuncCall(pkg, toObject(pkg, lm, nil), args, flags)
  2161  }
  2162  
  2163  // UnaryOp:
  2164  //   - cb.UnaryOp(op token.Token)
  2165  //   - cb.UnaryOp(op token.Token, twoValue bool)
  2166  //   - cb.UnaryOp(op token.Token, twoValue bool, src ast.Node)
  2167  func (p *CodeBuilder) UnaryOp(op token.Token, params ...interface{}) *CodeBuilder {
  2168  	var src ast.Node
  2169  	var flags InstrFlags
  2170  	switch len(params) {
  2171  	case 2:
  2172  		src, _ = params[1].(ast.Node)
  2173  		fallthrough
  2174  	case 1:
  2175  		if params[0].(bool) {
  2176  			flags = InstrFlagTwoValue
  2177  		}
  2178  	}
  2179  	if debugInstr {
  2180  		log.Println("UnaryOp", op, "flags:", flags)
  2181  	}
  2182  	ret, err := doUnaryOp(p, op, p.stk.GetArgs(1), flags)
  2183  	if err != nil {
  2184  		panic(err)
  2185  	}
  2186  	ret.Src = src
  2187  	p.stk.Ret(1, ret)
  2188  	return p
  2189  }
  2190  
  2191  // BinaryOp func
  2192  func (p *CodeBuilder) BinaryOp(op token.Token, src ...ast.Node) *CodeBuilder {
  2193  	const (
  2194  		errNotFound = syscall.ENOENT
  2195  	)
  2196  	if debugInstr {
  2197  		log.Println("BinaryOp", xtoken.String(op))
  2198  	}
  2199  	pkg := p.pkg
  2200  	name := goxPrefix + binaryOps[op]
  2201  	args := p.stk.GetArgs(2)
  2202  
  2203  	var ret *internal.Elem
  2204  	var err error = errNotFound
  2205  	isUserDef := false
  2206  	arg0 := args[0].Type
  2207  	named0, ok0 := checkNamed(arg0)
  2208  	if ok0 {
  2209  		if fn, e := pkg.MethodToFunc(arg0, name, src...); e == nil {
  2210  			ret, err = matchFuncCall(pkg, fn, args, instrFlagBinaryOp)
  2211  			isUserDef = true
  2212  		}
  2213  	}
  2214  	if err != nil {
  2215  		arg1 := args[1].Type
  2216  		if named1, ok1 := checkNamed(arg1); ok1 && named0 != named1 {
  2217  			if fn, e := pkg.MethodToFunc(arg1, name, src...); e == nil {
  2218  				ret, err = matchFuncCall(pkg, fn, args, instrFlagBinaryOp)
  2219  				isUserDef = true
  2220  			}
  2221  		}
  2222  	}
  2223  	if err != nil && !isUserDef {
  2224  		if op == token.QUO {
  2225  			checkDivisionByZero(p, args[0], args[1])
  2226  		}
  2227  		if op == token.EQL || op == token.NEQ {
  2228  			if !ComparableTo(pkg, args[0], args[1]) {
  2229  				err = errors.New("mismatched types")
  2230  			} else {
  2231  				ret, err = &internal.Elem{
  2232  					Val: &ast.BinaryExpr{
  2233  						X: checkParenExpr(args[0].Val), Op: op,
  2234  						Y: checkParenExpr(args[1].Val),
  2235  					},
  2236  					Type: types.Typ[types.UntypedBool],
  2237  					CVal: binaryOp(p, op, args),
  2238  				}, nil
  2239  			}
  2240  		} else if lm := pkg.builtin.TryRef(name); lm != nil {
  2241  			ret, err = matchFuncCall(pkg, toObject(pkg, lm, nil), args, 0)
  2242  		} else {
  2243  			err = errNotFound
  2244  		}
  2245  	}
  2246  
  2247  	expr := getSrc(src)
  2248  	if err != nil {
  2249  		opstr := xtoken.String(op)
  2250  		src, pos := p.loadExpr(expr)
  2251  		if src == "" {
  2252  			src = opstr
  2253  		}
  2254  		if err != errNotFound {
  2255  			p.panicCodeErrorf(
  2256  				pos, "invalid operation: %s (mismatched types %v and %v)", src, arg0, args[1].Type)
  2257  		} else {
  2258  			arg0Src, _ := p.loadExpr(args[0].Src)
  2259  			p.panicCodeErrorf(
  2260  				pos, "invalid operation: operator %s not defined on %s (%v)", opstr, arg0Src, arg0)
  2261  		}
  2262  	}
  2263  	ret.Src = expr
  2264  	p.stk.Ret(2, ret)
  2265  	return p
  2266  }
  2267  
  2268  func checkNamed(typ types.Type) (ret *types.Named, ok bool) {
  2269  	if t, ok := typ.(*types.Pointer); ok {
  2270  		typ = t.Elem()
  2271  	}
  2272  	ret, ok = typ.(*types.Named)
  2273  	return
  2274  }
  2275  
  2276  var (
  2277  	unaryOps = [...]string{
  2278  		token.SUB:   "Neg",
  2279  		token.ADD:   "Dup",
  2280  		token.XOR:   "Not",
  2281  		token.NOT:   "LNot",
  2282  		token.ARROW: "Recv",
  2283  		token.AND:   "Addr",
  2284  	}
  2285  	binaryOps = [...]string{
  2286  		token.ADD: "Add", // +
  2287  		token.SUB: "Sub", // -
  2288  		token.MUL: "Mul", // *
  2289  		token.QUO: "Quo", // /
  2290  		token.REM: "Rem", // %
  2291  
  2292  		token.AND:     "And",    // &
  2293  		token.OR:      "Or",     // |
  2294  		token.XOR:     "Xor",    // ^
  2295  		token.AND_NOT: "AndNot", // &^
  2296  		token.SHL:     "Lsh",    // <<
  2297  		token.SHR:     "Rsh",    // >>
  2298  
  2299  		token.LAND: "LAnd", // &&
  2300  		token.LOR:  "LOr",  // ||
  2301  
  2302  		token.LSS: "LT",
  2303  		token.LEQ: "LE",
  2304  		token.GTR: "GT",
  2305  		token.GEQ: "GE",
  2306  		token.EQL: "EQ",
  2307  		token.NEQ: "NE",
  2308  
  2309  		xtoken.SRARROW:   "PointTo", // ->
  2310  		xtoken.BIDIARROW: "PointBi", // <>
  2311  	}
  2312  )
  2313  
  2314  // CompareNil func
  2315  func (p *CodeBuilder) CompareNil(op token.Token, src ...ast.Node) *CodeBuilder {
  2316  	return p.Val(nil).BinaryOp(op)
  2317  }
  2318  
  2319  // Send func
  2320  func (p *CodeBuilder) Send() *CodeBuilder {
  2321  	if debugInstr {
  2322  		log.Println("Send")
  2323  	}
  2324  	val := p.stk.Pop()
  2325  	ch := p.stk.Pop()
  2326  	// TODO: check types
  2327  	p.emitStmt(&ast.SendStmt{Chan: ch.Val, Value: val.Val})
  2328  	return p
  2329  }
  2330  
  2331  // Defer func
  2332  func (p *CodeBuilder) Defer() *CodeBuilder {
  2333  	if debugInstr {
  2334  		log.Println("Defer")
  2335  	}
  2336  	arg := p.stk.Pop()
  2337  	call, ok := arg.Val.(*ast.CallExpr)
  2338  	if !ok {
  2339  		panic("TODO: please use defer callExpr()")
  2340  	}
  2341  	p.emitStmt(&ast.DeferStmt{Call: call})
  2342  	return p
  2343  }
  2344  
  2345  // Go func
  2346  func (p *CodeBuilder) Go() *CodeBuilder {
  2347  	if debugInstr {
  2348  		log.Println("Go")
  2349  	}
  2350  	arg := p.stk.Pop()
  2351  	call, ok := arg.Val.(*ast.CallExpr)
  2352  	if !ok {
  2353  		panic("TODO: please use go callExpr()")
  2354  	}
  2355  	p.emitStmt(&ast.GoStmt{Call: call})
  2356  	return p
  2357  }
  2358  
  2359  // Block starts a block statement.
  2360  func (p *CodeBuilder) Block(src ...ast.Node) *CodeBuilder {
  2361  	if debugInstr {
  2362  		log.Println("Block")
  2363  	}
  2364  	stmt := &blockStmt{}
  2365  	p.startBlockStmt(stmt, src, "block statement", &stmt.old)
  2366  	return p
  2367  }
  2368  
  2369  // VBlock starts a vblock statement.
  2370  func (p *CodeBuilder) VBlock() *CodeBuilder {
  2371  	if debugInstr {
  2372  		log.Println("VBlock")
  2373  	}
  2374  	stmt := &vblockStmt{}
  2375  	p.startVBlockStmt(stmt, "vblock statement", &stmt.old)
  2376  	return p
  2377  }
  2378  
  2379  // InVBlock checks if current statement is in vblock or not.
  2380  func (p *CodeBuilder) InVBlock() bool {
  2381  	_, ok := p.current.codeBlock.(*vblockStmt)
  2382  	return ok
  2383  }
  2384  
  2385  // Block starts a if statement.
  2386  func (p *CodeBuilder) If(src ...ast.Node) *CodeBuilder {
  2387  	if debugInstr {
  2388  		log.Println("If")
  2389  	}
  2390  	stmt := &ifStmt{}
  2391  	p.startBlockStmt(stmt, src, "if statement", &stmt.old)
  2392  	return p
  2393  }
  2394  
  2395  // Then starts body of a if/switch/for/case statement.
  2396  func (p *CodeBuilder) Then(src ...ast.Node) *CodeBuilder {
  2397  	if debugInstr {
  2398  		log.Println("Then")
  2399  	}
  2400  	if flow, ok := p.current.codeBlock.(controlFlow); ok {
  2401  		flow.Then(p, src...)
  2402  		return p
  2403  	}
  2404  	panic("use if..then or switch..then or for..then please")
  2405  }
  2406  
  2407  // Else starts else body of a if..else statement.
  2408  func (p *CodeBuilder) Else(src ...ast.Node) *CodeBuilder {
  2409  	if debugInstr {
  2410  		log.Println("Else")
  2411  	}
  2412  	if flow, ok := p.current.codeBlock.(*ifStmt); ok {
  2413  		flow.Else(p, src...)
  2414  		return p
  2415  	}
  2416  	panic("use if..else please")
  2417  }
  2418  
  2419  // TypeSwitch starts a type switch statement.
  2420  //
  2421  // <pre>
  2422  // typeSwitch(name) init; expr typeAssertThen
  2423  // type1, type2, ... typeN typeCase(N)
  2424  //
  2425  //	...
  2426  //	end
  2427  //
  2428  // type1, type2, ... typeM typeCase(M)
  2429  //
  2430  //	...
  2431  //	end
  2432  //
  2433  // end
  2434  // </pre>
  2435  func (p *CodeBuilder) TypeSwitch(name string, src ...ast.Node) *CodeBuilder {
  2436  	if debugInstr {
  2437  		log.Println("TypeSwitch")
  2438  	}
  2439  	stmt := &typeSwitchStmt{name: name}
  2440  	p.startBlockStmt(stmt, src, "type switch statement", &stmt.old)
  2441  	return p
  2442  }
  2443  
  2444  // TypeAssert func
  2445  func (p *CodeBuilder) TypeAssert(typ types.Type, twoValue bool, src ...ast.Node) *CodeBuilder {
  2446  	if debugInstr {
  2447  		log.Println("TypeAssert", typ, twoValue)
  2448  	}
  2449  	arg := p.stk.Get(-1)
  2450  	xType, ok := p.checkInterface(arg.Type)
  2451  	if !ok {
  2452  		text, pos := p.loadExpr(getSrc(src))
  2453  		p.panicCodeErrorf(
  2454  			pos, "invalid type assertion: %s (non-interface type %v on left)", text, arg.Type)
  2455  	}
  2456  	if missing := p.missingMethod(typ, xType); missing != "" {
  2457  		pos := getSrcPos(getSrc(src))
  2458  		p.panicCodeErrorf(
  2459  			pos, "impossible type assertion:\n\t%v does not implement %v (missing %s method)",
  2460  			typ, arg.Type, missing)
  2461  	}
  2462  	pkg := p.pkg
  2463  	ret := &ast.TypeAssertExpr{X: arg.Val, Type: toType(pkg, typ)}
  2464  	if twoValue {
  2465  		tyRet := types.NewTuple(
  2466  			pkg.NewParam(token.NoPos, "", typ),
  2467  			pkg.NewParam(token.NoPos, "", types.Typ[types.Bool]))
  2468  		p.stk.Ret(1, &internal.Elem{Type: tyRet, Val: ret})
  2469  	} else {
  2470  		p.stk.Ret(1, &internal.Elem{Type: typ, Val: ret})
  2471  	}
  2472  	return p
  2473  }
  2474  
  2475  func (p *CodeBuilder) missingMethod(T types.Type, V *types.Interface) (missing string) {
  2476  	p.ensureLoaded(T)
  2477  	if m, _ := types.MissingMethod(T, V, false); m != nil {
  2478  		missing = m.Name()
  2479  	}
  2480  	return
  2481  }
  2482  
  2483  func (p *CodeBuilder) checkInterface(typ types.Type) (*types.Interface, bool) {
  2484  retry:
  2485  	switch t := typ.(type) {
  2486  	case *types.Interface:
  2487  		return t, true
  2488  	case *types.Named:
  2489  		typ = p.getUnderlying(t)
  2490  		goto retry
  2491  	}
  2492  	return nil, false
  2493  }
  2494  
  2495  // TypeAssertThen starts body of a type switch statement.
  2496  func (p *CodeBuilder) TypeAssertThen() *CodeBuilder {
  2497  	if debugInstr {
  2498  		log.Println("TypeAssertThen")
  2499  	}
  2500  	if flow, ok := p.current.codeBlock.(*typeSwitchStmt); ok {
  2501  		flow.TypeAssertThen(p)
  2502  		return p
  2503  	}
  2504  	panic("use typeSwitch..typeAssertThen please")
  2505  }
  2506  
  2507  // TypeCase starts case body of a type switch statement.
  2508  func (p *CodeBuilder) TypeCase(src ...ast.Node) *CodeBuilder {
  2509  	if debugInstr {
  2510  		log.Println("TypeCase")
  2511  	}
  2512  	if flow, ok := p.current.codeBlock.(*typeSwitchStmt); ok {
  2513  		flow.TypeCase(p, src...)
  2514  		return p
  2515  	}
  2516  	panic("use switch x.(type) .. case please")
  2517  }
  2518  
  2519  // TypeDefaultThen starts default clause of a type switch statement.
  2520  func (p *CodeBuilder) TypeDefaultThen(src ...ast.Node) *CodeBuilder {
  2521  	return p.TypeCase(src...).Then(src...)
  2522  }
  2523  
  2524  // Select starts a select statement.
  2525  func (p *CodeBuilder) Select(src ...ast.Node) *CodeBuilder {
  2526  	if debugInstr {
  2527  		log.Println("Select")
  2528  	}
  2529  	stmt := &selectStmt{}
  2530  	p.startBlockStmt(stmt, src, "select statement", &stmt.old)
  2531  	return p
  2532  }
  2533  
  2534  // CommCase starts case clause of a select statement.
  2535  func (p *CodeBuilder) CommCase(src ...ast.Node) *CodeBuilder {
  2536  	if debugInstr {
  2537  		log.Println("CommCase")
  2538  	}
  2539  	if flow, ok := p.current.codeBlock.(*selectStmt); ok {
  2540  		flow.CommCase(p, src...)
  2541  		return p
  2542  	}
  2543  	panic("use select..case please")
  2544  }
  2545  
  2546  // CommDefaultThen starts default clause of a select statement.
  2547  func (p *CodeBuilder) CommDefaultThen(src ...ast.Node) *CodeBuilder {
  2548  	return p.CommCase(src...).Then(src...)
  2549  }
  2550  
  2551  // Switch starts a switch statement.
  2552  func (p *CodeBuilder) Switch(src ...ast.Node) *CodeBuilder {
  2553  	if debugInstr {
  2554  		log.Println("Switch")
  2555  	}
  2556  	stmt := &switchStmt{}
  2557  	p.startBlockStmt(stmt, src, "switch statement", &stmt.old)
  2558  	return p
  2559  }
  2560  
  2561  // Case starts case clause of a switch statement.
  2562  func (p *CodeBuilder) Case(src ...ast.Node) *CodeBuilder {
  2563  	if debugInstr {
  2564  		log.Println("Case")
  2565  	}
  2566  	if flow, ok := p.current.codeBlock.(*switchStmt); ok {
  2567  		flow.Case(p, src...)
  2568  		return p
  2569  	}
  2570  	panic("use switch..case please")
  2571  }
  2572  
  2573  // DefaultThen starts default clause of a switch statement.
  2574  func (p *CodeBuilder) DefaultThen(src ...ast.Node) *CodeBuilder {
  2575  	return p.Case(src...).Then(src...)
  2576  }
  2577  
  2578  func (p *CodeBuilder) NewLabel(pos token.Pos, name string) *Label {
  2579  	if p.current.fn == nil {
  2580  		panic(p.newCodeError(pos, "syntax error: non-declaration statement outside function body"))
  2581  	}
  2582  	if old, ok := p.current.labels[name]; ok {
  2583  		oldPos := p.fset.Position(old.Pos())
  2584  		p.handleCodeErrorf(pos, "label %s already defined at %v", name, oldPos)
  2585  		return nil
  2586  	}
  2587  	if p.current.labels == nil {
  2588  		p.current.labels = make(map[string]*Label)
  2589  	}
  2590  	l := &Label{Label: *types.NewLabel(pos, p.pkg.Types, name)}
  2591  	p.current.labels[name] = l
  2592  	return l
  2593  }
  2594  
  2595  // LookupLabel func
  2596  func (p *CodeBuilder) LookupLabel(name string) (l *Label, ok bool) {
  2597  	l, ok = p.current.labels[name]
  2598  	return
  2599  }
  2600  
  2601  // Label func
  2602  func (p *CodeBuilder) Label(l *Label) *CodeBuilder {
  2603  	name := l.Name()
  2604  	if debugInstr {
  2605  		log.Println("Label", name)
  2606  	}
  2607  	if p.current.label != nil {
  2608  		p.current.label.Stmt = &ast.EmptyStmt{}
  2609  		p.current.stmts = append(p.current.stmts, p.current.label)
  2610  	}
  2611  	p.current.label = &ast.LabeledStmt{Label: ident(name)}
  2612  	return p
  2613  }
  2614  
  2615  // Goto func
  2616  func (p *CodeBuilder) Goto(l *Label) *CodeBuilder {
  2617  	name := l.Name()
  2618  	if debugInstr {
  2619  		log.Println("Goto", name)
  2620  	}
  2621  	l.used = true
  2622  	p.current.flows |= flowFlagGoto
  2623  	p.emitStmt(&ast.BranchStmt{Tok: token.GOTO, Label: ident(name)})
  2624  	return p
  2625  }
  2626  
  2627  func (p *CodeBuilder) labelFlow(flow int, l *Label) (string, *ast.Ident) {
  2628  	if l != nil {
  2629  		l.used = true
  2630  		p.current.flows |= (flow | flowFlagWithLabel)
  2631  		return l.Name(), ident(l.Name())
  2632  	}
  2633  	p.current.flows |= flow
  2634  	return "", nil
  2635  }
  2636  
  2637  // Break func
  2638  func (p *CodeBuilder) Break(l *Label) *CodeBuilder {
  2639  	name, label := p.labelFlow(flowFlagBreak, l)
  2640  	if debugInstr {
  2641  		log.Println("Break", name)
  2642  	}
  2643  	p.emitStmt(&ast.BranchStmt{Tok: token.BREAK, Label: label})
  2644  	return p
  2645  }
  2646  
  2647  // Continue func
  2648  func (p *CodeBuilder) Continue(l *Label) *CodeBuilder {
  2649  	name, label := p.labelFlow(flowFlagContinue, l)
  2650  	if debugInstr {
  2651  		log.Println("Continue", name)
  2652  	}
  2653  	p.emitStmt(&ast.BranchStmt{Tok: token.CONTINUE, Label: label})
  2654  	return p
  2655  }
  2656  
  2657  // Fallthrough func
  2658  func (p *CodeBuilder) Fallthrough() *CodeBuilder {
  2659  	if debugInstr {
  2660  		log.Println("Fallthrough")
  2661  	}
  2662  	if flow, ok := p.current.codeBlock.(*caseStmt); ok {
  2663  		flow.Fallthrough(p)
  2664  		return p
  2665  	}
  2666  	panic("please use fallthrough in case statement")
  2667  }
  2668  
  2669  // For func
  2670  func (p *CodeBuilder) For(src ...ast.Node) *CodeBuilder {
  2671  	if debugInstr {
  2672  		log.Println("For")
  2673  	}
  2674  	stmt := &forStmt{}
  2675  	p.startBlockStmt(stmt, src, "for statement", &stmt.old)
  2676  	return p
  2677  }
  2678  
  2679  // Post func
  2680  func (p *CodeBuilder) Post() *CodeBuilder {
  2681  	if debugInstr {
  2682  		log.Println("Post")
  2683  	}
  2684  	if flow, ok := p.current.codeBlock.(*forStmt); ok {
  2685  		flow.Post(p)
  2686  		return p
  2687  	}
  2688  	panic("please use Post() in for statement")
  2689  }
  2690  
  2691  // ForRange func
  2692  func (p *CodeBuilder) ForRange(names ...string) *CodeBuilder {
  2693  	return p.ForRangeEx(names)
  2694  }
  2695  
  2696  // ForRangeEx func
  2697  func (p *CodeBuilder) ForRangeEx(names []string, src ...ast.Node) *CodeBuilder {
  2698  	if debugInstr {
  2699  		log.Println("ForRange", names)
  2700  	}
  2701  	stmt := &forRangeStmt{names: names}
  2702  	p.startBlockStmt(stmt, src, "for range statement", &stmt.old)
  2703  	return p
  2704  }
  2705  
  2706  // RangeAssignThen func
  2707  func (p *CodeBuilder) RangeAssignThen(pos token.Pos) *CodeBuilder {
  2708  	if debugInstr {
  2709  		log.Println("RangeAssignThen")
  2710  	}
  2711  	if flow, ok := p.current.codeBlock.(*forRangeStmt); ok {
  2712  		flow.RangeAssignThen(p, pos)
  2713  		return p
  2714  	}
  2715  	panic("please use RangeAssignThen() in for range statement")
  2716  }
  2717  
  2718  // ResetStmt resets the statement state of CodeBuilder.
  2719  func (p *CodeBuilder) ResetStmt() {
  2720  	if debugInstr {
  2721  		log.Println("ResetStmt")
  2722  	}
  2723  	p.stk.SetLen(p.current.base)
  2724  }
  2725  
  2726  // EndStmt func
  2727  func (p *CodeBuilder) EndStmt() *CodeBuilder {
  2728  	n := p.stk.Len() - p.current.base
  2729  	if n > 0 {
  2730  		if n != 1 {
  2731  			panic("syntax error: unexpected newline, expecting := or = or comma")
  2732  		}
  2733  		if e := p.stk.Pop(); p.noSkipConst || e.CVal == nil { // skip constant
  2734  			p.emitStmt(&ast.ExprStmt{X: e.Val})
  2735  		}
  2736  	}
  2737  	return p
  2738  }
  2739  
  2740  // End func
  2741  func (p *CodeBuilder) End(src ...ast.Node) *CodeBuilder {
  2742  	if debugInstr {
  2743  		typ := reflect.TypeOf(p.current.codeBlock)
  2744  		if typ.Kind() == reflect.Ptr {
  2745  			typ = typ.Elem()
  2746  		}
  2747  		name := strings.TrimSuffix(strings.Title(typ.Name()), "Stmt")
  2748  		log.Println("End //", name)
  2749  		if p.stk.Len() > p.current.base {
  2750  			panic("forget to call EndStmt()?")
  2751  		}
  2752  	}
  2753  	p.current.End(p, getSrc(src))
  2754  	return p
  2755  }
  2756  
  2757  func (p *CodeBuilder) SetBodyHandler(handle func(body *ast.BlockStmt, kind int)) *CodeBuilder {
  2758  	if ini, ok := p.current.codeBlock.(interface {
  2759  		SetBodyHandler(func(body *ast.BlockStmt, kind int))
  2760  	}); ok {
  2761  		ini.SetBodyHandler(handle)
  2762  	}
  2763  	return p
  2764  }
  2765  
  2766  // ResetInit resets the variable init state of CodeBuilder.
  2767  func (p *CodeBuilder) ResetInit() {
  2768  	if debugInstr {
  2769  		log.Println("ResetInit")
  2770  	}
  2771  	p.valDecl = p.valDecl.resetInit(p)
  2772  }
  2773  
  2774  // EndInit func
  2775  func (p *CodeBuilder) EndInit(n int) *CodeBuilder {
  2776  	if debugInstr {
  2777  		log.Println("EndInit", n)
  2778  	}
  2779  	p.valDecl = p.valDecl.endInit(p, n)
  2780  	return p
  2781  }
  2782  
  2783  // Debug func
  2784  func (p *CodeBuilder) Debug(dbg func(cb *CodeBuilder)) *CodeBuilder {
  2785  	dbg(p)
  2786  	return p
  2787  }
  2788  
  2789  // Get func
  2790  func (p *CodeBuilder) Get(idx int) *Element {
  2791  	return p.stk.Get(idx)
  2792  }
  2793  
  2794  // ----------------------------------------------------------------------------
  2795  
  2796  type InternalStack = internal.Stack
  2797  
  2798  // InternalStack: don't call it (only for internal use)
  2799  func (p *CodeBuilder) InternalStack() *InternalStack {
  2800  	return &p.stk
  2801  }
  2802  
  2803  // ----------------------------------------------------------------------------