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