github.com/HaHadaxigua/yaegi@v1.0.1/interp/cfg.go (about)

     1  package interp
     2  
     3  import (
     4  	"fmt"
     5  	"go/constant"
     6  	"log"
     7  	"math"
     8  	"path/filepath"
     9  	"reflect"
    10  	"strings"
    11  	"unicode"
    12  )
    13  
    14  // A cfgError represents an error during CFG build stage.
    15  type cfgError struct {
    16  	*node
    17  	error
    18  }
    19  
    20  func (c *cfgError) Error() string { return c.error.Error() }
    21  
    22  var constOp = map[action]func(*node){
    23  	aAdd:    addConst,
    24  	aSub:    subConst,
    25  	aMul:    mulConst,
    26  	aQuo:    quoConst,
    27  	aRem:    remConst,
    28  	aAnd:    andConst,
    29  	aOr:     orConst,
    30  	aShl:    shlConst,
    31  	aShr:    shrConst,
    32  	aAndNot: andNotConst,
    33  	aXor:    xorConst,
    34  	aNot:    notConst,
    35  	aBitNot: bitNotConst,
    36  	aNeg:    negConst,
    37  	aPos:    posConst,
    38  }
    39  
    40  var constBltn = map[string]func(*node){
    41  	bltnComplex: complexConst,
    42  	bltnImag:    imagConst,
    43  	bltnReal:    realConst,
    44  }
    45  
    46  const nilIdent = "nil"
    47  
    48  // cfg generates a control flow graph (CFG) from AST (wiring successors in AST)
    49  // and pre-compute frame sizes and indexes for all un-named (temporary) and named
    50  // variables. A list of nodes of init functions is returned.
    51  // Following this pass, the CFG is ready to run.
    52  func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string) ([]*node, error) {
    53  	if sc == nil {
    54  		sc = interp.initScopePkg(importPath, pkgName)
    55  	}
    56  	check := typecheck{scope: sc}
    57  	var initNodes []*node
    58  	var err error
    59  
    60  	baseName := filepath.Base(interp.fset.Position(root.pos).Filename)
    61  
    62  	root.Walk(func(n *node) bool {
    63  		// Pre-order processing
    64  		if err != nil {
    65  			return false
    66  		}
    67  		if n.scope == nil {
    68  			n.scope = sc
    69  		}
    70  		switch n.kind {
    71  		case binaryExpr, unaryExpr, parenExpr:
    72  			if isBoolAction(n) {
    73  				break
    74  			}
    75  			// Gather assigned type if set, to give context for type propagation at post-order.
    76  			switch n.anc.kind {
    77  			case assignStmt, defineStmt:
    78  				a := n.anc
    79  				i := childPos(n) - a.nright
    80  				if i < 0 {
    81  					break
    82  				}
    83  				if len(a.child) > a.nright+a.nleft {
    84  					i--
    85  				}
    86  				dest := a.child[i]
    87  				if dest.typ == nil {
    88  					break
    89  				}
    90  				if dest.typ.incomplete {
    91  					err = n.cfgErrorf("invalid type declaration")
    92  					return false
    93  				}
    94  				if !isInterface(dest.typ) {
    95  					// Interface type are not propagated, and will be resolved at post-order.
    96  					n.typ = dest.typ
    97  				}
    98  			case binaryExpr, unaryExpr, parenExpr:
    99  				n.typ = n.anc.typ
   100  			}
   101  
   102  		case defineStmt:
   103  			// Determine type of variables initialized at declaration, so it can be propagated.
   104  			if n.nleft+n.nright == len(n.child) {
   105  				// No type was specified on the left hand side, it will resolved at post-order.
   106  				break
   107  			}
   108  			n.typ, err = nodeType(interp, sc, n.child[n.nleft])
   109  			if err != nil {
   110  				break
   111  			}
   112  			for i := 0; i < n.nleft; i++ {
   113  				n.child[i].typ = n.typ
   114  			}
   115  
   116  		case blockStmt:
   117  			if n.anc != nil && n.anc.kind == rangeStmt {
   118  				// For range block: ensure that array or map type is propagated to iterators
   119  				// prior to process block. We cannot perform this at RangeStmt pre-order because
   120  				// type of array like value is not yet known. This could be fixed in ast structure
   121  				// by setting array/map node as 1st child of ForRangeStmt instead of 3rd child of
   122  				// RangeStmt. The following workaround is less elegant but ok.
   123  				c := n.anc.child[1]
   124  				if c != nil && c.typ != nil && isSendChan(c.typ) {
   125  					err = c.cfgErrorf("invalid operation: range %s receive from send-only channel", c.ident)
   126  					return false
   127  				}
   128  
   129  				if t := sc.rangeChanType(n.anc); t != nil {
   130  					// range over channel
   131  					e := n.anc.child[0]
   132  					index := sc.add(t.val)
   133  					sc.sym[e.ident] = &symbol{index: index, kind: varSym, typ: t.val}
   134  					e.typ = t.val
   135  					e.findex = index
   136  					n.anc.gen = rangeChan
   137  				} else {
   138  					// range over array or map
   139  					var ktyp, vtyp *itype
   140  					var k, v, o *node
   141  					if len(n.anc.child) == 4 {
   142  						k, v, o = n.anc.child[0], n.anc.child[1], n.anc.child[2]
   143  					} else {
   144  						k, o = n.anc.child[0], n.anc.child[1]
   145  					}
   146  
   147  					switch o.typ.cat {
   148  					case valueT:
   149  						typ := o.typ.rtype
   150  						switch typ.Kind() {
   151  						case reflect.Map:
   152  							n.anc.gen = rangeMap
   153  							ityp := valueTOf(reflect.TypeOf((*reflect.MapIter)(nil)))
   154  							sc.add(ityp)
   155  							ktyp = valueTOf(typ.Key())
   156  							vtyp = valueTOf(typ.Elem())
   157  						case reflect.String:
   158  							sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
   159  							sc.add(sc.getType("int")) // Add a dummy type to store index for range
   160  							ktyp = sc.getType("int")
   161  							vtyp = sc.getType("rune")
   162  						case reflect.Array, reflect.Slice:
   163  							sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
   164  							ktyp = sc.getType("int")
   165  							vtyp = valueTOf(typ.Elem())
   166  						}
   167  					case mapT:
   168  						n.anc.gen = rangeMap
   169  						ityp := valueTOf(reflect.TypeOf((*reflect.MapIter)(nil)))
   170  						sc.add(ityp)
   171  						ktyp = o.typ.key
   172  						vtyp = o.typ.val
   173  					case ptrT:
   174  						ktyp = sc.getType("int")
   175  						vtyp = o.typ.val
   176  						if vtyp.cat == valueT {
   177  							vtyp = valueTOf(vtyp.rtype.Elem())
   178  						} else {
   179  							vtyp = vtyp.val
   180  						}
   181  					case stringT:
   182  						sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
   183  						sc.add(sc.getType("int")) // Add a dummy type to store index for range
   184  						ktyp = sc.getType("int")
   185  						vtyp = sc.getType("rune")
   186  					case arrayT, sliceT, variadicT:
   187  						sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
   188  						ktyp = sc.getType("int")
   189  						vtyp = o.typ.val
   190  					}
   191  
   192  					kindex := sc.add(ktyp)
   193  					sc.sym[k.ident] = &symbol{index: kindex, kind: varSym, typ: ktyp}
   194  					k.typ = ktyp
   195  					k.findex = kindex
   196  
   197  					if v != nil {
   198  						vindex := sc.add(vtyp)
   199  						sc.sym[v.ident] = &symbol{index: vindex, kind: varSym, typ: vtyp}
   200  						v.typ = vtyp
   201  						v.findex = vindex
   202  					}
   203  				}
   204  			}
   205  
   206  			n.findex = -1
   207  			n.val = nil
   208  			sc = sc.pushBloc()
   209  			// Pre-define symbols for labels defined in this block, so we are sure that
   210  			// they are already defined when met.
   211  			// TODO(marc): labels must be stored outside of symbols to avoid collisions.
   212  			for _, c := range n.child {
   213  				if c.kind != labeledStmt {
   214  					continue
   215  				}
   216  				label := c.child[0].ident
   217  				sym := &symbol{kind: labelSym, node: c, index: -1}
   218  				sc.sym[label] = sym
   219  				c.sym = sym
   220  			}
   221  
   222  		case breakStmt, continueStmt, gotoStmt:
   223  			if len(n.child) == 0 {
   224  				break
   225  			}
   226  			// Handle labeled statements.
   227  			label := n.child[0].ident
   228  			if sym, _, ok := sc.lookup(label); ok {
   229  				if sym.kind != labelSym {
   230  					err = n.child[0].cfgErrorf("label %s not defined", label)
   231  					break
   232  				}
   233  				n.sym = sym
   234  			} else {
   235  				n.sym = &symbol{kind: labelSym, index: -1}
   236  				sc.sym[label] = n.sym
   237  			}
   238  			if n.kind == gotoStmt {
   239  				n.sym.from = append(n.sym.from, n) // To allow forward goto statements.
   240  			}
   241  
   242  		case caseClause:
   243  			sc = sc.pushBloc()
   244  			if sn := n.anc.anc; sn.kind == typeSwitch && sn.child[1].action == aAssign {
   245  				// Type switch clause with a var defined in switch guard.
   246  				var typ *itype
   247  				if len(n.child) == 2 {
   248  					// 1 type in clause: define the var with this type in the case clause scope.
   249  					switch {
   250  					case n.child[0].ident == nilIdent:
   251  						typ = sc.getType("interface{}")
   252  					case !n.child[0].isType(sc):
   253  						err = n.cfgErrorf("%s is not a type", n.child[0].ident)
   254  					default:
   255  						typ, err = nodeType(interp, sc, n.child[0])
   256  					}
   257  				} else {
   258  					// Define the var with the type in the switch guard expression.
   259  					typ = sn.child[1].child[1].child[0].typ
   260  				}
   261  				if err != nil {
   262  					return false
   263  				}
   264  				nod := n.lastChild().child[0]
   265  				index := sc.add(typ)
   266  				sc.sym[nod.ident] = &symbol{index: index, kind: varSym, typ: typ}
   267  				nod.findex = index
   268  				nod.typ = typ
   269  			}
   270  
   271  		case commClauseDefault:
   272  			sc = sc.pushBloc()
   273  
   274  		case commClause:
   275  			sc = sc.pushBloc()
   276  			if len(n.child) > 0 && n.child[0].action == aAssign {
   277  				ch := n.child[0].child[1].child[0]
   278  				var typ *itype
   279  				if typ, err = nodeType(interp, sc, ch); err != nil {
   280  					return false
   281  				}
   282  				if !isChan(typ) {
   283  					err = n.cfgErrorf("invalid operation: receive from non-chan type")
   284  					return false
   285  				}
   286  				elem := chanElement(typ)
   287  				assigned := n.child[0].child[0]
   288  				index := sc.add(elem)
   289  				sc.sym[assigned.ident] = &symbol{index: index, kind: varSym, typ: elem}
   290  				assigned.findex = index
   291  				assigned.typ = elem
   292  			}
   293  
   294  		case compositeLitExpr:
   295  			if len(n.child) > 0 && n.child[0].isType(sc) {
   296  				// Get type from 1st child.
   297  				if n.typ, err = nodeType(interp, sc, n.child[0]); err != nil {
   298  					return false
   299  				}
   300  				// Indicate that the first child is the type.
   301  				n.nleft = 1
   302  			} else {
   303  				// Get type from ancestor (implicit type)
   304  				if n.anc.kind == keyValueExpr && n == n.anc.child[0] {
   305  					n.typ = n.anc.typ.key
   306  				} else if atyp := n.anc.typ; atyp != nil {
   307  					if atyp.cat == valueT && hasElem(atyp.rtype) {
   308  						n.typ = valueTOf(atyp.rtype.Elem())
   309  					} else {
   310  						n.typ = atyp.val
   311  					}
   312  				}
   313  				if n.typ == nil {
   314  					err = n.cfgErrorf("undefined type")
   315  					return false
   316  				}
   317  			}
   318  
   319  			child := n.child
   320  			if n.nleft > 0 {
   321  				n.child[0].typ = n.typ
   322  				child = n.child[1:]
   323  			}
   324  			// Propagate type to children, to handle implicit types
   325  			for _, c := range child {
   326  				if isBlank(c) {
   327  					err = n.cfgErrorf("cannot use _ as value")
   328  					return false
   329  				}
   330  				switch c.kind {
   331  				case binaryExpr, unaryExpr, compositeLitExpr:
   332  					// Do not attempt to propagate composite type to operator expressions,
   333  					// it breaks constant folding.
   334  				case keyValueExpr, typeAssertExpr, indexExpr:
   335  					c.typ = n.typ
   336  				default:
   337  					if c.ident == nilIdent {
   338  						c.typ = sc.getType(nilIdent)
   339  						continue
   340  					}
   341  					if c.typ, err = nodeType(interp, sc, c); err != nil {
   342  						return false
   343  					}
   344  				}
   345  			}
   346  
   347  		case forStmt0, forStmt1, forStmt2, forStmt3, forStmt4, forStmt5, forStmt6, forStmt7, forRangeStmt:
   348  			sc = sc.pushBloc()
   349  			sc.loop, sc.loopRestart = n, n.lastChild()
   350  
   351  		case funcLit:
   352  			n.typ = nil // to force nodeType to recompute the type
   353  			if n.typ, err = nodeType(interp, sc, n); err != nil {
   354  				return false
   355  			}
   356  			n.findex = sc.add(n.typ)
   357  			fallthrough
   358  
   359  		case funcDecl:
   360  			n.val = n
   361  			// Compute function type before entering local scope to avoid
   362  			// possible collisions with function argument names.
   363  			n.child[2].typ, err = nodeType(interp, sc, n.child[2])
   364  			// Add a frame indirection level as we enter in a func
   365  			sc = sc.pushFunc()
   366  			sc.def = n
   367  			if len(n.child[2].child) == 2 {
   368  				// Allocate frame space for return values, define output symbols
   369  				for _, c := range n.child[2].child[1].child {
   370  					var typ *itype
   371  					if typ, err = nodeType(interp, sc, c.lastChild()); err != nil {
   372  						return false
   373  					}
   374  					if len(c.child) > 1 {
   375  						for _, cc := range c.child[:len(c.child)-1] {
   376  							sc.sym[cc.ident] = &symbol{index: sc.add(typ), kind: varSym, typ: typ}
   377  						}
   378  					} else {
   379  						sc.add(typ)
   380  					}
   381  				}
   382  			}
   383  			if len(n.child[0].child) > 0 {
   384  				// define receiver symbol
   385  				var typ *itype
   386  				fr := n.child[0].child[0]
   387  				recvTypeNode := fr.lastChild()
   388  				if typ, err = nodeType(interp, sc, recvTypeNode); err != nil {
   389  					return false
   390  				}
   391  				recvTypeNode.typ = typ
   392  				n.child[2].typ.recv = typ
   393  				n.typ.recv = typ
   394  				index := sc.add(typ)
   395  				if len(fr.child) > 1 {
   396  					sc.sym[fr.child[0].ident] = &symbol{index: index, kind: varSym, typ: typ}
   397  				}
   398  			}
   399  			for _, c := range n.child[2].child[0].child {
   400  				// define input parameter symbols
   401  				var typ *itype
   402  				if typ, err = nodeType(interp, sc, c.lastChild()); err != nil {
   403  					return false
   404  				}
   405  				for _, cc := range c.child[:len(c.child)-1] {
   406  					sc.sym[cc.ident] = &symbol{index: sc.add(typ), kind: varSym, typ: typ}
   407  				}
   408  			}
   409  			if n.child[1].ident == "init" && len(n.child[0].child) == 0 {
   410  				initNodes = append(initNodes, n)
   411  			}
   412  
   413  		case ifStmt0, ifStmt1, ifStmt2, ifStmt3:
   414  			sc = sc.pushBloc()
   415  
   416  		case switchStmt, switchIfStmt, typeSwitch:
   417  			// Make sure default clause is in last position.
   418  			c := n.lastChild().child
   419  			if i, l := getDefault(n), len(c)-1; i >= 0 && i != l {
   420  				c[i], c[l] = c[l], c[i]
   421  			}
   422  			sc = sc.pushBloc()
   423  			sc.loop = n
   424  
   425  		case importSpec:
   426  			// Already all done in GTA.
   427  			return false
   428  
   429  		case typeSpec:
   430  			// Processing already done in GTA pass for global types, only parses inlined types.
   431  			if sc.def == nil {
   432  				return false
   433  			}
   434  			typeName := n.child[0].ident
   435  			var typ *itype
   436  			if typ, err = nodeType(interp, sc, n.child[1]); err != nil {
   437  				return false
   438  			}
   439  			if typ.incomplete {
   440  				// Type may still be incomplete in case of a local recursive struct declaration.
   441  				if typ, err = typ.finalize(); err != nil {
   442  					err = n.cfgErrorf("invalid type declaration")
   443  					return false
   444  				}
   445  			}
   446  
   447  			switch n.child[1].kind {
   448  			case identExpr, selectorExpr:
   449  				n.typ = namedOf(typ, pkgName, typeName)
   450  			default:
   451  				n.typ = typ
   452  				n.typ.name = typeName
   453  			}
   454  			sc.sym[typeName] = &symbol{kind: typeSym, typ: n.typ}
   455  			return false
   456  
   457  		case constDecl:
   458  			// Early parse of constDecl subtrees, to compute all constant
   459  			// values which may be used in further declarations.
   460  			if !sc.global {
   461  				for _, c := range n.child {
   462  					if _, err = interp.cfg(c, sc, importPath, pkgName); err != nil {
   463  						// No error processing here, to allow recovery in subtree nodes.
   464  						err = nil
   465  					}
   466  				}
   467  			}
   468  
   469  		case arrayType, basicLit, chanType, chanTypeRecv, chanTypeSend, funcType, interfaceType, mapType, structType:
   470  			n.typ, err = nodeType(interp, sc, n)
   471  			return false
   472  		}
   473  		return true
   474  	}, func(n *node) {
   475  		// Post-order processing
   476  		if err != nil {
   477  			return
   478  		}
   479  
   480  		defer func() {
   481  			if r := recover(); r != nil {
   482  				// Display the exact location in input source which triggered the panic
   483  				panic(n.cfgErrorf("CFG post-order panic: %v", r))
   484  			}
   485  		}()
   486  
   487  		switch n.kind {
   488  		case addressExpr:
   489  			if isBlank(n.child[0]) {
   490  				err = n.cfgErrorf("cannot use _ as value")
   491  				break
   492  			}
   493  			wireChild(n)
   494  
   495  			err = check.addressExpr(n)
   496  			if err != nil {
   497  				break
   498  			}
   499  
   500  			n.typ = ptrOf(n.child[0].typ)
   501  			n.findex = sc.add(n.typ)
   502  
   503  		case assignStmt, defineStmt:
   504  			if n.anc.kind == typeSwitch && n.anc.child[1] == n {
   505  				// type switch guard assignment: assign dest to concrete value of src
   506  				n.gen = nop
   507  				break
   508  			}
   509  
   510  			var atyp *itype
   511  			if n.nleft+n.nright < len(n.child) {
   512  				if atyp, err = nodeType(interp, sc, n.child[n.nleft]); err != nil {
   513  					break
   514  				}
   515  			}
   516  
   517  			var sbase int
   518  			if n.nright > 0 {
   519  				sbase = len(n.child) - n.nright
   520  			}
   521  
   522  			wireChild(n)
   523  			for i := 0; i < n.nleft; i++ {
   524  				dest, src := n.child[i], n.child[sbase+i]
   525  				updateSym := false
   526  				var sym *symbol
   527  				var level int
   528  
   529  				if isBlank(src) {
   530  					err = n.cfgErrorf("cannot use _ as value")
   531  					break
   532  				}
   533  				if n.kind == defineStmt || (n.kind == assignStmt && dest.ident == "_") {
   534  					if atyp != nil {
   535  						dest.typ = atyp
   536  					} else {
   537  						if src.typ, err = nodeType(interp, sc, src); err != nil {
   538  							return
   539  						}
   540  						if src.typ.isBinMethod {
   541  							dest.typ = valueTOf(src.typ.methodCallType())
   542  						} else {
   543  							// In a new definition, propagate the source type to the destination
   544  							// type. If the source is an untyped constant, make sure that the
   545  							// type matches a default type.
   546  							dest.typ = sc.fixType(src.typ)
   547  						}
   548  					}
   549  					if dest.typ.incomplete {
   550  						return
   551  					}
   552  					if sc.global {
   553  						// Do not overload existing symbols (defined in GTA) in global scope
   554  						sym, _, _ = sc.lookup(dest.ident)
   555  					}
   556  					if sym == nil {
   557  						sym = &symbol{index: sc.add(dest.typ), kind: varSym, typ: dest.typ}
   558  						sc.sym[dest.ident] = sym
   559  					}
   560  					dest.val = src.val
   561  					dest.recv = src.recv
   562  					dest.findex = sym.index
   563  					updateSym = true
   564  				} else {
   565  					sym, level, _ = sc.lookup(dest.ident)
   566  				}
   567  
   568  				err = check.assignExpr(n, dest, src)
   569  				if err != nil {
   570  					break
   571  				}
   572  
   573  				if updateSym {
   574  					sym.typ = dest.typ
   575  					sym.rval = src.rval
   576  					// As we are updating the sym type, we need to update the sc.type
   577  					// when the sym has an index.
   578  					if sym.index >= 0 {
   579  						sc.types[sym.index] = sym.typ.frameType()
   580  					}
   581  				}
   582  				n.findex = dest.findex
   583  				n.level = dest.level
   584  
   585  				// In the following, we attempt to optimize by skipping the assign
   586  				// operation and setting the source location directly to the destination
   587  				// location in the frame.
   588  				//
   589  				switch {
   590  				case n.action != aAssign:
   591  					// Do not skip assign operation if it is combined with another operator.
   592  				case src.rval.IsValid():
   593  					// Do not skip assign operation if setting from a constant value.
   594  				case isMapEntry(dest):
   595  					// Setting a map entry requires an additional step, do not optimize.
   596  					// As we only write, skip the default useless getIndexMap dest action.
   597  					dest.gen = nop
   598  				case isFuncField(dest):
   599  					// Setting a struct field of function type requires an extra step. Do not optimize.
   600  				case isCall(src) && !isInterfaceSrc(dest.typ) && n.kind != defineStmt:
   601  					// Call action may perform the assignment directly.
   602  					if dest.typ.id() != src.typ.id() {
   603  						// Skip optimitization if returned type doesn't match assigned one.
   604  						break
   605  					}
   606  					n.gen = nop
   607  					src.level = level
   608  					src.findex = dest.findex
   609  					if src.typ.untyped && !dest.typ.untyped {
   610  						src.typ = dest.typ
   611  					}
   612  				case src.action == aRecv:
   613  					// Assign by reading from a receiving channel.
   614  					n.gen = nop
   615  					src.findex = dest.findex // Set recv address to LHS.
   616  					dest.typ = src.typ
   617  				case src.action == aCompositeLit:
   618  					if dest.typ.cat == valueT && dest.typ.rtype.Kind() == reflect.Interface {
   619  						// Skip optimisation for assigned interface.
   620  						break
   621  					}
   622  					if dest.action == aGetIndex || dest.action == aStar {
   623  						// Skip optimization, as it does not work when assigning to a struct field or a dereferenced pointer.
   624  						break
   625  					}
   626  					n.gen = nop
   627  					src.findex = dest.findex
   628  					src.level = level
   629  				case len(n.child) < 4 && isArithmeticAction(src):
   630  					// Optimize single assignments from some arithmetic operations.
   631  					src.typ = dest.typ
   632  					src.findex = dest.findex
   633  					src.level = level
   634  					n.gen = nop
   635  				case src.kind == basicLit:
   636  					// Assign to nil.
   637  					src.rval = reflect.New(dest.typ.TypeOf()).Elem()
   638  				case n.nright == 0:
   639  					n.gen = reset
   640  				}
   641  
   642  				n.typ = dest.typ
   643  				if sym != nil {
   644  					sym.typ = n.typ
   645  					sym.recv = src.recv
   646  				}
   647  
   648  				n.level = level
   649  
   650  				if n.anc.kind == constDecl {
   651  					n.gen = nop
   652  					n.findex = notInFrame
   653  					if sym, _, ok := sc.lookup(dest.ident); ok {
   654  						sym.kind = constSym
   655  					}
   656  					if childPos(n) == len(n.anc.child)-1 {
   657  						sc.iota = 0
   658  					} else {
   659  						sc.iota++
   660  					}
   661  				}
   662  			}
   663  
   664  		case incDecStmt:
   665  			err = check.unaryExpr(n)
   666  			if err != nil {
   667  				break
   668  			}
   669  			wireChild(n)
   670  			n.findex = n.child[0].findex
   671  			n.level = n.child[0].level
   672  			n.typ = n.child[0].typ
   673  			if sym, level, ok := sc.lookup(n.child[0].ident); ok {
   674  				sym.typ = n.typ
   675  				n.level = level
   676  			}
   677  
   678  		case assignXStmt:
   679  			wireChild(n)
   680  			l := len(n.child) - 1
   681  			switch lc := n.child[l]; lc.kind {
   682  			case callExpr:
   683  				if n.child[l-1].isType(sc) {
   684  					l--
   685  				}
   686  				if r := lc.child[0].typ.numOut(); r != l {
   687  					err = n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, lc.child[0].name(), r)
   688  				}
   689  				if isBinCall(lc, sc) {
   690  					n.gen = nop
   691  				} else {
   692  					// TODO (marc): skip if no conversion or wrapping is needed.
   693  					n.gen = assignFromCall
   694  				}
   695  			case indexExpr:
   696  				lc.gen = getIndexMap2
   697  				n.gen = nop
   698  			case typeAssertExpr:
   699  				if n.child[0].ident == "_" {
   700  					lc.gen = typeAssertStatus
   701  				} else {
   702  					lc.gen = typeAssertLong
   703  				}
   704  				n.gen = nop
   705  			case unaryExpr:
   706  				if lc.action == aRecv {
   707  					lc.gen = recv2
   708  					n.gen = nop
   709  				}
   710  			}
   711  
   712  		case defineXStmt:
   713  			wireChild(n)
   714  			if sc.def == nil {
   715  				// In global scope, type definition already handled by GTA.
   716  				break
   717  			}
   718  			err = compDefineX(sc, n)
   719  
   720  		case binaryExpr:
   721  			wireChild(n)
   722  			nilSym := interp.universe.sym[nilIdent]
   723  			c0, c1 := n.child[0], n.child[1]
   724  
   725  			err = check.binaryExpr(n)
   726  			if err != nil {
   727  				break
   728  			}
   729  
   730  			switch n.action {
   731  			case aRem:
   732  				n.typ = c0.typ
   733  			case aShl, aShr:
   734  				if c0.typ.untyped {
   735  					break
   736  				}
   737  				n.typ = c0.typ
   738  			case aEqual, aNotEqual:
   739  				n.typ = sc.getType("bool")
   740  				if c0.sym == nilSym || c1.sym == nilSym {
   741  					if n.action == aEqual {
   742  						n.gen = isNil
   743  					} else {
   744  						n.gen = isNotNil
   745  					}
   746  				}
   747  			case aGreater, aGreaterEqual, aLower, aLowerEqual:
   748  				n.typ = sc.getType("bool")
   749  			}
   750  			if err != nil {
   751  				break
   752  			}
   753  			if n.typ == nil {
   754  				if n.typ, err = nodeType(interp, sc, n); err != nil {
   755  					break
   756  				}
   757  			}
   758  			if c0.rval.IsValid() && c1.rval.IsValid() && (!isInterface(n.typ)) && constOp[n.action] != nil {
   759  				n.typ.TypeOf()       // Force compute of reflection type.
   760  				constOp[n.action](n) // Compute a constant result now rather than during exec.
   761  			}
   762  			switch {
   763  			case n.rval.IsValid():
   764  				// This operation involved constants, and the result is already computed
   765  				// by constOp and available in n.rval. Nothing else to do at execution.
   766  				n.gen = nop
   767  				n.findex = notInFrame
   768  			case n.anc.kind == assignStmt && n.anc.action == aAssign && n.anc.nleft == 1:
   769  				// To avoid a copy in frame, if the result is to be assigned, store it directly
   770  				// at the frame location of destination.
   771  				dest := n.anc.child[childPos(n)-n.anc.nright]
   772  				n.typ = dest.typ
   773  				n.findex = dest.findex
   774  				n.level = dest.level
   775  			case n.anc.kind == returnStmt:
   776  				// To avoid a copy in frame, if the result is to be returned, store it directly
   777  				// at the frame location reserved for output arguments.
   778  				pos := childPos(n)
   779  				n.typ = sc.def.typ.ret[pos]
   780  				n.findex = pos
   781  			default:
   782  				// Allocate a new location in frame, and store the result here.
   783  				n.findex = sc.add(n.typ)
   784  			}
   785  
   786  		case indexExpr:
   787  			if isBlank(n.child[0]) {
   788  				err = n.cfgErrorf("cannot use _ as value")
   789  				break
   790  			}
   791  			wireChild(n)
   792  			t := n.child[0].typ
   793  			switch t.cat {
   794  			case aliasT:
   795  				if isString(t.val.TypeOf()) {
   796  					n.typ = sc.getType("byte")
   797  					break
   798  				}
   799  				fallthrough
   800  			case ptrT:
   801  				n.typ = t.val
   802  				if t.val.cat == valueT {
   803  					n.typ = valueTOf(t.val.rtype.Elem())
   804  				} else {
   805  					n.typ = t.val.val
   806  				}
   807  			case stringT:
   808  				n.typ = sc.getType("byte")
   809  			case valueT:
   810  				if t.rtype.Kind() == reflect.String {
   811  					n.typ = sc.getType("byte")
   812  				} else {
   813  					n.typ = valueTOf(t.rtype.Elem())
   814  				}
   815  			default:
   816  				n.typ = t.val
   817  			}
   818  			n.findex = sc.add(n.typ)
   819  			typ := t.TypeOf()
   820  			if typ.Kind() == reflect.Map {
   821  				err = check.assignment(n.child[1], t.key, "map index")
   822  				n.gen = getIndexMap
   823  				break
   824  			}
   825  
   826  			l := -1
   827  			switch k := typ.Kind(); k {
   828  			case reflect.Array:
   829  				l = typ.Len()
   830  				fallthrough
   831  			case reflect.Slice, reflect.String:
   832  				n.gen = getIndexArray
   833  			case reflect.Ptr:
   834  				if typ2 := typ.Elem(); typ2.Kind() == reflect.Array {
   835  					l = typ2.Len()
   836  					n.gen = getIndexArray
   837  				} else {
   838  					err = n.cfgErrorf("type %v does not support indexing", typ)
   839  				}
   840  			default:
   841  				err = n.cfgErrorf("type is not an array, slice, string or map: %v", t.id())
   842  			}
   843  
   844  			err = check.index(n.child[1], l)
   845  
   846  		case blockStmt:
   847  			wireChild(n)
   848  			if len(n.child) > 0 {
   849  				l := n.lastChild()
   850  				n.findex = l.findex
   851  				n.level = l.level
   852  				n.val = l.val
   853  				n.sym = l.sym
   854  				n.typ = l.typ
   855  				n.rval = l.rval
   856  			}
   857  			sc = sc.pop()
   858  
   859  		case constDecl:
   860  			wireChild(n)
   861  
   862  		case varDecl:
   863  			// Global varDecl do not need to be wired as this
   864  			// will be handled after cfg.
   865  			if n.anc.kind == fileStmt {
   866  				break
   867  			}
   868  			wireChild(n)
   869  
   870  		case declStmt, exprStmt, sendStmt:
   871  			wireChild(n)
   872  			l := n.lastChild()
   873  			n.findex = l.findex
   874  			n.level = l.level
   875  			n.val = l.val
   876  			n.sym = l.sym
   877  			n.typ = l.typ
   878  			n.rval = l.rval
   879  
   880  		case breakStmt:
   881  			if len(n.child) == 0 {
   882  				n.tnext = sc.loop
   883  				break
   884  			}
   885  			if !n.hasAnc(n.sym.node) {
   886  				err = n.cfgErrorf("invalid break label %s", n.child[0].ident)
   887  				break
   888  			}
   889  			n.tnext = n.sym.node
   890  
   891  		case continueStmt:
   892  			if len(n.child) == 0 {
   893  				n.tnext = sc.loopRestart
   894  				break
   895  			}
   896  			if !n.hasAnc(n.sym.node) {
   897  				err = n.cfgErrorf("invalid continue label %s", n.child[0].ident)
   898  				break
   899  			}
   900  			n.tnext = n.sym.node.child[1].lastChild().start
   901  
   902  		case gotoStmt:
   903  			if n.sym.node == nil {
   904  				// It can be only due to a forward goto, to be resolved at labeledStmt.
   905  				// Invalid goto labels are catched at AST parsing.
   906  				break
   907  			}
   908  			n.tnext = n.sym.node.start
   909  
   910  		case labeledStmt:
   911  			wireChild(n)
   912  			if len(n.child) > 1 {
   913  				n.start = n.child[1].start
   914  			}
   915  			for _, c := range n.sym.from {
   916  				c.tnext = n.start // Resolve forward goto.
   917  			}
   918  
   919  		case callExpr:
   920  			for _, c := range n.child {
   921  				if isBlank(c) {
   922  					err = n.cfgErrorf("cannot use _ as value")
   923  					return
   924  				}
   925  			}
   926  			wireChild(n)
   927  			switch {
   928  			case isBuiltinCall(n, sc):
   929  				c0 := n.child[0]
   930  				bname := c0.ident
   931  				err = check.builtin(bname, n, n.child[1:], n.action == aCallSlice)
   932  				if err != nil {
   933  					break
   934  				}
   935  
   936  				n.gen = c0.sym.builtin
   937  				c0.typ = &itype{cat: builtinT}
   938  				if n.typ, err = nodeType(interp, sc, n); err != nil {
   939  					return
   940  				}
   941  				switch {
   942  				case n.typ.cat == builtinT:
   943  					n.findex = notInFrame
   944  					n.val = nil
   945  				case n.anc.kind == returnStmt:
   946  					// Store result directly to frame output location, to avoid a frame copy.
   947  					n.findex = 0
   948  				case bname == "cap" && isInConstOrTypeDecl(n):
   949  					t := n.child[1].typ.TypeOf()
   950  					for t.Kind() == reflect.Ptr {
   951  						t = t.Elem()
   952  					}
   953  					switch t.Kind() {
   954  					case reflect.Array, reflect.Chan:
   955  						capConst(n)
   956  					default:
   957  						err = n.cfgErrorf("cap argument is not an array or channel")
   958  					}
   959  					n.findex = notInFrame
   960  					n.gen = nop
   961  				case bname == "len" && isInConstOrTypeDecl(n):
   962  					t := n.child[1].typ.TypeOf()
   963  					for t.Kind() == reflect.Ptr {
   964  						t = t.Elem()
   965  					}
   966  					switch t.Kind() {
   967  					case reflect.Array, reflect.Chan, reflect.String:
   968  						lenConst(n)
   969  					default:
   970  						err = n.cfgErrorf("len argument is not an array, channel or string")
   971  					}
   972  					n.findex = notInFrame
   973  					n.gen = nop
   974  				default:
   975  					n.findex = sc.add(n.typ)
   976  				}
   977  				if op, ok := constBltn[bname]; ok && n.anc.action != aAssign {
   978  					op(n) // pre-compute non-assigned constant :
   979  				}
   980  			case n.child[0].isType(sc):
   981  				// Type conversion expression
   982  				c0, c1 := n.child[0], n.child[1]
   983  				switch len(n.child) {
   984  				case 1:
   985  					err = n.cfgErrorf("missing argument in conversion to %s", c0.typ.id())
   986  				case 2:
   987  					err = check.conversion(c1, c0.typ)
   988  				default:
   989  					err = n.cfgErrorf("too many arguments in conversion to %s", c0.typ.id())
   990  				}
   991  				if err != nil {
   992  					break
   993  				}
   994  
   995  				n.action = aConvert
   996  				switch {
   997  				case isInterface(c0.typ) && !c1.isNil():
   998  					// Convert to interface: just check that all required methods are defined by concrete type.
   999  					if !c1.typ.implements(c0.typ) {
  1000  						err = n.cfgErrorf("type %v does not implement interface %v", c1.typ.id(), c0.typ.id())
  1001  					}
  1002  					// Convert type to interface while keeping a reference to the original concrete type.
  1003  					// besides type, the node value remains preserved.
  1004  					n.gen = nop
  1005  					t := *c0.typ
  1006  					n.typ = &t
  1007  					n.typ.val = c1.typ
  1008  					n.findex = c1.findex
  1009  					n.level = c1.level
  1010  					n.val = c1.val
  1011  					n.rval = c1.rval
  1012  				case c1.rval.IsValid() && isConstType(c0.typ):
  1013  					n.gen = nop
  1014  					n.findex = notInFrame
  1015  					n.typ = c0.typ
  1016  					if c, ok := c1.rval.Interface().(constant.Value); ok {
  1017  						i, _ := constant.Int64Val(constant.ToInt(c))
  1018  						n.rval = reflect.ValueOf(i).Convert(c0.typ.rtype)
  1019  					} else {
  1020  						n.rval = c1.rval.Convert(c0.typ.rtype)
  1021  					}
  1022  				default:
  1023  					n.gen = convert
  1024  					n.typ = c0.typ
  1025  					n.findex = sc.add(n.typ)
  1026  				}
  1027  			case isBinCall(n, sc):
  1028  				err = check.arguments(n, n.child[1:], n.child[0], n.action == aCallSlice)
  1029  				if err != nil {
  1030  					break
  1031  				}
  1032  
  1033  				n.gen = callBin
  1034  				typ := n.child[0].typ.rtype
  1035  				if typ.NumOut() > 0 {
  1036  					if funcType := n.child[0].typ.val; funcType != nil {
  1037  						// Use the original unwrapped function type, to allow future field and
  1038  						// methods resolutions, otherwise impossible on the opaque bin type.
  1039  						n.typ = funcType.ret[0]
  1040  						n.findex = sc.add(n.typ)
  1041  						for i := 1; i < len(funcType.ret); i++ {
  1042  							sc.add(funcType.ret[i])
  1043  						}
  1044  					} else {
  1045  						n.typ = valueTOf(typ.Out(0))
  1046  						if n.anc.kind == returnStmt {
  1047  							n.findex = childPos(n)
  1048  						} else {
  1049  							n.findex = sc.add(n.typ)
  1050  							for i := 1; i < typ.NumOut(); i++ {
  1051  								sc.add(valueTOf(typ.Out(i)))
  1052  							}
  1053  						}
  1054  					}
  1055  				}
  1056  			case isOffsetof(n):
  1057  				if len(n.child) != 2 || n.child[1].kind != selectorExpr || !isStruct(n.child[1].child[0].typ) {
  1058  					err = n.cfgErrorf("Offsetof argument: invalid expression")
  1059  					break
  1060  				}
  1061  				c1 := n.child[1]
  1062  				field, ok := c1.child[0].typ.rtype.FieldByName(c1.child[1].ident)
  1063  				if !ok {
  1064  					err = n.cfgErrorf("struct does not contain field: %s", c1.child[1].ident)
  1065  					break
  1066  				}
  1067  				n.typ = valueTOf(reflect.TypeOf(field.Offset))
  1068  				n.rval = reflect.ValueOf(field.Offset)
  1069  				n.gen = nop
  1070  			default:
  1071  				err = check.arguments(n, n.child[1:], n.child[0], n.action == aCallSlice)
  1072  				if err != nil {
  1073  					break
  1074  				}
  1075  
  1076  				if n.child[0].action == aGetFunc {
  1077  					// Allocate a frame entry to store the anonymous function definition.
  1078  					sc.add(n.child[0].typ)
  1079  				}
  1080  				if typ := n.child[0].typ; len(typ.ret) > 0 {
  1081  					n.typ = typ.ret[0]
  1082  					if n.anc.kind == returnStmt && n.typ.id() == sc.def.typ.ret[0].id() {
  1083  						// Store the result directly to the return value area of frame.
  1084  						// It can be done only if no type conversion at return is involved.
  1085  						n.findex = childPos(n)
  1086  					} else {
  1087  						n.findex = sc.add(n.typ)
  1088  						for _, t := range typ.ret[1:] {
  1089  							sc.add(t)
  1090  						}
  1091  					}
  1092  				} else {
  1093  					n.findex = notInFrame
  1094  				}
  1095  			}
  1096  
  1097  		case caseBody:
  1098  			wireChild(n)
  1099  			switch {
  1100  			case typeSwichAssign(n) && len(n.child) > 1:
  1101  				n.start = n.child[1].start
  1102  			case len(n.child) == 0:
  1103  				// Empty case body: jump to switch node (exit node).
  1104  				n.start = n.anc.anc.anc
  1105  			default:
  1106  				n.start = n.child[0].start
  1107  			}
  1108  
  1109  		case caseClause:
  1110  			sc = sc.pop()
  1111  
  1112  		case commClauseDefault:
  1113  			wireChild(n)
  1114  			sc = sc.pop()
  1115  			if len(n.child) == 0 {
  1116  				return
  1117  			}
  1118  			n.start = n.child[0].start
  1119  			n.lastChild().tnext = n.anc.anc // exit node is selectStmt
  1120  
  1121  		case commClause:
  1122  			wireChild(n)
  1123  			sc = sc.pop()
  1124  			if len(n.child) == 0 {
  1125  				return
  1126  			}
  1127  			if len(n.child) > 1 {
  1128  				n.start = n.child[1].start // Skip chan operation, performed by select
  1129  			}
  1130  			n.lastChild().tnext = n.anc.anc // exit node is selectStmt
  1131  
  1132  		case compositeLitExpr:
  1133  			wireChild(n)
  1134  
  1135  			child := n.child
  1136  			if n.nleft > 0 {
  1137  				child = child[1:]
  1138  			}
  1139  
  1140  			switch n.typ.cat {
  1141  			case arrayT, sliceT:
  1142  				err = check.arrayLitExpr(child, n.typ)
  1143  			case mapT:
  1144  				err = check.mapLitExpr(child, n.typ.key, n.typ.val)
  1145  			case structT:
  1146  				err = check.structLitExpr(child, n.typ)
  1147  			case valueT:
  1148  				rtype := n.typ.rtype
  1149  				switch rtype.Kind() {
  1150  				case reflect.Struct:
  1151  					err = check.structBinLitExpr(child, rtype)
  1152  				case reflect.Map:
  1153  					ktyp := valueTOf(rtype.Key())
  1154  					vtyp := valueTOf(rtype.Elem())
  1155  					err = check.mapLitExpr(child, ktyp, vtyp)
  1156  				}
  1157  			}
  1158  			if err != nil {
  1159  				break
  1160  			}
  1161  
  1162  			n.findex = sc.add(n.typ)
  1163  			// TODO: Check that composite literal expr matches corresponding type
  1164  			n.gen = compositeGenerator(n, n.typ, nil)
  1165  
  1166  		case fallthroughtStmt:
  1167  			if n.anc.kind != caseBody {
  1168  				err = n.cfgErrorf("fallthrough statement out of place")
  1169  			}
  1170  
  1171  		case fileStmt:
  1172  			wireChild(n, varDecl)
  1173  			sc = sc.pop()
  1174  			n.findex = notInFrame
  1175  
  1176  		case forStmt0: // for {}
  1177  			body := n.child[0]
  1178  			n.start = body.start
  1179  			body.tnext = n.start
  1180  			sc = sc.pop()
  1181  
  1182  		case forStmt1: // for init; ; {}
  1183  			init, body := n.child[0], n.child[1]
  1184  			n.start = init.start
  1185  			init.tnext = body.start
  1186  			body.tnext = n.start
  1187  			sc = sc.pop()
  1188  
  1189  		case forStmt2: // for cond {}
  1190  			cond, body := n.child[0], n.child[1]
  1191  			if !isBool(cond.typ) {
  1192  				err = cond.cfgErrorf("non-bool used as for condition")
  1193  			}
  1194  			if cond.rval.IsValid() {
  1195  				// Condition is known at compile time, bypass test.
  1196  				if cond.rval.Bool() {
  1197  					n.start = body.start
  1198  					body.tnext = body.start
  1199  				}
  1200  			} else {
  1201  				n.start = cond.start
  1202  				cond.tnext = body.start
  1203  				body.tnext = cond.start
  1204  			}
  1205  			setFNext(cond, n)
  1206  			sc = sc.pop()
  1207  
  1208  		case forStmt3: // for init; cond; {}
  1209  			init, cond, body := n.child[0], n.child[1], n.child[2]
  1210  			if !isBool(cond.typ) {
  1211  				err = cond.cfgErrorf("non-bool used as for condition")
  1212  			}
  1213  			n.start = init.start
  1214  			if cond.rval.IsValid() {
  1215  				// Condition is known at compile time, bypass test.
  1216  				if cond.rval.Bool() {
  1217  					init.tnext = body.start
  1218  					body.tnext = body.start
  1219  				} else {
  1220  					init.tnext = n
  1221  				}
  1222  			} else {
  1223  				init.tnext = cond.start
  1224  				body.tnext = cond.start
  1225  			}
  1226  			cond.tnext = body.start
  1227  			setFNext(cond, n)
  1228  			sc = sc.pop()
  1229  
  1230  		case forStmt4: // for ; ; post {}
  1231  			post, body := n.child[0], n.child[1]
  1232  			n.start = body.start
  1233  			post.tnext = body.start
  1234  			body.tnext = post.start
  1235  			sc = sc.pop()
  1236  
  1237  		case forStmt5: // for ; cond; post {}
  1238  			cond, post, body := n.child[0], n.child[1], n.child[2]
  1239  			if !isBool(cond.typ) {
  1240  				err = cond.cfgErrorf("non-bool used as for condition")
  1241  			}
  1242  			if cond.rval.IsValid() {
  1243  				// Condition is known at compile time, bypass test.
  1244  				if cond.rval.Bool() {
  1245  					n.start = body.start
  1246  					post.tnext = body.start
  1247  				}
  1248  			} else {
  1249  				n.start = cond.start
  1250  				post.tnext = cond.start
  1251  			}
  1252  			cond.tnext = body.start
  1253  			setFNext(cond, n)
  1254  			body.tnext = post.start
  1255  			sc = sc.pop()
  1256  
  1257  		case forStmt6: // for init; ; post {}
  1258  			init, post, body := n.child[0], n.child[1], n.child[2]
  1259  			n.start = init.start
  1260  			init.tnext = body.start
  1261  			body.tnext = post.start
  1262  			post.tnext = body.start
  1263  			sc = sc.pop()
  1264  
  1265  		case forStmt7: // for init; cond; post {}
  1266  			init, cond, post, body := n.child[0], n.child[1], n.child[2], n.child[3]
  1267  			if !isBool(cond.typ) {
  1268  				err = cond.cfgErrorf("non-bool used as for condition")
  1269  			}
  1270  			n.start = init.start
  1271  			if cond.rval.IsValid() {
  1272  				// Condition is known at compile time, bypass test.
  1273  				if cond.rval.Bool() {
  1274  					init.tnext = body.start
  1275  					post.tnext = body.start
  1276  				} else {
  1277  					init.tnext = n
  1278  				}
  1279  			} else {
  1280  				init.tnext = cond.start
  1281  				post.tnext = cond.start
  1282  			}
  1283  			cond.tnext = body.start
  1284  			setFNext(cond, n)
  1285  			body.tnext = post.start
  1286  			sc = sc.pop()
  1287  
  1288  		case forRangeStmt:
  1289  			n.start = n.child[0].start
  1290  			setFNext(n.child[0], n)
  1291  			sc = sc.pop()
  1292  
  1293  		case funcDecl:
  1294  			n.start = n.child[3].start
  1295  			n.types, n.scope = sc.types, sc
  1296  			sc = sc.pop()
  1297  			funcName := n.child[1].ident
  1298  			if sym := sc.sym[funcName]; !isMethod(n) && sym != nil {
  1299  				sym.index = -1 // to force value to n.val
  1300  				sym.typ = n.typ
  1301  				sym.kind = funcSym
  1302  				sym.node = n
  1303  			}
  1304  
  1305  		case funcLit:
  1306  			n.types, n.scope = sc.types, sc
  1307  			sc = sc.pop()
  1308  			err = genRun(n)
  1309  
  1310  		case deferStmt, goStmt:
  1311  			wireChild(n)
  1312  
  1313  		case identExpr:
  1314  			if isKey(n) || isNewDefine(n, sc) {
  1315  				break
  1316  			}
  1317  			if n.anc.kind == funcDecl && n.anc.child[1] == n {
  1318  				// Dont process a function name identExpr.
  1319  				break
  1320  			}
  1321  
  1322  			sym, level, found := sc.lookup(n.ident)
  1323  			if !found {
  1324  				// retry with the filename, in case ident is a package name.
  1325  				sym, level, found = sc.lookup(filepath.Join(n.ident, baseName))
  1326  				if !found {
  1327  					err = n.cfgErrorf("undefined: %s", n.ident)
  1328  					break
  1329  				}
  1330  			}
  1331  			// Found symbol, populate node info
  1332  			n.sym, n.typ, n.findex, n.level = sym, sym.typ, sym.index, level
  1333  			if n.findex < 0 {
  1334  				n.val = sym.node
  1335  			} else {
  1336  				switch {
  1337  				case sym.kind == constSym && sym.rval.IsValid():
  1338  					n.rval = sym.rval
  1339  					n.kind = basicLit
  1340  				case n.ident == "iota":
  1341  					n.rval = reflect.ValueOf(constant.MakeInt64(int64(sc.iota)))
  1342  					n.kind = basicLit
  1343  				case n.ident == nilIdent:
  1344  					n.kind = basicLit
  1345  				case sym.kind == binSym:
  1346  					n.typ = sym.typ
  1347  					n.rval = sym.rval
  1348  				case sym.kind == bltnSym:
  1349  					if n.anc.kind != callExpr {
  1350  						err = n.cfgErrorf("use of builtin %s not in function call", n.ident)
  1351  					}
  1352  				}
  1353  			}
  1354  			if n.sym != nil {
  1355  				n.recv = n.sym.recv
  1356  			}
  1357  
  1358  		case ifStmt0: // if cond {}
  1359  			cond, tbody := n.child[0], n.child[1]
  1360  			if !isBool(cond.typ) {
  1361  				err = cond.cfgErrorf("non-bool used as if condition")
  1362  			}
  1363  			if cond.rval.IsValid() {
  1364  				// Condition is known at compile time, bypass test.
  1365  				if cond.rval.Bool() {
  1366  					n.start = tbody.start
  1367  				}
  1368  			} else {
  1369  				n.start = cond.start
  1370  				cond.tnext = tbody.start
  1371  			}
  1372  			setFNext(cond, n)
  1373  			tbody.tnext = n
  1374  			sc = sc.pop()
  1375  
  1376  		case ifStmt1: // if cond {} else {}
  1377  			cond, tbody, fbody := n.child[0], n.child[1], n.child[2]
  1378  			if !isBool(cond.typ) {
  1379  				err = cond.cfgErrorf("non-bool used as if condition")
  1380  			}
  1381  			if cond.rval.IsValid() {
  1382  				// Condition is known at compile time, bypass test and the useless branch.
  1383  				if cond.rval.Bool() {
  1384  					n.start = tbody.start
  1385  				} else {
  1386  					n.start = fbody.start
  1387  				}
  1388  			} else {
  1389  				n.start = cond.start
  1390  				cond.tnext = tbody.start
  1391  				setFNext(cond, fbody.start)
  1392  			}
  1393  			tbody.tnext = n
  1394  			fbody.tnext = n
  1395  			sc = sc.pop()
  1396  
  1397  		case ifStmt2: // if init; cond {}
  1398  			init, cond, tbody := n.child[0], n.child[1], n.child[2]
  1399  			if !isBool(cond.typ) {
  1400  				err = cond.cfgErrorf("non-bool used as if condition")
  1401  			}
  1402  			n.start = init.start
  1403  			if cond.rval.IsValid() {
  1404  				// Condition is known at compile time, bypass test.
  1405  				if cond.rval.Bool() {
  1406  					init.tnext = tbody.start
  1407  				} else {
  1408  					init.tnext = n
  1409  				}
  1410  			} else {
  1411  				init.tnext = cond.start
  1412  				cond.tnext = tbody.start
  1413  			}
  1414  			tbody.tnext = n
  1415  			setFNext(cond, n)
  1416  			sc = sc.pop()
  1417  
  1418  		case ifStmt3: // if init; cond {} else {}
  1419  			init, cond, tbody, fbody := n.child[0], n.child[1], n.child[2], n.child[3]
  1420  			if !isBool(cond.typ) {
  1421  				err = cond.cfgErrorf("non-bool used as if condition")
  1422  			}
  1423  			n.start = init.start
  1424  			if cond.rval.IsValid() {
  1425  				// Condition is known at compile time, bypass test.
  1426  				if cond.rval.Bool() {
  1427  					init.tnext = tbody.start
  1428  				} else {
  1429  					init.tnext = fbody.start
  1430  				}
  1431  			} else {
  1432  				init.tnext = cond.start
  1433  				cond.tnext = tbody.start
  1434  				setFNext(cond, fbody.start)
  1435  			}
  1436  			tbody.tnext = n
  1437  			fbody.tnext = n
  1438  			sc = sc.pop()
  1439  
  1440  		case keyValueExpr:
  1441  			if isBlank(n.child[1]) {
  1442  				err = n.cfgErrorf("cannot use _ as value")
  1443  				break
  1444  			}
  1445  			wireChild(n)
  1446  
  1447  		case landExpr:
  1448  			if isBlank(n.child[0]) || isBlank(n.child[1]) {
  1449  				err = n.cfgErrorf("cannot use _ as value")
  1450  				break
  1451  			}
  1452  			n.start = n.child[0].start
  1453  			n.child[0].tnext = n.child[1].start
  1454  			setFNext(n.child[0], n)
  1455  			n.child[1].tnext = n
  1456  			n.typ = n.child[0].typ
  1457  			n.findex = sc.add(n.typ)
  1458  			if n.start.action == aNop {
  1459  				n.start.gen = branch
  1460  			}
  1461  
  1462  		case lorExpr:
  1463  			if isBlank(n.child[0]) || isBlank(n.child[1]) {
  1464  				err = n.cfgErrorf("cannot use _ as value")
  1465  				break
  1466  			}
  1467  			n.start = n.child[0].start
  1468  			n.child[0].tnext = n
  1469  			setFNext(n.child[0], n.child[1].start)
  1470  			n.child[1].tnext = n
  1471  			n.typ = n.child[0].typ
  1472  			n.findex = sc.add(n.typ)
  1473  			if n.start.action == aNop {
  1474  				n.start.gen = branch
  1475  			}
  1476  
  1477  		case parenExpr:
  1478  			wireChild(n)
  1479  			c := n.lastChild()
  1480  			n.findex = c.findex
  1481  			n.level = c.level
  1482  			n.typ = c.typ
  1483  			n.rval = c.rval
  1484  
  1485  		case rangeStmt:
  1486  			if sc.rangeChanType(n) != nil {
  1487  				n.start = n.child[1].start // Get chan
  1488  				n.child[1].tnext = n       // then go to range function
  1489  				n.tnext = n.child[2].start // then go to range body
  1490  				n.child[2].tnext = n       // then body go to range function (loop)
  1491  				n.child[0].gen = empty
  1492  			} else {
  1493  				var k, o, body *node
  1494  				if len(n.child) == 4 {
  1495  					k, o, body = n.child[0], n.child[2], n.child[3]
  1496  				} else {
  1497  					k, o, body = n.child[0], n.child[1], n.child[2]
  1498  				}
  1499  				n.start = o.start    // Get array or map object
  1500  				o.tnext = k.start    // then go to iterator init
  1501  				k.tnext = n          // then go to range function
  1502  				n.tnext = body.start // then go to range body
  1503  				body.tnext = n       // then body go to range function (loop)
  1504  				k.gen = empty        // init filled later by generator
  1505  			}
  1506  
  1507  		case returnStmt:
  1508  			if len(n.child) > sc.def.typ.numOut() {
  1509  				err = n.cfgErrorf("too many arguments to return")
  1510  				break
  1511  			}
  1512  			for _, c := range n.child {
  1513  				if isBlank(c) {
  1514  					err = n.cfgErrorf("cannot use _ as value")
  1515  					return
  1516  				}
  1517  			}
  1518  			returnSig := sc.def.child[2]
  1519  			if mustReturnValue(returnSig) {
  1520  				nret := len(n.child)
  1521  				if nret == 1 && isCall(n.child[0]) {
  1522  					nret = n.child[0].child[0].typ.numOut()
  1523  				}
  1524  				if nret < sc.def.typ.numOut() {
  1525  					err = n.cfgErrorf("not enough arguments to return")
  1526  					break
  1527  				}
  1528  			}
  1529  			wireChild(n)
  1530  			n.tnext = nil
  1531  			n.val = sc.def
  1532  			for i, c := range n.child {
  1533  				var typ *itype
  1534  				typ, err = nodeType(interp, sc.upperLevel(), returnSig.child[1].fieldType(i))
  1535  				if err != nil {
  1536  					return
  1537  				}
  1538  				// TODO(mpl): move any of that code to typecheck?
  1539  				c.typ.node = c
  1540  				if !c.typ.assignableTo(typ) {
  1541  					err = c.cfgErrorf("cannot use %v (type %v) as type %v in return argument", c.ident, c.typ.cat, typ.cat)
  1542  					return
  1543  				}
  1544  				if c.typ.cat == nilT {
  1545  					// nil: Set node value to zero of return type
  1546  					if typ.cat == funcT {
  1547  						// Wrap the typed nil value in a node, as per other interpreter functions
  1548  						c.rval = reflect.ValueOf(&node{kind: basicLit, rval: reflect.New(typ.TypeOf()).Elem()})
  1549  					} else {
  1550  						c.rval = reflect.New(typ.TypeOf()).Elem()
  1551  					}
  1552  				}
  1553  			}
  1554  
  1555  		case selectorExpr:
  1556  			wireChild(n)
  1557  			n.typ = n.child[0].typ
  1558  			n.recv = n.child[0].recv
  1559  			if n.typ == nil {
  1560  				err = n.cfgErrorf("undefined type")
  1561  				break
  1562  			}
  1563  			switch {
  1564  			case n.typ.cat == binPkgT:
  1565  				// Resolve binary package symbol: a type or a value
  1566  				name := n.child[1].ident
  1567  				pkg := n.child[0].sym.typ.path
  1568  				if s, ok := interp.binPkg[pkg][name]; ok {
  1569  					if isBinType(s) {
  1570  						n.typ = valueTOf(s.Type().Elem())
  1571  					} else {
  1572  						n.typ = valueTOf(fixPossibleConstType(s.Type()), withUntyped(isValueUntyped(s)))
  1573  						n.rval = s
  1574  					}
  1575  					n.action = aGetSym
  1576  					n.gen = nop
  1577  				} else {
  1578  					err = n.cfgErrorf("package %s \"%s\" has no symbol %s", n.child[0].ident, pkg, name)
  1579  				}
  1580  			case n.typ.cat == srcPkgT:
  1581  				pkg, name := n.child[0].sym.typ.path, n.child[1].ident
  1582  				// Resolve source package symbol
  1583  				if sym, ok := interp.srcPkg[pkg][name]; ok {
  1584  					n.findex = sym.index
  1585  					if sym.global {
  1586  						n.level = globalFrame
  1587  					}
  1588  					n.val = sym.node
  1589  					n.gen = nop
  1590  					n.action = aGetSym
  1591  					n.typ = sym.typ
  1592  					n.sym = sym
  1593  					n.recv = sym.recv
  1594  					n.rval = sym.rval
  1595  				} else {
  1596  					err = n.cfgErrorf("undefined selector: %s.%s", pkg, name)
  1597  				}
  1598  			case isStruct(n.typ) || isInterfaceSrc(n.typ):
  1599  				// Find a matching field.
  1600  				if ti := n.typ.lookupField(n.child[1].ident); len(ti) > 0 {
  1601  					if isStruct(n.typ) {
  1602  						// If a method of the same name exists, use it if it is shallower than the struct field.
  1603  						// if method's depth is the same as field's, this is an error.
  1604  						d := n.typ.methodDepth(n.child[1].ident)
  1605  						if d >= 0 && d < len(ti) {
  1606  							goto tryMethods
  1607  						}
  1608  						if d == len(ti) {
  1609  							err = n.cfgErrorf("ambiguous selector: %s", n.child[1].ident)
  1610  							break
  1611  						}
  1612  					}
  1613  					n.val = ti
  1614  					switch {
  1615  					case isInterfaceSrc(n.typ):
  1616  						n.typ = n.typ.fieldSeq(ti)
  1617  						n.gen = getMethodByName
  1618  						n.action = aMethod
  1619  					case n.typ.cat == ptrT:
  1620  						n.typ = n.typ.fieldSeq(ti)
  1621  						n.gen = getPtrIndexSeq
  1622  						if n.typ.cat == funcT {
  1623  							// Function in a struct field is always wrapped in reflect.Value.
  1624  							n.typ = wrapperValueTOf(n.typ.TypeOf(), n.typ)
  1625  						}
  1626  					default:
  1627  						n.gen = getIndexSeq
  1628  						n.typ = n.typ.fieldSeq(ti)
  1629  						if n.typ.cat == funcT {
  1630  							// Function in a struct field is always wrapped in reflect.Value.
  1631  							n.typ = wrapperValueTOf(n.typ.TypeOf(), n.typ)
  1632  						}
  1633  					}
  1634  					break
  1635  				}
  1636  				if s, lind, ok := n.typ.lookupBinField(n.child[1].ident); ok {
  1637  					// Handle an embedded binary field into a struct field.
  1638  					n.gen = getIndexSeqField
  1639  					lind = append(lind, s.Index...)
  1640  					if isStruct(n.typ) {
  1641  						// If a method of the same name exists, use it if it is shallower than the struct field.
  1642  						// if method's depth is the same as field's, this is an error.
  1643  						d := n.typ.methodDepth(n.child[1].ident)
  1644  						if d >= 0 && d < len(lind) {
  1645  							goto tryMethods
  1646  						}
  1647  						if d == len(lind) {
  1648  							err = n.cfgErrorf("ambiguous selector: %s", n.child[1].ident)
  1649  							break
  1650  						}
  1651  					}
  1652  					n.val = lind
  1653  					n.typ = valueTOf(s.Type)
  1654  					break
  1655  				}
  1656  				// No field (embedded or not) matched. Try to match a method.
  1657  			tryMethods:
  1658  				fallthrough
  1659  			default:
  1660  				// Find a matching method.
  1661  				// TODO (marc): simplify the following if/elseif blocks.
  1662  				if n.typ.cat == valueT || n.typ.cat == errorT {
  1663  					switch method, ok := n.typ.rtype.MethodByName(n.child[1].ident); {
  1664  					case ok:
  1665  						hasRecvType := n.typ.rtype.Kind() != reflect.Interface
  1666  						n.val = method.Index
  1667  						n.gen = getIndexBinMethod
  1668  						n.action = aGetMethod
  1669  						n.recv = &receiver{node: n.child[0]}
  1670  						n.typ = valueTOf(method.Type, isBinMethod())
  1671  						if hasRecvType {
  1672  							n.typ.recv = n.typ
  1673  						}
  1674  					case n.typ.rtype.Kind() == reflect.Ptr:
  1675  						if field, ok := n.typ.rtype.Elem().FieldByName(n.child[1].ident); ok {
  1676  							n.typ = valueTOf(field.Type)
  1677  							n.val = field.Index
  1678  							n.gen = getPtrIndexSeq
  1679  							break
  1680  						}
  1681  						err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
  1682  					case n.typ.rtype.Kind() == reflect.Struct:
  1683  						if field, ok := n.typ.rtype.FieldByName(n.child[1].ident); ok {
  1684  							n.typ = valueTOf(field.Type)
  1685  							n.val = field.Index
  1686  							n.gen = getIndexSeq
  1687  							break
  1688  						}
  1689  						fallthrough
  1690  					default:
  1691  						// method lookup failed on type, now lookup on pointer to type
  1692  						pt := reflect.PtrTo(n.typ.rtype)
  1693  						if m2, ok2 := pt.MethodByName(n.child[1].ident); ok2 {
  1694  							n.val = m2.Index
  1695  							n.gen = getIndexBinPtrMethod
  1696  							n.typ = valueTOf(m2.Type, isBinMethod(), withRecv(valueTOf(pt)))
  1697  							n.recv = &receiver{node: n.child[0]}
  1698  							n.action = aGetMethod
  1699  							break
  1700  						}
  1701  						err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
  1702  					}
  1703  				} else if n.typ.cat == ptrT && (n.typ.val.cat == valueT || n.typ.val.cat == errorT) {
  1704  					// Handle pointer on object defined in runtime
  1705  					if method, ok := n.typ.val.rtype.MethodByName(n.child[1].ident); ok {
  1706  						n.val = method.Index
  1707  						n.typ = valueTOf(method.Type, isBinMethod(), withRecv(n.typ))
  1708  						n.recv = &receiver{node: n.child[0]}
  1709  						n.gen = getIndexBinElemMethod
  1710  						n.action = aGetMethod
  1711  					} else if method, ok := reflect.PtrTo(n.typ.val.rtype).MethodByName(n.child[1].ident); ok {
  1712  						n.val = method.Index
  1713  						n.gen = getIndexBinMethod
  1714  						n.typ = valueTOf(method.Type, withRecv(valueTOf(reflect.PtrTo(n.typ.val.rtype), isBinMethod())))
  1715  						n.recv = &receiver{node: n.child[0]}
  1716  						n.action = aGetMethod
  1717  					} else if field, ok := n.typ.val.rtype.FieldByName(n.child[1].ident); ok {
  1718  						n.typ = valueTOf(field.Type)
  1719  						n.val = field.Index
  1720  						n.gen = getPtrIndexSeq
  1721  					} else {
  1722  						err = n.cfgErrorf("undefined selector: %s", n.child[1].ident)
  1723  					}
  1724  				} else if m, lind := n.typ.lookupMethod(n.child[1].ident); m != nil {
  1725  					n.action = aGetMethod
  1726  					if n.child[0].isType(sc) {
  1727  						// Handle method as a function with receiver in 1st argument
  1728  						n.val = m
  1729  						n.findex = notInFrame
  1730  						n.gen = nop
  1731  						n.typ = &itype{}
  1732  						*n.typ = *m.typ
  1733  						n.typ.arg = append([]*itype{n.child[0].typ}, m.typ.arg...)
  1734  					} else {
  1735  						// Handle method with receiver
  1736  						n.gen = getMethod
  1737  						n.val = m
  1738  						n.typ = m.typ
  1739  						n.recv = &receiver{node: n.child[0], index: lind}
  1740  					}
  1741  				} else if m, lind, isPtr, ok := n.typ.lookupBinMethod(n.child[1].ident); ok {
  1742  					n.action = aGetMethod
  1743  					switch {
  1744  					case isPtr && n.typ.fieldSeq(lind).cat != ptrT:
  1745  						n.gen = getIndexSeqPtrMethod
  1746  					case isInterfaceSrc(n.typ):
  1747  						n.gen = getMethodByName
  1748  					default:
  1749  						n.gen = getIndexSeqMethod
  1750  					}
  1751  					n.recv = &receiver{node: n.child[0], index: lind}
  1752  					n.val = append([]int{m.Index}, lind...)
  1753  					n.typ = valueTOf(m.Type, isBinMethod(), withRecv(n.child[0].typ))
  1754  				} else {
  1755  					err = n.cfgErrorf("undefined selector: %s", n.child[1].ident)
  1756  				}
  1757  			}
  1758  			if err == nil && n.findex != -1 {
  1759  				n.findex = sc.add(n.typ)
  1760  			}
  1761  
  1762  		case selectStmt:
  1763  			wireChild(n)
  1764  			// Move action to block statement, so select node can be an exit point.
  1765  			n.child[0].gen = _select
  1766  			// Chain channel init actions in commClauses prior to invoke select.
  1767  			var cur *node
  1768  			for _, c := range n.child[0].child {
  1769  				var an, pn *node // channel init action nodes
  1770  				if len(c.child) > 0 {
  1771  					switch c0 := c.child[0]; {
  1772  					case c0.kind == exprStmt && len(c0.child) == 1 && c0.child[0].action == aRecv:
  1773  						an = c0.child[0].child[0]
  1774  						pn = an
  1775  					case c0.action == aAssign:
  1776  						an = c0.lastChild().child[0]
  1777  						pn = an
  1778  					case c0.kind == sendStmt:
  1779  						an = c0.child[0]
  1780  						pn = c0.child[1]
  1781  					}
  1782  				}
  1783  				if an == nil {
  1784  					continue
  1785  				}
  1786  				if cur == nil {
  1787  					// First channel init action, the entry point for the select block.
  1788  					n.start = an.start
  1789  				} else {
  1790  					// Chain channel init action to the previous one.
  1791  					cur.tnext = an.start
  1792  				}
  1793  				if pn != nil {
  1794  					// Chain channect init action to send data init action.
  1795  					// (already done by wireChild, but let's be explicit).
  1796  					an.tnext = pn
  1797  					cur = pn
  1798  				}
  1799  			}
  1800  			if cur == nil {
  1801  				// There is no channel init action, call select directly.
  1802  				n.start = n.child[0]
  1803  			} else {
  1804  				// Select is called after the last channel init action.
  1805  				cur.tnext = n.child[0]
  1806  			}
  1807  
  1808  		case starExpr:
  1809  			if isBlank(n.child[0]) {
  1810  				err = n.cfgErrorf("cannot use _ as value")
  1811  				break
  1812  			}
  1813  			switch {
  1814  			case n.anc.kind == defineStmt && len(n.anc.child) == 3 && n.anc.child[1] == n:
  1815  				// pointer type expression in a var definition
  1816  				n.gen = nop
  1817  			case n.anc.kind == valueSpec && n.anc.lastChild() == n:
  1818  				// pointer type expression in a value spec
  1819  				n.gen = nop
  1820  			case n.anc.kind == fieldExpr:
  1821  				// pointer type expression in a field expression (arg or struct field)
  1822  				n.gen = nop
  1823  			case n.child[0].isType(sc):
  1824  				// pointer type expression
  1825  				n.gen = nop
  1826  				n.typ = ptrOf(n.child[0].typ)
  1827  			default:
  1828  				// dereference expression
  1829  				wireChild(n)
  1830  
  1831  				err = check.starExpr(n.child[0])
  1832  				if err != nil {
  1833  					break
  1834  				}
  1835  
  1836  				if c0 := n.child[0]; c0.typ.cat == valueT {
  1837  					n.typ = valueTOf(c0.typ.rtype.Elem())
  1838  				} else {
  1839  					n.typ = c0.typ.val
  1840  				}
  1841  				n.findex = sc.add(n.typ)
  1842  			}
  1843  
  1844  		case typeSwitch:
  1845  			// Check that cases expressions are all different
  1846  			usedCase := map[string]bool{}
  1847  			for _, c := range n.lastChild().child {
  1848  				for _, t := range c.child[:len(c.child)-1] {
  1849  					tid := t.typ.id()
  1850  					if usedCase[tid] {
  1851  						err = c.cfgErrorf("duplicate case %s in type switch", t.ident)
  1852  						return
  1853  					}
  1854  					usedCase[tid] = true
  1855  				}
  1856  			}
  1857  			fallthrough
  1858  
  1859  		case switchStmt:
  1860  			sc = sc.pop()
  1861  			sbn := n.lastChild() // switch block node
  1862  			clauses := sbn.child
  1863  			l := len(clauses)
  1864  			if l == 0 {
  1865  				// Switch is empty
  1866  				break
  1867  			}
  1868  			// Chain case clauses.
  1869  			for i := l - 1; i >= 0; i-- {
  1870  				c := clauses[i]
  1871  				if len(c.child) == 0 {
  1872  					c.tnext = n // Clause body is empty, exit.
  1873  				} else {
  1874  					body := c.lastChild()
  1875  					c.tnext = body.start
  1876  					c.child[0].tnext = c
  1877  					c.start = c.child[0].start
  1878  
  1879  					if i < l-1 && len(body.child) > 0 && body.lastChild().kind == fallthroughtStmt {
  1880  						if n.kind == typeSwitch {
  1881  							err = body.lastChild().cfgErrorf("cannot fallthrough in type switch")
  1882  						}
  1883  						if len(clauses[i+1].child) == 0 {
  1884  							body.tnext = n // Fallthrough to next with empty body, just exit.
  1885  						} else {
  1886  							body.tnext = clauses[i+1].lastChild().start
  1887  						}
  1888  					} else {
  1889  						body.tnext = n // Exit switch at end of clause body.
  1890  					}
  1891  				}
  1892  
  1893  				if i == l-1 {
  1894  					setFNext(clauses[i], n)
  1895  					continue
  1896  				}
  1897  				if len(clauses[i+1].child) > 1 {
  1898  					setFNext(c, clauses[i+1].start)
  1899  				} else {
  1900  					setFNext(c, clauses[i+1])
  1901  				}
  1902  			}
  1903  			sbn.start = clauses[0].start
  1904  			n.start = n.child[0].start
  1905  			n.child[0].tnext = sbn.start
  1906  
  1907  		case switchIfStmt: // like an if-else chain
  1908  			sc = sc.pop()
  1909  			sbn := n.lastChild() // switch block node
  1910  			clauses := sbn.child
  1911  			l := len(clauses)
  1912  			if l == 0 {
  1913  				// Switch is empty
  1914  				break
  1915  			}
  1916  			// Wire case clauses in reverse order so the next start node is already resolved when used.
  1917  			for i := l - 1; i >= 0; i-- {
  1918  				c := clauses[i]
  1919  				c.gen = nop
  1920  				if len(c.child) == 0 {
  1921  					c.tnext = n
  1922  					c.fnext = n
  1923  				} else {
  1924  					body := c.lastChild()
  1925  					if len(c.child) > 1 {
  1926  						cond := c.child[0]
  1927  						cond.tnext = body.start
  1928  						if i == l-1 {
  1929  							setFNext(cond, n)
  1930  						} else {
  1931  							setFNext(cond, clauses[i+1].start)
  1932  						}
  1933  						c.start = cond.start
  1934  					} else {
  1935  						c.start = body.start
  1936  					}
  1937  					// If last case body statement is a fallthrough, then jump to next case body
  1938  					if i < l-1 && len(body.child) > 0 && body.lastChild().kind == fallthroughtStmt {
  1939  						body.tnext = clauses[i+1].lastChild().start
  1940  					} else {
  1941  						body.tnext = n
  1942  					}
  1943  				}
  1944  			}
  1945  			sbn.start = clauses[0].start
  1946  			n.start = n.child[0].start
  1947  			n.child[0].tnext = sbn.start
  1948  
  1949  		case typeAssertExpr:
  1950  			if len(n.child) == 1 {
  1951  				// The "o.(type)" is handled by typeSwitch.
  1952  				n.gen = nop
  1953  				break
  1954  			}
  1955  
  1956  			wireChild(n)
  1957  			c0, c1 := n.child[0], n.child[1]
  1958  			if isBlank(c0) || isBlank(c1) {
  1959  				err = n.cfgErrorf("cannot use _ as value")
  1960  				break
  1961  			}
  1962  			if c1.typ == nil {
  1963  				if c1.typ, err = nodeType(interp, sc, c1); err != nil {
  1964  					return
  1965  				}
  1966  			}
  1967  
  1968  			err = check.typeAssertionExpr(c0, c1.typ)
  1969  			if err != nil {
  1970  				break
  1971  			}
  1972  
  1973  			if n.anc.action != aAssignX {
  1974  				if c0.typ.cat == valueT && isFunc(c1.typ) {
  1975  					// Avoid special wrapping of interfaces and func types.
  1976  					n.typ = valueTOf(c1.typ.TypeOf())
  1977  				} else {
  1978  					n.typ = c1.typ
  1979  				}
  1980  				n.findex = sc.add(n.typ)
  1981  			}
  1982  
  1983  		case sliceExpr:
  1984  			wireChild(n)
  1985  
  1986  			err = check.sliceExpr(n)
  1987  			if err != nil {
  1988  				break
  1989  			}
  1990  
  1991  			if n.typ, err = nodeType(interp, sc, n); err != nil {
  1992  				return
  1993  			}
  1994  			n.findex = sc.add(n.typ)
  1995  
  1996  		case unaryExpr:
  1997  			wireChild(n)
  1998  
  1999  			err = check.unaryExpr(n)
  2000  			if err != nil {
  2001  				break
  2002  			}
  2003  
  2004  			n.typ = n.child[0].typ
  2005  			if n.action == aRecv {
  2006  				// Channel receive operation: set type to the channel data type
  2007  				if n.typ.cat == valueT {
  2008  					n.typ = valueTOf(n.typ.rtype.Elem())
  2009  				} else {
  2010  					n.typ = n.typ.val
  2011  				}
  2012  			}
  2013  			if n.typ == nil {
  2014  				if n.typ, err = nodeType(interp, sc, n); err != nil {
  2015  					return
  2016  				}
  2017  			}
  2018  
  2019  			// TODO: Optimisation: avoid allocation if boolean branch op (i.e. '!' in an 'if' expr)
  2020  			if n.child[0].rval.IsValid() && !isInterface(n.typ) && constOp[n.action] != nil {
  2021  				n.typ.TypeOf() // init reflect type
  2022  				constOp[n.action](n)
  2023  			}
  2024  			switch {
  2025  			case n.rval.IsValid():
  2026  				n.gen = nop
  2027  				n.findex = notInFrame
  2028  			case n.anc.kind == assignStmt && n.anc.action == aAssign && n.anc.nright == 1:
  2029  				dest := n.anc.child[childPos(n)-n.anc.nright]
  2030  				n.typ = dest.typ
  2031  				n.findex = dest.findex
  2032  				n.level = dest.level
  2033  			case n.anc.kind == returnStmt:
  2034  				pos := childPos(n)
  2035  				n.typ = sc.def.typ.ret[pos]
  2036  				n.findex = pos
  2037  			default:
  2038  				n.findex = sc.add(n.typ)
  2039  			}
  2040  
  2041  		case valueSpec:
  2042  			n.gen = reset
  2043  			l := len(n.child) - 1
  2044  			if n.typ = n.child[l].typ; n.typ == nil {
  2045  				if n.typ, err = nodeType(interp, sc, n.child[l]); err != nil {
  2046  					return
  2047  				}
  2048  			}
  2049  
  2050  			for _, c := range n.child[:l] {
  2051  				var index int
  2052  				if sc.global {
  2053  					// Global object allocation is already performed in GTA.
  2054  					index = sc.sym[c.ident].index
  2055  					c.level = globalFrame
  2056  				} else {
  2057  					index = sc.add(n.typ)
  2058  					sc.sym[c.ident] = &symbol{index: index, kind: varSym, typ: n.typ}
  2059  				}
  2060  				c.typ = n.typ
  2061  				c.findex = index
  2062  			}
  2063  		}
  2064  	})
  2065  
  2066  	if sc != interp.universe {
  2067  		sc.pop()
  2068  	}
  2069  	return initNodes, err
  2070  }
  2071  
  2072  func compDefineX(sc *scope, n *node) error {
  2073  	l := len(n.child) - 1
  2074  	types := []*itype{}
  2075  
  2076  	switch src := n.child[l]; src.kind {
  2077  	case callExpr:
  2078  		funtype, err := nodeType(n.interp, sc, src.child[0])
  2079  		if err != nil {
  2080  			return err
  2081  		}
  2082  		for funtype.cat == valueT && funtype.val != nil {
  2083  			// Retrieve original interpreter type from a wrapped function.
  2084  			// Struct fields of function types are always wrapped in valueT to ensure
  2085  			// their possible use in runtime. In that case, the val field retains the
  2086  			// original interpreter type, which is used now.
  2087  			funtype = funtype.val
  2088  		}
  2089  		if funtype.cat == valueT {
  2090  			// Handle functions imported from runtime.
  2091  			for i := 0; i < funtype.rtype.NumOut(); i++ {
  2092  				types = append(types, valueTOf(funtype.rtype.Out(i)))
  2093  			}
  2094  		} else {
  2095  			types = funtype.ret
  2096  		}
  2097  		if n.anc.kind == varDecl && n.child[l-1].isType(sc) {
  2098  			l--
  2099  		}
  2100  		if len(types) != l {
  2101  			return n.cfgErrorf("assignment mismatch: %d variables but %s returns %d values", l, src.child[0].name(), len(types))
  2102  		}
  2103  		if isBinCall(src, sc) {
  2104  			n.gen = nop
  2105  		} else {
  2106  			// TODO (marc): skip if no conversion or wrapping is needed.
  2107  			n.gen = assignFromCall
  2108  		}
  2109  
  2110  	case indexExpr:
  2111  		types = append(types, src.typ, sc.getType("bool"))
  2112  		n.child[l].gen = getIndexMap2
  2113  		n.gen = nop
  2114  
  2115  	case typeAssertExpr:
  2116  		if n.child[0].ident == "_" {
  2117  			n.child[l].gen = typeAssertStatus
  2118  		} else {
  2119  			n.child[l].gen = typeAssertLong
  2120  		}
  2121  		types = append(types, n.child[l].child[1].typ, sc.getType("bool"))
  2122  		n.gen = nop
  2123  
  2124  	case unaryExpr:
  2125  		if n.child[l].action == aRecv {
  2126  			types = append(types, src.typ, sc.getType("bool"))
  2127  			n.child[l].gen = recv2
  2128  			n.gen = nop
  2129  		}
  2130  
  2131  	default:
  2132  		return n.cfgErrorf("unsupported assign expression")
  2133  	}
  2134  
  2135  	for i, t := range types {
  2136  		var index int
  2137  		id := n.child[i].ident
  2138  		if sym, level, ok := sc.lookup(id); ok && level == n.child[i].level && sym.kind == varSym && sym.typ.id() == t.id() {
  2139  			// Reuse symbol in case of a variable redeclaration with the same type.
  2140  			index = sym.index
  2141  		} else {
  2142  			index = sc.add(t)
  2143  			sc.sym[id] = &symbol{index: index, kind: varSym, typ: t}
  2144  		}
  2145  		n.child[i].typ = t
  2146  		n.child[i].findex = index
  2147  	}
  2148  	return nil
  2149  }
  2150  
  2151  // TODO used for allocation optimization, temporarily disabled
  2152  // func isAncBranch(n *node) bool {
  2153  //	switch n.anc.kind {
  2154  //	case If0, If1, If2, If3:
  2155  //		return true
  2156  //	}
  2157  //	return false
  2158  // }
  2159  
  2160  func childPos(n *node) int {
  2161  	for i, c := range n.anc.child {
  2162  		if n == c {
  2163  			return i
  2164  		}
  2165  	}
  2166  	return -1
  2167  }
  2168  
  2169  func (n *node) cfgErrorf(format string, a ...interface{}) *cfgError {
  2170  	pos := n.interp.fset.Position(n.pos)
  2171  	posString := n.interp.fset.Position(n.pos).String()
  2172  	if pos.Filename == DefaultSourceName {
  2173  		posString = strings.TrimPrefix(posString, DefaultSourceName+":")
  2174  	}
  2175  	a = append([]interface{}{posString}, a...)
  2176  	return &cfgError{n, fmt.Errorf("%s: "+format, a...)}
  2177  }
  2178  
  2179  func genRun(nod *node) error {
  2180  	var err error
  2181  
  2182  	nod.Walk(func(n *node) bool {
  2183  		if err != nil {
  2184  			return false
  2185  		}
  2186  		switch n.kind {
  2187  		case funcType:
  2188  			if len(n.anc.child) == 4 {
  2189  				// function body entry point
  2190  				setExec(n.anc.child[3].start)
  2191  			}
  2192  			// continue in function body as there may be inner function definitions
  2193  		case constDecl, varDecl:
  2194  			setExec(n.start)
  2195  			return false
  2196  		}
  2197  		return true
  2198  	}, nil)
  2199  
  2200  	return err
  2201  }
  2202  
  2203  func genGlobalVars(roots []*node, sc *scope) (*node, error) {
  2204  	var vars []*node
  2205  	for _, n := range roots {
  2206  		vars = append(vars, getVars(n)...)
  2207  	}
  2208  
  2209  	if len(vars) == 0 {
  2210  		return nil, nil
  2211  	}
  2212  
  2213  	varNode, err := genGlobalVarDecl(vars, sc)
  2214  	if err != nil {
  2215  		return nil, err
  2216  	}
  2217  	setExec(varNode.start)
  2218  	return varNode, nil
  2219  }
  2220  
  2221  func getVars(n *node) (vars []*node) {
  2222  	for _, child := range n.child {
  2223  		if child.kind == varDecl {
  2224  			vars = append(vars, child.child...)
  2225  		}
  2226  	}
  2227  	return vars
  2228  }
  2229  
  2230  func genGlobalVarDecl(nodes []*node, sc *scope) (*node, error) {
  2231  	varNode := &node{kind: varDecl, action: aNop, gen: nop}
  2232  
  2233  	deps := map[*node][]*node{}
  2234  	for _, n := range nodes {
  2235  		deps[n] = getVarDependencies(n, sc)
  2236  	}
  2237  
  2238  	inited := map[*node]bool{}
  2239  	revisit := []*node{}
  2240  	for {
  2241  		for _, n := range nodes {
  2242  			canInit := true
  2243  			for _, d := range deps[n] {
  2244  				if !inited[d] {
  2245  					canInit = false
  2246  				}
  2247  			}
  2248  			if !canInit {
  2249  				revisit = append(revisit, n)
  2250  				continue
  2251  			}
  2252  
  2253  			varNode.child = append(varNode.child, n)
  2254  			inited[n] = true
  2255  		}
  2256  
  2257  		if len(revisit) == 0 || equalNodes(nodes, revisit) {
  2258  			break
  2259  		}
  2260  
  2261  		nodes = revisit
  2262  		revisit = []*node{}
  2263  	}
  2264  
  2265  	if len(revisit) > 0 {
  2266  		return nil, revisit[0].cfgErrorf("variable definition loop")
  2267  	}
  2268  	wireChild(varNode)
  2269  	return varNode, nil
  2270  }
  2271  
  2272  func getVarDependencies(nod *node, sc *scope) (deps []*node) {
  2273  	nod.Walk(func(n *node) bool {
  2274  		if n.kind == identExpr {
  2275  			if sym, _, ok := sc.lookup(n.ident); ok {
  2276  				if sym.kind != varSym || !sym.global || sym.node == nod {
  2277  					return false
  2278  				}
  2279  				deps = append(deps, sym.node)
  2280  			}
  2281  		}
  2282  		return true
  2283  	}, nil)
  2284  	return deps
  2285  }
  2286  
  2287  // setFnext sets the cond fnext field to next, propagates it for parenthesis blocks
  2288  // and sets the action to branch.
  2289  func setFNext(cond, next *node) {
  2290  	if cond.action == aNop {
  2291  		cond.action = aBranch
  2292  		cond.gen = branch
  2293  		cond.fnext = next
  2294  	}
  2295  	if cond.kind == parenExpr {
  2296  		setFNext(cond.lastChild(), next)
  2297  		return
  2298  	}
  2299  	cond.fnext = next
  2300  }
  2301  
  2302  // GetDefault return the index of default case clause in a switch statement, or -1.
  2303  func getDefault(n *node) int {
  2304  	for i, c := range n.lastChild().child {
  2305  		switch len(c.child) {
  2306  		case 0:
  2307  			return i
  2308  		case 1:
  2309  			if c.child[0].kind == caseBody {
  2310  				return i
  2311  			}
  2312  		}
  2313  	}
  2314  	return -1
  2315  }
  2316  
  2317  func isBinType(v reflect.Value) bool { return v.IsValid() && v.Kind() == reflect.Ptr && v.IsNil() }
  2318  
  2319  // isType returns true if node refers to a type definition, false otherwise.
  2320  func (n *node) isType(sc *scope) bool {
  2321  	switch n.kind {
  2322  	case arrayType, chanType, chanTypeRecv, chanTypeSend, funcType, interfaceType, mapType, structType:
  2323  		return true
  2324  	case parenExpr, starExpr:
  2325  		if len(n.child) == 1 {
  2326  			return n.child[0].isType(sc)
  2327  		}
  2328  	case selectorExpr:
  2329  		pkg, name := n.child[0].ident, n.child[1].ident
  2330  		baseName := filepath.Base(n.interp.fset.Position(n.pos).Filename)
  2331  		suffixedPkg := filepath.Join(pkg, baseName)
  2332  		sym, _, ok := sc.lookup(suffixedPkg)
  2333  		if !ok {
  2334  			sym, _, ok = sc.lookup(pkg)
  2335  			if !ok {
  2336  				return false
  2337  			}
  2338  		}
  2339  		if sym.kind != pkgSym {
  2340  			return false
  2341  		}
  2342  		path := sym.typ.path
  2343  		if p, ok := n.interp.binPkg[path]; ok && isBinType(p[name]) {
  2344  			return true // Imported binary type
  2345  		}
  2346  		if p, ok := n.interp.srcPkg[path]; ok && p[name] != nil && p[name].kind == typeSym {
  2347  			return true // Imported source type
  2348  		}
  2349  	case identExpr:
  2350  		return sc.getType(n.ident) != nil
  2351  	}
  2352  	return false
  2353  }
  2354  
  2355  // wireChild wires AST nodes for CFG in subtree.
  2356  func wireChild(n *node, exclude ...nkind) {
  2357  	child := excludeNodeKind(n.child, exclude)
  2358  
  2359  	// Set start node, in subtree (propagated to ancestors by post-order processing)
  2360  	for _, c := range child {
  2361  		switch c.kind {
  2362  		case arrayType, chanType, chanTypeRecv, chanTypeSend, funcDecl, importDecl, mapType, basicLit, identExpr, typeDecl:
  2363  			continue
  2364  		default:
  2365  			n.start = c.start
  2366  		}
  2367  		break
  2368  	}
  2369  
  2370  	// Chain sequential operations inside a block (next is right sibling)
  2371  	for i := 1; i < len(child); i++ {
  2372  		switch child[i].kind {
  2373  		case funcDecl:
  2374  			child[i-1].tnext = child[i]
  2375  		default:
  2376  			switch child[i-1].kind {
  2377  			case breakStmt, continueStmt, gotoStmt, returnStmt:
  2378  				// tnext is already computed, no change
  2379  			default:
  2380  				child[i-1].tnext = child[i].start
  2381  			}
  2382  		}
  2383  	}
  2384  
  2385  	// Chain subtree next to self
  2386  	for i := len(child) - 1; i >= 0; i-- {
  2387  		switch child[i].kind {
  2388  		case arrayType, chanType, chanTypeRecv, chanTypeSend, importDecl, mapType, funcDecl, basicLit, identExpr, typeDecl:
  2389  			continue
  2390  		case breakStmt, continueStmt, gotoStmt, returnStmt:
  2391  			// tnext is already computed, no change
  2392  		default:
  2393  			child[i].tnext = n
  2394  		}
  2395  		break
  2396  	}
  2397  }
  2398  
  2399  func excludeNodeKind(child []*node, kinds []nkind) []*node {
  2400  	if len(kinds) == 0 {
  2401  		return child
  2402  	}
  2403  	var res []*node
  2404  	for _, c := range child {
  2405  		exclude := false
  2406  		for _, k := range kinds {
  2407  			if c.kind == k {
  2408  				exclude = true
  2409  			}
  2410  		}
  2411  		if !exclude {
  2412  			res = append(res, c)
  2413  		}
  2414  	}
  2415  	return res
  2416  }
  2417  
  2418  func (n *node) name() (s string) {
  2419  	switch {
  2420  	case n.ident != "":
  2421  		s = n.ident
  2422  	case n.action == aGetSym:
  2423  		s = n.child[0].ident + "." + n.child[1].ident
  2424  	}
  2425  	return s
  2426  }
  2427  
  2428  // isNatural returns true if node type is natural, false otherwise.
  2429  func (n *node) isNatural() bool {
  2430  	if isUint(n.typ.TypeOf()) {
  2431  		return true
  2432  	}
  2433  	if n.rval.IsValid() {
  2434  		t := n.rval.Type()
  2435  		if isUint(t) {
  2436  			return true
  2437  		}
  2438  		if isInt(t) && n.rval.Int() >= 0 {
  2439  			// positive untyped integer constant is ok
  2440  			return true
  2441  		}
  2442  		if isFloat(t) {
  2443  			// positive untyped float constant with null decimal part is ok
  2444  			f := n.rval.Float()
  2445  			if f == math.Trunc(f) && f >= 0 {
  2446  				n.rval = reflect.ValueOf(uint(f))
  2447  				n.typ.rtype = n.rval.Type()
  2448  				return true
  2449  			}
  2450  		}
  2451  		if isConstantValue(t) {
  2452  			c := n.rval.Interface().(constant.Value)
  2453  			switch c.Kind() {
  2454  			case constant.Int:
  2455  				i, _ := constant.Int64Val(c)
  2456  				if i >= 0 {
  2457  					return true
  2458  				}
  2459  			case constant.Float:
  2460  				f, _ := constant.Float64Val(c)
  2461  				if f == math.Trunc(f) {
  2462  					n.rval = reflect.ValueOf(constant.ToInt(c))
  2463  					n.typ.rtype = n.rval.Type()
  2464  					return true
  2465  				}
  2466  			}
  2467  		}
  2468  	}
  2469  	return false
  2470  }
  2471  
  2472  // isNil returns true if node is a literal nil value, false otherwise.
  2473  func (n *node) isNil() bool { return n.kind == basicLit && !n.rval.IsValid() }
  2474  
  2475  // fieldType returns the nth parameter field node (type) of a fieldList node.
  2476  func (n *node) fieldType(m int) *node {
  2477  	k := 0
  2478  	l := len(n.child)
  2479  	for i := 0; i < l; i++ {
  2480  		cl := len(n.child[i].child)
  2481  		if cl < 2 {
  2482  			if k == m {
  2483  				return n.child[i].lastChild()
  2484  			}
  2485  			k++
  2486  			continue
  2487  		}
  2488  		for j := 0; j < cl-1; j++ {
  2489  			if k == m {
  2490  				return n.child[i].lastChild()
  2491  			}
  2492  			k++
  2493  		}
  2494  	}
  2495  	return nil
  2496  }
  2497  
  2498  // lastChild returns the last child of a node.
  2499  func (n *node) lastChild() *node { return n.child[len(n.child)-1] }
  2500  
  2501  func (n *node) hasAnc(nod *node) bool {
  2502  	for a := n.anc; a != nil; a = a.anc {
  2503  		if a == nod {
  2504  			return true
  2505  		}
  2506  	}
  2507  	return false
  2508  }
  2509  
  2510  func isKey(n *node) bool {
  2511  	return n.anc.kind == fileStmt ||
  2512  		(n.anc.kind == selectorExpr && n.anc.child[0] != n) ||
  2513  		(n.anc.kind == funcDecl && isMethod(n.anc)) ||
  2514  		(n.anc.kind == keyValueExpr && isStruct(n.anc.typ) && n.anc.child[0] == n) ||
  2515  		(n.anc.kind == fieldExpr && len(n.anc.child) > 1 && n.anc.child[0] == n)
  2516  }
  2517  
  2518  func isField(n *node) bool {
  2519  	return n.kind == selectorExpr && len(n.child) > 0 && n.child[0].typ != nil && isStruct(n.child[0].typ)
  2520  }
  2521  
  2522  func isInConstOrTypeDecl(n *node) bool {
  2523  	anc := n.anc
  2524  	for anc != nil {
  2525  		switch anc.kind {
  2526  		case constDecl, typeDecl, arrayType, chanType:
  2527  			return true
  2528  		case varDecl, funcDecl:
  2529  			return false
  2530  		}
  2531  		anc = anc.anc
  2532  	}
  2533  	return false
  2534  }
  2535  
  2536  // isNewDefine returns true if node refers to a new definition.
  2537  func isNewDefine(n *node, sc *scope) bool {
  2538  	if n.ident == "_" {
  2539  		return true
  2540  	}
  2541  	if (n.anc.kind == defineXStmt || n.anc.kind == defineStmt || n.anc.kind == valueSpec) && childPos(n) < n.anc.nleft {
  2542  		return true
  2543  	}
  2544  	if n.anc.kind == rangeStmt {
  2545  		if n.anc.child[0] == n {
  2546  			return true // array or map key, or chan element
  2547  		}
  2548  		if sc.rangeChanType(n.anc) == nil && n.anc.child[1] == n && len(n.anc.child) == 4 {
  2549  			return true // array or map value
  2550  		}
  2551  		return false // array, map or channel are always pre-defined in range expression
  2552  	}
  2553  	return false
  2554  }
  2555  
  2556  func isMethod(n *node) bool {
  2557  	return len(n.child[0].child) > 0 // receiver defined
  2558  }
  2559  
  2560  func isFuncField(n *node) bool {
  2561  	return isField(n) && isFunc(n.typ)
  2562  }
  2563  
  2564  func isMapEntry(n *node) bool {
  2565  	return n.action == aGetIndex && isMap(n.child[0].typ)
  2566  }
  2567  
  2568  func isCall(n *node) bool {
  2569  	return n.action == aCall || n.action == aCallSlice
  2570  }
  2571  
  2572  func isBinCall(n *node, sc *scope) bool {
  2573  	if !isCall(n) || len(n.child) == 0 {
  2574  		return false
  2575  	}
  2576  	c0 := n.child[0]
  2577  	if c0.typ == nil {
  2578  		// If called early in parsing, child type may not be known yet.
  2579  		c0.typ, _ = nodeType(n.interp, sc, c0)
  2580  		if c0.typ == nil {
  2581  			return false
  2582  		}
  2583  	}
  2584  	return c0.typ.cat == valueT && c0.typ.rtype.Kind() == reflect.Func
  2585  }
  2586  
  2587  func isOffsetof(n *node) bool {
  2588  	return isCall(n) && n.child[0].typ.cat == valueT && n.child[0].rval.String() == "Offsetof"
  2589  }
  2590  
  2591  func mustReturnValue(n *node) bool {
  2592  	if len(n.child) < 2 {
  2593  		return false
  2594  	}
  2595  	for _, f := range n.child[1].child {
  2596  		if len(f.child) > 1 {
  2597  			return false
  2598  		}
  2599  	}
  2600  	return true
  2601  }
  2602  
  2603  func isRegularCall(n *node) bool {
  2604  	return isCall(n) && n.child[0].typ.cat == funcT
  2605  }
  2606  
  2607  func variadicPos(n *node) int {
  2608  	if len(n.child[0].typ.arg) == 0 {
  2609  		return -1
  2610  	}
  2611  	last := len(n.child[0].typ.arg) - 1
  2612  	if n.child[0].typ.arg[last].cat == variadicT {
  2613  		return last
  2614  	}
  2615  	return -1
  2616  }
  2617  
  2618  func canExport(name string) bool {
  2619  	if r := []rune(name); len(r) > 0 && unicode.IsUpper(r[0]) {
  2620  		return true
  2621  	}
  2622  	return false
  2623  }
  2624  
  2625  func getExec(n *node) bltn {
  2626  	if n == nil {
  2627  		return nil
  2628  	}
  2629  	if n.exec == nil {
  2630  		setExec(n)
  2631  	}
  2632  	return n.exec
  2633  }
  2634  
  2635  // setExec recursively sets the node exec builtin function by walking the CFG
  2636  // from the entry point (first node to exec).
  2637  func setExec(n *node) {
  2638  	if n.exec != nil {
  2639  		return
  2640  	}
  2641  	seen := map[*node]bool{}
  2642  	var set func(n *node)
  2643  
  2644  	set = func(n *node) {
  2645  		if n == nil || n.exec != nil {
  2646  			return
  2647  		}
  2648  		seen[n] = true
  2649  		if n.tnext != nil && n.tnext.exec == nil {
  2650  			if seen[n.tnext] {
  2651  				m := n.tnext
  2652  				n.tnext.exec = func(f *frame) bltn { return m.exec(f) }
  2653  			} else {
  2654  				set(n.tnext)
  2655  			}
  2656  		}
  2657  		if n.fnext != nil && n.fnext.exec == nil {
  2658  			if seen[n.fnext] {
  2659  				m := n.fnext
  2660  				n.fnext.exec = func(f *frame) bltn { return m.exec(f) }
  2661  			} else {
  2662  				set(n.fnext)
  2663  			}
  2664  		}
  2665  		n.gen(n)
  2666  	}
  2667  
  2668  	set(n)
  2669  }
  2670  
  2671  func typeSwichAssign(n *node) bool {
  2672  	ts := n.anc.anc.anc
  2673  	return ts.kind == typeSwitch && ts.child[1].action == aAssign
  2674  }
  2675  
  2676  func compositeGenerator(n *node, typ *itype, rtyp reflect.Type) (gen bltnGenerator) {
  2677  	switch typ.cat {
  2678  	case aliasT, ptrT:
  2679  		gen = compositeGenerator(n, typ.val, rtyp)
  2680  	case arrayT, sliceT:
  2681  		gen = arrayLit
  2682  	case mapT:
  2683  		gen = mapLit
  2684  	case structT:
  2685  		switch {
  2686  		case len(n.child) == 0:
  2687  			gen = compositeLitNotype
  2688  		case n.lastChild().kind == keyValueExpr:
  2689  			if n.nleft == 1 {
  2690  				gen = compositeLitKeyed
  2691  			} else {
  2692  				gen = compositeLitKeyedNotype
  2693  			}
  2694  		default:
  2695  			if n.nleft == 1 {
  2696  				gen = compositeLit
  2697  			} else {
  2698  				gen = compositeLitNotype
  2699  			}
  2700  		}
  2701  	case valueT:
  2702  		if rtyp == nil {
  2703  			rtyp = n.typ.TypeOf()
  2704  		}
  2705  		switch k := rtyp.Kind(); k {
  2706  		case reflect.Struct:
  2707  			if n.nleft == 1 {
  2708  				gen = compositeBinStruct
  2709  			} else {
  2710  				gen = compositeBinStructNotype
  2711  			}
  2712  		case reflect.Map:
  2713  			// TODO(mpl): maybe needs a NoType version too
  2714  			gen = compositeBinMap
  2715  		case reflect.Ptr:
  2716  			gen = compositeGenerator(n, typ, n.typ.val.rtype)
  2717  		case reflect.Slice, reflect.Array:
  2718  			gen = compositeBinSlice
  2719  		default:
  2720  			log.Panic(n.cfgErrorf("compositeGenerator not implemented for type kind: %s", k))
  2721  		}
  2722  	}
  2723  	return gen
  2724  }
  2725  
  2726  // arrayTypeLen returns the node's array length. If the expression is an
  2727  // array variable it is determined from the value's type, otherwise it is
  2728  // computed from the source definition.
  2729  func arrayTypeLen(n *node, sc *scope) (int, error) {
  2730  	if n.typ != nil && n.typ.cat == arrayT {
  2731  		return n.typ.length, nil
  2732  	}
  2733  	max := -1
  2734  	for _, c := range n.child[1:] {
  2735  		var r int
  2736  
  2737  		if c.kind != keyValueExpr {
  2738  			r = max + 1
  2739  			max = r
  2740  			continue
  2741  		}
  2742  
  2743  		c0 := c.child[0]
  2744  		v := c0.rval
  2745  		if v.IsValid() {
  2746  			r = int(v.Int())
  2747  		} else {
  2748  			// Resolve array key value as a constant.
  2749  			if c0.kind == identExpr {
  2750  				// Key is defined by a symbol which must be a constant integer.
  2751  				sym, _, ok := sc.lookup(c0.ident)
  2752  				if !ok {
  2753  					return 0, c0.cfgErrorf("undefined: %s", c0.ident)
  2754  				}
  2755  				if sym.kind != constSym {
  2756  					return 0, c0.cfgErrorf("non-constant array bound %q", c0.ident)
  2757  				}
  2758  				r = int(vInt(sym.rval))
  2759  			} else {
  2760  				// Key is defined by a numeric constant expression.
  2761  				if _, err := c0.interp.cfg(c0, sc, sc.pkgID, sc.pkgName); err != nil {
  2762  					return 0, err
  2763  				}
  2764  				cv, ok := c0.rval.Interface().(constant.Value)
  2765  				if !ok {
  2766  					return 0, c0.cfgErrorf("non-constant expression")
  2767  				}
  2768  				r = constToInt(cv)
  2769  			}
  2770  		}
  2771  
  2772  		if r > max {
  2773  			max = r
  2774  		}
  2775  	}
  2776  	return max + 1, nil
  2777  }
  2778  
  2779  // isValueUntyped returns true if value is untyped.
  2780  func isValueUntyped(v reflect.Value) bool {
  2781  	// Consider only constant values.
  2782  	if v.CanSet() {
  2783  		return false
  2784  	}
  2785  	return v.Type().Implements(constVal)
  2786  }
  2787  
  2788  // isArithmeticAction returns true if the node action is an arithmetic operator.
  2789  func isArithmeticAction(n *node) bool {
  2790  	switch n.action {
  2791  	case aAdd, aAnd, aAndNot, aBitNot, aMul, aNeg, aOr, aPos, aQuo, aRem, aShl, aShr, aSub, aXor:
  2792  		return true
  2793  	}
  2794  	return false
  2795  }
  2796  
  2797  func isBoolAction(n *node) bool {
  2798  	switch n.action {
  2799  	case aEqual, aGreater, aGreaterEqual, aLand, aLor, aLower, aLowerEqual, aNot, aNotEqual:
  2800  		return true
  2801  	}
  2802  	return false
  2803  }
  2804  
  2805  func isBlank(n *node) bool {
  2806  	if n.kind == parenExpr && len(n.child) > 0 {
  2807  		return isBlank(n.child[0])
  2808  	}
  2809  	return n.ident == "_"
  2810  }