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.
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.
19 // TODO(gri) The ' ' flag is not used anymore in %-formats.
20 // Eliminate eventually.
22 const ( // fmt.Format flag/prec or verb
23 FmtLeft FmtFlag = 1 << iota // '-'
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)
33 // fmtFlag computes the (internal) FmtFlag
34 // value given the fmt.State and format verb.
35 func fmtFlag(s fmt.State, verb rune) FmtFlag {
49 if _, ok := s.Precision(); ok {
64 // Format conversions:
65 // TODO(gri) verify these; eliminate those not used anymore
68 // Flags: #: print Go syntax (automatic unless fmtmode == FDbg)
70 // %j *Node Node details
71 // Flags: 0: suppresses things not relevant until walk
73 // %v *Val Constant values
76 // %S unqualified identifier in any mode
77 // Flags: +,- #: mode (see below)
78 // 0: in export mode: unqualified identifier if exported, qualified if not
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.
87 // %S (only in +/debug mode) suppress recursion
88 // %L (only in Error mode) print "foo (type Bar)"
89 // Flags: +,- #: mode (see below)
91 // %v Nodes Node lists
92 // Flags: those of *Node
93 // .: separate items with ',' instead of ';'
95 // *Sym, *Type, and *Node types use the flags below to set the format mode
102 var fmtmode int = FErr
104 var fmtpkgpfx int // "% v" stickyness for *Type objects
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.
110 // Example: given a *Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode
112 // Useful format combinations:
113 // TODO(gri): verify these
116 // %+v multiline recursive debug dump of *Node/Nodes
117 // %+S non-recursive debug dump
121 // %L "foo (type Bar)" for error messages
125 // %#L type definition instead of name
126 // %#S omit"func" and receiver in function signature
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)
132 func setfmode(flags *FmtFlag) (fm int) {
134 if *flags&FmtSign != 0 {
136 } else if *flags&FmtSharp != 0 {
137 // ignore (textual export format no longer supported)
138 } else if *flags&FmtLeft != 0 {
142 *flags &^= (FmtSharp | FmtLeft | FmtSign)
146 var goopnames = []string{
150 OALIGNOF: "unsafe.Alignof",
158 OCALL: "function call", // not actual syntax
164 OCONTINUE: "continue",
171 OFALL: "fallthrough",
191 OOFFSETOF: "unsafe.Offsetof",
206 OSIZEOF: "unsafe.Sizeof",
210 OXFALL: "fallthrough",
213 func (o Op) String() string {
217 func (o Op) GoString() string {
218 return fmt.Sprintf("%#v", o)
221 func (o Op) Format(s fmt.State, verb rune) {
224 o.oconv(s, fmtFlag(s, verb))
227 fmt.Fprintf(s, "%%!%c(Op=%d)", verb, int(o))
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])
239 if o >= 0 && int(o) < len(opnames) && opnames[o] != "" {
240 fmt.Fprint(s, opnames[o])
244 fmt.Fprintf(s, "O-%d", int(o))
247 var classnames = []string{
257 func (n *Node) Format(s fmt.State, verb rune) {
260 n.Nconv(s, fmtFlag(s, verb))
263 n.jconv(s, fmtFlag(s, verb))
266 fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n)
271 func (n *Node) jconv(s fmt.State, flag FmtFlag) {
274 if c == 0 && n.Ullman != 0 {
275 fmt.Fprintf(s, " u(%d)", n.Ullman)
278 if c == 0 && n.Addable {
279 fmt.Fprintf(s, " a(%v)", n.Addable)
282 if c == 0 && n.Name != nil && n.Name.Vargen != 0 {
283 fmt.Fprintf(s, " g(%d)", n.Name.Vargen)
287 fmt.Fprintf(s, " l(%d)", n.Pos.Line())
290 if c == 0 && n.Xoffset != BADWIDTH {
291 fmt.Fprintf(s, " x(%d)", n.Xoffset)
295 if int(n.Class) < len(classnames) {
296 fmt.Fprintf(s, " class(%s)", classnames[n.Class])
298 fmt.Fprintf(s, " class(%d?)", n.Class)
303 fmt.Fprintf(s, " colas(%v)", n.Colas)
306 if n.Name != nil && n.Name.Funcdepth != 0 {
307 fmt.Fprintf(s, " f(%d)", n.Name.Funcdepth)
309 if n.Func != nil && n.Func.Depth != 0 {
310 fmt.Fprintf(s, " ff(%d)", n.Func.Depth)
318 fmt.Fprint(s, " esc(h)")
321 fmt.Fprint(s, " esc(no)")
325 fmt.Fprint(s, " esc(N)")
329 fmt.Fprintf(s, " esc(%d)", n.Esc)
332 if e, ok := n.Opt().(*NodeEscState); ok && e.Loopdepth != 0 {
333 fmt.Fprintf(s, " ld(%d)", e.Loopdepth)
336 if c == 0 && n.Typecheck != 0 {
337 fmt.Fprintf(s, " tc(%d)", n.Typecheck)
340 if c == 0 && n.IsStatic {
341 fmt.Fprint(s, " static")
345 fmt.Fprintf(s, " isddd(%v)", n.Isddd)
349 fmt.Fprintf(s, " implicit(%v)", n.Implicit)
353 fmt.Fprintf(s, " embedded(%d)", n.Embedded)
357 fmt.Fprint(s, " addrtaken")
361 fmt.Fprint(s, " assigned")
364 fmt.Fprint(s, " bounded")
367 fmt.Fprint(s, " nonnil")
370 if c == 0 && n.Used {
371 fmt.Fprintf(s, " used(%v)", n.Used)
375 func (v Val) Format(s fmt.State, verb rune) {
378 v.vconv(s, fmtFlag(s, verb))
381 fmt.Fprintf(s, "%%!%c(Val=%T)", verb, v)
385 func (v Val) vconv(s fmt.State, flag FmtFlag) {
386 switch u := v.U.(type) {
389 if flag&FmtSharp != 0 {
390 fmt.Fprint(s, bconv(u, FmtSharp))
393 fmt.Fprint(s, bconv(u, 0))
397 switch x := u.Int64(); {
398 case ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'':
399 fmt.Fprintf(s, "'%c'", int(x))
401 case 0 <= x && x < 1<<16:
402 fmt.Fprintf(s, "'\\u%04x'", uint(int(x)))
404 case 0 <= x && x <= utf8.MaxRune:
405 fmt.Fprintf(s, "'\\U%08x'", uint64(x))
408 fmt.Fprintf(s, "('\\x00' + %v)", u)
412 if flag&FmtSharp != 0 {
413 fmt.Fprint(s, fconv(u, 0))
416 fmt.Fprint(s, fconv(u, FmtSharp))
421 case flag&FmtSharp != 0:
422 fmt.Fprintf(s, "(%v+%vi)", &u.Real, &u.Imag)
424 case v.U.(*Mpcplx).Real.CmpFloat64(0) == 0:
425 fmt.Fprintf(s, "%vi", fconv(&u.Imag, FmtSharp))
427 case v.U.(*Mpcplx).Imag.CmpFloat64(0) == 0:
428 fmt.Fprint(s, fconv(&u.Real, FmtSharp))
430 case v.U.(*Mpcplx).Imag.CmpFloat64(0) < 0:
431 fmt.Fprintf(s, "(%v%vi)", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp))
434 fmt.Fprintf(s, "(%v+%vi)", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp))
438 fmt.Fprint(s, strconv.Quote(u))
451 fmt.Fprintf(s, "<ctype=%d>", v.Ctype())
464 var etnames = []string{
479 TCOMPLEX64: "COMPLEX64",
480 TCOMPLEX128: "COMPLEX128",
493 TUNSAFEPTR: "TUNSAFEPTR",
498 TFUNCARGS: "TFUNCARGS",
499 TCHANARGS: "TCHANARGS",
500 TINTERMETH: "TINTERMETH",
501 TDDDFIELD: "TDDDFIELD",
504 func (et EType) String() string {
505 if int(et) < len(etnames) && etnames[et] != "" {
508 return fmt.Sprintf("E-%d", et)
511 func (s *Sym) symfmt(flag FmtFlag) string {
512 if s.Pkg != nil && flag&FmtShort == 0 {
514 case FErr: // This is for the user
515 if s.Pkg == builtinpkg || s.Pkg == localpkg {
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)
523 return s.Pkg.Name + "." + s.Name
526 return s.Pkg.Name + "." + s.Name
529 if flag&FmtUnsigned != 0 {
530 return s.Pkg.Name + "." + s.Name // dcommontype, typehash
532 return s.Pkg.Prefix + "." + s.Name // (methodsym), typesym, weaksym
536 if flag&FmtByte != 0 {
537 // FmtByte (hh) implies FmtShort (h)
538 // skip leading "type." in method name
540 if i := strings.LastIndex(name, "."); i >= 0 {
545 return fmt.Sprintf("@%q.%s", s.Pkg.Path, name)
554 var basicnames = []string{
568 TCOMPLEX64: "complex64",
569 TCOMPLEX128: "complex128",
574 TIDEAL: "untyped number",
578 func (t *Type) typefmt(flag FmtFlag) string {
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)
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] {
599 if flag&FmtShort != 0 {
601 return fmt.Sprintf("%v·%d", t.Sym.sconv(FmtShort), t.Vargen)
603 return t.Sym.sconv(FmtShort)
606 if flag&FmtUnsigned != 0 {
607 return t.Sym.sconv(FmtUnsigned)
610 if t.Sym.Pkg == localpkg && t.Vargen != 0 {
611 return fmt.Sprintf("%v·%d", t.Sym, t.Vargen)
615 return t.Sym.String()
618 if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
620 if fmtmode == FErr && (t == idealbool || t == idealstring) {
623 return prefix + basicnames[t.Etype]
628 str := t.Etype.String() + "-" + t.typefmt(flag)
635 if fmtmode == FTypeId && (flag&FmtShort != 0) {
636 return "*" + t.Elem().tconv(FmtShort)
638 return "*" + t.Elem().String()
642 return "[...]" + t.Elem().String()
644 return fmt.Sprintf("[%d]%v", t.NumElem(), t.Elem())
647 return "[]" + t.Elem().String()
652 return "<-chan " + t.Elem().String()
655 return "chan<- " + t.Elem().String()
658 if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == Crecv {
659 return "chan (" + t.Elem().String() + ")"
661 return "chan " + t.Elem().String()
664 return "map[" + t.Key().String() + "]" + t.Val().String()
667 if t.IsEmptyInterface() {
668 return "interface {}"
670 buf := make([]byte, 0, 64)
671 buf = append(buf, "interface {"...)
672 for i, f := range t.Fields().Slice() {
674 buf = append(buf, ';')
676 buf = append(buf, ' ')
679 // Check first that a symbol is defined for this type.
680 // Wrong interface definitions may have types lacking a symbol.
682 case exportname(f.Sym.Name):
683 buf = append(buf, f.Sym.sconv(FmtShort)...)
685 buf = append(buf, f.Sym.sconv(FmtUnsigned)...)
687 buf = append(buf, f.Type.tconv(FmtShort)...)
689 if t.NumFields() != 0 {
690 buf = append(buf, ' ')
692 buf = append(buf, '}')
696 buf := make([]byte, 0, 64)
697 if flag&FmtShort != 0 {
701 buf = append(buf, "method"...)
702 buf = append(buf, t.Recvs().String()...)
703 buf = append(buf, ' ')
705 buf = append(buf, "func"...)
707 buf = append(buf, t.Params().String()...)
709 switch t.Results().NumFields() {
714 buf = append(buf, ' ')
715 buf = append(buf, t.Results().Field(0).Type.String()...) // struct->field->field's type
718 buf = append(buf, ' ')
719 buf = append(buf, t.Results().String()...)
724 if m := t.StructType().Map; m != nil {
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.
729 return "map.bucket[" + m.Key().String() + "]" + m.Val().String()
733 return "map.hdr[" + m.Key().String() + "]" + m.Val().String()
737 return "map.iter[" + m.Key().String() + "]" + m.Val().String()
740 yyerror("unknown internal map type")
743 buf := make([]byte, 0, 64)
744 if t.IsFuncArgStruct() {
745 buf = append(buf, '(')
747 if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
750 for i, f := range t.Fields().Slice() {
752 buf = append(buf, ", "...)
754 buf = append(buf, fldconv(f, flag1)...)
756 buf = append(buf, ')')
758 buf = append(buf, "struct {"...)
759 for i, f := range t.Fields().Slice() {
761 buf = append(buf, ';')
763 buf = append(buf, ' ')
764 buf = append(buf, fldconv(f, FmtLong)...)
766 if t.NumFields() != 0 {
767 buf = append(buf, ' ')
769 buf = append(buf, '}')
775 return "undefined " + t.Sym.String()
780 return "unsafe.Pointer"
783 return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.DDDField())
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())
793 // Statements which may be rendered with a simplestmt as init.
794 func stmtwithinit(op Op) bool {
796 case OIF, OFOR, OSWITCH:
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.
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)
812 // otherwise, print the inits as separate statements
813 complexinit := n.Ninit.Len() != 0 && !simpleinit && (fmtmode != FErr)
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)
823 fmt.Fprintf(s, " %v; ", n.Ninit)
828 fmt.Fprintf(s, "var %v %v", n.Left.Sym, n.Left.Type)
832 fmt.Fprintf(s, "%v %v", n.Left, n.Right)
834 fmt.Fprintf(s, "%v", n.Right)
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.
841 if n.Colas && !complexinit {
842 fmt.Fprintf(s, "%v := %v", n.Left, n.Right)
844 fmt.Fprintf(s, "%v = %v", n.Left, n.Right)
849 if Op(n.Etype) == OADD {
850 fmt.Fprintf(s, "%v++", n.Left)
852 fmt.Fprintf(s, "%v--", n.Left)
857 fmt.Fprintf(s, "%v %#v= %v", n.Left, Op(n.Etype), n.Right)
860 if n.Colas && !complexinit {
861 fmt.Fprintf(s, "%.v := %.v", n.List, n.Rlist)
866 case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
867 fmt.Fprintf(s, "%.v = %.v", n.List, n.Rlist)
870 fmt.Fprintf(s, "return %.v", n.List)
873 fmt.Fprintf(s, "retjmp %v", n.Sym)
876 fmt.Fprintf(s, "go %v", n.Left)
879 fmt.Fprintf(s, "defer %v", n.Left)
883 fmt.Fprintf(s, "if %v; %v { %v }", n.Ninit.First(), n.Left, n.Nbody)
885 fmt.Fprintf(s, "if %v { %v }", n.Left, n.Nbody)
887 if n.Rlist.Len() != 0 {
888 fmt.Fprintf(s, " else { %v }", n.Rlist)
892 if fmtmode == FErr { // TODO maybe only if FmtShort, same below
893 fmt.Fprint(s, "for loop")
899 fmt.Fprintf(s, " %v;", n.Ninit.First())
900 } else if n.Right != nil {
905 fmt.Fprintf(s, " %v", n.Left)
909 fmt.Fprintf(s, "; %v", n.Right)
910 } else if simpleinit {
914 fmt.Fprintf(s, " { %v }", n.Nbody)
918 fmt.Fprint(s, "for loop")
922 if n.List.Len() == 0 {
923 fmt.Fprintf(s, "for range %v { %v }", n.Right, n.Nbody)
927 fmt.Fprintf(s, "for %.v = range %v { %v }", n.List, n.Right, n.Nbody)
929 case OSELECT, OSWITCH:
931 fmt.Fprintf(s, "%v statement", n.Op)
935 fmt.Fprint(s, n.Op.GoString()) // %#v
937 fmt.Fprintf(s, " %v;", n.Ninit.First())
940 fmt.Fprintf(s, " %v ", n.Left)
943 fmt.Fprintf(s, " { %v }", n.List)
946 if n.List.Len() != 0 {
947 fmt.Fprintf(s, "case %.v", n.List)
949 fmt.Fprint(s, "default")
951 fmt.Fprintf(s, ": %v", n.Nbody)
957 fmt.Fprintf(s, "case %v", n.Left)
958 case n.List.Len() > 0:
960 if n.List.Len() != 2 {
961 Fatalf("bad OCASE list length %d", n.List.Len())
963 fmt.Fprintf(s, "case %v..%v", n.List.First(), n.List.Second())
965 fmt.Fprint(s, "default")
967 fmt.Fprintf(s, ": %v", n.Nbody)
975 fmt.Fprintf(s, "%#v %v", n.Op, n.Left)
977 fmt.Fprint(s, n.Op.GoString()) // %#v
984 fmt.Fprintf(s, "%v: ", n.Left)
1081 // Statements handled by stmtfmt
1112 func (n *Node) exprfmt(s fmt.State, prec int) {
1113 for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) {
1118 fmt.Fprint(s, "<N>")
1122 nprec := opprec[n.Op]
1123 if n.Op == OTYPE && n.Sym != nil {
1128 fmt.Fprintf(s, "(%v)", n)
1134 fmt.Fprintf(s, "(%v)", n.Left)
1137 fmt.Fprint(s, "... argument")
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)
1146 fmt.Fprint(s, n.Sym.String())
1150 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
1151 n.Orig.exprfmt(s, prec)
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())
1161 fmt.Fprintf(s, "%v(%v)", n.Type, n.Val())
1166 fmt.Fprintf(s, "%v", n.Val())
1168 // Special case: name used as local variable in export.
1169 // _ becomes ~b%d internally; print as _ for export
1171 if fmtmode == FErr && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
1176 case OPACK, ONONAME:
1177 fmt.Fprint(s, n.Sym.String())
1180 if n.Type == nil && n.Sym != nil {
1181 fmt.Fprint(s, n.Sym.String())
1184 fmt.Fprintf(s, "%v", n.Type)
1188 fmt.Fprintf(s, "[]%v", n.Left)
1191 fmt.Fprintf(s, "[]%v", n.Right) // happens before typecheck
1194 fmt.Fprintf(s, "map[%v]%v", n.Left, n.Right)
1197 switch ChanDir(n.Etype) {
1199 fmt.Fprintf(s, "<-chan %v", n.Left)
1202 fmt.Fprintf(s, "chan<- %v", n.Left)
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)
1208 fmt.Fprintf(s, "chan %v", n.Left)
1213 fmt.Fprint(s, "<struct>")
1216 fmt.Fprint(s, "<inter>")
1219 fmt.Fprint(s, "<func>")
1222 if fmtmode == FErr {
1223 fmt.Fprint(s, "func literal")
1226 if n.Nbody.Len() != 0 {
1227 fmt.Fprintf(s, "%v { %v }", n.Type, n.Nbody)
1230 fmt.Fprintf(s, "%v { %v }", n.Type, n.Func.Closure.Nbody)
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 {
1237 fmt.Fprintf(s, "&%v literal", n.Right.Type.Elem())
1240 fmt.Fprintf(s, "%v literal", n.Right.Type)
1245 fmt.Fprint(s, "composite literal")
1248 fmt.Fprintf(s, "(%v{ %.v })", n.Right, n.List)
1251 fmt.Fprintf(s, "&%v", n.Left)
1253 case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
1254 if fmtmode == FErr {
1255 fmt.Fprintf(s, "%v literal", n.Type)
1258 fmt.Fprintf(s, "(%v{ %.v })", n.Type, n.List)
1261 if n.Left != nil && n.Right != nil {
1262 fmt.Fprintf(s, "%v:%v", n.Left, n.Right)
1266 if n.Left == nil && n.Right != nil {
1267 fmt.Fprintf(s, ":%v", n.Right)
1270 if n.Left != nil && n.Right == nil {
1271 fmt.Fprintf(s, "%v:", n.Left)
1277 fmt.Fprintf(s, "%v:%v", n.Sym, n.Left)
1280 n.Left.exprfmt(s, nprec)
1281 if n.Right == nil || n.Right.Sym == nil {
1282 fmt.Fprint(s, ".<nil>")
1285 fmt.Fprintf(s, ".%0S", n.Right.Sym)
1287 case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
1288 n.Left.exprfmt(s, nprec)
1290 fmt.Fprint(s, ".<nil>")
1293 fmt.Fprintf(s, ".%0S", n.Sym)
1295 case ODOTTYPE, ODOTTYPE2:
1296 n.Left.exprfmt(s, nprec)
1298 fmt.Fprintf(s, ".(%v)", n.Right)
1301 fmt.Fprintf(s, ".(%v)", n.Type)
1303 case OINDEX, OINDEXMAP:
1304 n.Left.exprfmt(s, nprec)
1305 fmt.Fprintf(s, "[%v]", n.Right)
1307 case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
1308 n.Left.exprfmt(s, nprec)
1310 low, high, max := n.SliceBounds()
1312 fmt.Fprint(s, low.String())
1316 fmt.Fprint(s, high.String())
1318 if n.Op.IsSlice3() {
1321 fmt.Fprint(s, max.String())
1326 case OCOPY, OCOMPLEX:
1327 fmt.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
1337 if n.Type == nil || n.Type.Sym == nil {
1338 fmt.Fprintf(s, "(%v)(%v)", n.Type, n.Left)
1342 fmt.Fprintf(s, "%v(%v)", n.Type, n.Left)
1345 fmt.Fprintf(s, "%v(%.v)", n.Type, n.List)
1364 fmt.Fprintf(s, "%#v(%v)", n.Op, n.Left)
1368 fmt.Fprintf(s, "%#v(%.v...)", n.Op, n.List)
1371 fmt.Fprintf(s, "%#v(%.v)", n.Op, n.List)
1373 case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
1374 n.Left.exprfmt(s, nprec)
1376 fmt.Fprintf(s, "(%.v...)", n.List)
1379 fmt.Fprintf(s, "(%.v)", n.List)
1381 case OMAKEMAP, OMAKECHAN, OMAKESLICE:
1382 if n.List.Len() != 0 { // pre-typecheck
1383 fmt.Fprintf(s, "make(%v, %.v)", n.Type, n.List)
1387 fmt.Fprintf(s, "make(%v, %v, %v)", n.Type, n.Left, n.Right)
1390 if n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()) {
1391 fmt.Fprintf(s, "make(%v, %v)", n.Type, n.Left)
1394 fmt.Fprintf(s, "make(%v)", n.Type)
1404 fmt.Fprint(s, n.Op.GoString()) // %#v
1405 if n.Left.Op == n.Op {
1408 n.Left.exprfmt(s, nprec+1)
1431 n.Left.exprfmt(s, nprec)
1432 fmt.Fprintf(s, " %#v ", n.Op)
1433 n.Right.exprfmt(s, nprec+1)
1437 for _, n1 := range n.List.Slice() {
1439 fmt.Fprint(s, " + ")
1441 n1.exprfmt(s, nprec)
1445 case OCMPSTR, OCMPIFACE:
1446 n.Left.exprfmt(s, nprec)
1447 // TODO(marvin): Fix Node.EType type union.
1448 fmt.Fprintf(s, " %#v ", Op(n.Etype))
1449 n.Right.exprfmt(s, nprec+1)
1452 fmt.Fprintf(s, "<node %v>", n.Op)
1456 func (n *Node) nodefmt(s fmt.State, flag FmtFlag) {
1459 // we almost always want the original, except in export mode for literals
1460 // this saves the importer some work, and avoids us having to redo some
1461 // special casing for package unsafe
1462 if n.Op != OLITERAL && n.Orig != nil {
1466 if flag&FmtLong != 0 && t != nil {
1467 if t.Etype == TNIL {
1468 fmt.Fprint(s, "nil")
1470 fmt.Fprintf(s, "%v (type %v)", n, t)
1475 // TODO inlining produces expressions with ninits. we can't print these yet.
1477 if opprec[n.Op] < 0 {
1485 func (n *Node) nodedump(s fmt.State, flag FmtFlag) {
1490 recur := flag&FmtShort == 0
1495 fmt.Fprint(s, "...")
1499 if n.Ninit.Len() != 0 {
1500 fmt.Fprintf(s, "%v-init%v", n.Op, n.Ninit)
1507 fmt.Fprintf(s, "%v%j", n.Op, n)
1510 fmt.Fprintf(s, "%v-SP%j", n.Op, n)
1513 fmt.Fprintf(s, "%v-%v%j", n.Op, n.Val(), n)
1515 case ONAME, ONONAME:
1517 fmt.Fprintf(s, "%v-%v%j", n.Op, n.Sym, n)
1519 fmt.Fprintf(s, "%v%j", n.Op, n)
1521 if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil {
1523 fmt.Fprintf(s, "%v-ntype%v", n.Op, n.Name.Param.Ntype)
1527 fmt.Fprintf(s, "%v-%v%j", n.Op, Op(n.Etype), n)
1530 fmt.Fprintf(s, "%v %v%j type=%v", n.Op, n.Sym, n, n.Type)
1531 if recur && n.Type == nil && n.Name.Param.Ntype != nil {
1533 fmt.Fprintf(s, "%v-ntype%v", n.Op, n.Name.Param.Ntype)
1537 if n.Sym != nil && n.Op != ONAME {
1538 fmt.Fprintf(s, " %v", n.Sym)
1542 fmt.Fprintf(s, " %v", n.Type)
1547 fmt.Fprintf(s, "%v", n.Left)
1550 fmt.Fprintf(s, "%v", n.Right)
1552 if n.List.Len() != 0 {
1554 fmt.Fprintf(s, "%v-list%v", n.Op, n.List)
1557 if n.Rlist.Len() != 0 {
1559 fmt.Fprintf(s, "%v-rlist%v", n.Op, n.Rlist)
1562 if n.Nbody.Len() != 0 {
1564 fmt.Fprintf(s, "%v-body%v", n.Op, n.Nbody)
1569 // "%S" suppresses qualifying with package
1570 func (s *Sym) Format(f fmt.State, verb rune) {
1573 fmt.Fprint(f, s.sconv(fmtFlag(f, verb)))
1576 fmt.Fprintf(f, "%%!%c(*Sym=%p)", verb, s)
1580 func (s *Sym) String() string {
1584 // See #16897 before changing the implementation of sconv.
1585 func (s *Sym) sconv(flag FmtFlag) string {
1586 if flag&FmtLong != 0 {
1599 sm := setfmode(&flag)
1600 str := s.symfmt(flag)
1606 func (t *Type) String() string {
1610 func fldconv(f *Field, flag FmtFlag) string {
1616 sm := setfmode(&flag)
1618 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
1626 if flag&FmtShort == 0 {
1629 // Take the name from the original, lest we substituted it with ~r%d or ~b%d.
1630 // ~r%d is a (formerly) unnamed result.
1631 if fmtmode == FErr && f.Nname != nil {
1632 if f.Nname.Orig != nil {
1633 s = f.Nname.Orig.Sym
1634 if s != nil && s.Name[0] == '~' {
1635 if s.Name[1] == 'r' { // originally an unnamed result
1637 } else if s.Name[1] == 'b' { // originally the blank identifier _
1646 if s != nil && f.Embedded == 0 {
1647 if f.Funarg != FunargNone {
1648 name = f.Nname.String()
1649 } else if flag&FmtLong != 0 {
1650 name = fmt.Sprintf("%0S", s)
1651 if !exportname(name) && flag&FmtUnsigned == 0 {
1652 name = s.String() // qualify non-exported names (used on structs, not on funarg)
1662 typ = fmt.Sprintf("...%v", f.Type.Elem())
1664 typ = fmt.Sprintf("%v", f.Type)
1669 str = name + " " + typ
1672 if flag&FmtShort == 0 && f.Funarg == FunargNone && f.Note != "" {
1673 str += " " + strconv.Quote(f.Note)
1676 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
1685 // "%L" print definition, not name
1686 // "%S" omit 'func' and receiver from function types, short type names
1687 // "% v" package name, not prefix (FTypeId mode, sticky)
1688 func (t *Type) Format(s fmt.State, verb rune) {
1691 fmt.Fprint(s, t.tconv(fmtFlag(s, verb)))
1694 fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
1698 // See #16897 before changing the implementation of tconv.
1699 func (t *Type) tconv(flag FmtFlag) string {
1710 sm := setfmode(&flag)
1712 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
1719 str := t.typefmt(flag)
1721 if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
1731 func (n *Node) String() string {
1732 return fmt.Sprint(n)
1735 // "%L" suffix with "(type %T)" where possible
1736 // "%+S" in debug mode, don't recurse, no multiline output
1737 func (n *Node) Nconv(s fmt.State, flag FmtFlag) {
1739 fmt.Fprint(s, "<N>")
1744 sm := setfmode(&flag)
1756 Fatalf("unhandled %%N mode: %d", fmtmode)
1763 func (l Nodes) Format(s fmt.State, verb rune) {
1766 l.hconv(s, fmtFlag(s, verb))
1769 fmt.Fprintf(s, "%%!%c(Nodes)", verb)
1773 func (n Nodes) String() string {
1774 return fmt.Sprint(n)
1777 // Flags: all those of %N plus '.': separate with comma's instead of semicolons.
1778 func (l Nodes) hconv(s fmt.State, flag FmtFlag) {
1779 if l.Len() == 0 && fmtmode == FDbg {
1780 fmt.Fprint(s, "<nil>")
1785 sm := setfmode(&flag)
1787 if fmtmode == FDbg {
1789 } else if flag&FmtComma != 0 {
1793 for i, n := range l.Slice() {
1804 func dumplist(s string, l Nodes) {
1805 fmt.Printf("%s%+v\n", s, l)
1808 func Dump(s string, n *Node) {
1809 fmt.Printf("%s [%p]%+v\n", s, n, n)
1812 // TODO(gri) make variable local somehow
1815 // indent prints indentation to s.
1816 func indent(s fmt.State) {
1818 for i := 0; i < dumpdepth; i++ {