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