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