github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/cmd/compile/internal/gc/noder.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gc 6 7 import ( 8 "fmt" 9 "strconv" 10 "strings" 11 "unicode/utf8" 12 13 "cmd/compile/internal/syntax" 14 ) 15 16 func parseFile(filename string) { 17 p := noder{baseline: lexlineno} 18 file, err := syntax.ReadFile(filename, p.error, p.pragma, 0) 19 if err != nil { 20 fmt.Printf("parse %s: %v\n", filename, err) 21 errorexit() 22 } 23 24 p.file(file) 25 26 if !imported_unsafe { 27 for _, x := range p.linknames { 28 p.error(0, x, "//go:linkname only allowed in Go files that import \"unsafe\"") 29 } 30 } 31 32 if nsyntaxerrors == 0 { 33 testdclstack() 34 } 35 } 36 37 // noder transforms package syntax's AST into a Nod tree. 38 type noder struct { 39 baseline int32 40 linknames []int // tracks //go:linkname lines 41 } 42 43 func (p *noder) file(file *syntax.File) { 44 p.lineno(file.PkgName) 45 mkpackage(file.PkgName.Value) 46 47 xtop = append(xtop, p.decls(file.DeclList)...) 48 49 lexlineno = p.baseline + int32(file.Lines) - 1 50 lineno = lexlineno 51 } 52 53 func (p *noder) decls(decls []syntax.Decl) (l []*Node) { 54 var lastConstGroup *syntax.Group 55 var lastConstRHS []*Node 56 var iotaVal int64 57 58 for _, decl := range decls { 59 p.lineno(decl) 60 switch decl := decl.(type) { 61 case *syntax.ImportDecl: 62 p.importDecl(decl) 63 64 case *syntax.AliasDecl: 65 p.aliasDecl(decl) 66 67 case *syntax.VarDecl: 68 l = append(l, p.varDecl(decl)...) 69 70 case *syntax.ConstDecl: 71 // Tricky to handle golang.org/issue/15550 correctly. 72 73 prevIota := iota_ 74 75 if decl.Group == nil || decl.Group != lastConstGroup { 76 iotaVal = 0 77 lastConstRHS = nil 78 } 79 80 iota_ = iotaVal 81 lastconst = lastConstRHS 82 83 l = append(l, p.constDecl(decl)...) 84 85 lastConstRHS = lastconst 86 lastconst = nil 87 88 iota_ = prevIota 89 iotaVal++ 90 91 lastConstGroup = decl.Group 92 93 case *syntax.TypeDecl: 94 l = append(l, p.typeDecl(decl)) 95 96 case *syntax.FuncDecl: 97 l = append(l, p.funcDecl(decl)) 98 99 default: 100 panic("unhandled Decl") 101 } 102 } 103 104 return 105 } 106 107 func (p *noder) importDecl(imp *syntax.ImportDecl) { 108 val := p.basicLit(imp.Path) 109 importfile(&val, nil) 110 ipkg := importpkg 111 importpkg = nil 112 113 if ipkg == nil { 114 if nerrors == 0 { 115 Fatalf("phase error in import") 116 } 117 return 118 } 119 120 ipkg.Direct = true 121 122 var my *Sym 123 if imp.LocalPkgName != nil { 124 my = p.name(imp.LocalPkgName) 125 } else { 126 my = lookup(ipkg.Name) 127 } 128 129 pack := p.nod(imp, OPACK, nil, nil) 130 pack.Sym = my 131 pack.Name.Pkg = ipkg 132 133 if my.Name == "." { 134 importdot(ipkg, pack) 135 return 136 } 137 if my.Name == "init" { 138 yyerrorl(pack.Lineno, "cannot import package as init - init must be a func") 139 return 140 } 141 if my.Name == "_" { 142 return 143 } 144 if my.Def != nil { 145 lineno = pack.Lineno 146 redeclare(my, "as imported package name") 147 } 148 my.Def = pack 149 my.Lastlineno = pack.Lineno 150 my.Block = 1 // at top level 151 } 152 153 func (p *noder) aliasDecl(decl *syntax.AliasDecl) { 154 // Because alias declarations must refer to imported entities 155 // which are already set up, we can do all checks right here. 156 // We won't know anything about entities that have not been 157 // declared yet, but since they cannot have been imported, we 158 // know there's an error and we don't care about the details. 159 160 // The original entity must be denoted by a qualified identifier. 161 // (The parser doesn't make this restriction to be more error- 162 // tolerant.) 163 qident, ok := decl.Orig.(*syntax.SelectorExpr) 164 if !ok { 165 // TODO(gri) This prints a dot-imported object with qualification 166 // (confusing error). Fix this. 167 yyerror("invalid alias: %v is not a package-qualified identifier", p.expr(decl.Orig)) 168 return 169 } 170 171 pkg := p.expr(qident.X) 172 if pkg.Op != OPACK { 173 yyerror("invalid alias: %v is not a package", pkg) 174 return 175 } 176 pkg.Used = true 177 178 // Resolve original entity 179 orig := oldname(restrictlookup(qident.Sel.Value, pkg.Name.Pkg)) 180 if orig.Sym.Flags&SymAlias != 0 { 181 Fatalf("original %v marked as alias", orig.Sym) 182 } 183 184 // An alias declaration must not refer to package unsafe. 185 if orig.Sym.Pkg == unsafepkg { 186 yyerror("invalid alias: %v refers to package unsafe (%v)", decl.Name.Value, orig) 187 return 188 } 189 190 // The aliased entity must be from a matching constant, type, variable, 191 // or function declaration, respectively. 192 var what string 193 switch decl.Tok { 194 case syntax.Const: 195 if orig.Op != OLITERAL { 196 what = "constant" 197 } 198 case syntax.Type: 199 if orig.Op != OTYPE { 200 what = "type" 201 } 202 case syntax.Var: 203 if orig.Op != ONAME || orig.Class != PEXTERN { 204 what = "variable" 205 } 206 case syntax.Func: 207 if orig.Op != ONAME || orig.Class != PFUNC { 208 what = "function" 209 } 210 default: 211 Fatalf("unexpected token: %s", decl.Tok) 212 } 213 if what != "" { 214 yyerror("invalid alias: %v is not a %s", orig, what) 215 return 216 } 217 218 // handle special cases 219 switch decl.Name.Value { 220 case "_": 221 return // don't declare blank aliases 222 case "init": 223 yyerror("cannot declare init - must be non-alias function declaration") 224 return 225 } 226 227 // declare alias 228 // (this is similar to handling dot imports) 229 asym := p.name(decl.Name) 230 if asym.Def != nil { 231 redeclare(asym, "in alias declaration") 232 return 233 } 234 asym.Flags |= SymAlias 235 asym.Def = orig 236 asym.Block = block 237 asym.Lastlineno = lineno 238 239 if exportname(asym.Name) { 240 // TODO(gri) newname(asym) is only needed to satisfy exportsym 241 // (and indirectly, exportlist). We should be able to just 242 // collect the Syms, eventually. 243 exportsym(newname(asym)) 244 } 245 } 246 247 func (p *noder) varDecl(decl *syntax.VarDecl) []*Node { 248 names := p.declNames(decl.NameList) 249 250 var typ *Node 251 if decl.Type != nil { 252 typ = p.typeExpr(decl.Type) 253 } 254 255 var exprs []*Node 256 if decl.Values != nil { 257 exprs = p.exprList(decl.Values) 258 } 259 260 p.lineno(decl) 261 return variter(names, typ, exprs) 262 } 263 264 func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node { 265 names := p.declNames(decl.NameList) 266 267 var typ *Node 268 if decl.Type != nil { 269 typ = p.typeExpr(decl.Type) 270 } 271 272 var exprs []*Node 273 if decl.Values != nil { 274 exprs = p.exprList(decl.Values) 275 } 276 277 return constiter(names, typ, exprs) 278 } 279 280 func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node { 281 name := typedcl0(p.name(decl.Name)) 282 name.Name.Param.Pragma = Pragma(decl.Pragma) 283 284 var typ *Node 285 if decl.Type != nil { 286 typ = p.typeExpr(decl.Type) 287 } 288 289 return typedcl1(name, typ, true) 290 } 291 292 func (p *noder) declNames(names []*syntax.Name) []*Node { 293 var nodes []*Node 294 for _, name := range names { 295 nodes = append(nodes, p.declName(name)) 296 } 297 return nodes 298 } 299 300 func (p *noder) declName(name *syntax.Name) *Node { 301 // TODO(mdempsky): Set lineno? 302 return dclname(p.name(name)) 303 } 304 305 func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { 306 f := p.funcHeader(fun) 307 if f == nil { 308 return nil 309 } 310 311 var body []*Node 312 if fun.Body != nil { 313 body = p.stmts(fun.Body) 314 if body == nil { 315 body = []*Node{p.nod(fun, OEMPTY, nil, nil)} 316 } 317 } 318 319 pragma := Pragma(fun.Pragma) 320 321 f.Nbody.Set(body) 322 f.Noescape = pragma&Noescape != 0 323 if f.Noescape && len(body) != 0 { 324 yyerror("can only use //go:noescape with external func implementations") 325 } 326 f.Func.Pragma = pragma 327 lineno = p.baseline + int32(fun.EndLine) - 1 328 f.Func.Endlineno = lineno 329 330 funcbody(f) 331 332 return f 333 } 334 335 func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node { 336 name := p.name(fun.Name) 337 t := p.signature(fun.Recv, fun.Type) 338 f := p.nod(fun, ODCLFUNC, nil, nil) 339 340 if fun.Recv == nil { 341 // FunctionName Signature 342 if name.Name == "init" { 343 name = renameinit() 344 if t.List.Len() > 0 || t.Rlist.Len() > 0 { 345 yyerror("func init must have no arguments and no return values") 346 } 347 } 348 349 if localpkg.Name == "main" && name.Name == "main" { 350 if t.List.Len() > 0 || t.Rlist.Len() > 0 { 351 yyerror("func main must have no arguments and no return values") 352 } 353 } 354 355 f.Func.Nname = newfuncname(name) 356 } else { 357 // Receiver MethodName Signature 358 359 f.Func.Shortname = newfuncname(name) 360 f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right) 361 } 362 363 f.Func.Nname.Name.Defn = f 364 f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype 365 366 declare(f.Func.Nname, PFUNC) 367 funchdr(f) 368 return f 369 } 370 371 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node { 372 n := p.nod(typ, OTFUNC, nil, nil) 373 if recv != nil { 374 n.Left = p.param(recv, false, false) 375 } 376 n.List.Set(p.params(typ.ParamList, true)) 377 n.Rlist.Set(p.params(typ.ResultList, false)) 378 return n 379 } 380 381 func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node { 382 var nodes []*Node 383 for i, param := range params { 384 p.lineno(param) 385 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) 386 } 387 return nodes 388 } 389 390 func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { 391 var name *Node 392 if param.Name != nil { 393 name = p.newname(param.Name) 394 } 395 396 typ := p.typeExpr(param.Type) 397 n := p.nod(param, ODCLFIELD, name, typ) 398 399 // rewrite ...T parameter 400 if typ.Op == ODDD { 401 if !dddOk { 402 yyerror("cannot use ... in receiver or result parameter list") 403 } else if !final { 404 yyerror("can only use ... with final parameter in list") 405 } 406 typ.Op = OTARRAY 407 typ.Right = typ.Left 408 typ.Left = nil 409 n.Isddd = true 410 if n.Left != nil { 411 n.Left.Isddd = true 412 } 413 } 414 415 return n 416 } 417 418 func (p *noder) exprList(expr syntax.Expr) []*Node { 419 if list, ok := expr.(*syntax.ListExpr); ok { 420 return p.exprs(list.ElemList) 421 } 422 return []*Node{p.expr(expr)} 423 } 424 425 func (p *noder) exprs(exprs []syntax.Expr) []*Node { 426 var nodes []*Node 427 for _, expr := range exprs { 428 nodes = append(nodes, p.expr(expr)) 429 } 430 return nodes 431 } 432 433 func (p *noder) expr(expr syntax.Expr) *Node { 434 p.lineno(expr) 435 switch expr := expr.(type) { 436 case nil: 437 return nil 438 case *syntax.Name: 439 return p.mkname(expr) 440 case *syntax.BasicLit: 441 return p.setlineno(expr, nodlit(p.basicLit(expr))) 442 443 case *syntax.CompositeLit: 444 n := p.nod(expr, OCOMPLIT, nil, nil) 445 if expr.Type != nil { 446 n.Right = p.expr(expr.Type) 447 } 448 l := p.exprs(expr.ElemList) 449 for i, e := range l { 450 l[i] = p.wrapname(expr.ElemList[i], e) 451 } 452 n.List.Set(l) 453 lineno = p.baseline + int32(expr.EndLine) - 1 454 return n 455 case *syntax.KeyValueExpr: 456 return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value))) 457 case *syntax.FuncLit: 458 closurehdr(p.typeExpr(expr.Type)) 459 body := p.stmts(expr.Body) 460 lineno = p.baseline + int32(expr.EndLine) - 1 461 return p.setlineno(expr, closurebody(body)) 462 case *syntax.ParenExpr: 463 return p.nod(expr, OPAREN, p.expr(expr.X), nil) 464 case *syntax.SelectorExpr: 465 // parser.new_dotname 466 obj := p.expr(expr.X) 467 if obj.Op == OPACK { 468 obj.Used = true 469 return oldname(restrictlookup(expr.Sel.Value, obj.Name.Pkg)) 470 } 471 return p.setlineno(expr, nodSym(OXDOT, obj, p.name(expr.Sel))) 472 case *syntax.IndexExpr: 473 return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index)) 474 case *syntax.SliceExpr: 475 op := OSLICE 476 if expr.Full { 477 op = OSLICE3 478 } 479 n := p.nod(expr, op, p.expr(expr.X), nil) 480 var index [3]*Node 481 for i, x := range expr.Index { 482 if x != nil { 483 index[i] = p.expr(x) 484 } 485 } 486 n.SetSliceBounds(index[0], index[1], index[2]) 487 return n 488 case *syntax.AssertExpr: 489 if expr.Type == nil { 490 panic("unexpected AssertExpr") 491 } 492 // TODO(mdempsky): parser.pexpr uses p.expr(), but 493 // seems like the type field should be parsed with 494 // ntype? Shrug, doesn't matter here. 495 return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.expr(expr.Type)) 496 case *syntax.Operation: 497 x := p.expr(expr.X) 498 if expr.Y == nil { 499 if expr.Op == syntax.And { 500 x = unparen(x) // TODO(mdempsky): Needed? 501 if x.Op == OCOMPLIT { 502 // Special case for &T{...}: turn into (*T){...}. 503 // TODO(mdempsky): Switch back to p.nod after we 504 // get rid of gcCompat. 505 x.Right = nod(OIND, x.Right, nil) 506 x.Right.Implicit = true 507 return x 508 } 509 } 510 return p.nod(expr, p.unOp(expr.Op), x, nil) 511 } 512 return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y)) 513 case *syntax.CallExpr: 514 n := p.nod(expr, OCALL, p.expr(expr.Fun), nil) 515 n.List.Set(p.exprs(expr.ArgList)) 516 n.Isddd = expr.HasDots 517 return n 518 519 case *syntax.ArrayType: 520 var len *Node 521 if expr.Len != nil { 522 len = p.expr(expr.Len) 523 } else { 524 len = p.nod(expr, ODDD, nil, nil) 525 } 526 return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem)) 527 case *syntax.SliceType: 528 return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem)) 529 case *syntax.DotsType: 530 return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil) 531 case *syntax.StructType: 532 return p.structType(expr) 533 case *syntax.InterfaceType: 534 return p.interfaceType(expr) 535 case *syntax.FuncType: 536 return p.signature(nil, expr) 537 case *syntax.MapType: 538 return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) 539 case *syntax.ChanType: 540 n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil) 541 n.Etype = EType(p.chanDir(expr.Dir)) 542 return n 543 544 case *syntax.TypeSwitchGuard: 545 n := p.nod(expr, OTYPESW, nil, p.expr(expr.X)) 546 if expr.Lhs != nil { 547 n.Left = p.declName(expr.Lhs) 548 if isblank(n.Left) { 549 yyerror("invalid variable name %v in type switch", n.Left) 550 } 551 } 552 return n 553 } 554 panic("unhandled Expr") 555 } 556 557 func (p *noder) typeExpr(typ syntax.Expr) *Node { 558 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway. 559 return p.expr(typ) 560 } 561 562 func (p *noder) chanDir(dir syntax.ChanDir) ChanDir { 563 switch dir { 564 case 0: 565 return Cboth 566 case syntax.SendOnly: 567 return Csend 568 case syntax.RecvOnly: 569 return Crecv 570 } 571 panic("unhandled ChanDir") 572 } 573 574 func (p *noder) structType(expr *syntax.StructType) *Node { 575 var l []*Node 576 for i, field := range expr.FieldList { 577 p.lineno(field) 578 var n *Node 579 if field.Name == nil { 580 n = p.embedded(field.Type) 581 } else { 582 n = p.nod(field, ODCLFIELD, p.newname(field.Name), p.typeExpr(field.Type)) 583 } 584 if i < len(expr.TagList) && expr.TagList[i] != nil { 585 n.SetVal(p.basicLit(expr.TagList[i])) 586 } 587 l = append(l, n) 588 } 589 590 p.lineno(expr) 591 n := p.nod(expr, OTSTRUCT, nil, nil) 592 n.List.Set(l) 593 return n 594 } 595 596 func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node { 597 var l []*Node 598 for _, method := range expr.MethodList { 599 p.lineno(method) 600 var n *Node 601 if method.Name == nil { 602 n = p.nod(method, ODCLFIELD, nil, oldname(p.packname(method.Type))) 603 } else { 604 mname := p.newname(method.Name) 605 sig := p.typeExpr(method.Type) 606 sig.Left = fakethis() 607 n = p.nod(method, ODCLFIELD, mname, sig) 608 ifacedcl(n) 609 } 610 l = append(l, n) 611 } 612 613 n := p.nod(expr, OTINTER, nil, nil) 614 n.List.Set(l) 615 return n 616 } 617 618 func (p *noder) packname(expr syntax.Expr) *Sym { 619 switch expr := expr.(type) { 620 case *syntax.Name: 621 name := p.name(expr) 622 if n := oldname(name); n.Name != nil && n.Name.Pack != nil { 623 n.Name.Pack.Used = true 624 } 625 return name 626 case *syntax.SelectorExpr: 627 name := p.name(expr.X.(*syntax.Name)) 628 var pkg *Pkg 629 if name.Def == nil || name.Def.Op != OPACK { 630 yyerror("%v is not a package", name) 631 pkg = localpkg 632 } else { 633 name.Def.Used = true 634 pkg = name.Def.Name.Pkg 635 } 636 return restrictlookup(expr.Sel.Value, pkg) 637 } 638 panic(fmt.Sprintf("unexpected packname: %#v", expr)) 639 } 640 641 func (p *noder) embedded(typ syntax.Expr) *Node { 642 op, isStar := typ.(*syntax.Operation) 643 if isStar { 644 if op.Op != syntax.Mul || op.Y != nil { 645 panic("unexpected Operation") 646 } 647 typ = op.X 648 } 649 n := embedded(p.packname(typ), localpkg) 650 if isStar { 651 n.Right = p.nod(op, OIND, n.Right, nil) 652 } 653 return n 654 } 655 656 func (p *noder) stmts(stmts []syntax.Stmt) []*Node { 657 var nodes []*Node 658 for _, stmt := range stmts { 659 s := p.stmt(stmt) 660 if s == nil { 661 } else if s.Op == OBLOCK && s.Ninit.Len() == 0 { 662 nodes = append(nodes, s.List.Slice()...) 663 } else { 664 nodes = append(nodes, s) 665 } 666 } 667 return nodes 668 } 669 670 func (p *noder) stmt(stmt syntax.Stmt) *Node { 671 p.lineno(stmt) 672 switch stmt := stmt.(type) { 673 case *syntax.EmptyStmt: 674 return nil 675 case *syntax.LabeledStmt: 676 return p.labeledStmt(stmt) 677 case *syntax.BlockStmt: 678 return p.body(stmt.Body) 679 case *syntax.ExprStmt: 680 return p.wrapname(stmt, p.expr(stmt.X)) 681 case *syntax.SendStmt: 682 return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) 683 case *syntax.DeclStmt: 684 return liststmt(p.decls(stmt.DeclList)) 685 case *syntax.AssignStmt: 686 if stmt.Op != 0 && stmt.Op != syntax.Def { 687 n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) 688 n.Implicit = stmt.Rhs == syntax.ImplicitOne 689 n.Etype = EType(p.binOp(stmt.Op)) 690 return n 691 } 692 693 lhs := p.exprList(stmt.Lhs) 694 rhs := p.exprList(stmt.Rhs) 695 696 n := p.nod(stmt, OAS, nil, nil) // assume common case 697 698 if stmt.Op == syntax.Def { 699 n.Colas = true 700 colasdefn(lhs, n) // modifies lhs, call before using lhs[0] in common case 701 } 702 703 if len(lhs) == 1 && len(rhs) == 1 { 704 // common case 705 n.Left = lhs[0] 706 n.Right = rhs[0] 707 } else { 708 n.Op = OAS2 709 n.List.Set(lhs) 710 n.Rlist.Set(rhs) 711 } 712 return n 713 714 case *syntax.BranchStmt: 715 var op Op 716 switch stmt.Tok { 717 case syntax.Break: 718 op = OBREAK 719 case syntax.Continue: 720 op = OCONTINUE 721 case syntax.Fallthrough: 722 op = OXFALL 723 case syntax.Goto: 724 op = OGOTO 725 default: 726 panic("unhandled BranchStmt") 727 } 728 n := p.nod(stmt, op, nil, nil) 729 if stmt.Label != nil { 730 n.Left = p.newname(stmt.Label) 731 } 732 if op == OGOTO { 733 n.Sym = dclstack // context, for goto restriction 734 } 735 if op == OXFALL { 736 n.Xoffset = int64(block) 737 } 738 return n 739 case *syntax.CallStmt: 740 var op Op 741 switch stmt.Tok { 742 case syntax.Defer: 743 op = ODEFER 744 case syntax.Go: 745 op = OPROC 746 default: 747 panic("unhandled CallStmt") 748 } 749 return p.nod(stmt, op, p.expr(stmt.Call), nil) 750 case *syntax.ReturnStmt: 751 var results []*Node 752 if stmt.Results != nil { 753 results = p.exprList(stmt.Results) 754 } 755 n := p.nod(stmt, ORETURN, nil, nil) 756 n.List.Set(results) 757 if n.List.Len() == 0 && Curfn != nil { 758 for _, ln := range Curfn.Func.Dcl { 759 if ln.Class == PPARAM { 760 continue 761 } 762 if ln.Class != PPARAMOUT { 763 break 764 } 765 if ln.Sym.Def != ln { 766 yyerror("%s is shadowed during return", ln.Sym.Name) 767 } 768 } 769 } 770 return n 771 case *syntax.IfStmt: 772 return p.ifStmt(stmt) 773 case *syntax.ForStmt: 774 return p.forStmt(stmt) 775 case *syntax.SwitchStmt: 776 return p.switchStmt(stmt) 777 case *syntax.SelectStmt: 778 return p.selectStmt(stmt) 779 } 780 panic("unhandled Stmt") 781 } 782 783 func (p *noder) body(body []syntax.Stmt) *Node { 784 l := p.bodyList(body) 785 if len(l) == 0 { 786 // TODO(mdempsky): Line number? 787 return nod(OEMPTY, nil, nil) 788 } 789 return liststmt(l) 790 } 791 792 func (p *noder) bodyList(body []syntax.Stmt) []*Node { 793 markdcl() 794 nodes := p.stmts(body) 795 popdcl() 796 return nodes 797 } 798 799 func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { 800 markdcl() 801 n := p.nod(stmt, OIF, nil, nil) 802 if stmt.Init != nil { 803 n.Ninit.Set1(p.stmt(stmt.Init)) 804 } 805 if stmt.Cond != nil { 806 n.Left = p.expr(stmt.Cond) 807 } 808 n.Nbody.Set(p.bodyList(stmt.Then)) 809 if stmt.Else != nil { 810 e := p.stmt(stmt.Else) 811 if e.Op == OBLOCK && e.Ninit.Len() == 0 { 812 n.Rlist.Set(e.List.Slice()) 813 } else { 814 n.Rlist.Set1(e) 815 } 816 } 817 popdcl() 818 return n 819 } 820 821 func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { 822 markdcl() 823 var n *Node 824 if r, ok := stmt.Init.(*syntax.RangeClause); ok { 825 if stmt.Cond != nil || stmt.Post != nil { 826 panic("unexpected RangeClause") 827 } 828 829 n = p.nod(r, ORANGE, nil, p.expr(r.X)) 830 if r.Lhs != nil { 831 lhs := p.exprList(r.Lhs) 832 n.List.Set(lhs) 833 if r.Def { 834 n.Colas = true 835 colasdefn(lhs, n) 836 } 837 } 838 } else { 839 n = p.nod(stmt, OFOR, nil, nil) 840 if stmt.Init != nil { 841 n.Ninit.Set1(p.stmt(stmt.Init)) 842 } 843 if stmt.Cond != nil { 844 n.Left = p.expr(stmt.Cond) 845 } 846 if stmt.Post != nil { 847 n.Right = p.stmt(stmt.Post) 848 } 849 } 850 n.Nbody.Set(p.bodyList(stmt.Body)) 851 popdcl() 852 return n 853 } 854 855 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { 856 markdcl() 857 n := p.nod(stmt, OSWITCH, nil, nil) 858 if stmt.Init != nil { 859 n.Ninit.Set1(p.stmt(stmt.Init)) 860 } 861 if stmt.Tag != nil { 862 n.Left = p.expr(stmt.Tag) 863 } 864 865 tswitch := n.Left 866 if tswitch != nil && (tswitch.Op != OTYPESW || tswitch.Left == nil) { 867 tswitch = nil 868 } 869 870 n.List.Set(p.caseClauses(stmt.Body, tswitch)) 871 872 popdcl() 873 return n 874 } 875 876 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node { 877 var nodes []*Node 878 for _, clause := range clauses { 879 p.lineno(clause) 880 markdcl() 881 n := p.nod(clause, OXCASE, nil, nil) 882 if clause.Cases != nil { 883 n.List.Set(p.exprList(clause.Cases)) 884 } 885 if tswitch != nil { 886 nn := newname(tswitch.Left.Sym) 887 declare(nn, dclcontext) 888 n.Rlist.Set1(nn) 889 // keep track of the instances for reporting unused 890 nn.Name.Defn = tswitch 891 } 892 n.Xoffset = int64(block) 893 n.Nbody.Set(p.stmts(clause.Body)) 894 popdcl() 895 nodes = append(nodes, n) 896 } 897 return nodes 898 } 899 900 func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node { 901 n := p.nod(stmt, OSELECT, nil, nil) 902 n.List.Set(p.commClauses(stmt.Body)) 903 return n 904 } 905 906 func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node { 907 var nodes []*Node 908 for _, clause := range clauses { 909 p.lineno(clause) 910 markdcl() 911 n := p.nod(clause, OXCASE, nil, nil) 912 if clause.Comm != nil { 913 n.List.Set1(p.stmt(clause.Comm)) 914 } 915 n.Xoffset = int64(block) 916 n.Nbody.Set(p.stmts(clause.Body)) 917 popdcl() 918 nodes = append(nodes, n) 919 } 920 return nodes 921 } 922 923 func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node { 924 lhs := p.nod(label, OLABEL, p.newname(label.Label), nil) 925 lhs.Sym = dclstack 926 927 var ls *Node 928 if label.Stmt != nil { // TODO(mdempsky): Should always be present. 929 ls = p.stmt(label.Stmt) 930 } 931 932 lhs.Name.Defn = ls 933 l := []*Node{lhs} 934 if ls != nil { 935 if ls.Op == OBLOCK && ls.Ninit.Len() == 0 { 936 l = append(l, ls.List.Slice()...) 937 } else { 938 l = append(l, ls) 939 } 940 } 941 return liststmt(l) 942 } 943 944 var unOps = [...]Op{ 945 syntax.Recv: ORECV, 946 syntax.Mul: OIND, 947 syntax.And: OADDR, 948 949 syntax.Not: ONOT, 950 syntax.Xor: OCOM, 951 syntax.Add: OPLUS, 952 syntax.Sub: OMINUS, 953 } 954 955 func (p *noder) unOp(op syntax.Operator) Op { 956 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 { 957 panic("invalid Operator") 958 } 959 return unOps[op] 960 } 961 962 var binOps = [...]Op{ 963 syntax.OrOr: OOROR, 964 syntax.AndAnd: OANDAND, 965 966 syntax.Eql: OEQ, 967 syntax.Neq: ONE, 968 syntax.Lss: OLT, 969 syntax.Leq: OLE, 970 syntax.Gtr: OGT, 971 syntax.Geq: OGE, 972 973 syntax.Add: OADD, 974 syntax.Sub: OSUB, 975 syntax.Or: OOR, 976 syntax.Xor: OXOR, 977 978 syntax.Mul: OMUL, 979 syntax.Div: ODIV, 980 syntax.Rem: OMOD, 981 syntax.And: OAND, 982 syntax.AndNot: OANDNOT, 983 syntax.Shl: OLSH, 984 syntax.Shr: ORSH, 985 } 986 987 func (p *noder) binOp(op syntax.Operator) Op { 988 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 { 989 panic("invalid Operator") 990 } 991 return binOps[op] 992 } 993 994 func (p *noder) basicLit(lit *syntax.BasicLit) Val { 995 // TODO: Don't try to convert if we had syntax errors (conversions may fail). 996 // Use dummy values so we can continue to compile. Eventually, use a 997 // form of "unknown" literals that are ignored during type-checking so 998 // we can continue type-checking w/o spurious follow-up errors. 999 switch s := lit.Value; lit.Kind { 1000 case syntax.IntLit: 1001 x := new(Mpint) 1002 x.SetString(s) 1003 return Val{U: x} 1004 1005 case syntax.FloatLit: 1006 x := newMpflt() 1007 x.SetString(s) 1008 return Val{U: x} 1009 1010 case syntax.ImagLit: 1011 x := new(Mpcplx) 1012 x.Imag.SetString(strings.TrimSuffix(s, "i")) 1013 return Val{U: x} 1014 1015 case syntax.RuneLit: 1016 var r rune 1017 if u, err := strconv.Unquote(s); err == nil && len(u) > 0 { 1018 // Package syntax already reported any errors. 1019 // Check for them again though because 0 is a 1020 // better fallback value for invalid rune 1021 // literals than 0xFFFD. 1022 if len(u) == 1 { 1023 r = rune(u[0]) 1024 } else { 1025 r, _ = utf8.DecodeRuneInString(u) 1026 } 1027 } 1028 x := new(Mpint) 1029 x.SetInt64(int64(r)) 1030 x.Rune = true 1031 return Val{U: x} 1032 1033 case syntax.StringLit: 1034 if len(s) > 0 && s[0] == '`' { 1035 // strip carriage returns from raw string 1036 s = strings.Replace(s, "\r", "", -1) 1037 } 1038 // Ignore errors because package syntax already reported them. 1039 u, _ := strconv.Unquote(s) 1040 return Val{U: u} 1041 1042 default: 1043 panic("unhandled BasicLit kind") 1044 } 1045 } 1046 1047 func (p *noder) name(name *syntax.Name) *Sym { 1048 return lookup(name.Value) 1049 } 1050 1051 func (p *noder) mkname(name *syntax.Name) *Node { 1052 // TODO(mdempsky): Set line number? 1053 return mkname(p.name(name)) 1054 } 1055 1056 func (p *noder) newname(name *syntax.Name) *Node { 1057 // TODO(mdempsky): Set line number? 1058 return newname(p.name(name)) 1059 } 1060 1061 func (p *noder) wrapname(n syntax.Node, x *Node) *Node { 1062 // These nodes do not carry line numbers. 1063 // Introduce a wrapper node to give them the correct line. 1064 switch x.Op { 1065 case OTYPE, OLITERAL: 1066 if x.Sym == nil { 1067 break 1068 } 1069 fallthrough 1070 case ONAME, ONONAME, OPACK: 1071 x = p.nod(n, OPAREN, x, nil) 1072 x.Implicit = true 1073 } 1074 return x 1075 } 1076 1077 func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { 1078 return p.setlineno(orig, nod(op, left, right)) 1079 } 1080 1081 func (p *noder) setlineno(src syntax.Node, dst *Node) *Node { 1082 l := int32(src.Line()) 1083 if l == 0 { 1084 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 1085 return dst 1086 } 1087 dst.Lineno = p.baseline + l - 1 1088 return dst 1089 } 1090 1091 func (p *noder) lineno(n syntax.Node) { 1092 if n == nil { 1093 return 1094 } 1095 l := int32(n.Line()) 1096 if l == 0 { 1097 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 1098 return 1099 } 1100 lineno = p.baseline + l - 1 1101 } 1102 1103 func (p *noder) error(_, line int, msg string) { 1104 yyerrorl(p.baseline+int32(line)-1, "%s", msg) 1105 } 1106 1107 func (p *noder) pragma(pos, line int, text string) syntax.Pragma { 1108 switch { 1109 case strings.HasPrefix(text, "line "): 1110 i := strings.IndexByte(text, ':') 1111 if i < 0 { 1112 break 1113 } 1114 n, err := strconv.Atoi(text[i+1:]) 1115 if err != nil { 1116 // todo: make this an error instead? it is almost certainly a bug. 1117 break 1118 } 1119 if n > 1e8 { 1120 p.error(pos, line, "line number out of range") 1121 errorexit() 1122 } 1123 if n <= 0 { 1124 break 1125 } 1126 lexlineno = p.baseline + int32(line) 1127 linehistupdate(text[5:i], n) 1128 1129 case strings.HasPrefix(text, "go:linkname "): 1130 // Record line number so we can emit an error later if 1131 // the file doesn't import package unsafe. 1132 p.linknames = append(p.linknames, line) 1133 1134 f := strings.Fields(text) 1135 if len(f) != 3 { 1136 p.error(pos, line, "usage: //go:linkname localname linkname") 1137 break 1138 } 1139 lookup(f[1]).Linkname = f[2] 1140 1141 case strings.HasPrefix(text, "go:cgo_"): 1142 pragcgobuf += pragcgo(text) 1143 fallthrough // because of //go:cgo_unsafe_args 1144 default: 1145 verb := text 1146 if i := strings.Index(text, " "); i >= 0 { 1147 verb = verb[:i] 1148 } 1149 return syntax.Pragma(pragmaValue(verb)) 1150 } 1151 1152 return 0 1153 } 1154 1155 func mkname(sym *Sym) *Node { 1156 n := oldname(sym) 1157 if n.Name != nil && n.Name.Pack != nil { 1158 n.Name.Pack.Used = true 1159 } 1160 return n 1161 } 1162 1163 func unparen(x *Node) *Node { 1164 for x.Op == OPAREN { 1165 x = x.Left 1166 } 1167 return x 1168 }