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.
18 // %L int Line numbers
20 // %E int etype values (aka 'Kind')
22 // %O int Node Opcodes
23 // Flags: "%#O": print go syntax. (automatic unless fmtmode == FDbg)
25 // %J Node* Node details
26 // Flags: "%hJ" suppresses things not relevant until walk.
28 // %V Val* Constant values
31 // Flags: +,- #: mode (see below)
32 // "%hS" unqualified identifier in any mode
33 // "%hhS" in export mode: unqualified identifier if exported, qualified if not
36 // Flags: +,- #: mode (see below)
37 // 'l' definition instead of name.
38 // 'h' omit "func" and receiver in function types
39 // 'u' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
42 // Flags: +,- #: mode (see below)
43 // 'h' (only in +/debug mode) suppress recursion
44 // 'l' (only in Error mode) print "foo (type Bar)"
46 // %H NodeList* NodeLists
48 // ',' separate items with ',' instead of ';'
50 // In mparith2.go and mparith3.go:
51 // %B Mpint* Big integers
52 // %F Mpflt* Big floats
54 // %S, %T and %N obey use the following flags to set the format mode:
62 var fmtmode int = FErr
64 var fmtpkgpfx int // %uT stickyness
69 // E.g. for %S: %+S %#S %-S print an identifier properly qualified for debug/export/internal mode.
71 // The mode flags +, - and # are sticky, meaning they persist through
72 // recursions of %N, %T and %S, but not the h and l flags. The u flag is
73 // sticky only on %T recursions and only used in %-/Sym mode.
76 // Useful format combinations:
78 // %+N %+H multiline recursive debug dump of node/nodelist
79 // %+hN %+hH non recursive debug dump
81 // %#N %#T export format
82 // %#lT type definition instead of name
83 // %#hT omit"func" and receiver in function signature
85 // %lN "foo (type Bar)" for error messages
87 // %-T type identifiers
88 // %-hT type identifiers without "func" and arg names in type signatures (methodsym)
89 // %-uT type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
92 func setfmode(flags *int) (fm int, fb bool) {
95 if *flags&obj.FmtSign != 0 {
97 } else if *flags&obj.FmtSharp != 0 {
99 } else if *flags&obj.FmtLeft != 0 {
103 if *flags&obj.FmtBody != 0 {
107 *flags &^= (obj.FmtSharp | obj.FmtLeft | obj.FmtSign | obj.FmtBody)
111 // Fmt "%L": Linenumbers
113 var goopnames = []string{
124 OCALL: "function call", // not actual syntax
130 OCONTINUE: "continue",
137 OFALL: "fallthrough",
176 // Fmt "%O": Node opcodes
177 func Oconv(o int, flag int) string {
178 if (flag&obj.FmtSharp != 0) || fmtmode != FDbg {
179 if o >= 0 && o < len(goopnames) && goopnames[o] != "" {
184 if o >= 0 && o < len(opnames) && opnames[o] != "" {
188 return fmt.Sprintf("O-%d", o)
191 var classnames = []string{
201 // Fmt "%J": Node details.
202 func Jconv(n *Node, flag int) string {
205 c := flag & obj.FmtShort
207 if c == 0 && n.Ullman != 0 {
208 fmt.Fprintf(&buf, " u(%d)", n.Ullman)
211 if c == 0 && n.Addable {
212 fmt.Fprintf(&buf, " a(%v)", n.Addable)
215 if c == 0 && n.Name != nil && n.Name.Vargen != 0 {
216 fmt.Fprintf(&buf, " g(%d)", n.Name.Vargen)
220 fmt.Fprintf(&buf, " l(%d)", n.Lineno)
223 if c == 0 && n.Xoffset != BADWIDTH {
224 fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, stkdelta[n])
229 if n.Class&PHEAP != 0 {
232 if int(n.Class&^PHEAP) < len(classnames) {
233 fmt.Fprintf(&buf, " class(%s%s)", classnames[n.Class&^PHEAP], s)
235 fmt.Fprintf(&buf, " class(%d?%s)", n.Class&^PHEAP, s)
240 fmt.Fprintf(&buf, " colas(%v)", n.Colas)
243 if n.Name != nil && n.Name.Funcdepth != 0 {
244 fmt.Fprintf(&buf, " f(%d)", n.Name.Funcdepth)
246 if n.Func != nil && n.Func.Depth != 0 {
247 fmt.Fprintf(&buf, " ff(%d)", n.Func.Depth)
255 buf.WriteString(" esc(h)")
258 buf.WriteString(" esc(s)")
261 buf.WriteString(" esc(no)")
265 buf.WriteString(" esc(N)")
269 fmt.Fprintf(&buf, " esc(%d)", n.Esc)
272 if e, ok := n.Opt().(*NodeEscState); ok && e.Escloopdepth != 0 {
273 fmt.Fprintf(&buf, " ld(%d)", e.Escloopdepth)
276 if c == 0 && n.Typecheck != 0 {
277 fmt.Fprintf(&buf, " tc(%d)", n.Typecheck)
280 if c == 0 && n.Dodata != 0 {
281 fmt.Fprintf(&buf, " dd(%d)", n.Dodata)
285 fmt.Fprintf(&buf, " isddd(%v)", n.Isddd)
289 fmt.Fprintf(&buf, " implicit(%v)", n.Implicit)
293 fmt.Fprintf(&buf, " embedded(%d)", n.Embedded)
297 buf.WriteString(" addrtaken")
301 buf.WriteString(" assigned")
304 if c == 0 && n.Used {
305 fmt.Fprintf(&buf, " used(%v)", n.Used)
311 func Vconv(v Val, flag int) string {
314 if (flag&obj.FmtSharp != 0) || fmtmode == FExp {
315 return Bconv(v.U.(*Mpint), obj.FmtSharp)
317 return Bconv(v.U.(*Mpint), 0)
320 x := Mpgetfix(v.U.(*Mpint))
321 if ' ' <= x && x < 0x80 && x != '\\' && x != '\'' {
322 return fmt.Sprintf("'%c'", int(x))
324 if 0 <= x && x < 1<<16 {
325 return fmt.Sprintf("'\\u%04x'", uint(int(x)))
327 if 0 <= x && x <= utf8.MaxRune {
328 return fmt.Sprintf("'\\U%08x'", uint64(x))
330 return fmt.Sprintf("('\\x00' + %v)", v.U.(*Mpint))
333 if (flag&obj.FmtSharp != 0) || fmtmode == FExp {
334 return Fconv(v.U.(*Mpflt), 0)
336 return Fconv(v.U.(*Mpflt), obj.FmtSharp)
339 if (flag&obj.FmtSharp != 0) || fmtmode == FExp {
340 return fmt.Sprintf("(%v+%vi)", &v.U.(*Mpcplx).Real, &v.U.(*Mpcplx).Imag)
342 if mpcmpfltc(&v.U.(*Mpcplx).Real, 0) == 0 {
343 return fmt.Sprintf("%vi", Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp))
345 if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) == 0 {
346 return Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp)
348 if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) < 0 {
349 return fmt.Sprintf("(%v%vi)", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp))
351 return fmt.Sprintf("(%v+%vi)", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp))
354 return strconv.Quote(v.U.(string))
366 return fmt.Sprintf("<ctype=%d>", v.Ctype())
378 var etnames = []string{
392 TCOMPLEX64: "COMPLEX64",
393 TCOMPLEX128: "COMPLEX128",
406 TUNSAFEPTR: "TUNSAFEPTR",
411 func Econv(et EType) string {
412 if int(et) < len(etnames) && etnames[et] != "" {
415 return fmt.Sprintf("E-%d", et)
419 func symfmt(s *Sym, flag int) string {
420 if s.Pkg != nil && flag&obj.FmtShort == 0 {
422 case FErr: // This is for the user
423 if s.Pkg == builtinpkg || s.Pkg == localpkg {
427 // If the name was used by multiple packages, display the full path,
428 if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 {
429 return fmt.Sprintf("%q.%s", s.Pkg.Path, s.Name)
431 return fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name)
434 return fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name)
437 if flag&obj.FmtUnsigned != 0 {
438 return fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name) // dcommontype, typehash
440 return fmt.Sprintf("%s.%s", s.Pkg.Prefix, s.Name) // (methodsym), typesym, weaksym
443 if s.Name != "" && s.Name[0] == '.' {
444 Fatalf("exporting synthetic symbol %s", s.Name)
446 if s.Pkg != builtinpkg {
447 return fmt.Sprintf("@%q.%s", s.Pkg.Path, s.Name)
452 if flag&obj.FmtByte != 0 {
453 // FmtByte (hh) implies FmtShort (h)
454 // skip leading "type." in method name
456 if i := strings.LastIndex(s.Name, "."); i >= 0 {
460 // exportname needs to see the name without the prefix too.
461 if (fmtmode == FExp && !exportname(p)) || fmtmode == FDbg {
462 return fmt.Sprintf("@%q.%s", s.Pkg.Path, p)
471 var basicnames = []string{
485 TCOMPLEX64: "complex64",
486 TCOMPLEX128: "complex128",
491 TIDEAL: "untyped number",
495 func typefmt(t *Type, flag int) string {
500 if t == bytetype || t == runetype {
501 // in %-T mode collapse rune and byte with their originals.
502 if fmtmode != FTypeId {
503 return Sconv(t.Sym, obj.FmtShort)
512 // Unless the 'l' flag was specified, if the type has a name, just print that name.
513 if flag&obj.FmtLong == 0 && t.Sym != nil && t.Etype != TFIELD && t != Types[t.Etype] {
516 if flag&obj.FmtShort != 0 {
518 return fmt.Sprintf("%v·%d", Sconv(t.Sym, obj.FmtShort), t.Vargen)
520 return Sconv(t.Sym, obj.FmtShort)
523 if flag&obj.FmtUnsigned != 0 {
524 return Sconv(t.Sym, obj.FmtUnsigned)
529 if t.Sym.Pkg == localpkg && t.Vargen != 0 {
530 return fmt.Sprintf("%v·%d", t.Sym, t.Vargen)
534 return Sconv(t.Sym, 0)
537 if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
539 if fmtmode == FErr && (t == idealbool || t == idealstring) {
542 return prefix + basicnames[t.Etype]
547 str := Econv(t.Etype) + "-" + typefmt(t, flag)
554 if fmtmode == FTypeId && (flag&obj.FmtShort != 0) {
555 return fmt.Sprintf("*%v", Tconv(t.Type, obj.FmtShort))
557 return fmt.Sprintf("*%v", t.Type)
561 return fmt.Sprintf("[%d]%v", t.Bound, t.Type)
564 return fmt.Sprintf("[...]%v", t.Type)
566 return fmt.Sprintf("[]%v", t.Type)
571 return fmt.Sprintf("<-chan %v", t.Type)
574 return fmt.Sprintf("chan<- %v", t.Type)
577 if t.Type != nil && t.Type.Etype == TCHAN && t.Type.Sym == nil && t.Type.Chan == Crecv {
578 return fmt.Sprintf("chan (%v)", t.Type)
580 return fmt.Sprintf("chan %v", t.Type)
583 return fmt.Sprintf("map[%v]%v", t.Down, t.Type)
587 buf.WriteString("interface {")
588 for t1 := t.Type; t1 != nil; t1 = t1.Down {
592 // Check first that a symbol is defined for this type.
593 // Wrong interface definitions may have types lacking a symbol.
595 case exportname(t1.Sym.Name):
596 buf.WriteString(Sconv(t1.Sym, obj.FmtShort))
598 buf.WriteString(Sconv(t1.Sym, obj.FmtUnsigned))
600 buf.WriteString(Tconv(t1.Type, obj.FmtShort))
613 if flag&obj.FmtShort != 0 {
616 if t.Thistuple != 0 {
617 buf.WriteString("method")
618 buf.WriteString(Tconv(getthisx(t), 0))
621 buf.WriteString("func")
623 buf.WriteString(Tconv(getinargx(t), 0))
632 buf.WriteString(Tconv(getoutargx(t).Type.Type, 0)) // struct->field->field's type
639 buf.WriteString(Tconv(getoutargx(t), 0))
645 // Format the bucket struct for map[x]y as map.bucket[x]y.
646 // This avoids a recursive print that generates very long names.
647 if t.Map.Bucket == t {
648 return fmt.Sprintf("map.bucket[%v]%v", t.Map.Down, t.Map.Type)
652 return fmt.Sprintf("map.hdr[%v]%v", t.Map.Down, t.Map.Type)
655 if t.Map.Hiter == t {
656 return fmt.Sprintf("map.iter[%v]%v", t.Map.Down, t.Map.Type)
659 Yyerror("unknown internal map type")
665 if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
666 for t1 := t.Type; t1 != nil; t1 = t1.Down {
667 buf.WriteString(Tconv(t1, obj.FmtShort))
669 buf.WriteString(", ")
673 for t1 := t.Type; t1 != nil; t1 = t1.Down {
674 buf.WriteString(Tconv(t1, 0))
676 buf.WriteString(", ")
682 buf.WriteString("struct {")
683 for t1 := t.Type; t1 != nil; t1 = t1.Down {
685 buf.WriteString(Tconv(t1, obj.FmtLong))
699 if flag&obj.FmtShort == 0 {
702 // Take the name from the original, lest we substituted it with ~r%d or ~b%d.
703 // ~r%d is a (formerly) unnamed result.
704 if (fmtmode == FErr || fmtmode == FExp) && t.Nname != nil {
705 if t.Nname.Orig != nil {
707 if s != nil && s.Name[0] == '~' {
708 if s.Name[1] == 'r' { // originally an unnamed result
710 } else if s.Name[1] == 'b' { // originally the blank identifier _
719 if s != nil && t.Embedded == 0 {
721 name = Nconv(t.Nname, 0)
722 } else if flag&obj.FmtLong != 0 {
723 name = Sconv(s, obj.FmtShort|obj.FmtByte) // qualify non-exported names (used on structs, not on funarg)
727 } else if fmtmode == FExp {
728 // TODO(rsc) this breaks on the eliding of unused arguments in the backend
729 // when this is fixed, the special case in dcl.go checkarglist can go.
731 // fmtstrcpy(fp, "_ ");
733 if t.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path) > 0 {
734 name = fmt.Sprintf("@%q.?", s.Pkg.Path)
743 typ = "..." + Tconv(t.Type.Type, 0)
745 typ = Tconv(t.Type, 0)
750 str = name + " " + typ
753 // The fmtbody flag is intended to suppress escape analysis annotations
754 // when printing a function type used in a function body.
755 // (The escape analysis tags do not apply to func vars.)
756 // But it must not suppress struct field tags.
757 // See golang.org/issue/13777 and golang.org/issue/14331.
758 if flag&obj.FmtShort == 0 && (!fmtbody || !t.Funarg) && t.Note != nil {
759 str += " " + strconv.Quote(*t.Note)
765 return fmt.Sprintf("undefined %v", t.Sym)
771 return "@\"unsafe\".Pointer"
773 return "unsafe.Pointer"
777 Fatalf("missing %v case during export", Econv(t.Etype))
780 // Don't know how to handle - fall back to detailed prints.
781 return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Type)
784 // Statements which may be rendered with a simplestmt as init.
785 func stmtwithinit(op Op) bool {
787 case OIF, OFOR, OSWITCH:
794 func stmtfmt(n *Node) string {
797 // some statements allow for an init, but at most one,
798 // but we may have an arbitrary number added, eg by typecheck
799 // and inlining. If it doesn't fit the syntax, emit an enclosing
800 // block starting with the init statements.
802 // if we can just say "for" n->ninit; ... then do so
803 simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(n.Op)
805 // otherwise, print the inits as separate statements
806 complexinit := n.Ninit != nil && !simpleinit && (fmtmode != FErr)
808 // but if it was for if/for/switch, put in an extra surrounding block to limit the scope
809 extrablock := complexinit && stmtwithinit(n.Op)
816 f += fmt.Sprintf(" %v; ", n.Ninit)
822 switch n.Left.Class &^ PHEAP {
823 case PPARAM, PPARAMOUT, PAUTO:
824 f += fmt.Sprintf("var %v %v", n.Left, n.Left.Type)
829 f += fmt.Sprintf("var %v %v", n.Left.Sym, n.Left.Type)
833 f += fmt.Sprintf("%v %v", n.Left, n.Right)
835 f += Nconv(n.Right, 0)
838 // Don't export "v = <N>" initializing statements, hope they're always
839 // preceded by the DCL which will be re-parsed and typecheck to reproduce
840 // the "v = <N>" again.
842 if fmtmode == FExp && n.Right == nil {
846 if n.Colas && !complexinit {
847 f += fmt.Sprintf("%v := %v", n.Left, n.Right)
849 f += fmt.Sprintf("%v = %v", n.Left, n.Right)
854 if Op(n.Etype) == OADD {
855 f += fmt.Sprintf("%v++", n.Left)
857 f += fmt.Sprintf("%v--", n.Left)
862 f += fmt.Sprintf("%v %v= %v", n.Left, Oconv(int(n.Etype), obj.FmtSharp), n.Right)
865 if n.Colas && !complexinit {
866 f += fmt.Sprintf("%v := %v", Hconv(n.List, obj.FmtComma), Hconv(n.Rlist, obj.FmtComma))
871 case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
872 f += fmt.Sprintf("%v = %v", Hconv(n.List, obj.FmtComma), Hconv(n.Rlist, obj.FmtComma))
875 f += fmt.Sprintf("return %v", Hconv(n.List, obj.FmtComma))
878 f += fmt.Sprintf("retjmp %v", n.Sym)
881 f += fmt.Sprintf("go %v", n.Left)
884 f += fmt.Sprintf("defer %v", n.Left)
888 f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.N, n.Left, n.Nbody)
890 f += fmt.Sprintf("if %v { %v }", n.Left, n.Nbody)
893 f += fmt.Sprintf(" else { %v }", n.Rlist)
897 if fmtmode == FErr { // TODO maybe only if FmtShort, same below
904 f += fmt.Sprintf(" %v;", n.Ninit.N)
905 } else if n.Right != nil {
910 f += fmt.Sprintf(" %v", n.Left)
914 f += fmt.Sprintf("; %v", n.Right)
915 } else if simpleinit {
919 f += fmt.Sprintf(" { %v }", n.Nbody)
928 f += fmt.Sprintf("for range %v { %v }", n.Right, n.Nbody)
932 f += fmt.Sprintf("for %v = range %v { %v }", Hconv(n.List, obj.FmtComma), n.Right, n.Nbody)
934 case OSELECT, OSWITCH:
936 f += fmt.Sprintf("%v statement", Oconv(int(n.Op), 0))
940 f += Oconv(int(n.Op), obj.FmtSharp)
942 f += fmt.Sprintf(" %v;", n.Ninit.N)
945 f += Nconv(n.Left, 0)
948 f += fmt.Sprintf(" { %v }", n.List)
952 f += fmt.Sprintf("case %v: %v", Hconv(n.List, obj.FmtComma), n.Nbody)
954 f += fmt.Sprintf("default: %v", n.Nbody)
963 f += fmt.Sprintf("%v %v", Oconv(int(n.Op), obj.FmtSharp), n.Left)
965 f += Oconv(int(n.Op), obj.FmtSharp)
972 f += fmt.Sprintf("%v: ", n.Left)
1067 // Statements handled by stmtfmt
1097 func exprfmt(n *Node, prec int) string {
1098 for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) {
1106 nprec := opprec[n.Op]
1107 if n.Op == OTYPE && n.Sym != nil {
1112 return fmt.Sprintf("(%v)", n)
1117 return fmt.Sprintf("(%v)", n.Left)
1120 return "... argument"
1123 return obj.Rconv(int(n.Reg))
1125 case OLITERAL: // this is a bit of a mess
1126 if fmtmode == FErr {
1127 if n.Orig != nil && n.Orig != n {
1128 return exprfmt(n.Orig, prec)
1131 return Sconv(n.Sym, 0)
1134 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
1135 return exprfmt(n.Orig, prec)
1137 if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != idealbool && n.Type != idealstring {
1138 // Need parens when type begins with what might
1139 // be misinterpreted as a unary operator: * or <-.
1140 if Isptr[n.Type.Etype] || (n.Type.Etype == TCHAN && n.Type.Chan == Crecv) {
1141 return fmt.Sprintf("(%v)(%v)", n.Type, Vconv(n.Val(), 0))
1143 return fmt.Sprintf("%v(%v)", n.Type, Vconv(n.Val(), 0))
1147 return Vconv(n.Val(), 0)
1149 // Special case: name used as local variable in export.
1150 // _ becomes ~b%d internally; print as _ for export
1152 if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
1155 if fmtmode == FExp && n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 {
1156 return fmt.Sprintf("%v·%d", n.Sym, n.Name.Vargen)
1159 // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
1160 // but for export, this should be rendered as (*pkg.T).meth.
1161 // These nodes have the special property that they are names with a left OTYPE and a right ONAME.
1162 if fmtmode == FExp && n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
1163 if Isptr[n.Left.Type.Etype] {
1164 return fmt.Sprintf("(%v).%v", n.Left.Type, Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte))
1166 return fmt.Sprintf("%v.%v", n.Left.Type, Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte))
1171 case OPACK, ONONAME:
1172 return Sconv(n.Sym, 0)
1175 if n.Type == nil && n.Sym != nil {
1176 return Sconv(n.Sym, 0)
1178 return Tconv(n.Type, 0)
1182 return fmt.Sprintf("[]%v", n.Left)
1185 f += fmt.Sprintf("[]%v", n.Right)
1186 return f // happens before typecheck
1189 return fmt.Sprintf("map[%v]%v", n.Left, n.Right)
1194 return fmt.Sprintf("<-chan %v", n.Left)
1197 return fmt.Sprintf("chan<- %v", n.Left)
1200 if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && n.Left.Etype == Crecv {
1201 return fmt.Sprintf("chan (%v)", n.Left)
1203 return fmt.Sprintf("chan %v", n.Left)
1217 if fmtmode == FErr {
1218 return "func literal"
1221 return fmt.Sprintf("%v { %v }", n.Type, n.Nbody)
1223 return fmt.Sprintf("%v { %v }", n.Type, n.Name.Param.Closure.Nbody)
1226 ptrlit := n.Right != nil && n.Right.Implicit && n.Right.Type != nil && Isptr[n.Right.Type.Etype]
1227 if fmtmode == FErr {
1228 if n.Right != nil && n.Right.Type != nil && !n.Implicit {
1230 return fmt.Sprintf("&%v literal", n.Right.Type.Type)
1232 return fmt.Sprintf("%v literal", n.Right.Type)
1236 return "composite literal"
1239 if fmtmode == FExp && ptrlit {
1240 // typecheck has overwritten OIND by OTYPE with pointer type.
1241 return fmt.Sprintf("(&%v{ %v })", n.Right.Type.Type, Hconv(n.List, obj.FmtComma))
1244 return fmt.Sprintf("(%v{ %v })", n.Right, Hconv(n.List, obj.FmtComma))
1247 if fmtmode == FExp && n.Left.Implicit {
1248 return Nconv(n.Left, 0)
1250 return fmt.Sprintf("&%v", n.Left)
1253 if fmtmode == FExp { // requires special handling of field names
1258 f += fmt.Sprintf("(%v{", n.Type)
1260 for l := n.List; l != nil; l = l.Next {
1261 f += fmt.Sprintf(" %v:%v", Sconv(l.N.Left.Sym, obj.FmtShort|obj.FmtByte), l.N.Right)
1279 case OARRAYLIT, OMAPLIT:
1280 if fmtmode == FErr {
1281 return fmt.Sprintf("%v literal", n.Type)
1283 if fmtmode == FExp && n.Implicit {
1284 return fmt.Sprintf("{ %v }", Hconv(n.List, obj.FmtComma))
1286 return fmt.Sprintf("(%v{ %v })", n.Type, Hconv(n.List, obj.FmtComma))
1289 if n.Left != nil && n.Right != nil {
1290 if fmtmode == FExp && n.Left.Type != nil && n.Left.Type.Etype == TFIELD {
1291 // requires special handling of field names
1292 return fmt.Sprintf("%v:%v", Sconv(n.Left.Sym, obj.FmtShort|obj.FmtByte), n.Right)
1294 return fmt.Sprintf("%v:%v", n.Left, n.Right)
1298 if n.Left == nil && n.Right != nil {
1299 return fmt.Sprintf(":%v", n.Right)
1301 if n.Left != nil && n.Right == nil {
1302 return fmt.Sprintf("%v:", n.Left)
1313 f += exprfmt(n.Left, nprec)
1314 if n.Right == nil || n.Right.Sym == nil {
1318 f += fmt.Sprintf(".%v", Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte))
1321 case ODOTTYPE, ODOTTYPE2:
1323 f += exprfmt(n.Left, nprec)
1325 f += fmt.Sprintf(".(%v)", n.Right)
1328 f += fmt.Sprintf(".(%v)", n.Type)
1339 f += exprfmt(n.Left, nprec)
1340 f += fmt.Sprintf("[%v]", n.Right)
1343 case OCOPY, OCOMPLEX:
1344 return fmt.Sprintf("%v(%v, %v)", Oconv(int(n.Op), obj.FmtSharp), n.Left, n.Right)
1354 if n.Type == nil || n.Type.Sym == nil {
1355 return fmt.Sprintf("(%v)(%v)", n.Type, n.Left)
1358 return fmt.Sprintf("%v(%v)", n.Type, n.Left)
1360 return fmt.Sprintf("%v(%v)", n.Type, Hconv(n.List, obj.FmtComma))
1376 return fmt.Sprintf("%v(%v)", Oconv(int(n.Op), obj.FmtSharp), n.Left)
1379 return fmt.Sprintf("%v(%v...)", Oconv(int(n.Op), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
1381 return fmt.Sprintf("%v(%v)", Oconv(int(n.Op), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
1383 case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
1385 f += exprfmt(n.Left, nprec)
1387 f += fmt.Sprintf("(%v...)", Hconv(n.List, obj.FmtComma))
1390 f += fmt.Sprintf("(%v)", Hconv(n.List, obj.FmtComma))
1393 case OMAKEMAP, OMAKECHAN, OMAKESLICE:
1394 if n.List != nil { // pre-typecheck
1395 return fmt.Sprintf("make(%v, %v)", n.Type, Hconv(n.List, obj.FmtComma))
1398 return fmt.Sprintf("make(%v, %v, %v)", n.Type, n.Left, n.Right)
1400 if n.Left != nil && (n.Op == OMAKESLICE || !isideal(n.Left.Type)) {
1401 return fmt.Sprintf("make(%v, %v)", n.Type, n.Left)
1403 return fmt.Sprintf("make(%v)", n.Type)
1414 if n.Left.Op == n.Op {
1415 f += fmt.Sprintf("%v ", Oconv(int(n.Op), obj.FmtSharp))
1417 f += Oconv(int(n.Op), obj.FmtSharp)
1419 f += exprfmt(n.Left, nprec+1)
1444 f += exprfmt(n.Left, nprec)
1446 f += fmt.Sprintf(" %v ", Oconv(int(n.Op), obj.FmtSharp))
1447 f += exprfmt(n.Right, nprec+1)
1452 for l := n.List; l != nil; l = l.Next {
1456 f += exprfmt(l.N, nprec)
1461 case OCMPSTR, OCMPIFACE:
1463 f += exprfmt(n.Left, nprec)
1464 // TODO(marvin): Fix Node.EType type union.
1465 f += fmt.Sprintf(" %v ", Oconv(int(n.Etype), obj.FmtSharp))
1466 f += exprfmt(n.Right, nprec+1)
1470 return fmt.Sprintf("<node %v>", Oconv(int(n.Op), 0))
1473 func nodefmt(n *Node, flag int) string {
1476 // we almost always want the original, except in export mode for literals
1477 // this saves the importer some work, and avoids us having to redo some
1478 // special casing for package unsafe
1479 if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
1483 if flag&obj.FmtLong != 0 && t != nil {
1484 if t.Etype == TNIL {
1487 return fmt.Sprintf("%v (type %v)", n, t)
1491 // TODO inlining produces expressions with ninits. we can't print these yet.
1493 if opprec[n.Op] < 0 {
1497 return exprfmt(n, 0)
1502 func indent(buf *bytes.Buffer) {
1503 buf.WriteString("\n")
1504 for i := 0; i < dumpdepth; i++ {
1505 buf.WriteString(". ")
1509 func nodedump(n *Node, flag int) string {
1514 recur := flag&obj.FmtShort == 0
1516 var buf bytes.Buffer
1520 buf.WriteString("...")
1525 fmt.Fprintf(&buf, "%v-init%v", Oconv(int(n.Op), 0), n.Ninit)
1532 fmt.Fprintf(&buf, "%v%v", Oconv(int(n.Op), 0), Jconv(n, 0))
1534 case OREGISTER, OINDREG:
1535 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), obj.Rconv(int(n.Reg)), Jconv(n, 0))
1538 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), Vconv(n.Val(), 0), Jconv(n, 0))
1540 case ONAME, ONONAME:
1542 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), n.Sym, Jconv(n, 0))
1544 fmt.Fprintf(&buf, "%v%v", Oconv(int(n.Op), 0), Jconv(n, 0))
1546 if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil {
1548 fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Name.Param.Ntype)
1552 fmt.Fprintf(&buf, "%v-%v%v", Oconv(int(n.Op), 0), Oconv(int(n.Etype), 0), Jconv(n, 0))
1555 fmt.Fprintf(&buf, "%v %v%v type=%v", Oconv(int(n.Op), 0), n.Sym, Jconv(n, 0), n.Type)
1556 if recur && n.Type == nil && n.Name.Param.Ntype != nil {
1558 fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Name.Param.Ntype)
1562 if n.Sym != nil && n.Op != ONAME {
1563 fmt.Fprintf(&buf, " %v", n.Sym)
1567 fmt.Fprintf(&buf, " %v", n.Type)
1572 buf.WriteString(Nconv(n.Left, 0))
1575 buf.WriteString(Nconv(n.Right, 0))
1579 fmt.Fprintf(&buf, "%v-list%v", Oconv(int(n.Op), 0), n.List)
1584 fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist)
1589 fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody)
1596 func (s *Sym) String() string {
1601 // Flags: "%hS" suppresses qualifying with package
1602 func Sconv(s *Sym, flag int) string {
1603 if flag&obj.FmtLong != 0 {
1616 sm, sb := setfmode(&flag)
1617 str := symfmt(s, flag)
1624 func (t *Type) String() string {
1629 // Flags: 'l' print definition, not name
1630 // 'h' omit 'func' and receiver from function types, short type names
1631 // 'u' package name, not prefix (FTypeId mode, sticky)
1632 func Tconv(t *Type, flag int) string {
1643 sm, sb := setfmode(&flag)
1645 if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
1649 flag |= obj.FmtUnsigned
1652 str := typefmt(t, flag)
1654 if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
1665 func (n *Node) String() string {
1670 // Flags: 'l' suffix with "(type %T)" where possible
1671 // '+h' in debug mode, don't recurse, no multiline output
1672 func Nconv(n *Node, flag int) string {
1677 sm, sb := setfmode(&flag)
1682 str = nodefmt(n, flag)
1686 str = nodedump(n, flag)
1690 Fatalf("unhandled %%N mode")
1699 func (l *NodeList) String() string {
1703 // Fmt '%H': NodeList.
1704 // Flags: all those of %N plus ',': separate with comma's instead of semicolons.
1705 func Hconv(l *NodeList, flag int) string {
1706 if l == nil && fmtmode == FDbg {
1711 sm, sb := setfmode(&flag)
1713 if fmtmode == FDbg {
1715 } else if flag&obj.FmtComma != 0 {
1719 var buf bytes.Buffer
1720 for ; l != nil; l = l.Next {
1721 buf.WriteString(Nconv(l.N, 0))
1723 buf.WriteString(sep)
1733 func Hconvslice(l []*Node, flag int) string {
1734 if len(l) == 0 && fmtmode == FDbg {
1739 sm, sb := setfmode(&flag)
1741 if fmtmode == FDbg {
1743 } else if flag&obj.FmtComma != 0 {
1747 var buf bytes.Buffer
1748 for i, n := range l {
1749 buf.WriteString(Nconv(n, 0))
1751 buf.WriteString(sep)
1761 func dumplist(s string, l *NodeList) {
1762 fmt.Printf("%s%v\n", s, Hconv(l, obj.FmtSign))
1765 func dumpslice(s string, l []*Node) {
1766 fmt.Printf("%s%v\n", s, Hconvslice(l, obj.FmtSign))
1769 func Dump(s string, n *Node) {
1770 fmt.Printf("%s [%p]%v\n", s, n, Nconv(n, obj.FmtSign))