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