...

Source file src/pkg/cmd/compile/internal/gc/fmt.go

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

View as plain text