1 // Copyright 2011 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 "cmd/compile/internal/types" 9 "fmt" 10 "strconv" 11 "strings" 12 "unicode/utf8" 13 ) 14 15 // A FmtFlag value is a set of flags (or 0). 16 // They control how the Xconv functions format their values. 17 // See the respective function's documentation for details. 18 type FmtFlag int 19 20 const ( // fmt.Format flag/prec or verb 21 FmtLeft FmtFlag = 1 << iota // '-' 22 FmtSharp // '#' 23 FmtSign // '+' 24 FmtUnsigned // internal use only (historic: u flag) 25 FmtShort // verb == 'S' (historic: h flag) 26 FmtLong // verb == 'L' (historic: l flag) 27 FmtComma // '.' (== hasPrec) (historic: , flag) 28 FmtByte // '0' (historic: hh flag) 29 ) 30 31 // fmtFlag computes the (internal) FmtFlag 32 // value given the fmt.State and format verb. 33 func fmtFlag(s fmt.State, verb rune) FmtFlag { 34 var flag FmtFlag 35 if s.Flag('-') { 36 flag |= FmtLeft 37 } 38 if s.Flag('#') { 39 flag |= FmtSharp 40 } 41 if s.Flag('+') { 42 flag |= FmtSign 43 } 44 if s.Flag(' ') { 45 Fatalf("FmtUnsigned in format string") 46 } 47 if _, ok := s.Precision(); ok { 48 flag |= FmtComma 49 } 50 if s.Flag('0') { 51 flag |= FmtByte 52 } 53 switch verb { 54 case 'S': 55 flag |= FmtShort 56 case 'L': 57 flag |= FmtLong 58 } 59 return flag 60 } 61 62 // Format conversions: 63 // TODO(gri) verify these; eliminate those not used anymore 64 // 65 // %v Op Node opcodes 66 // Flags: #: print Go syntax (automatic unless mode == FDbg) 67 // 68 // %j *Node Node details 69 // Flags: 0: suppresses things not relevant until walk 70 // 71 // %v *Val Constant values 72 // 73 // %v *types.Sym Symbols 74 // %S unqualified identifier in any mode 75 // Flags: +,- #: mode (see below) 76 // 0: in export mode: unqualified identifier if exported, qualified if not 77 // 78 // %v *types.Type Types 79 // %S omit "func" and receiver in function types 80 // %L definition instead of name. 81 // Flags: +,- #: mode (see below) 82 // ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix. 83 // 84 // %v *Node Nodes 85 // %S (only in +/debug mode) suppress recursion 86 // %L (only in Error mode) print "foo (type Bar)" 87 // Flags: +,- #: mode (see below) 88 // 89 // %v Nodes Node lists 90 // Flags: those of *Node 91 // .: separate items with ',' instead of ';' 92 93 // *types.Sym, *types.Type, and *Node types use the flags below to set the format mode 94 const ( 95 FErr = iota 96 FDbg 97 FTypeId 98 FTypeIdName // same as FTypeId, but use package name instead of prefix 99 ) 100 101 // The mode flags '+', '-', and '#' are sticky; they persist through 102 // recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is 103 // sticky only on *types.Type recursions and only used in %-/*types.Sym mode. 104 // 105 // Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode 106 107 // Useful format combinations: 108 // TODO(gri): verify these 109 // 110 // *Node, Nodes: 111 // %+v multiline recursive debug dump of *Node/Nodes 112 // %+S non-recursive debug dump 113 // 114 // *Node: 115 // %#v Go format 116 // %L "foo (type Bar)" for error messages 117 // 118 // *types.Type: 119 // %#v Go format 120 // %#L type definition instead of name 121 // %#S omit"func" and receiver in function signature 122 // 123 // %-v type identifiers 124 // %-S type identifiers without "func" and arg names in type signatures (methodsym) 125 // %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) 126 127 // update returns the results of applying f to mode. 128 func (f FmtFlag) update(mode fmtMode) (FmtFlag, fmtMode) { 129 switch { 130 case f&FmtSign != 0: 131 mode = FDbg 132 case f&FmtSharp != 0: 133 // ignore (textual export format no longer supported) 134 case f&FmtUnsigned != 0: 135 mode = FTypeIdName 136 case f&FmtLeft != 0: 137 mode = FTypeId 138 } 139 140 f &^= FmtSharp | FmtLeft | FmtSign 141 return f, mode 142 } 143 144 var goopnames = []string{ 145 OADDR: "&", 146 OADD: "+", 147 OADDSTR: "+", 148 OALIGNOF: "unsafe.Alignof", 149 OANDAND: "&&", 150 OANDNOT: "&^", 151 OAND: "&", 152 OAPPEND: "append", 153 OAS: "=", 154 OAS2: "=", 155 OBREAK: "break", 156 OCALL: "function call", // not actual syntax 157 OCAP: "cap", 158 OCASE: "case", 159 OCLOSE: "close", 160 OCOMPLEX: "complex", 161 OCOM: "^", 162 OCONTINUE: "continue", 163 OCOPY: "copy", 164 ODELETE: "delete", 165 ODEFER: "defer", 166 ODIV: "/", 167 OEQ: "==", 168 OFALL: "fallthrough", 169 OFOR: "for", 170 OFORUNTIL: "foruntil", // not actual syntax; used to avoid off-end pointer live on backedge.892 171 OGE: ">=", 172 OGOTO: "goto", 173 OGT: ">", 174 OIF: "if", 175 OIMAG: "imag", 176 OIND: "*", 177 OLEN: "len", 178 OLE: "<=", 179 OLSH: "<<", 180 OLT: "<", 181 OMAKE: "make", 182 OMINUS: "-", 183 OMOD: "%", 184 OMUL: "*", 185 ONEW: "new", 186 ONE: "!=", 187 ONOT: "!", 188 OOFFSETOF: "unsafe.Offsetof", 189 OOROR: "||", 190 OOR: "|", 191 OPANIC: "panic", 192 OPLUS: "+", 193 OPRINTN: "println", 194 OPRINT: "print", 195 ORANGE: "range", 196 OREAL: "real", 197 ORECV: "<-", 198 ORECOVER: "recover", 199 ORETURN: "return", 200 ORSH: ">>", 201 OSELECT: "select", 202 OSEND: "<-", 203 OSIZEOF: "unsafe.Sizeof", 204 OSUB: "-", 205 OSWITCH: "switch", 206 OXOR: "^", 207 } 208 209 func (o Op) GoString() string { 210 return fmt.Sprintf("%#v", o) 211 } 212 213 func (o Op) format(s fmt.State, verb rune, mode fmtMode) { 214 switch verb { 215 case 'v': 216 o.oconv(s, fmtFlag(s, verb), mode) 217 218 default: 219 fmt.Fprintf(s, "%%!%c(Op=%d)", verb, int(o)) 220 } 221 } 222 223 func (o Op) oconv(s fmt.State, flag FmtFlag, mode fmtMode) { 224 if flag&FmtSharp != 0 || mode != FDbg { 225 if int(o) < len(goopnames) && goopnames[o] != "" { 226 fmt.Fprint(s, goopnames[o]) 227 return 228 } 229 } 230 231 // 'o.String()' instead of just 'o' to avoid infinite recursion 232 fmt.Fprint(s, o.String()) 233 } 234 235 type ( 236 fmtMode int 237 238 fmtNodeErr Node 239 fmtNodeDbg Node 240 fmtNodeTypeId Node 241 fmtNodeTypeIdName Node 242 243 fmtOpErr Op 244 fmtOpDbg Op 245 fmtOpTypeId Op 246 fmtOpTypeIdName Op 247 248 fmtTypeErr types.Type 249 fmtTypeDbg types.Type 250 fmtTypeTypeId types.Type 251 fmtTypeTypeIdName types.Type 252 253 fmtSymErr types.Sym 254 fmtSymDbg types.Sym 255 fmtSymTypeId types.Sym 256 fmtSymTypeIdName types.Sym 257 258 fmtNodesErr Nodes 259 fmtNodesDbg Nodes 260 fmtNodesTypeId Nodes 261 fmtNodesTypeIdName Nodes 262 ) 263 264 func (n *fmtNodeErr) Format(s fmt.State, verb rune) { (*Node)(n).format(s, verb, FErr) } 265 func (n *fmtNodeDbg) Format(s fmt.State, verb rune) { (*Node)(n).format(s, verb, FDbg) } 266 func (n *fmtNodeTypeId) Format(s fmt.State, verb rune) { (*Node)(n).format(s, verb, FTypeId) } 267 func (n *fmtNodeTypeIdName) Format(s fmt.State, verb rune) { (*Node)(n).format(s, verb, FTypeIdName) } 268 func (n *Node) Format(s fmt.State, verb rune) { n.format(s, verb, FErr) } 269 270 func (o fmtOpErr) Format(s fmt.State, verb rune) { Op(o).format(s, verb, FErr) } 271 func (o fmtOpDbg) Format(s fmt.State, verb rune) { Op(o).format(s, verb, FDbg) } 272 func (o fmtOpTypeId) Format(s fmt.State, verb rune) { Op(o).format(s, verb, FTypeId) } 273 func (o fmtOpTypeIdName) Format(s fmt.State, verb rune) { Op(o).format(s, verb, FTypeIdName) } 274 func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } 275 276 func (t *fmtTypeErr) Format(s fmt.State, verb rune) { typeFormat((*types.Type)(t), s, verb, FErr) } 277 func (t *fmtTypeDbg) Format(s fmt.State, verb rune) { typeFormat((*types.Type)(t), s, verb, FDbg) } 278 func (t *fmtTypeTypeId) Format(s fmt.State, verb rune) { typeFormat((*types.Type)(t), s, verb, FTypeId) } 279 func (t *fmtTypeTypeIdName) Format(s fmt.State, verb rune) { 280 typeFormat((*types.Type)(t), s, verb, FTypeIdName) 281 } 282 283 // func (t *types.Type) Format(s fmt.State, verb rune) // in package types 284 285 func (y *fmtSymErr) Format(s fmt.State, verb rune) { symFormat((*types.Sym)(y), s, verb, FErr) } 286 func (y *fmtSymDbg) Format(s fmt.State, verb rune) { symFormat((*types.Sym)(y), s, verb, FDbg) } 287 func (y *fmtSymTypeId) Format(s fmt.State, verb rune) { symFormat((*types.Sym)(y), s, verb, FTypeId) } 288 func (y *fmtSymTypeIdName) Format(s fmt.State, verb rune) { 289 symFormat((*types.Sym)(y), s, verb, FTypeIdName) 290 } 291 292 // func (y *types.Sym) Format(s fmt.State, verb rune) // in package types { y.format(s, verb, FErr) } 293 294 func (n fmtNodesErr) Format(s fmt.State, verb rune) { (Nodes)(n).format(s, verb, FErr) } 295 func (n fmtNodesDbg) Format(s fmt.State, verb rune) { (Nodes)(n).format(s, verb, FDbg) } 296 func (n fmtNodesTypeId) Format(s fmt.State, verb rune) { (Nodes)(n).format(s, verb, FTypeId) } 297 func (n fmtNodesTypeIdName) Format(s fmt.State, verb rune) { (Nodes)(n).format(s, verb, FTypeIdName) } 298 func (n Nodes) Format(s fmt.State, verb rune) { n.format(s, verb, FErr) } 299 300 func (m fmtMode) Fprintf(s fmt.State, format string, args ...interface{}) { 301 m.prepareArgs(args) 302 fmt.Fprintf(s, format, args...) 303 } 304 305 func (m fmtMode) Sprintf(format string, args ...interface{}) string { 306 m.prepareArgs(args) 307 return fmt.Sprintf(format, args...) 308 } 309 310 func (m fmtMode) Sprint(args ...interface{}) string { 311 m.prepareArgs(args) 312 return fmt.Sprint(args...) 313 } 314 315 func (m fmtMode) prepareArgs(args []interface{}) { 316 switch m { 317 case FErr: 318 for i, arg := range args { 319 switch arg := arg.(type) { 320 case Op: 321 args[i] = fmtOpErr(arg) 322 case *Node: 323 args[i] = (*fmtNodeErr)(arg) 324 case *types.Type: 325 args[i] = (*fmtTypeErr)(arg) 326 case *types.Sym: 327 args[i] = (*fmtSymErr)(arg) 328 case Nodes: 329 args[i] = fmtNodesErr(arg) 330 case Val, int32, int64, string, types.EType: 331 // OK: printing these types doesn't depend on mode 332 default: 333 Fatalf("mode.prepareArgs type %T", arg) 334 } 335 } 336 case FDbg: 337 for i, arg := range args { 338 switch arg := arg.(type) { 339 case Op: 340 args[i] = fmtOpDbg(arg) 341 case *Node: 342 args[i] = (*fmtNodeDbg)(arg) 343 case *types.Type: 344 args[i] = (*fmtTypeDbg)(arg) 345 case *types.Sym: 346 args[i] = (*fmtSymDbg)(arg) 347 case Nodes: 348 args[i] = fmtNodesDbg(arg) 349 case Val, int32, int64, string, types.EType: 350 // OK: printing these types doesn't depend on mode 351 default: 352 Fatalf("mode.prepareArgs type %T", arg) 353 } 354 } 355 case FTypeId: 356 for i, arg := range args { 357 switch arg := arg.(type) { 358 case Op: 359 args[i] = fmtOpTypeId(arg) 360 case *Node: 361 args[i] = (*fmtNodeTypeId)(arg) 362 case *types.Type: 363 args[i] = (*fmtTypeTypeId)(arg) 364 case *types.Sym: 365 args[i] = (*fmtSymTypeId)(arg) 366 case Nodes: 367 args[i] = fmtNodesTypeId(arg) 368 case Val, int32, int64, string, types.EType: 369 // OK: printing these types doesn't depend on mode 370 default: 371 Fatalf("mode.prepareArgs type %T", arg) 372 } 373 } 374 case FTypeIdName: 375 for i, arg := range args { 376 switch arg := arg.(type) { 377 case Op: 378 args[i] = fmtOpTypeIdName(arg) 379 case *Node: 380 args[i] = (*fmtNodeTypeIdName)(arg) 381 case *types.Type: 382 args[i] = (*fmtTypeTypeIdName)(arg) 383 case *types.Sym: 384 args[i] = (*fmtSymTypeIdName)(arg) 385 case Nodes: 386 args[i] = fmtNodesTypeIdName(arg) 387 case Val, int32, int64, string, types.EType: 388 // OK: printing these types doesn't depend on mode 389 default: 390 Fatalf("mode.prepareArgs type %T", arg) 391 } 392 } 393 default: 394 Fatalf("mode.prepareArgs mode %d", m) 395 } 396 } 397 398 func (n *Node) format(s fmt.State, verb rune, mode fmtMode) { 399 switch verb { 400 case 'v', 'S', 'L': 401 n.nconv(s, fmtFlag(s, verb), mode) 402 403 case 'j': 404 n.jconv(s, fmtFlag(s, verb)) 405 406 default: 407 fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n) 408 } 409 } 410 411 // *Node details 412 func (n *Node) jconv(s fmt.State, flag FmtFlag) { 413 c := flag & FmtShort 414 415 if c == 0 && n.Addable() { 416 fmt.Fprintf(s, " a(%v)", n.Addable()) 417 } 418 419 if c == 0 && n.Name != nil && n.Name.Vargen != 0 { 420 fmt.Fprintf(s, " g(%d)", n.Name.Vargen) 421 } 422 423 if n.Pos.IsKnown() { 424 fmt.Fprintf(s, " l(%d)", n.Pos.Line()) 425 } 426 427 if c == 0 && n.Xoffset != BADWIDTH { 428 fmt.Fprintf(s, " x(%d)", n.Xoffset) 429 } 430 431 if n.Class() != 0 { 432 fmt.Fprintf(s, " class(%v)", n.Class()) 433 } 434 435 if n.Colas() { 436 fmt.Fprintf(s, " colas(%v)", n.Colas()) 437 } 438 439 if n.Name != nil && n.Name.Funcdepth != 0 { 440 fmt.Fprintf(s, " f(%d)", n.Name.Funcdepth) 441 } 442 if n.Func != nil && n.Func.Depth != 0 { 443 fmt.Fprintf(s, " ff(%d)", n.Func.Depth) 444 } 445 446 switch n.Esc { 447 case EscUnknown: 448 break 449 450 case EscHeap: 451 fmt.Fprint(s, " esc(h)") 452 453 case EscNone: 454 fmt.Fprint(s, " esc(no)") 455 456 case EscNever: 457 if c == 0 { 458 fmt.Fprint(s, " esc(N)") 459 } 460 461 default: 462 fmt.Fprintf(s, " esc(%d)", n.Esc) 463 } 464 465 if e, ok := n.Opt().(*NodeEscState); ok && e.Loopdepth != 0 { 466 fmt.Fprintf(s, " ld(%d)", e.Loopdepth) 467 } 468 469 if c == 0 && n.Typecheck() != 0 { 470 fmt.Fprintf(s, " tc(%d)", n.Typecheck()) 471 } 472 473 if n.Isddd() { 474 fmt.Fprintf(s, " isddd(%v)", n.Isddd()) 475 } 476 477 if n.Implicit() { 478 fmt.Fprintf(s, " implicit(%v)", n.Implicit()) 479 } 480 481 if n.Embedded() { 482 fmt.Fprintf(s, " embedded") 483 } 484 485 if n.Addrtaken() { 486 fmt.Fprint(s, " addrtaken") 487 } 488 489 if n.Assigned() { 490 fmt.Fprint(s, " assigned") 491 } 492 if n.Bounded() { 493 fmt.Fprint(s, " bounded") 494 } 495 if n.NonNil() { 496 fmt.Fprint(s, " nonnil") 497 } 498 499 if c == 0 && n.HasCall() { 500 fmt.Fprint(s, " hascall") 501 } 502 503 if c == 0 && n.Name != nil && n.Name.Used() { 504 fmt.Fprint(s, " used") 505 } 506 } 507 508 func (v Val) Format(s fmt.State, verb rune) { 509 switch verb { 510 case 'v': 511 v.vconv(s, fmtFlag(s, verb)) 512 513 default: 514 fmt.Fprintf(s, "%%!%c(Val=%T)", verb, v) 515 } 516 } 517 518 func (v Val) vconv(s fmt.State, flag FmtFlag) { 519 switch u := v.U.(type) { 520 case *Mpint: 521 if !u.Rune { 522 if flag&FmtSharp != 0 { 523 fmt.Fprint(s, bconv(u, FmtSharp)) 524 return 525 } 526 fmt.Fprint(s, bconv(u, 0)) 527 return 528 } 529 530 switch x := u.Int64(); { 531 case ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'': 532 fmt.Fprintf(s, "'%c'", int(x)) 533 534 case 0 <= x && x < 1<<16: 535 fmt.Fprintf(s, "'\\u%04x'", uint(int(x))) 536 537 case 0 <= x && x <= utf8.MaxRune: 538 fmt.Fprintf(s, "'\\U%08x'", uint64(x)) 539 540 default: 541 fmt.Fprintf(s, "('\\x00' + %v)", u) 542 } 543 544 case *Mpflt: 545 if flag&FmtSharp != 0 { 546 fmt.Fprint(s, fconv(u, 0)) 547 return 548 } 549 fmt.Fprint(s, fconv(u, FmtSharp)) 550 return 551 552 case *Mpcplx: 553 switch { 554 case flag&FmtSharp != 0: 555 fmt.Fprintf(s, "(%v+%vi)", &u.Real, &u.Imag) 556 557 case v.U.(*Mpcplx).Real.CmpFloat64(0) == 0: 558 fmt.Fprintf(s, "%vi", fconv(&u.Imag, FmtSharp)) 559 560 case v.U.(*Mpcplx).Imag.CmpFloat64(0) == 0: 561 fmt.Fprint(s, fconv(&u.Real, FmtSharp)) 562 563 case v.U.(*Mpcplx).Imag.CmpFloat64(0) < 0: 564 fmt.Fprintf(s, "(%v%vi)", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp)) 565 566 default: 567 fmt.Fprintf(s, "(%v+%vi)", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp)) 568 } 569 570 case string: 571 fmt.Fprint(s, strconv.Quote(u)) 572 573 case bool: 574 fmt.Fprint(s, u) 575 576 case *NilVal: 577 fmt.Fprint(s, "nil") 578 579 default: 580 fmt.Fprintf(s, "<ctype=%d>", v.Ctype()) 581 } 582 } 583 584 /* 585 s%,%,\n%g 586 s%\n+%\n%g 587 s%^[ ]*T%%g 588 s%,.*%%g 589 s%.+% [T&] = "&",%g 590 s%^ ........*\]%&~%g 591 s%~ %%g 592 */ 593 594 func symfmt(s *types.Sym, flag FmtFlag, mode fmtMode) string { 595 if s.Pkg != nil && flag&FmtShort == 0 { 596 switch mode { 597 case FErr: // This is for the user 598 if s.Pkg == builtinpkg || s.Pkg == localpkg { 599 return s.Name 600 } 601 602 // If the name was used by multiple packages, display the full path, 603 if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 { 604 return fmt.Sprintf("%q.%s", s.Pkg.Path, s.Name) 605 } 606 return s.Pkg.Name + "." + s.Name 607 608 case FDbg: 609 return s.Pkg.Name + "." + s.Name 610 611 case FTypeIdName: 612 return s.Pkg.Name + "." + s.Name // dcommontype, typehash 613 614 case FTypeId: 615 return s.Pkg.Prefix + "." + s.Name // (methodsym), typesym, weaksym 616 } 617 } 618 619 if flag&FmtByte != 0 { 620 // FmtByte (hh) implies FmtShort (h) 621 // skip leading "type." in method name 622 name := s.Name 623 if i := strings.LastIndex(name, "."); i >= 0 { 624 name = name[i+1:] 625 } 626 627 if mode == FDbg { 628 return fmt.Sprintf("@%q.%s", s.Pkg.Path, name) 629 } 630 631 return name 632 } 633 634 return s.Name 635 } 636 637 var basicnames = []string{ 638 TINT: "int", 639 TUINT: "uint", 640 TINT8: "int8", 641 TUINT8: "uint8", 642 TINT16: "int16", 643 TUINT16: "uint16", 644 TINT32: "int32", 645 TUINT32: "uint32", 646 TINT64: "int64", 647 TUINT64: "uint64", 648 TUINTPTR: "uintptr", 649 TFLOAT32: "float32", 650 TFLOAT64: "float64", 651 TCOMPLEX64: "complex64", 652 TCOMPLEX128: "complex128", 653 TBOOL: "bool", 654 TANY: "any", 655 TSTRING: "string", 656 TNIL: "nil", 657 TIDEAL: "untyped number", 658 TBLANK: "blank", 659 } 660 661 func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string { 662 if t == nil { 663 return "<T>" 664 } 665 666 if t == types.Bytetype || t == types.Runetype { 667 // in %-T mode collapse rune and byte with their originals. 668 switch mode { 669 case FTypeIdName, FTypeId: 670 t = types.Types[t.Etype] 671 default: 672 return sconv(t.Sym, FmtShort, mode) 673 } 674 } 675 676 if t == types.Errortype { 677 return "error" 678 } 679 680 // Unless the 'l' flag was specified, if the type has a name, just print that name. 681 if flag&FmtLong == 0 && t.Sym != nil && t != types.Types[t.Etype] { 682 switch mode { 683 case FTypeId, FTypeIdName: 684 if flag&FmtShort != 0 { 685 if t.Vargen != 0 { 686 return mode.Sprintf("%v%d", sconv(t.Sym, FmtShort, mode), t.Vargen) 687 } 688 return sconv(t.Sym, FmtShort, mode) 689 } 690 691 if mode == FTypeIdName { 692 return sconv(t.Sym, FmtUnsigned, mode) 693 } 694 695 if t.Sym.Pkg == localpkg && t.Vargen != 0 { 696 return mode.Sprintf("%v%d", t.Sym, t.Vargen) 697 } 698 } 699 700 return smodeString(t.Sym, mode) 701 } 702 703 if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" { 704 prefix := "" 705 if mode == FErr && (t == types.Idealbool || t == types.Idealstring) { 706 prefix = "untyped " 707 } 708 return prefix + basicnames[t.Etype] 709 } 710 711 if mode == FDbg { 712 return t.Etype.String() + "-" + typefmt(t, flag, 0, depth) 713 } 714 715 switch t.Etype { 716 case TPTR32, TPTR64: 717 switch mode { 718 case FTypeId, FTypeIdName: 719 if flag&FmtShort != 0 { 720 return "*" + tconv(t.Elem(), FmtShort, mode, depth) 721 } 722 } 723 return "*" + tmodeString(t.Elem(), mode, depth) 724 725 case TARRAY: 726 if t.IsDDDArray() { 727 return "[...]" + tmodeString(t.Elem(), mode, depth) 728 } 729 return "[" + strconv.FormatInt(t.NumElem(), 10) + "]" + tmodeString(t.Elem(), mode, depth) 730 731 case TSLICE: 732 return "[]" + tmodeString(t.Elem(), mode, depth) 733 734 case TCHAN: 735 switch t.ChanDir() { 736 case types.Crecv: 737 return "<-chan " + tmodeString(t.Elem(), mode, depth) 738 739 case types.Csend: 740 return "chan<- " + tmodeString(t.Elem(), mode, depth) 741 } 742 743 if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == types.Crecv { 744 return "chan (" + tmodeString(t.Elem(), mode, depth) + ")" 745 } 746 return "chan " + tmodeString(t.Elem(), mode, depth) 747 748 case TMAP: 749 return "map[" + tmodeString(t.Key(), mode, depth) + "]" + tmodeString(t.Val(), mode, depth) 750 751 case TINTER: 752 if t.IsEmptyInterface() { 753 return "interface {}" 754 } 755 buf := make([]byte, 0, 64) 756 buf = append(buf, "interface {"...) 757 for i, f := range t.Fields().Slice() { 758 if i != 0 { 759 buf = append(buf, ';') 760 } 761 buf = append(buf, ' ') 762 switch { 763 case f.Sym == nil: 764 // Check first that a symbol is defined for this type. 765 // Wrong interface definitions may have types lacking a symbol. 766 break 767 case exportname(f.Sym.Name): 768 buf = append(buf, sconv(f.Sym, FmtShort, mode)...) 769 default: 770 buf = append(buf, sconv(f.Sym, FmtUnsigned, mode)...) 771 } 772 buf = append(buf, tconv(f.Type, FmtShort, mode, depth)...) 773 } 774 if t.NumFields() != 0 { 775 buf = append(buf, ' ') 776 } 777 buf = append(buf, '}') 778 return string(buf) 779 780 case TFUNC: 781 buf := make([]byte, 0, 64) 782 if flag&FmtShort != 0 { 783 // no leading func 784 } else { 785 if t.Recv() != nil { 786 buf = append(buf, "method"...) 787 buf = append(buf, tmodeString(t.Recvs(), mode, depth)...) 788 buf = append(buf, ' ') 789 } 790 buf = append(buf, "func"...) 791 } 792 buf = append(buf, tmodeString(t.Params(), mode, depth)...) 793 794 switch t.NumResults() { 795 case 0: 796 // nothing to do 797 798 case 1: 799 buf = append(buf, ' ') 800 buf = append(buf, tmodeString(t.Results().Field(0).Type, mode, depth)...) // struct->field->field's type 801 802 default: 803 buf = append(buf, ' ') 804 buf = append(buf, tmodeString(t.Results(), mode, depth)...) 805 } 806 return string(buf) 807 808 case TSTRUCT: 809 if m := t.StructType().Map; m != nil { 810 mt := m.MapType() 811 // Format the bucket struct for map[x]y as map.bucket[x]y. 812 // This avoids a recursive print that generates very long names. 813 if mt.Bucket == t { 814 return "map.bucket[" + tmodeString(m.Key(), mode, depth) + "]" + tmodeString(m.Val(), mode, depth) 815 } 816 817 if mt.Hmap == t { 818 return "map.hdr[" + tmodeString(m.Key(), mode, depth) + "]" + tmodeString(m.Val(), mode, depth) 819 } 820 821 if mt.Hiter == t { 822 return "map.iter[" + tmodeString(m.Key(), mode, depth) + "]" + tmodeString(m.Val(), mode, depth) 823 } 824 825 Fatalf("unknown internal map type") 826 } 827 828 buf := make([]byte, 0, 64) 829 if t.IsFuncArgStruct() { 830 buf = append(buf, '(') 831 var flag1 FmtFlag 832 switch mode { 833 case FTypeId, FTypeIdName, FErr: 834 // no argument names on function signature, and no "noescape"/"nosplit" tags 835 flag1 = FmtShort 836 } 837 for i, f := range t.Fields().Slice() { 838 if i != 0 { 839 buf = append(buf, ", "...) 840 } 841 buf = append(buf, fldconv(f, flag1, mode, depth)...) 842 } 843 buf = append(buf, ')') 844 } else { 845 buf = append(buf, "struct {"...) 846 for i, f := range t.Fields().Slice() { 847 if i != 0 { 848 buf = append(buf, ';') 849 } 850 buf = append(buf, ' ') 851 buf = append(buf, fldconv(f, FmtLong, mode, depth)...) 852 } 853 if t.NumFields() != 0 { 854 buf = append(buf, ' ') 855 } 856 buf = append(buf, '}') 857 } 858 return string(buf) 859 860 case TFORW: 861 if t.Sym != nil { 862 return "undefined " + smodeString(t.Sym, mode) 863 } 864 return "undefined" 865 866 case TUNSAFEPTR: 867 return "unsafe.Pointer" 868 869 case TDDDFIELD: 870 return mode.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.DDDField()) 871 872 case Txxx: 873 return "Txxx" 874 } 875 876 // Don't know how to handle - fall back to detailed prints. 877 return mode.Sprintf("%v <%v>", t.Etype, t.Sym) 878 } 879 880 // Statements which may be rendered with a simplestmt as init. 881 func stmtwithinit(op Op) bool { 882 switch op { 883 case OIF, OFOR, OFORUNTIL, OSWITCH: 884 return true 885 } 886 887 return false 888 } 889 890 func (n *Node) stmtfmt(s fmt.State, mode fmtMode) { 891 // some statements allow for an init, but at most one, 892 // but we may have an arbitrary number added, eg by typecheck 893 // and inlining. If it doesn't fit the syntax, emit an enclosing 894 // block starting with the init statements. 895 896 // if we can just say "for" n->ninit; ... then do so 897 simpleinit := n.Ninit.Len() == 1 && n.Ninit.First().Ninit.Len() == 0 && stmtwithinit(n.Op) 898 899 // otherwise, print the inits as separate statements 900 complexinit := n.Ninit.Len() != 0 && !simpleinit && (mode != FErr) 901 902 // but if it was for if/for/switch, put in an extra surrounding block to limit the scope 903 extrablock := complexinit && stmtwithinit(n.Op) 904 905 if extrablock { 906 fmt.Fprint(s, "{") 907 } 908 909 if complexinit { 910 mode.Fprintf(s, " %v; ", n.Ninit) 911 } 912 913 switch n.Op { 914 case ODCL: 915 mode.Fprintf(s, "var %v %v", n.Left.Sym, n.Left.Type) 916 917 case ODCLFIELD: 918 if n.Left != nil { 919 mode.Fprintf(s, "%v %v", n.Left, n.Right) 920 } else { 921 mode.Fprintf(s, "%v", n.Right) 922 } 923 924 // Don't export "v = <N>" initializing statements, hope they're always 925 // preceded by the DCL which will be re-parsed and typechecked to reproduce 926 // the "v = <N>" again. 927 case OAS: 928 if n.Colas() && !complexinit { 929 mode.Fprintf(s, "%v := %v", n.Left, n.Right) 930 } else { 931 mode.Fprintf(s, "%v = %v", n.Left, n.Right) 932 } 933 934 case OASOP: 935 if n.Implicit() { 936 if Op(n.Etype) == OADD { 937 mode.Fprintf(s, "%v++", n.Left) 938 } else { 939 mode.Fprintf(s, "%v--", n.Left) 940 } 941 break 942 } 943 944 mode.Fprintf(s, "%v %#v= %v", n.Left, Op(n.Etype), n.Right) 945 946 case OAS2: 947 if n.Colas() && !complexinit { 948 mode.Fprintf(s, "%.v := %.v", n.List, n.Rlist) 949 break 950 } 951 fallthrough 952 953 case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 954 mode.Fprintf(s, "%.v = %.v", n.List, n.Rlist) 955 956 case ORETURN: 957 mode.Fprintf(s, "return %.v", n.List) 958 959 case ORETJMP: 960 mode.Fprintf(s, "retjmp %v", n.Sym) 961 962 case OPROC: 963 mode.Fprintf(s, "go %v", n.Left) 964 965 case ODEFER: 966 mode.Fprintf(s, "defer %v", n.Left) 967 968 case OIF: 969 if simpleinit { 970 mode.Fprintf(s, "if %v; %v { %v }", n.Ninit.First(), n.Left, n.Nbody) 971 } else { 972 mode.Fprintf(s, "if %v { %v }", n.Left, n.Nbody) 973 } 974 if n.Rlist.Len() != 0 { 975 mode.Fprintf(s, " else { %v }", n.Rlist) 976 } 977 978 case OFOR, OFORUNTIL: 979 opname := "for" 980 if n.Op == OFORUNTIL { 981 opname = "foruntil" 982 } 983 if mode == FErr { // TODO maybe only if FmtShort, same below 984 fmt.Fprintf(s, "%s loop", opname) 985 break 986 } 987 988 fmt.Fprint(s, opname) 989 if simpleinit { 990 mode.Fprintf(s, " %v;", n.Ninit.First()) 991 } else if n.Right != nil { 992 fmt.Fprint(s, " ;") 993 } 994 995 if n.Left != nil { 996 mode.Fprintf(s, " %v", n.Left) 997 } 998 999 if n.Right != nil { 1000 mode.Fprintf(s, "; %v", n.Right) 1001 } else if simpleinit { 1002 fmt.Fprint(s, ";") 1003 } 1004 1005 mode.Fprintf(s, " { %v }", n.Nbody) 1006 1007 case ORANGE: 1008 if mode == FErr { 1009 fmt.Fprint(s, "for loop") 1010 break 1011 } 1012 1013 if n.List.Len() == 0 { 1014 mode.Fprintf(s, "for range %v { %v }", n.Right, n.Nbody) 1015 break 1016 } 1017 1018 mode.Fprintf(s, "for %.v = range %v { %v }", n.List, n.Right, n.Nbody) 1019 1020 case OSELECT, OSWITCH: 1021 if mode == FErr { 1022 mode.Fprintf(s, "%v statement", n.Op) 1023 break 1024 } 1025 1026 mode.Fprintf(s, "%#v", n.Op) 1027 if simpleinit { 1028 mode.Fprintf(s, " %v;", n.Ninit.First()) 1029 } 1030 if n.Left != nil { 1031 mode.Fprintf(s, " %v ", n.Left) 1032 } 1033 1034 mode.Fprintf(s, " { %v }", n.List) 1035 1036 case OXCASE: 1037 if n.List.Len() != 0 { 1038 mode.Fprintf(s, "case %.v", n.List) 1039 } else { 1040 fmt.Fprint(s, "default") 1041 } 1042 mode.Fprintf(s, ": %v", n.Nbody) 1043 1044 case OCASE: 1045 switch { 1046 case n.Left != nil: 1047 // single element 1048 mode.Fprintf(s, "case %v", n.Left) 1049 case n.List.Len() > 0: 1050 // range 1051 if n.List.Len() != 2 { 1052 Fatalf("bad OCASE list length %d", n.List.Len()) 1053 } 1054 mode.Fprintf(s, "case %v..%v", n.List.First(), n.List.Second()) 1055 default: 1056 fmt.Fprint(s, "default") 1057 } 1058 mode.Fprintf(s, ": %v", n.Nbody) 1059 1060 case OBREAK, OCONTINUE, OGOTO, OFALL: 1061 if n.Left != nil { 1062 mode.Fprintf(s, "%#v %v", n.Op, n.Left) 1063 } else { 1064 mode.Fprintf(s, "%#v", n.Op) 1065 } 1066 1067 case OEMPTY: 1068 break 1069 1070 case OLABEL: 1071 mode.Fprintf(s, "%v: ", n.Left) 1072 } 1073 1074 if extrablock { 1075 fmt.Fprint(s, "}") 1076 } 1077 } 1078 1079 var opprec = []int{ 1080 OALIGNOF: 8, 1081 OAPPEND: 8, 1082 OARRAYBYTESTR: 8, 1083 OARRAYLIT: 8, 1084 OSLICELIT: 8, 1085 OARRAYRUNESTR: 8, 1086 OCALLFUNC: 8, 1087 OCALLINTER: 8, 1088 OCALLMETH: 8, 1089 OCALL: 8, 1090 OCAP: 8, 1091 OCLOSE: 8, 1092 OCONVIFACE: 8, 1093 OCONVNOP: 8, 1094 OCONV: 8, 1095 OCOPY: 8, 1096 ODELETE: 8, 1097 OGETG: 8, 1098 OLEN: 8, 1099 OLITERAL: 8, 1100 OMAKESLICE: 8, 1101 OMAKE: 8, 1102 OMAPLIT: 8, 1103 ONAME: 8, 1104 ONEW: 8, 1105 ONONAME: 8, 1106 OOFFSETOF: 8, 1107 OPACK: 8, 1108 OPANIC: 8, 1109 OPAREN: 8, 1110 OPRINTN: 8, 1111 OPRINT: 8, 1112 ORUNESTR: 8, 1113 OSIZEOF: 8, 1114 OSTRARRAYBYTE: 8, 1115 OSTRARRAYRUNE: 8, 1116 OSTRUCTLIT: 8, 1117 OTARRAY: 8, 1118 OTCHAN: 8, 1119 OTFUNC: 8, 1120 OTINTER: 8, 1121 OTMAP: 8, 1122 OTSTRUCT: 8, 1123 OINDEXMAP: 8, 1124 OINDEX: 8, 1125 OSLICE: 8, 1126 OSLICESTR: 8, 1127 OSLICEARR: 8, 1128 OSLICE3: 8, 1129 OSLICE3ARR: 8, 1130 ODOTINTER: 8, 1131 ODOTMETH: 8, 1132 ODOTPTR: 8, 1133 ODOTTYPE2: 8, 1134 ODOTTYPE: 8, 1135 ODOT: 8, 1136 OXDOT: 8, 1137 OCALLPART: 8, 1138 OPLUS: 7, 1139 ONOT: 7, 1140 OCOM: 7, 1141 OMINUS: 7, 1142 OADDR: 7, 1143 OIND: 7, 1144 ORECV: 7, 1145 OMUL: 6, 1146 ODIV: 6, 1147 OMOD: 6, 1148 OLSH: 6, 1149 ORSH: 6, 1150 OAND: 6, 1151 OANDNOT: 6, 1152 OADD: 5, 1153 OSUB: 5, 1154 OOR: 5, 1155 OXOR: 5, 1156 OEQ: 4, 1157 OLT: 4, 1158 OLE: 4, 1159 OGE: 4, 1160 OGT: 4, 1161 ONE: 4, 1162 OCMPSTR: 4, 1163 OCMPIFACE: 4, 1164 OSEND: 3, 1165 OANDAND: 2, 1166 OOROR: 1, 1167 1168 // Statements handled by stmtfmt 1169 OAS: -1, 1170 OAS2: -1, 1171 OAS2DOTTYPE: -1, 1172 OAS2FUNC: -1, 1173 OAS2MAPR: -1, 1174 OAS2RECV: -1, 1175 OASOP: -1, 1176 OBREAK: -1, 1177 OCASE: -1, 1178 OCONTINUE: -1, 1179 ODCL: -1, 1180 ODCLFIELD: -1, 1181 ODEFER: -1, 1182 OEMPTY: -1, 1183 OFALL: -1, 1184 OFOR: -1, 1185 OFORUNTIL: -1, 1186 OGOTO: -1, 1187 OIF: -1, 1188 OLABEL: -1, 1189 OPROC: -1, 1190 ORANGE: -1, 1191 ORETURN: -1, 1192 OSELECT: -1, 1193 OSWITCH: -1, 1194 OXCASE: -1, 1195 1196 OEND: 0, 1197 } 1198 1199 func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { 1200 for n != nil && n.Implicit() && (n.Op == OIND || n.Op == OADDR) { 1201 n = n.Left 1202 } 1203 1204 if n == nil { 1205 fmt.Fprint(s, "<N>") 1206 return 1207 } 1208 1209 nprec := opprec[n.Op] 1210 if n.Op == OTYPE && n.Sym != nil { 1211 nprec = 8 1212 } 1213 1214 if prec > nprec { 1215 mode.Fprintf(s, "(%v)", n) 1216 return 1217 } 1218 1219 switch n.Op { 1220 case OPAREN: 1221 mode.Fprintf(s, "(%v)", n.Left) 1222 1223 case ODDDARG: 1224 fmt.Fprint(s, "... argument") 1225 1226 case OLITERAL: // this is a bit of a mess 1227 if mode == FErr { 1228 if n.Orig != nil && n.Orig != n { 1229 n.Orig.exprfmt(s, prec, mode) 1230 return 1231 } 1232 if n.Sym != nil { 1233 fmt.Fprint(s, smodeString(n.Sym, mode)) 1234 return 1235 } 1236 } 1237 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n { 1238 n.Orig.exprfmt(s, prec, mode) 1239 return 1240 } 1241 if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != types.Idealbool && n.Type != types.Idealstring { 1242 // Need parens when type begins with what might 1243 // be misinterpreted as a unary operator: * or <-. 1244 if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == types.Crecv) { 1245 mode.Fprintf(s, "(%v)(%v)", n.Type, n.Val()) 1246 return 1247 } else { 1248 mode.Fprintf(s, "%v(%v)", n.Type, n.Val()) 1249 return 1250 } 1251 } 1252 1253 mode.Fprintf(s, "%v", n.Val()) 1254 1255 // Special case: name used as local variable in export. 1256 // _ becomes ~b%d internally; print as _ for export 1257 case ONAME: 1258 if mode == FErr && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' { 1259 fmt.Fprint(s, "_") 1260 return 1261 } 1262 fallthrough 1263 case OPACK, ONONAME: 1264 fmt.Fprint(s, smodeString(n.Sym, mode)) 1265 1266 case OTYPE: 1267 if n.Type == nil && n.Sym != nil { 1268 fmt.Fprint(s, smodeString(n.Sym, mode)) 1269 return 1270 } 1271 mode.Fprintf(s, "%v", n.Type) 1272 1273 case OTARRAY: 1274 if n.Left != nil { 1275 mode.Fprintf(s, "[]%v", n.Left) 1276 return 1277 } 1278 mode.Fprintf(s, "[]%v", n.Right) // happens before typecheck 1279 1280 case OTMAP: 1281 mode.Fprintf(s, "map[%v]%v", n.Left, n.Right) 1282 1283 case OTCHAN: 1284 switch types.ChanDir(n.Etype) { 1285 case types.Crecv: 1286 mode.Fprintf(s, "<-chan %v", n.Left) 1287 1288 case types.Csend: 1289 mode.Fprintf(s, "chan<- %v", n.Left) 1290 1291 default: 1292 if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && types.ChanDir(n.Left.Etype) == types.Crecv { 1293 mode.Fprintf(s, "chan (%v)", n.Left) 1294 } else { 1295 mode.Fprintf(s, "chan %v", n.Left) 1296 } 1297 } 1298 1299 case OTSTRUCT: 1300 fmt.Fprint(s, "<struct>") 1301 1302 case OTINTER: 1303 fmt.Fprint(s, "<inter>") 1304 1305 case OTFUNC: 1306 fmt.Fprint(s, "<func>") 1307 1308 case OCLOSURE: 1309 if mode == FErr { 1310 fmt.Fprint(s, "func literal") 1311 return 1312 } 1313 if n.Nbody.Len() != 0 { 1314 mode.Fprintf(s, "%v { %v }", n.Type, n.Nbody) 1315 return 1316 } 1317 mode.Fprintf(s, "%v { %v }", n.Type, n.Func.Closure.Nbody) 1318 1319 case OCOMPLIT: 1320 ptrlit := n.Right != nil && n.Right.Implicit() && n.Right.Type != nil && n.Right.Type.IsPtr() 1321 if mode == FErr { 1322 if n.Right != nil && n.Right.Type != nil && !n.Implicit() { 1323 if ptrlit { 1324 mode.Fprintf(s, "&%v literal", n.Right.Type.Elem()) 1325 return 1326 } else { 1327 mode.Fprintf(s, "%v literal", n.Right.Type) 1328 return 1329 } 1330 } 1331 1332 fmt.Fprint(s, "composite literal") 1333 return 1334 } 1335 mode.Fprintf(s, "(%v{ %.v })", n.Right, n.List) 1336 1337 case OPTRLIT: 1338 mode.Fprintf(s, "&%v", n.Left) 1339 1340 case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT: 1341 if mode == FErr { 1342 mode.Fprintf(s, "%v literal", n.Type) 1343 return 1344 } 1345 mode.Fprintf(s, "(%v{ %.v })", n.Type, n.List) 1346 1347 case OKEY: 1348 if n.Left != nil && n.Right != nil { 1349 mode.Fprintf(s, "%v:%v", n.Left, n.Right) 1350 return 1351 } 1352 1353 if n.Left == nil && n.Right != nil { 1354 mode.Fprintf(s, ":%v", n.Right) 1355 return 1356 } 1357 if n.Left != nil && n.Right == nil { 1358 mode.Fprintf(s, "%v:", n.Left) 1359 return 1360 } 1361 fmt.Fprint(s, ":") 1362 1363 case OSTRUCTKEY: 1364 mode.Fprintf(s, "%v:%v", n.Sym, n.Left) 1365 1366 case OCALLPART: 1367 n.Left.exprfmt(s, nprec, mode) 1368 if n.Right == nil || n.Right.Sym == nil { 1369 fmt.Fprint(s, ".<nil>") 1370 return 1371 } 1372 mode.Fprintf(s, ".%0S", n.Right.Sym) 1373 1374 case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 1375 n.Left.exprfmt(s, nprec, mode) 1376 if n.Sym == nil { 1377 fmt.Fprint(s, ".<nil>") 1378 return 1379 } 1380 mode.Fprintf(s, ".%0S", n.Sym) 1381 1382 case ODOTTYPE, ODOTTYPE2: 1383 n.Left.exprfmt(s, nprec, mode) 1384 if n.Right != nil { 1385 mode.Fprintf(s, ".(%v)", n.Right) 1386 return 1387 } 1388 mode.Fprintf(s, ".(%v)", n.Type) 1389 1390 case OINDEX, OINDEXMAP: 1391 n.Left.exprfmt(s, nprec, mode) 1392 mode.Fprintf(s, "[%v]", n.Right) 1393 1394 case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: 1395 n.Left.exprfmt(s, nprec, mode) 1396 fmt.Fprint(s, "[") 1397 low, high, max := n.SliceBounds() 1398 if low != nil { 1399 fmt.Fprint(s, low.modeString(mode)) 1400 } 1401 fmt.Fprint(s, ":") 1402 if high != nil { 1403 fmt.Fprint(s, high.modeString(mode)) 1404 } 1405 if n.Op.IsSlice3() { 1406 fmt.Fprint(s, ":") 1407 if max != nil { 1408 fmt.Fprint(s, max.modeString(mode)) 1409 } 1410 } 1411 fmt.Fprint(s, "]") 1412 1413 case OCOPY, OCOMPLEX: 1414 mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right) 1415 1416 case OCONV, 1417 OCONVIFACE, 1418 OCONVNOP, 1419 OARRAYBYTESTR, 1420 OARRAYRUNESTR, 1421 OSTRARRAYBYTE, 1422 OSTRARRAYRUNE, 1423 ORUNESTR: 1424 if n.Type == nil || n.Type.Sym == nil { 1425 mode.Fprintf(s, "(%v)", n.Type) 1426 } else { 1427 mode.Fprintf(s, "%v", n.Type) 1428 } 1429 if n.Left != nil { 1430 mode.Fprintf(s, "(%v)", n.Left) 1431 } else { 1432 mode.Fprintf(s, "(%.v)", n.List) 1433 } 1434 1435 case OREAL, 1436 OIMAG, 1437 OAPPEND, 1438 OCAP, 1439 OCLOSE, 1440 ODELETE, 1441 OLEN, 1442 OMAKE, 1443 ONEW, 1444 OPANIC, 1445 ORECOVER, 1446 OALIGNOF, 1447 OOFFSETOF, 1448 OSIZEOF, 1449 OPRINT, 1450 OPRINTN: 1451 if n.Left != nil { 1452 mode.Fprintf(s, "%#v(%v)", n.Op, n.Left) 1453 return 1454 } 1455 if n.Isddd() { 1456 mode.Fprintf(s, "%#v(%.v...)", n.Op, n.List) 1457 return 1458 } 1459 mode.Fprintf(s, "%#v(%.v)", n.Op, n.List) 1460 1461 case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG: 1462 n.Left.exprfmt(s, nprec, mode) 1463 if n.Isddd() { 1464 mode.Fprintf(s, "(%.v...)", n.List) 1465 return 1466 } 1467 mode.Fprintf(s, "(%.v)", n.List) 1468 1469 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 1470 if n.List.Len() != 0 { // pre-typecheck 1471 mode.Fprintf(s, "make(%v, %.v)", n.Type, n.List) 1472 return 1473 } 1474 if n.Right != nil { 1475 mode.Fprintf(s, "make(%v, %v, %v)", n.Type, n.Left, n.Right) 1476 return 1477 } 1478 if n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()) { 1479 mode.Fprintf(s, "make(%v, %v)", n.Type, n.Left) 1480 return 1481 } 1482 mode.Fprintf(s, "make(%v)", n.Type) 1483 1484 case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV: 1485 // Unary 1486 mode.Fprintf(s, "%#v", n.Op) 1487 if n.Left != nil && n.Left.Op == n.Op { 1488 fmt.Fprint(s, " ") 1489 } 1490 n.Left.exprfmt(s, nprec+1, mode) 1491 1492 // Binary 1493 case OADD, 1494 OAND, 1495 OANDAND, 1496 OANDNOT, 1497 ODIV, 1498 OEQ, 1499 OGE, 1500 OGT, 1501 OLE, 1502 OLT, 1503 OLSH, 1504 OMOD, 1505 OMUL, 1506 ONE, 1507 OOR, 1508 OOROR, 1509 ORSH, 1510 OSEND, 1511 OSUB, 1512 OXOR: 1513 n.Left.exprfmt(s, nprec, mode) 1514 mode.Fprintf(s, " %#v ", n.Op) 1515 n.Right.exprfmt(s, nprec+1, mode) 1516 1517 case OADDSTR: 1518 for i, n1 := range n.List.Slice() { 1519 if i != 0 { 1520 fmt.Fprint(s, " + ") 1521 } 1522 n1.exprfmt(s, nprec, mode) 1523 } 1524 1525 case OCMPSTR, OCMPIFACE: 1526 n.Left.exprfmt(s, nprec, mode) 1527 // TODO(marvin): Fix Node.EType type union. 1528 mode.Fprintf(s, " %#v ", Op(n.Etype)) 1529 n.Right.exprfmt(s, nprec+1, mode) 1530 1531 default: 1532 mode.Fprintf(s, "<node %v>", n.Op) 1533 } 1534 } 1535 1536 func (n *Node) nodefmt(s fmt.State, flag FmtFlag, mode fmtMode) { 1537 t := n.Type 1538 1539 // We almost always want the original, except in export mode for literals. 1540 // This saves the importer some work, and avoids us having to redo some 1541 // special casing for package unsafe. 1542 if n.Op != OLITERAL && n.Orig != nil { 1543 n = n.Orig 1544 } 1545 1546 if flag&FmtLong != 0 && t != nil { 1547 if t.Etype == TNIL { 1548 fmt.Fprint(s, "nil") 1549 } else { 1550 mode.Fprintf(s, "%v (type %v)", n, t) 1551 } 1552 return 1553 } 1554 1555 // TODO inlining produces expressions with ninits. we can't print these yet. 1556 1557 if opprec[n.Op] < 0 { 1558 n.stmtfmt(s, mode) 1559 return 1560 } 1561 1562 n.exprfmt(s, 0, mode) 1563 } 1564 1565 func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) { 1566 recur := flag&FmtShort == 0 1567 1568 if recur { 1569 indent(s) 1570 if dumpdepth > 40 { 1571 fmt.Fprint(s, "...") 1572 return 1573 } 1574 1575 if n.Ninit.Len() != 0 { 1576 mode.Fprintf(s, "%v-init%v", n.Op, n.Ninit) 1577 indent(s) 1578 } 1579 } 1580 1581 switch n.Op { 1582 default: 1583 mode.Fprintf(s, "%v%j", n.Op, n) 1584 1585 case OINDREGSP: 1586 mode.Fprintf(s, "%v-SP%j", n.Op, n) 1587 1588 case OLITERAL: 1589 mode.Fprintf(s, "%v-%v%j", n.Op, n.Val(), n) 1590 1591 case ONAME, ONONAME: 1592 if n.Sym != nil { 1593 mode.Fprintf(s, "%v-%v%j", n.Op, n.Sym, n) 1594 } else { 1595 mode.Fprintf(s, "%v%j", n.Op, n) 1596 } 1597 if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil { 1598 indent(s) 1599 mode.Fprintf(s, "%v-ntype%v", n.Op, n.Name.Param.Ntype) 1600 } 1601 1602 case OASOP: 1603 mode.Fprintf(s, "%v-%v%j", n.Op, Op(n.Etype), n) 1604 1605 case OTYPE: 1606 mode.Fprintf(s, "%v %v%j type=%v", n.Op, n.Sym, n, n.Type) 1607 if recur && n.Type == nil && n.Name.Param.Ntype != nil { 1608 indent(s) 1609 mode.Fprintf(s, "%v-ntype%v", n.Op, n.Name.Param.Ntype) 1610 } 1611 } 1612 1613 if n.Sym != nil && n.Op != ONAME { 1614 mode.Fprintf(s, " %v", n.Sym) 1615 } 1616 1617 if n.Type != nil { 1618 mode.Fprintf(s, " %v", n.Type) 1619 } 1620 1621 if recur { 1622 if n.Left != nil { 1623 mode.Fprintf(s, "%v", n.Left) 1624 } 1625 if n.Right != nil { 1626 mode.Fprintf(s, "%v", n.Right) 1627 } 1628 if n.List.Len() != 0 { 1629 indent(s) 1630 mode.Fprintf(s, "%v-list%v", n.Op, n.List) 1631 } 1632 1633 if n.Rlist.Len() != 0 { 1634 indent(s) 1635 mode.Fprintf(s, "%v-rlist%v", n.Op, n.Rlist) 1636 } 1637 1638 if n.Nbody.Len() != 0 { 1639 indent(s) 1640 mode.Fprintf(s, "%v-body%v", n.Op, n.Nbody) 1641 } 1642 } 1643 } 1644 1645 // "%S" suppresses qualifying with package 1646 func symFormat(s *types.Sym, f fmt.State, verb rune, mode fmtMode) { 1647 switch verb { 1648 case 'v', 'S': 1649 fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode)) 1650 1651 default: 1652 fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s) 1653 } 1654 } 1655 1656 func smodeString(s *types.Sym, mode fmtMode) string { return sconv(s, 0, mode) } 1657 1658 // See #16897 before changing the implementation of sconv. 1659 func sconv(s *types.Sym, flag FmtFlag, mode fmtMode) string { 1660 if flag&FmtLong != 0 { 1661 panic("linksymfmt") 1662 } 1663 1664 if s == nil { 1665 return "<S>" 1666 } 1667 1668 if s.Name == "_" { 1669 return "_" 1670 } 1671 1672 flag, mode = flag.update(mode) 1673 return symfmt(s, flag, mode) 1674 } 1675 1676 func tmodeString(t *types.Type, mode fmtMode, depth int) string { 1677 return tconv(t, 0, mode, depth) 1678 } 1679 1680 func fldconv(f *types.Field, flag FmtFlag, mode fmtMode, depth int) string { 1681 if f == nil { 1682 return "<T>" 1683 } 1684 1685 flag, mode = flag.update(mode) 1686 if mode == FTypeIdName { 1687 flag |= FmtUnsigned 1688 } 1689 1690 var name string 1691 if flag&FmtShort == 0 { 1692 s := f.Sym 1693 1694 // Take the name from the original, lest we substituted it with ~r%d or ~b%d. 1695 // ~r%d is a (formerly) unnamed result. 1696 if mode == FErr && asNode(f.Nname) != nil { 1697 if asNode(f.Nname).Orig != nil { 1698 s = asNode(f.Nname).Orig.Sym 1699 if s != nil && s.Name[0] == '~' { 1700 if s.Name[1] == 'r' { // originally an unnamed result 1701 s = nil 1702 } else if s.Name[1] == 'b' { // originally the blank identifier _ 1703 s = lookup("_") 1704 } 1705 } 1706 } else { 1707 s = nil 1708 } 1709 } 1710 1711 if s != nil && f.Embedded == 0 { 1712 if f.Funarg != types.FunargNone { 1713 name = asNode(f.Nname).modeString(mode) 1714 } else if flag&FmtLong != 0 { 1715 name = mode.Sprintf("%0S", s) 1716 if !exportname(name) && flag&FmtUnsigned == 0 { 1717 name = smodeString(s, mode) // qualify non-exported names (used on structs, not on funarg) 1718 } 1719 } else { 1720 name = smodeString(s, mode) 1721 } 1722 } 1723 } 1724 1725 var typ string 1726 if f.Isddd() { 1727 var et *types.Type 1728 if f.Type != nil { 1729 et = f.Type.Elem() 1730 } 1731 typ = "..." + tmodeString(et, mode, depth) 1732 } else { 1733 typ = tmodeString(f.Type, mode, depth) 1734 } 1735 1736 str := typ 1737 if name != "" { 1738 str = name + " " + typ 1739 } 1740 1741 if flag&FmtShort == 0 && f.Funarg == types.FunargNone && f.Note != "" { 1742 str += " " + strconv.Quote(f.Note) 1743 } 1744 1745 return str 1746 } 1747 1748 // "%L" print definition, not name 1749 // "%S" omit 'func' and receiver from function types, short type names 1750 func typeFormat(t *types.Type, s fmt.State, verb rune, mode fmtMode) { 1751 switch verb { 1752 case 'v', 'S', 'L': 1753 // This is an external entry point, so we pass depth 0 to tconv. 1754 // See comments in Type.String. 1755 fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode, 0)) 1756 1757 default: 1758 fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) 1759 } 1760 } 1761 1762 // See #16897 before changing the implementation of tconv. 1763 func tconv(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string { 1764 if t == nil { 1765 return "<T>" 1766 } 1767 if t.Etype == types.TSSA { 1768 return t.Extra.(string) 1769 } 1770 if t.Etype == types.TTUPLE { 1771 return t.FieldType(0).String() + "," + t.FieldType(1).String() 1772 } 1773 1774 if depth > 100 { 1775 return "<...>" 1776 } 1777 1778 flag, mode = flag.update(mode) 1779 if mode == FTypeIdName { 1780 flag |= FmtUnsigned 1781 } 1782 1783 str := typefmt(t, flag, mode, depth+1) 1784 1785 return str 1786 } 1787 1788 func (n *Node) String() string { return fmt.Sprint(n) } 1789 func (n *Node) modeString(mode fmtMode) string { return mode.Sprint(n) } 1790 1791 // "%L" suffix with "(type %T)" where possible 1792 // "%+S" in debug mode, don't recurse, no multiline output 1793 func (n *Node) nconv(s fmt.State, flag FmtFlag, mode fmtMode) { 1794 if n == nil { 1795 fmt.Fprint(s, "<N>") 1796 return 1797 } 1798 1799 flag, mode = flag.update(mode) 1800 1801 switch mode { 1802 case FErr: 1803 n.nodefmt(s, flag, mode) 1804 1805 case FDbg: 1806 dumpdepth++ 1807 n.nodedump(s, flag, mode) 1808 dumpdepth-- 1809 1810 default: 1811 Fatalf("unhandled %%N mode: %d", mode) 1812 } 1813 } 1814 1815 func (l Nodes) format(s fmt.State, verb rune, mode fmtMode) { 1816 switch verb { 1817 case 'v': 1818 l.hconv(s, fmtFlag(s, verb), mode) 1819 1820 default: 1821 fmt.Fprintf(s, "%%!%c(Nodes)", verb) 1822 } 1823 } 1824 1825 func (n Nodes) String() string { 1826 return fmt.Sprint(n) 1827 } 1828 1829 // Flags: all those of %N plus '.': separate with comma's instead of semicolons. 1830 func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode fmtMode) { 1831 if l.Len() == 0 && mode == FDbg { 1832 fmt.Fprint(s, "<nil>") 1833 return 1834 } 1835 1836 flag, mode = flag.update(mode) 1837 sep := "; " 1838 if mode == FDbg { 1839 sep = "\n" 1840 } else if flag&FmtComma != 0 { 1841 sep = ", " 1842 } 1843 1844 for i, n := range l.Slice() { 1845 fmt.Fprint(s, n.modeString(mode)) 1846 if i+1 < l.Len() { 1847 fmt.Fprint(s, sep) 1848 } 1849 } 1850 } 1851 1852 func dumplist(s string, l Nodes) { 1853 fmt.Printf("%s%+v\n", s, l) 1854 } 1855 1856 func Dump(s string, n *Node) { 1857 fmt.Printf("%s [%p]%+v\n", s, n, n) 1858 } 1859 1860 // TODO(gri) make variable local somehow 1861 var dumpdepth int 1862 1863 // indent prints indentation to s. 1864 func indent(s fmt.State) { 1865 fmt.Fprint(s, "\n") 1866 for i := 0; i < dumpdepth; i++ { 1867 fmt.Fprint(s, ". ") 1868 } 1869 } 1870