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