github.com/gmemcc/yaegi@v0.12.1-0.20221128122509-aa99124c5d16/interp/ast.go (about)

     1  package interp
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/constant"
     7  	"go/parser"
     8  	"go/scanner"
     9  	"go/token"
    10  	"reflect"
    11  	"strconv"
    12  	"strings"
    13  	"sync/atomic"
    14  )
    15  
    16  // nkind defines the kind of AST, i.e. the grammar category.
    17  type nkind uint
    18  
    19  // Node kinds for the go language.
    20  const (
    21  	undefNode nkind = iota
    22  	addressExpr
    23  	arrayType
    24  	assignStmt
    25  	assignXStmt
    26  	basicLit
    27  	binaryExpr
    28  	blockStmt
    29  	branchStmt
    30  	breakStmt
    31  	callExpr
    32  	caseBody
    33  	caseClause
    34  	chanType
    35  	chanTypeSend
    36  	chanTypeRecv
    37  	commClause
    38  	commClauseDefault
    39  	compositeLitExpr
    40  	constDecl
    41  	continueStmt
    42  	declStmt
    43  	deferStmt
    44  	defineStmt
    45  	defineXStmt
    46  	ellipsisExpr
    47  	exprStmt
    48  	fallthroughtStmt
    49  	fieldExpr
    50  	fieldList
    51  	fileStmt
    52  	forStmt0     // for {}
    53  	forStmt1     // for init; ; {}
    54  	forStmt2     // for cond {}
    55  	forStmt3     // for init; cond; {}
    56  	forStmt4     // for ; ; post {}
    57  	forStmt5     // for ; cond; post {}
    58  	forStmt6     // for init; ; post {}
    59  	forStmt7     // for init; cond; post {}
    60  	forRangeStmt // for range {}
    61  	funcDecl
    62  	funcLit
    63  	funcType
    64  	goStmt
    65  	gotoStmt
    66  	identExpr
    67  	ifStmt0 // if cond {}
    68  	ifStmt1 // if cond {} else {}
    69  	ifStmt2 // if init; cond {}
    70  	ifStmt3 // if init; cond {} else {}
    71  	importDecl
    72  	importSpec
    73  	incDecStmt
    74  	indexExpr
    75  	interfaceType
    76  	keyValueExpr
    77  	labeledStmt
    78  	landExpr
    79  	lorExpr
    80  	mapType
    81  	parenExpr
    82  	rangeStmt
    83  	returnStmt
    84  	selectStmt
    85  	selectorExpr
    86  	selectorImport
    87  	sendStmt
    88  	sliceExpr
    89  	starExpr
    90  	structType
    91  	switchStmt
    92  	switchIfStmt
    93  	typeAssertExpr
    94  	typeDecl
    95  	typeSpec       // type A int
    96  	typeSpecAssign // type A = int
    97  	typeSwitch
    98  	unaryExpr
    99  	valueSpec
   100  	varDecl
   101  )
   102  
   103  var kinds = [...]string{
   104  	undefNode:         "undefNode",
   105  	addressExpr:       "addressExpr",
   106  	arrayType:         "arrayType",
   107  	assignStmt:        "assignStmt",
   108  	assignXStmt:       "assignXStmt",
   109  	basicLit:          "basicLit",
   110  	binaryExpr:        "binaryExpr",
   111  	blockStmt:         "blockStmt",
   112  	branchStmt:        "branchStmt",
   113  	breakStmt:         "breakStmt",
   114  	callExpr:          "callExpr",
   115  	caseBody:          "caseBody",
   116  	caseClause:        "caseClause",
   117  	chanType:          "chanType",
   118  	chanTypeSend:      "chanTypeSend",
   119  	chanTypeRecv:      "chanTypeRecv",
   120  	commClause:        "commClause",
   121  	commClauseDefault: "commClauseDefault",
   122  	compositeLitExpr:  "compositeLitExpr",
   123  	constDecl:         "constDecl",
   124  	continueStmt:      "continueStmt",
   125  	declStmt:          "declStmt",
   126  	deferStmt:         "deferStmt",
   127  	defineStmt:        "defineStmt",
   128  	defineXStmt:       "defineXStmt",
   129  	ellipsisExpr:      "ellipsisExpr",
   130  	exprStmt:          "exprStmt",
   131  	fallthroughtStmt:  "fallthroughStmt",
   132  	fieldExpr:         "fieldExpr",
   133  	fieldList:         "fieldList",
   134  	fileStmt:          "fileStmt",
   135  	forStmt0:          "forStmt0",
   136  	forStmt1:          "forStmt1",
   137  	forStmt2:          "forStmt2",
   138  	forStmt3:          "forStmt3",
   139  	forStmt4:          "forStmt4",
   140  	forStmt5:          "forStmt5",
   141  	forStmt6:          "forStmt6",
   142  	forStmt7:          "forStmt7",
   143  	forRangeStmt:      "forRangeStmt",
   144  	funcDecl:          "funcDecl",
   145  	funcType:          "funcType",
   146  	funcLit:           "funcLit",
   147  	goStmt:            "goStmt",
   148  	gotoStmt:          "gotoStmt",
   149  	identExpr:         "identExpr",
   150  	ifStmt0:           "ifStmt0",
   151  	ifStmt1:           "ifStmt1",
   152  	ifStmt2:           "ifStmt2",
   153  	ifStmt3:           "ifStmt3",
   154  	importDecl:        "importDecl",
   155  	importSpec:        "importSpec",
   156  	incDecStmt:        "incDecStmt",
   157  	indexExpr:         "indexExpr",
   158  	interfaceType:     "interfaceType",
   159  	keyValueExpr:      "keyValueExpr",
   160  	labeledStmt:       "labeledStmt",
   161  	landExpr:          "landExpr",
   162  	lorExpr:           "lorExpr",
   163  	mapType:           "mapType",
   164  	parenExpr:         "parenExpr",
   165  	rangeStmt:         "rangeStmt",
   166  	returnStmt:        "returnStmt",
   167  	selectStmt:        "selectStmt",
   168  	selectorExpr:      "selectorExpr",
   169  	selectorImport:    "selectorImport",
   170  	sendStmt:          "sendStmt",
   171  	sliceExpr:         "sliceExpr",
   172  	starExpr:          "starExpr",
   173  	structType:        "structType",
   174  	switchStmt:        "switchStmt",
   175  	switchIfStmt:      "switchIfStmt",
   176  	typeAssertExpr:    "typeAssertExpr",
   177  	typeDecl:          "typeDecl",
   178  	typeSpec:          "typeSpec",
   179  	typeSpecAssign:    "typeSpecAssign",
   180  	typeSwitch:        "typeSwitch",
   181  	unaryExpr:         "unaryExpr",
   182  	valueSpec:         "valueSpec",
   183  	varDecl:           "varDecl",
   184  }
   185  
   186  func (k nkind) String() string {
   187  	if k < nkind(len(kinds)) {
   188  		return kinds[k]
   189  	}
   190  	return "nKind(" + strconv.Itoa(int(k)) + ")"
   191  }
   192  
   193  // astError represents an error during AST build stage.
   194  type astError error
   195  
   196  // action defines the node action to perform at execution.
   197  type action uint
   198  
   199  // Node actions for the go language.
   200  // It is important for type checking that *Assign directly
   201  // follows it non-assign counterpart.
   202  const (
   203  	aNop action = iota
   204  	aAddr
   205  	aAssign
   206  	aAssignX
   207  	aAdd
   208  	aAddAssign
   209  	aAnd
   210  	aAndAssign
   211  	aAndNot
   212  	aAndNotAssign
   213  	aBitNot
   214  	aBranch
   215  	aCall
   216  	aCallSlice
   217  	aCase
   218  	aCompositeLit
   219  	aConvert
   220  	aDec
   221  	aEqual
   222  	aGreater
   223  	aGreaterEqual
   224  	aGetFunc
   225  	aGetIndex
   226  	aGetMethod
   227  	aGetSym
   228  	aInc
   229  	aLand
   230  	aLor
   231  	aLower
   232  	aLowerEqual
   233  	aMethod
   234  	aMul
   235  	aMulAssign
   236  	aNeg
   237  	aNot
   238  	aNotEqual
   239  	aOr
   240  	aOrAssign
   241  	aPos
   242  	aQuo
   243  	aQuoAssign
   244  	aRange
   245  	aRecv
   246  	aRem
   247  	aRemAssign
   248  	aReturn
   249  	aSend
   250  	aShl
   251  	aShlAssign
   252  	aShr
   253  	aShrAssign
   254  	aSlice
   255  	aSlice0
   256  	aStar
   257  	aSub
   258  	aSubAssign
   259  	aTypeAssert
   260  	aXor
   261  	aXorAssign
   262  )
   263  
   264  var actions = [...]string{
   265  	aNop:          "nop",
   266  	aAddr:         "&",
   267  	aAssign:       "=",
   268  	aAssignX:      "X=",
   269  	aAdd:          "+",
   270  	aAddAssign:    "+=",
   271  	aAnd:          "&",
   272  	aAndAssign:    "&=",
   273  	aAndNot:       "&^",
   274  	aAndNotAssign: "&^=",
   275  	aBitNot:       "^",
   276  	aBranch:       "branch",
   277  	aCall:         "call",
   278  	aCallSlice:    "callSlice",
   279  	aCase:         "case",
   280  	aCompositeLit: "compositeLit",
   281  	aConvert:      "convert",
   282  	aDec:          "--",
   283  	aEqual:        "==",
   284  	aGreater:      ">",
   285  	aGreaterEqual: ">=",
   286  	aGetFunc:      "getFunc",
   287  	aGetIndex:     "getIndex",
   288  	aGetMethod:    "getMethod",
   289  	aGetSym:       ".",
   290  	aInc:          "++",
   291  	aLand:         "&&",
   292  	aLor:          "||",
   293  	aLower:        "<",
   294  	aLowerEqual:   "<=",
   295  	aMethod:       "Method",
   296  	aMul:          "*",
   297  	aMulAssign:    "*=",
   298  	aNeg:          "-",
   299  	aNot:          "!",
   300  	aNotEqual:     "!=",
   301  	aOr:           "|",
   302  	aOrAssign:     "|=",
   303  	aPos:          "+",
   304  	aQuo:          "/",
   305  	aQuoAssign:    "/=",
   306  	aRange:        "range",
   307  	aRecv:         "<-",
   308  	aRem:          "%",
   309  	aRemAssign:    "%=",
   310  	aReturn:       "return",
   311  	aSend:         "<~",
   312  	aShl:          "<<",
   313  	aShlAssign:    "<<=",
   314  	aShr:          ">>",
   315  	aShrAssign:    ">>=",
   316  	aSlice:        "slice",
   317  	aSlice0:       "slice0",
   318  	aStar:         "*",
   319  	aSub:          "-",
   320  	aSubAssign:    "-=",
   321  	aTypeAssert:   "TypeAssert",
   322  	aXor:          "^",
   323  	aXorAssign:    "^=",
   324  }
   325  
   326  func (a action) String() string {
   327  	if a < action(len(actions)) {
   328  		return actions[a]
   329  	}
   330  	return "Action(" + strconv.Itoa(int(a)) + ")"
   331  }
   332  
   333  func isAssignAction(a action) bool {
   334  	switch a {
   335  	case aAddAssign, aAndAssign, aAndNotAssign, aMulAssign, aOrAssign,
   336  		aQuoAssign, aRemAssign, aShlAssign, aShrAssign, aSubAssign, aXorAssign:
   337  		return true
   338  	}
   339  	return false
   340  }
   341  
   342  func (interp *Interpreter) firstToken(src string) token.Token {
   343  	var s scanner.Scanner
   344  	file := interp.fset.AddFile("", interp.fset.Base(), len(src))
   345  	s.Init(file, []byte(src), nil, 0)
   346  
   347  	_, tok, _ := s.Scan()
   348  	return tok
   349  }
   350  
   351  func ignoreError(err error, src string) bool {
   352  	se, ok := err.(scanner.ErrorList)
   353  	if !ok {
   354  		return false
   355  	}
   356  	if len(se) == 0 {
   357  		return false
   358  	}
   359  	return ignoreScannerError(se[0], src)
   360  }
   361  
   362  func wrapInMain(src string) string {
   363  	return fmt.Sprintf("package main; func main() {%s\n}", src)
   364  }
   365  
   366  func (interp *Interpreter) parse(src, name string, inc bool) (node ast.Node, err error) {
   367  	mode := parser.DeclarationErrors
   368  
   369  	// Allow incremental parsing of declarations or statements, by inserting
   370  	// them in a pseudo file package or function. Those statements or
   371  	// declarations will be always evaluated in the global scope.
   372  	var tok token.Token
   373  	var inFunc bool
   374  	if inc {
   375  		tok = interp.firstToken(src)
   376  		switch tok {
   377  		case token.PACKAGE:
   378  			// nothing to do.
   379  		case token.CONST, token.FUNC, token.IMPORT, token.TYPE, token.VAR:
   380  			src = "package main;" + src
   381  		default:
   382  			inFunc = true
   383  			src = wrapInMain(src)
   384  		}
   385  		// Parse comments in REPL mode, to allow tag setting.
   386  		mode |= parser.ParseComments
   387  	}
   388  
   389  	if ok, err := interp.buildOk(&interp.context, name, src); !ok || err != nil {
   390  		return nil, err // skip source not matching build constraints
   391  	}
   392  
   393  	f, err := parser.ParseFile(interp.fset, name, src, mode)
   394  	if err != nil {
   395  		// only retry if we're on an expression/statement about a func
   396  		if !inc || tok != token.FUNC {
   397  			return nil, err
   398  		}
   399  		// do not bother retrying if we know it's an error we're going to ignore later on.
   400  		if ignoreError(err, src) {
   401  			return nil, err
   402  		}
   403  		// do not lose initial error, in case retrying fails.
   404  		initialError := err
   405  		// retry with default source code "wrapping", in the main function scope.
   406  		src := wrapInMain(strings.TrimPrefix(src, "package main;"))
   407  		f, err = parser.ParseFile(interp.fset, name, src, mode)
   408  		if err != nil {
   409  			return nil, initialError
   410  		}
   411  	}
   412  
   413  	if inFunc {
   414  		// return the body of the wrapper main function
   415  		return f.Decls[0].(*ast.FuncDecl).Body, nil
   416  	}
   417  
   418  	setYaegiTags(&interp.context, f.Comments)
   419  	return f, nil
   420  }
   421  
   422  // Note: no type analysis is performed at this stage, it is done in pre-order
   423  // processing of CFG, in order to accommodate forward type declarations.
   424  
   425  // ast parses src string containing Go code and generates the corresponding AST.
   426  // The package name and the AST root node are returned.
   427  // The given name is used to set the filename of the relevant source file in the
   428  // interpreter's FileSet.
   429  func (interp *Interpreter) ast(f ast.Node) (string, *node, error) {
   430  	var err error
   431  	var root *node
   432  	var anc astNode
   433  	var st nodestack
   434  	pkgName := "main"
   435  
   436  	addChild := func(root **node, anc astNode, pos, end token.Pos, kind nkind, act action) *node {
   437  		var i interface{}
   438  		nindex := atomic.AddInt64(&interp.nindex, 1)
   439  		n := &node{anc: anc.node, interp: interp, index: nindex, pos: pos, end: end, kind: kind, action: act, val: &i, gen: builtin[act]}
   440  		n.start = n
   441  		if anc.node == nil {
   442  			*root = n
   443  		} else {
   444  			anc.node.child = append(anc.node.child, n)
   445  			if anc.node.action == aCase {
   446  				ancAst := anc.ast.(*ast.CaseClause)
   447  				if len(ancAst.List)+len(ancAst.Body) == len(anc.node.child) {
   448  					// All case clause children are collected.
   449  					// Split children in condition and body nodes to desambiguify the AST.
   450  					nindex = atomic.AddInt64(&interp.nindex, 1)
   451  					body := &node{anc: anc.node, interp: interp, index: nindex, pos: pos, kind: caseBody, action: aNop, val: &i, gen: nop}
   452  
   453  					if ts := anc.node.anc.anc; ts.kind == typeSwitch && ts.child[1].action == aAssign {
   454  						// In type switch clause, if a switch guard is assigned, duplicate the switch guard symbol
   455  						// in each clause body, so a different guard type can be set in each clause
   456  						name := ts.child[1].child[0].ident
   457  						nindex = atomic.AddInt64(&interp.nindex, 1)
   458  						gn := &node{anc: body, interp: interp, ident: name, index: nindex, pos: pos, kind: identExpr, action: aNop, val: &i, gen: nop}
   459  						body.child = append(body.child, gn)
   460  					}
   461  
   462  					// Add regular body children
   463  					body.child = append(body.child, anc.node.child[len(ancAst.List):]...)
   464  					for i := range body.child {
   465  						body.child[i].anc = body
   466  					}
   467  					anc.node.child = append(anc.node.child[:len(ancAst.List)], body)
   468  				}
   469  			}
   470  		}
   471  		return n
   472  	}
   473  
   474  	// Populate our own private AST from Go parser AST.
   475  	// A stack of ancestor nodes is used to keep track of current ancestor for each depth level
   476  	ast.Inspect(f, func(nod ast.Node) bool {
   477  		anc = st.top()
   478  		var pos, end token.Pos
   479  		if nod != nil {
   480  			pos = nod.Pos()
   481  			end = nod.End()
   482  		}
   483  		switch a := nod.(type) {
   484  		case nil:
   485  			anc = st.pop()
   486  
   487  		case *ast.ArrayType:
   488  			st.push(addChild(&root, anc, pos, end, arrayType, aNop), nod)
   489  
   490  		case *ast.AssignStmt:
   491  			var act action
   492  			var kind nkind
   493  			if len(a.Lhs) > 1 && len(a.Rhs) == 1 {
   494  				if a.Tok == token.DEFINE {
   495  					kind = defineXStmt
   496  				} else {
   497  					kind = assignXStmt
   498  				}
   499  				act = aAssignX
   500  			} else {
   501  				kind = assignStmt
   502  				switch a.Tok {
   503  				case token.ASSIGN:
   504  					act = aAssign
   505  				case token.ADD_ASSIGN:
   506  					act = aAddAssign
   507  				case token.AND_ASSIGN:
   508  					act = aAndAssign
   509  				case token.AND_NOT_ASSIGN:
   510  					act = aAndNotAssign
   511  				case token.DEFINE:
   512  					kind = defineStmt
   513  					act = aAssign
   514  				case token.SHL_ASSIGN:
   515  					act = aShlAssign
   516  				case token.SHR_ASSIGN:
   517  					act = aShrAssign
   518  				case token.MUL_ASSIGN:
   519  					act = aMulAssign
   520  				case token.OR_ASSIGN:
   521  					act = aOrAssign
   522  				case token.QUO_ASSIGN:
   523  					act = aQuoAssign
   524  				case token.REM_ASSIGN:
   525  					act = aRemAssign
   526  				case token.SUB_ASSIGN:
   527  					act = aSubAssign
   528  				case token.XOR_ASSIGN:
   529  					act = aXorAssign
   530  				}
   531  			}
   532  			n := addChild(&root, anc, pos, end, kind, act)
   533  			n.nleft = len(a.Lhs)
   534  			n.nright = len(a.Rhs)
   535  			st.push(n, nod)
   536  
   537  		case *ast.BasicLit:
   538  			n := addChild(&root, anc, pos, end, basicLit, aNop)
   539  			n.ident = a.Value
   540  			switch a.Kind {
   541  			case token.CHAR:
   542  				// Char cannot be converted to a const here as we cannot tell the type.
   543  				v, _, _, _ := strconv.UnquoteChar(a.Value[1:len(a.Value)-1], '\'')
   544  				n.rval = reflect.ValueOf(v)
   545  			case token.FLOAT, token.IMAG, token.INT, token.STRING:
   546  				v := constant.MakeFromLiteral(a.Value, a.Kind, 0)
   547  				n.rval = reflect.ValueOf(v)
   548  			}
   549  			st.push(n, nod)
   550  
   551  		case *ast.BinaryExpr:
   552  			kind := binaryExpr
   553  			act := aNop
   554  			switch a.Op {
   555  			case token.ADD:
   556  				act = aAdd
   557  			case token.AND:
   558  				act = aAnd
   559  			case token.AND_NOT:
   560  				act = aAndNot
   561  			case token.EQL:
   562  				act = aEqual
   563  			case token.GEQ:
   564  				act = aGreaterEqual
   565  			case token.GTR:
   566  				act = aGreater
   567  			case token.LAND:
   568  				kind = landExpr
   569  				act = aLand
   570  			case token.LOR:
   571  				kind = lorExpr
   572  				act = aLor
   573  			case token.LEQ:
   574  				act = aLowerEqual
   575  			case token.LSS:
   576  				act = aLower
   577  			case token.MUL:
   578  				act = aMul
   579  			case token.NEQ:
   580  				act = aNotEqual
   581  			case token.OR:
   582  				act = aOr
   583  			case token.REM:
   584  				act = aRem
   585  			case token.SUB:
   586  				act = aSub
   587  			case token.SHL:
   588  				act = aShl
   589  			case token.SHR:
   590  				act = aShr
   591  			case token.QUO:
   592  				act = aQuo
   593  			case token.XOR:
   594  				act = aXor
   595  			}
   596  			st.push(addChild(&root, anc, pos, end, kind, act), nod)
   597  
   598  		case *ast.BlockStmt:
   599  			st.push(addChild(&root, anc, pos, end, blockStmt, aNop), nod)
   600  
   601  		case *ast.BranchStmt:
   602  			var kind nkind
   603  			switch a.Tok {
   604  			case token.BREAK:
   605  				kind = breakStmt
   606  			case token.CONTINUE:
   607  				kind = continueStmt
   608  			case token.FALLTHROUGH:
   609  				kind = fallthroughtStmt
   610  			case token.GOTO:
   611  				kind = gotoStmt
   612  			}
   613  			st.push(addChild(&root, anc, pos, end, kind, aNop), nod)
   614  
   615  		case *ast.CallExpr:
   616  			action := aCall
   617  			if a.Ellipsis != token.NoPos {
   618  				action = aCallSlice
   619  			}
   620  
   621  			st.push(addChild(&root, anc, pos, end, callExpr, action), nod)
   622  
   623  		case *ast.CaseClause:
   624  			st.push(addChild(&root, anc, pos, end, caseClause, aCase), nod)
   625  
   626  		case *ast.ChanType:
   627  			switch a.Dir {
   628  			case ast.SEND | ast.RECV:
   629  				st.push(addChild(&root, anc, pos, end, chanType, aNop), nod)
   630  			case ast.SEND:
   631  				st.push(addChild(&root, anc, pos, end, chanTypeSend, aNop), nod)
   632  			case ast.RECV:
   633  				st.push(addChild(&root, anc, pos, end, chanTypeRecv, aNop), nod)
   634  			}
   635  
   636  		case *ast.CommClause:
   637  			kind := commClause
   638  			if a.Comm == nil {
   639  				kind = commClauseDefault
   640  			}
   641  			st.push(addChild(&root, anc, pos, end, kind, aNop), nod)
   642  
   643  		case *ast.CommentGroup, *ast.EmptyStmt:
   644  			return false
   645  
   646  		case *ast.CompositeLit:
   647  			st.push(addChild(&root, anc, pos, end, compositeLitExpr, aCompositeLit), nod)
   648  
   649  		case *ast.DeclStmt:
   650  			st.push(addChild(&root, anc, pos, end, declStmt, aNop), nod)
   651  
   652  		case *ast.DeferStmt:
   653  			st.push(addChild(&root, anc, pos, end, deferStmt, aNop), nod)
   654  
   655  		case *ast.Ellipsis:
   656  			st.push(addChild(&root, anc, pos, end, ellipsisExpr, aNop), nod)
   657  
   658  		case *ast.ExprStmt:
   659  			st.push(addChild(&root, anc, pos, end, exprStmt, aNop), nod)
   660  
   661  		case *ast.Field:
   662  			st.push(addChild(&root, anc, pos, end, fieldExpr, aNop), nod)
   663  
   664  		case *ast.FieldList:
   665  			st.push(addChild(&root, anc, pos, end, fieldList, aNop), nod)
   666  
   667  		case *ast.File:
   668  			pkgName = a.Name.Name
   669  			st.push(addChild(&root, anc, pos, end, fileStmt, aNop), nod)
   670  
   671  		case *ast.ForStmt:
   672  			// Disambiguate variants of FOR statements with a node kind per variant
   673  			var kind nkind
   674  			switch {
   675  			case a.Cond == nil && a.Init == nil && a.Post == nil:
   676  				kind = forStmt0
   677  			case a.Cond == nil && a.Init != nil && a.Post == nil:
   678  				kind = forStmt1
   679  			case a.Cond != nil && a.Init == nil && a.Post == nil:
   680  				kind = forStmt2
   681  			case a.Cond != nil && a.Init != nil && a.Post == nil:
   682  				kind = forStmt3
   683  			case a.Cond == nil && a.Init == nil && a.Post != nil:
   684  				kind = forStmt4
   685  			case a.Cond != nil && a.Init == nil && a.Post != nil:
   686  				kind = forStmt5
   687  			case a.Cond == nil && a.Init != nil && a.Post != nil:
   688  				kind = forStmt6
   689  			case a.Cond != nil && a.Init != nil && a.Post != nil:
   690  				kind = forStmt7
   691  			}
   692  			st.push(addChild(&root, anc, pos, end, kind, aNop), nod)
   693  
   694  		case *ast.FuncDecl:
   695  			n := addChild(&root, anc, pos, end, funcDecl, aNop)
   696  			n.val = n
   697  			if a.Recv == nil {
   698  				// function is not a method, create an empty receiver list
   699  				addChild(&root, astNode{n, nod}, pos, end, fieldList, aNop)
   700  			}
   701  			st.push(n, nod)
   702  
   703  		case *ast.FuncLit:
   704  			n := addChild(&root, anc, pos, end, funcLit, aGetFunc)
   705  			addChild(&root, astNode{n, nod}, pos, end, fieldList, aNop)
   706  			addChild(&root, astNode{n, nod}, pos, end, undefNode, aNop)
   707  			st.push(n, nod)
   708  
   709  		case *ast.FuncType:
   710  			st.push(addChild(&root, anc, pos, end, funcType, aNop), nod)
   711  
   712  		case *ast.GenDecl:
   713  			var kind nkind
   714  			switch a.Tok {
   715  			case token.CONST:
   716  				kind = constDecl
   717  			case token.IMPORT:
   718  				kind = importDecl
   719  			case token.TYPE:
   720  				kind = typeDecl
   721  			case token.VAR:
   722  				kind = varDecl
   723  			}
   724  			st.push(addChild(&root, anc, pos, end, kind, aNop), nod)
   725  
   726  		case *ast.GoStmt:
   727  			st.push(addChild(&root, anc, pos, end, goStmt, aNop), nod)
   728  
   729  		case *ast.Ident:
   730  			n := addChild(&root, anc, pos, end, identExpr, aNop)
   731  			n.ident = a.Name
   732  			st.push(n, nod)
   733  			if n.anc.kind == defineStmt && n.anc.anc.kind == constDecl && n.anc.nright == 0 {
   734  				// Implicit assign expression (in a ConstDecl block).
   735  				// Clone assign source and type from previous
   736  				a := n.anc
   737  				pa := a.anc.child[childPos(a)-1]
   738  
   739  				if len(pa.child) > pa.nleft+pa.nright {
   740  					// duplicate previous type spec
   741  					a.child = append(a.child, interp.dup(pa.child[a.nleft], a))
   742  				}
   743  
   744  				// duplicate previous assign right hand side
   745  				a.child = append(a.child, interp.dup(pa.lastChild(), a))
   746  				a.nright++
   747  			}
   748  
   749  		case *ast.IfStmt:
   750  			// Disambiguate variants of IF statements with a node kind per variant
   751  			var kind nkind
   752  			switch {
   753  			case a.Init == nil && a.Else == nil:
   754  				kind = ifStmt0
   755  			case a.Init == nil && a.Else != nil:
   756  				kind = ifStmt1
   757  			case a.Else == nil:
   758  				kind = ifStmt2
   759  			default:
   760  				kind = ifStmt3
   761  			}
   762  			st.push(addChild(&root, anc, pos, end, kind, aNop), nod)
   763  
   764  		case *ast.ImportSpec:
   765  			st.push(addChild(&root, anc, pos, end, importSpec, aNop), nod)
   766  
   767  		case *ast.IncDecStmt:
   768  			var act action
   769  			switch a.Tok {
   770  			case token.INC:
   771  				act = aInc
   772  			case token.DEC:
   773  				act = aDec
   774  			}
   775  			st.push(addChild(&root, anc, pos, end, incDecStmt, act), nod)
   776  
   777  		case *ast.IndexExpr:
   778  			st.push(addChild(&root, anc, pos, end, indexExpr, aGetIndex), nod)
   779  
   780  		case *ast.InterfaceType:
   781  			st.push(addChild(&root, anc, pos, end, interfaceType, aNop), nod)
   782  
   783  		case *ast.KeyValueExpr:
   784  			st.push(addChild(&root, anc, pos, end, keyValueExpr, aNop), nod)
   785  
   786  		case *ast.LabeledStmt:
   787  			st.push(addChild(&root, anc, pos, end, labeledStmt, aNop), nod)
   788  
   789  		case *ast.MapType:
   790  			st.push(addChild(&root, anc, pos, end, mapType, aNop), nod)
   791  
   792  		case *ast.ParenExpr:
   793  			st.push(addChild(&root, anc, pos, end, parenExpr, aNop), nod)
   794  
   795  		case *ast.RangeStmt:
   796  			// Insert a missing ForRangeStmt for AST correctness
   797  			n := addChild(&root, anc, pos, end, forRangeStmt, aNop)
   798  			r := addChild(&root, astNode{n, nod}, pos, end, rangeStmt, aRange)
   799  			st.push(r, nod)
   800  			if a.Key == nil {
   801  				// range not in an assign expression: insert a "_" key variable to store iteration index
   802  				k := addChild(&root, astNode{r, nod}, pos, end, identExpr, aNop)
   803  				k.ident = "_"
   804  			}
   805  
   806  		case *ast.ReturnStmt:
   807  			st.push(addChild(&root, anc, pos, end, returnStmt, aReturn), nod)
   808  
   809  		case *ast.SelectStmt:
   810  			st.push(addChild(&root, anc, pos, end, selectStmt, aNop), nod)
   811  
   812  		case *ast.SelectorExpr:
   813  			st.push(addChild(&root, anc, pos, end, selectorExpr, aGetIndex), nod)
   814  
   815  		case *ast.SendStmt:
   816  			st.push(addChild(&root, anc, pos, end, sendStmt, aSend), nod)
   817  
   818  		case *ast.SliceExpr:
   819  			if a.Low == nil {
   820  				st.push(addChild(&root, anc, pos, end, sliceExpr, aSlice0), nod)
   821  			} else {
   822  				st.push(addChild(&root, anc, pos, end, sliceExpr, aSlice), nod)
   823  			}
   824  
   825  		case *ast.StarExpr:
   826  			st.push(addChild(&root, anc, pos, end, starExpr, aStar), nod)
   827  
   828  		case *ast.StructType:
   829  			st.push(addChild(&root, anc, pos, end, structType, aNop), nod)
   830  
   831  		case *ast.SwitchStmt:
   832  			if a.Tag == nil {
   833  				st.push(addChild(&root, anc, pos, end, switchIfStmt, aNop), nod)
   834  			} else {
   835  				st.push(addChild(&root, anc, pos, end, switchStmt, aNop), nod)
   836  			}
   837  
   838  		case *ast.TypeAssertExpr:
   839  			st.push(addChild(&root, anc, pos, end, typeAssertExpr, aTypeAssert), nod)
   840  
   841  		case *ast.TypeSpec:
   842  			if a.Assign.IsValid() {
   843  				st.push(addChild(&root, anc, pos, end, typeSpecAssign, aNop), nod)
   844  				break
   845  			}
   846  			st.push(addChild(&root, anc, pos, end, typeSpec, aNop), nod)
   847  
   848  		case *ast.TypeSwitchStmt:
   849  			n := addChild(&root, anc, pos, end, typeSwitch, aNop)
   850  			st.push(n, nod)
   851  			if a.Init == nil {
   852  				// add an empty init node to disambiguate AST
   853  				addChild(&root, astNode{n, nil}, pos, end, fieldList, aNop)
   854  			}
   855  
   856  		case *ast.UnaryExpr:
   857  			kind := unaryExpr
   858  			var act action
   859  			switch a.Op {
   860  			case token.ADD:
   861  				act = aPos
   862  			case token.AND:
   863  				kind = addressExpr
   864  				act = aAddr
   865  			case token.ARROW:
   866  				act = aRecv
   867  			case token.NOT:
   868  				act = aNot
   869  			case token.SUB:
   870  				act = aNeg
   871  			case token.XOR:
   872  				act = aBitNot
   873  			}
   874  			st.push(addChild(&root, anc, pos, end, kind, act), nod)
   875  
   876  		case *ast.ValueSpec:
   877  			kind := valueSpec
   878  			act := aNop
   879  			switch {
   880  			case a.Values != nil:
   881  				if len(a.Names) > 1 && len(a.Values) == 1 {
   882  					if anc.node.kind == constDecl || anc.node.kind == varDecl {
   883  						kind = defineXStmt
   884  					} else {
   885  						kind = assignXStmt
   886  					}
   887  					act = aAssignX
   888  				} else {
   889  					if anc.node.kind == constDecl || anc.node.kind == varDecl {
   890  						kind = defineStmt
   891  					} else {
   892  						kind = assignStmt
   893  					}
   894  					act = aAssign
   895  				}
   896  			case anc.node.kind == constDecl:
   897  				kind, act = defineStmt, aAssign
   898  			case anc.node.kind == varDecl && anc.node.anc.kind != fileStmt:
   899  				kind, act = defineStmt, aAssign
   900  			}
   901  			n := addChild(&root, anc, pos, end, kind, act)
   902  			n.nleft = len(a.Names)
   903  			n.nright = len(a.Values)
   904  			st.push(n, nod)
   905  
   906  		default:
   907  			err = astError(fmt.Errorf("ast: %T not implemented, line %s", a, interp.fset.Position(pos)))
   908  			return false
   909  		}
   910  		return true
   911  	})
   912  
   913  	interp.roots = append(interp.roots, root)
   914  	return pkgName, root, err
   915  }
   916  
   917  type astNode struct {
   918  	node *node
   919  	ast  ast.Node
   920  }
   921  
   922  type nodestack []astNode
   923  
   924  func (s *nodestack) push(n *node, a ast.Node) {
   925  	*s = append(*s, astNode{n, a})
   926  }
   927  
   928  func (s *nodestack) pop() astNode {
   929  	l := len(*s) - 1
   930  	res := (*s)[l]
   931  	*s = (*s)[:l]
   932  	return res
   933  }
   934  
   935  func (s *nodestack) top() astNode {
   936  	l := len(*s)
   937  	if l > 0 {
   938  		return (*s)[l-1]
   939  	}
   940  	return astNode{}
   941  }
   942  
   943  // dup returns a duplicated node subtree.
   944  func (interp *Interpreter) dup(nod, anc *node) *node {
   945  	nindex := atomic.AddInt64(&interp.nindex, 1)
   946  	n := *nod
   947  	n.index = nindex
   948  	n.anc = anc
   949  	n.start = &n
   950  	n.pos = anc.pos
   951  	n.child = nil
   952  	for _, c := range nod.child {
   953  		n.child = append(n.child, interp.dup(c, &n))
   954  	}
   955  	return &n
   956  }