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