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