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