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