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