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