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 }