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