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