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 }