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