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