github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/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.Pos.IsKnown() { 287 fmt.Fprintf(s, " l(%d)", n.Pos.Line()) 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 1081 // Statements handled by stmtfmt 1082 OAS: -1, 1083 OAS2: -1, 1084 OAS2DOTTYPE: -1, 1085 OAS2FUNC: -1, 1086 OAS2MAPR: -1, 1087 OAS2RECV: -1, 1088 OASOP: -1, 1089 OBREAK: -1, 1090 OCASE: -1, 1091 OCONTINUE: -1, 1092 ODCL: -1, 1093 ODCLFIELD: -1, 1094 ODEFER: -1, 1095 OEMPTY: -1, 1096 OFALL: -1, 1097 OFOR: -1, 1098 OGOTO: -1, 1099 OIF: -1, 1100 OLABEL: -1, 1101 OPROC: -1, 1102 ORANGE: -1, 1103 ORETURN: -1, 1104 OSELECT: -1, 1105 OSWITCH: -1, 1106 OXCASE: -1, 1107 OXFALL: -1, 1108 1109 OEND: 0, 1110 } 1111 1112 func (n *Node) exprfmt(s fmt.State, prec int) { 1113 for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) { 1114 n = n.Left 1115 } 1116 1117 if n == nil { 1118 fmt.Fprint(s, "<N>") 1119 return 1120 } 1121 1122 nprec := opprec[n.Op] 1123 if n.Op == OTYPE && n.Sym != nil { 1124 nprec = 8 1125 } 1126 1127 if prec > nprec { 1128 fmt.Fprintf(s, "(%v)", n) 1129 return 1130 } 1131 1132 switch n.Op { 1133 case OPAREN: 1134 fmt.Fprintf(s, "(%v)", n.Left) 1135 1136 case ODDDARG: 1137 fmt.Fprint(s, "... argument") 1138 1139 case OLITERAL: // this is a bit of a mess 1140 if fmtmode == FErr { 1141 if n.Orig != nil && n.Orig != n { 1142 n.Orig.exprfmt(s, prec) 1143 return 1144 } 1145 if n.Sym != nil { 1146 fmt.Fprint(s, n.Sym.String()) 1147 return 1148 } 1149 } 1150 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n { 1151 n.Orig.exprfmt(s, prec) 1152 return 1153 } 1154 if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != idealbool && n.Type != idealstring { 1155 // Need parens when type begins with what might 1156 // be misinterpreted as a unary operator: * or <-. 1157 if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == Crecv) { 1158 fmt.Fprintf(s, "(%v)(%v)", n.Type, n.Val()) 1159 return 1160 } else { 1161 fmt.Fprintf(s, "%v(%v)", n.Type, n.Val()) 1162 return 1163 } 1164 } 1165 1166 fmt.Fprintf(s, "%v", n.Val()) 1167 1168 // Special case: name used as local variable in export. 1169 // _ becomes ~b%d internally; print as _ for export 1170 case ONAME: 1171 if fmtmode == FErr && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' { 1172 fmt.Fprint(s, "_") 1173 return 1174 } 1175 fallthrough 1176 case OPACK, ONONAME: 1177 fmt.Fprint(s, n.Sym.String()) 1178 1179 case OTYPE: 1180 if n.Type == nil && n.Sym != nil { 1181 fmt.Fprint(s, n.Sym.String()) 1182 return 1183 } 1184 fmt.Fprintf(s, "%v", n.Type) 1185 1186 case OTARRAY: 1187 if n.Left != nil { 1188 fmt.Fprintf(s, "[]%v", n.Left) 1189 return 1190 } 1191 fmt.Fprintf(s, "[]%v", n.Right) // happens before typecheck 1192 1193 case OTMAP: 1194 fmt.Fprintf(s, "map[%v]%v", n.Left, n.Right) 1195 1196 case OTCHAN: 1197 switch ChanDir(n.Etype) { 1198 case Crecv: 1199 fmt.Fprintf(s, "<-chan %v", n.Left) 1200 1201 case Csend: 1202 fmt.Fprintf(s, "chan<- %v", n.Left) 1203 1204 default: 1205 if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && ChanDir(n.Left.Etype) == Crecv { 1206 fmt.Fprintf(s, "chan (%v)", n.Left) 1207 } else { 1208 fmt.Fprintf(s, "chan %v", n.Left) 1209 } 1210 } 1211 1212 case OTSTRUCT: 1213 fmt.Fprint(s, "<struct>") 1214 1215 case OTINTER: 1216 fmt.Fprint(s, "<inter>") 1217 1218 case OTFUNC: 1219 fmt.Fprint(s, "<func>") 1220 1221 case OCLOSURE: 1222 if fmtmode == FErr { 1223 fmt.Fprint(s, "func literal") 1224 return 1225 } 1226 if n.Nbody.Len() != 0 { 1227 fmt.Fprintf(s, "%v { %v }", n.Type, n.Nbody) 1228 return 1229 } 1230 fmt.Fprintf(s, "%v { %v }", n.Type, n.Func.Closure.Nbody) 1231 1232 case OCOMPLIT: 1233 ptrlit := n.Right != nil && n.Right.Implicit && n.Right.Type != nil && n.Right.Type.IsPtr() 1234 if fmtmode == FErr { 1235 if n.Right != nil && n.Right.Type != nil && !n.Implicit { 1236 if ptrlit { 1237 fmt.Fprintf(s, "&%v literal", n.Right.Type.Elem()) 1238 return 1239 } else { 1240 fmt.Fprintf(s, "%v literal", n.Right.Type) 1241 return 1242 } 1243 } 1244 1245 fmt.Fprint(s, "composite literal") 1246 return 1247 } 1248 fmt.Fprintf(s, "(%v{ %.v })", n.Right, n.List) 1249 1250 case OPTRLIT: 1251 fmt.Fprintf(s, "&%v", n.Left) 1252 1253 case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT: 1254 if fmtmode == FErr { 1255 fmt.Fprintf(s, "%v literal", n.Type) 1256 return 1257 } 1258 fmt.Fprintf(s, "(%v{ %.v })", n.Type, n.List) 1259 1260 case OKEY: 1261 if n.Left != nil && n.Right != nil { 1262 fmt.Fprintf(s, "%v:%v", n.Left, n.Right) 1263 return 1264 } 1265 1266 if n.Left == nil && n.Right != nil { 1267 fmt.Fprintf(s, ":%v", n.Right) 1268 return 1269 } 1270 if n.Left != nil && n.Right == nil { 1271 fmt.Fprintf(s, "%v:", n.Left) 1272 return 1273 } 1274 fmt.Fprint(s, ":") 1275 1276 case OSTRUCTKEY: 1277 fmt.Fprintf(s, "%v:%v", n.Sym, n.Left) 1278 1279 case OCALLPART: 1280 n.Left.exprfmt(s, nprec) 1281 if n.Right == nil || n.Right.Sym == nil { 1282 fmt.Fprint(s, ".<nil>") 1283 return 1284 } 1285 fmt.Fprintf(s, ".%0S", n.Right.Sym) 1286 1287 case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 1288 n.Left.exprfmt(s, nprec) 1289 if n.Sym == nil { 1290 fmt.Fprint(s, ".<nil>") 1291 return 1292 } 1293 fmt.Fprintf(s, ".%0S", n.Sym) 1294 1295 case ODOTTYPE, ODOTTYPE2: 1296 n.Left.exprfmt(s, nprec) 1297 if n.Right != nil { 1298 fmt.Fprintf(s, ".(%v)", n.Right) 1299 return 1300 } 1301 fmt.Fprintf(s, ".(%v)", n.Type) 1302 1303 case OINDEX, OINDEXMAP: 1304 n.Left.exprfmt(s, nprec) 1305 fmt.Fprintf(s, "[%v]", n.Right) 1306 1307 case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: 1308 n.Left.exprfmt(s, nprec) 1309 fmt.Fprint(s, "[") 1310 low, high, max := n.SliceBounds() 1311 if low != nil { 1312 fmt.Fprint(s, low.String()) 1313 } 1314 fmt.Fprint(s, ":") 1315 if high != nil { 1316 fmt.Fprint(s, high.String()) 1317 } 1318 if n.Op.IsSlice3() { 1319 fmt.Fprint(s, ":") 1320 if max != nil { 1321 fmt.Fprint(s, max.String()) 1322 } 1323 } 1324 fmt.Fprint(s, "]") 1325 1326 case OCOPY, OCOMPLEX: 1327 fmt.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right) 1328 1329 case OCONV, 1330 OCONVIFACE, 1331 OCONVNOP, 1332 OARRAYBYTESTR, 1333 OARRAYRUNESTR, 1334 OSTRARRAYBYTE, 1335 OSTRARRAYRUNE, 1336 ORUNESTR: 1337 if n.Type == nil || n.Type.Sym == nil { 1338 fmt.Fprintf(s, "(%v)", n.Type) 1339 } else { 1340 fmt.Fprintf(s, "%v", n.Type) 1341 } 1342 if n.Left != nil { 1343 fmt.Fprintf(s, "(%v)", n.Left) 1344 } else { 1345 fmt.Fprintf(s, "(%.v)", n.List) 1346 } 1347 1348 case OREAL, 1349 OIMAG, 1350 OAPPEND, 1351 OCAP, 1352 OCLOSE, 1353 ODELETE, 1354 OLEN, 1355 OMAKE, 1356 ONEW, 1357 OPANIC, 1358 ORECOVER, 1359 OALIGNOF, 1360 OOFFSETOF, 1361 OSIZEOF, 1362 OPRINT, 1363 OPRINTN: 1364 if n.Left != nil { 1365 fmt.Fprintf(s, "%#v(%v)", n.Op, n.Left) 1366 return 1367 } 1368 if n.Isddd { 1369 fmt.Fprintf(s, "%#v(%.v...)", n.Op, n.List) 1370 return 1371 } 1372 fmt.Fprintf(s, "%#v(%.v)", n.Op, n.List) 1373 1374 case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG: 1375 n.Left.exprfmt(s, nprec) 1376 if n.Isddd { 1377 fmt.Fprintf(s, "(%.v...)", n.List) 1378 return 1379 } 1380 fmt.Fprintf(s, "(%.v)", n.List) 1381 1382 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 1383 if n.List.Len() != 0 { // pre-typecheck 1384 fmt.Fprintf(s, "make(%v, %.v)", n.Type, n.List) 1385 return 1386 } 1387 if n.Right != nil { 1388 fmt.Fprintf(s, "make(%v, %v, %v)", n.Type, n.Left, n.Right) 1389 return 1390 } 1391 if n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()) { 1392 fmt.Fprintf(s, "make(%v, %v)", n.Type, n.Left) 1393 return 1394 } 1395 fmt.Fprintf(s, "make(%v)", n.Type) 1396 1397 // Unary 1398 case OPLUS, 1399 OMINUS, 1400 OADDR, 1401 OCOM, 1402 OIND, 1403 ONOT, 1404 ORECV: 1405 fmt.Fprint(s, n.Op.GoString()) // %#v 1406 if n.Left.Op == n.Op { 1407 fmt.Fprint(s, " ") 1408 } 1409 n.Left.exprfmt(s, nprec+1) 1410 1411 // Binary 1412 case OADD, 1413 OAND, 1414 OANDAND, 1415 OANDNOT, 1416 ODIV, 1417 OEQ, 1418 OGE, 1419 OGT, 1420 OLE, 1421 OLT, 1422 OLSH, 1423 OMOD, 1424 OMUL, 1425 ONE, 1426 OOR, 1427 OOROR, 1428 ORSH, 1429 OSEND, 1430 OSUB, 1431 OXOR: 1432 n.Left.exprfmt(s, nprec) 1433 fmt.Fprintf(s, " %#v ", n.Op) 1434 n.Right.exprfmt(s, nprec+1) 1435 1436 case OADDSTR: 1437 i := 0 1438 for _, n1 := range n.List.Slice() { 1439 if i != 0 { 1440 fmt.Fprint(s, " + ") 1441 } 1442 n1.exprfmt(s, nprec) 1443 i++ 1444 } 1445 1446 case OCMPSTR, OCMPIFACE: 1447 n.Left.exprfmt(s, nprec) 1448 // TODO(marvin): Fix Node.EType type union. 1449 fmt.Fprintf(s, " %#v ", Op(n.Etype)) 1450 n.Right.exprfmt(s, nprec+1) 1451 1452 default: 1453 fmt.Fprintf(s, "<node %v>", n.Op) 1454 } 1455 } 1456 1457 func (n *Node) nodefmt(s fmt.State, flag FmtFlag) { 1458 t := n.Type 1459 1460 // we almost always want the original, except in export mode for literals 1461 // this saves the importer some work, and avoids us having to redo some 1462 // special casing for package unsafe 1463 if n.Op != OLITERAL && n.Orig != nil { 1464 n = n.Orig 1465 } 1466 1467 if flag&FmtLong != 0 && t != nil { 1468 if t.Etype == TNIL { 1469 fmt.Fprint(s, "nil") 1470 } else { 1471 fmt.Fprintf(s, "%v (type %v)", n, t) 1472 } 1473 return 1474 } 1475 1476 // TODO inlining produces expressions with ninits. we can't print these yet. 1477 1478 if opprec[n.Op] < 0 { 1479 n.stmtfmt(s) 1480 return 1481 } 1482 1483 n.exprfmt(s, 0) 1484 } 1485 1486 func (n *Node) nodedump(s fmt.State, flag FmtFlag) { 1487 if n == nil { 1488 return 1489 } 1490 1491 recur := flag&FmtShort == 0 1492 1493 if recur { 1494 indent(s) 1495 if dumpdepth > 10 { 1496 fmt.Fprint(s, "...") 1497 return 1498 } 1499 1500 if n.Ninit.Len() != 0 { 1501 fmt.Fprintf(s, "%v-init%v", n.Op, n.Ninit) 1502 indent(s) 1503 } 1504 } 1505 1506 switch n.Op { 1507 default: 1508 fmt.Fprintf(s, "%v%j", n.Op, n) 1509 1510 case OINDREGSP: 1511 fmt.Fprintf(s, "%v-SP%j", n.Op, n) 1512 1513 case OLITERAL: 1514 fmt.Fprintf(s, "%v-%v%j", n.Op, n.Val(), n) 1515 1516 case ONAME, ONONAME: 1517 if n.Sym != nil { 1518 fmt.Fprintf(s, "%v-%v%j", n.Op, n.Sym, n) 1519 } else { 1520 fmt.Fprintf(s, "%v%j", n.Op, n) 1521 } 1522 if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil { 1523 indent(s) 1524 fmt.Fprintf(s, "%v-ntype%v", n.Op, n.Name.Param.Ntype) 1525 } 1526 1527 case OASOP: 1528 fmt.Fprintf(s, "%v-%v%j", n.Op, Op(n.Etype), n) 1529 1530 case OTYPE: 1531 fmt.Fprintf(s, "%v %v%j type=%v", n.Op, n.Sym, n, n.Type) 1532 if recur && n.Type == nil && n.Name.Param.Ntype != nil { 1533 indent(s) 1534 fmt.Fprintf(s, "%v-ntype%v", n.Op, n.Name.Param.Ntype) 1535 } 1536 } 1537 1538 if n.Sym != nil && n.Op != ONAME { 1539 fmt.Fprintf(s, " %v", n.Sym) 1540 } 1541 1542 if n.Type != nil { 1543 fmt.Fprintf(s, " %v", n.Type) 1544 } 1545 1546 if recur { 1547 if n.Left != nil { 1548 fmt.Fprintf(s, "%v", n.Left) 1549 } 1550 if n.Right != nil { 1551 fmt.Fprintf(s, "%v", n.Right) 1552 } 1553 if n.List.Len() != 0 { 1554 indent(s) 1555 fmt.Fprintf(s, "%v-list%v", n.Op, n.List) 1556 } 1557 1558 if n.Rlist.Len() != 0 { 1559 indent(s) 1560 fmt.Fprintf(s, "%v-rlist%v", n.Op, n.Rlist) 1561 } 1562 1563 if n.Nbody.Len() != 0 { 1564 indent(s) 1565 fmt.Fprintf(s, "%v-body%v", n.Op, n.Nbody) 1566 } 1567 } 1568 } 1569 1570 // "%S" suppresses qualifying with package 1571 func (s *Sym) Format(f fmt.State, verb rune) { 1572 switch verb { 1573 case 'v', 'S': 1574 fmt.Fprint(f, s.sconv(fmtFlag(f, verb))) 1575 1576 default: 1577 fmt.Fprintf(f, "%%!%c(*Sym=%p)", verb, s) 1578 } 1579 } 1580 1581 func (s *Sym) String() string { 1582 return s.sconv(0) 1583 } 1584 1585 // See #16897 before changing the implementation of sconv. 1586 func (s *Sym) sconv(flag FmtFlag) string { 1587 if flag&FmtLong != 0 { 1588 panic("linksymfmt") 1589 } 1590 1591 if s == nil { 1592 return "<S>" 1593 } 1594 1595 if s.Name == "_" { 1596 return "_" 1597 } 1598 1599 sf := flag 1600 sm := setfmode(&flag) 1601 str := s.symfmt(flag) 1602 flag = sf 1603 fmtmode = sm 1604 return str 1605 } 1606 1607 func (t *Type) String() string { 1608 return t.tconv(0) 1609 } 1610 1611 func fldconv(f *Field, flag FmtFlag) string { 1612 if f == nil { 1613 return "<T>" 1614 } 1615 1616 sf := flag 1617 sm := setfmode(&flag) 1618 1619 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) { 1620 fmtpkgpfx++ 1621 } 1622 if fmtpkgpfx != 0 { 1623 flag |= FmtUnsigned 1624 } 1625 1626 var name string 1627 if flag&FmtShort == 0 { 1628 s := f.Sym 1629 1630 // Take the name from the original, lest we substituted it with ~r%d or ~b%d. 1631 // ~r%d is a (formerly) unnamed result. 1632 if fmtmode == FErr && f.Nname != nil { 1633 if f.Nname.Orig != nil { 1634 s = f.Nname.Orig.Sym 1635 if s != nil && s.Name[0] == '~' { 1636 if s.Name[1] == 'r' { // originally an unnamed result 1637 s = nil 1638 } else if s.Name[1] == 'b' { // originally the blank identifier _ 1639 s = lookup("_") 1640 } 1641 } 1642 } else { 1643 s = nil 1644 } 1645 } 1646 1647 if s != nil && f.Embedded == 0 { 1648 if f.Funarg != FunargNone { 1649 name = f.Nname.String() 1650 } else if flag&FmtLong != 0 { 1651 name = fmt.Sprintf("%0S", s) 1652 if !exportname(name) && flag&FmtUnsigned == 0 { 1653 name = s.String() // qualify non-exported names (used on structs, not on funarg) 1654 } 1655 } else { 1656 name = s.String() 1657 } 1658 } 1659 } 1660 1661 var typ string 1662 if f.Isddd { 1663 typ = fmt.Sprintf("...%v", f.Type.Elem()) 1664 } else { 1665 typ = fmt.Sprintf("%v", f.Type) 1666 } 1667 1668 str := typ 1669 if name != "" { 1670 str = name + " " + typ 1671 } 1672 1673 if flag&FmtShort == 0 && f.Funarg == FunargNone && f.Note != "" { 1674 str += " " + strconv.Quote(f.Note) 1675 } 1676 1677 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) { 1678 fmtpkgpfx-- 1679 } 1680 1681 flag = sf 1682 fmtmode = sm 1683 return str 1684 } 1685 1686 // "%L" print definition, not name 1687 // "%S" omit 'func' and receiver from function types, short type names 1688 // "% v" package name, not prefix (FTypeId mode, sticky) 1689 func (t *Type) Format(s fmt.State, verb rune) { 1690 switch verb { 1691 case 'v', 'S', 'L': 1692 fmt.Fprint(s, t.tconv(fmtFlag(s, verb))) 1693 1694 default: 1695 fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t) 1696 } 1697 } 1698 1699 // See #16897 before changing the implementation of tconv. 1700 func (t *Type) tconv(flag FmtFlag) string { 1701 if t == nil { 1702 return "<T>" 1703 } 1704 1705 if t.Trecur > 4 { 1706 return "<...>" 1707 } 1708 1709 t.Trecur++ 1710 sf := flag 1711 sm := setfmode(&flag) 1712 1713 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) { 1714 fmtpkgpfx++ 1715 } 1716 if fmtpkgpfx != 0 { 1717 flag |= FmtUnsigned 1718 } 1719 1720 str := t.typefmt(flag) 1721 1722 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) { 1723 fmtpkgpfx-- 1724 } 1725 1726 flag = sf 1727 fmtmode = sm 1728 t.Trecur-- 1729 return str 1730 } 1731 1732 func (n *Node) String() string { 1733 return fmt.Sprint(n) 1734 } 1735 1736 // "%L" suffix with "(type %T)" where possible 1737 // "%+S" in debug mode, don't recurse, no multiline output 1738 func (n *Node) Nconv(s fmt.State, flag FmtFlag) { 1739 if n == nil { 1740 fmt.Fprint(s, "<N>") 1741 return 1742 } 1743 1744 sf := flag 1745 sm := setfmode(&flag) 1746 1747 switch fmtmode { 1748 case FErr: 1749 n.nodefmt(s, flag) 1750 1751 case FDbg: 1752 dumpdepth++ 1753 n.nodedump(s, flag) 1754 dumpdepth-- 1755 1756 default: 1757 Fatalf("unhandled %%N mode: %d", fmtmode) 1758 } 1759 1760 flag = sf 1761 fmtmode = sm 1762 } 1763 1764 func (l Nodes) Format(s fmt.State, verb rune) { 1765 switch verb { 1766 case 'v': 1767 l.hconv(s, fmtFlag(s, verb)) 1768 1769 default: 1770 fmt.Fprintf(s, "%%!%c(Nodes)", verb) 1771 } 1772 } 1773 1774 func (n Nodes) String() string { 1775 return fmt.Sprint(n) 1776 } 1777 1778 // Flags: all those of %N plus '.': separate with comma's instead of semicolons. 1779 func (l Nodes) hconv(s fmt.State, flag FmtFlag) { 1780 if l.Len() == 0 && fmtmode == FDbg { 1781 fmt.Fprint(s, "<nil>") 1782 return 1783 } 1784 1785 sf := flag 1786 sm := setfmode(&flag) 1787 sep := "; " 1788 if fmtmode == FDbg { 1789 sep = "\n" 1790 } else if flag&FmtComma != 0 { 1791 sep = ", " 1792 } 1793 1794 for i, n := range l.Slice() { 1795 fmt.Fprint(s, n) 1796 if i+1 < l.Len() { 1797 fmt.Fprint(s, sep) 1798 } 1799 } 1800 1801 flag = sf 1802 fmtmode = sm 1803 } 1804 1805 func dumplist(s string, l Nodes) { 1806 fmt.Printf("%s%+v\n", s, l) 1807 } 1808 1809 func Dump(s string, n *Node) { 1810 fmt.Printf("%s [%p]%+v\n", s, n, n) 1811 } 1812 1813 // TODO(gri) make variable local somehow 1814 var dumpdepth int 1815 1816 // indent prints indentation to s. 1817 func indent(s fmt.State) { 1818 fmt.Fprint(s, "\n") 1819 for i := 0; i < dumpdepth; i++ { 1820 fmt.Fprint(s, ". ") 1821 } 1822 }