github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/compile/internal/gc/fmt.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gc
     6  
     7  import (
     8  	"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  				buf = append(buf, sconv(f.Sym, FmtUnsigned, mode)...)
   756  			}
   757  			buf = append(buf, tconv(f.Type, FmtShort, mode, depth)...)
   758  		}
   759  		if t.NumFields() != 0 {
   760  			buf = append(buf, ' ')
   761  		}
   762  		buf = append(buf, '}')
   763  		return string(buf)
   764  
   765  	case TFUNC:
   766  		buf := make([]byte, 0, 64)
   767  		if flag&FmtShort != 0 {
   768  			// no leading func
   769  		} else {
   770  			if t.Recv() != nil {
   771  				buf = append(buf, "method"...)
   772  				buf = append(buf, tmodeString(t.Recvs(), mode, depth)...)
   773  				buf = append(buf, ' ')
   774  			}
   775  			buf = append(buf, "func"...)
   776  		}
   777  		buf = append(buf, tmodeString(t.Params(), mode, depth)...)
   778  
   779  		switch t.NumResults() {
   780  		case 0:
   781  			// nothing to do
   782  
   783  		case 1:
   784  			buf = append(buf, ' ')
   785  			buf = append(buf, tmodeString(t.Results().Field(0).Type, mode, depth)...) // struct->field->field's type
   786  
   787  		default:
   788  			buf = append(buf, ' ')
   789  			buf = append(buf, tmodeString(t.Results(), mode, depth)...)
   790  		}
   791  		return string(buf)
   792  
   793  	case TSTRUCT:
   794  		if m := t.StructType().Map; m != nil {
   795  			mt := m.MapType()
   796  			// Format the bucket struct for map[x]y as map.bucket[x]y.
   797  			// This avoids a recursive print that generates very long names.
   798  			var subtype string
   799  			switch t {
   800  			case mt.Bucket:
   801  				subtype = "bucket"
   802  			case mt.Hmap:
   803  				subtype = "hdr"
   804  			case mt.Hiter:
   805  				subtype = "iter"
   806  			default:
   807  				Fatalf("unknown internal map type")
   808  			}
   809  			return fmt.Sprintf("map.%s[%s]%s", subtype, tmodeString(m.Key(), mode, depth), tmodeString(m.Elem(), mode, depth))
   810  		}
   811  
   812  		buf := make([]byte, 0, 64)
   813  		if funarg := t.StructType().Funarg; funarg != types.FunargNone {
   814  			buf = append(buf, '(')
   815  			var flag1 FmtFlag
   816  			switch mode {
   817  			case FTypeId, FTypeIdName, FErr:
   818  				// no argument names on function signature, and no "noescape"/"nosplit" tags
   819  				flag1 = FmtShort
   820  			}
   821  			for i, f := range t.Fields().Slice() {
   822  				if i != 0 {
   823  					buf = append(buf, ", "...)
   824  				}
   825  				buf = append(buf, fldconv(f, flag1, mode, depth, funarg)...)
   826  			}
   827  			buf = append(buf, ')')
   828  		} else {
   829  			buf = append(buf, "struct {"...)
   830  			for i, f := range t.Fields().Slice() {
   831  				if i != 0 {
   832  					buf = append(buf, ';')
   833  				}
   834  				buf = append(buf, ' ')
   835  				buf = append(buf, fldconv(f, FmtLong, mode, depth, funarg)...)
   836  			}
   837  			if t.NumFields() != 0 {
   838  				buf = append(buf, ' ')
   839  			}
   840  			buf = append(buf, '}')
   841  		}
   842  		return string(buf)
   843  
   844  	case TFORW:
   845  		if t.Sym != nil {
   846  			return "undefined " + smodeString(t.Sym, mode)
   847  		}
   848  		return "undefined"
   849  
   850  	case TUNSAFEPTR:
   851  		return "unsafe.Pointer"
   852  
   853  	case TDDDFIELD:
   854  		return mode.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.DDDField())
   855  
   856  	case Txxx:
   857  		return "Txxx"
   858  	}
   859  
   860  	// Don't know how to handle - fall back to detailed prints.
   861  	return mode.Sprintf("%v <%v>", t.Etype, t.Sym)
   862  }
   863  
   864  // Statements which may be rendered with a simplestmt as init.
   865  func stmtwithinit(op Op) bool {
   866  	switch op {
   867  	case OIF, OFOR, OFORUNTIL, OSWITCH:
   868  		return true
   869  	}
   870  
   871  	return false
   872  }
   873  
   874  func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
   875  	// some statements allow for an init, but at most one,
   876  	// but we may have an arbitrary number added, eg by typecheck
   877  	// and inlining. If it doesn't fit the syntax, emit an enclosing
   878  	// block starting with the init statements.
   879  
   880  	// if we can just say "for" n->ninit; ... then do so
   881  	simpleinit := n.Ninit.Len() == 1 && n.Ninit.First().Ninit.Len() == 0 && stmtwithinit(n.Op)
   882  
   883  	// otherwise, print the inits as separate statements
   884  	complexinit := n.Ninit.Len() != 0 && !simpleinit && (mode != FErr)
   885  
   886  	// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
   887  	extrablock := complexinit && stmtwithinit(n.Op)
   888  
   889  	if extrablock {
   890  		fmt.Fprint(s, "{")
   891  	}
   892  
   893  	if complexinit {
   894  		mode.Fprintf(s, " %v; ", n.Ninit)
   895  	}
   896  
   897  	switch n.Op {
   898  	case ODCL:
   899  		mode.Fprintf(s, "var %v %v", n.Left.Sym, n.Left.Type)
   900  
   901  	case ODCLFIELD:
   902  		if n.Sym != nil {
   903  			mode.Fprintf(s, "%v %v", n.Sym, n.Left)
   904  		} else {
   905  			mode.Fprintf(s, "%v", n.Left)
   906  		}
   907  
   908  	// Don't export "v = <N>" initializing statements, hope they're always
   909  	// preceded by the DCL which will be re-parsed and typechecked to reproduce
   910  	// the "v = <N>" again.
   911  	case OAS:
   912  		if n.Colas() && !complexinit {
   913  			mode.Fprintf(s, "%v := %v", n.Left, n.Right)
   914  		} else {
   915  			mode.Fprintf(s, "%v = %v", n.Left, n.Right)
   916  		}
   917  
   918  	case OASOP:
   919  		if n.Implicit() {
   920  			if n.SubOp() == OADD {
   921  				mode.Fprintf(s, "%v++", n.Left)
   922  			} else {
   923  				mode.Fprintf(s, "%v--", n.Left)
   924  			}
   925  			break
   926  		}
   927  
   928  		mode.Fprintf(s, "%v %#v= %v", n.Left, n.SubOp(), n.Right)
   929  
   930  	case OAS2:
   931  		if n.Colas() && !complexinit {
   932  			mode.Fprintf(s, "%.v := %.v", n.List, n.Rlist)
   933  			break
   934  		}
   935  		fallthrough
   936  
   937  	case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
   938  		mode.Fprintf(s, "%.v = %.v", n.List, n.Rlist)
   939  
   940  	case ORETURN:
   941  		mode.Fprintf(s, "return %.v", n.List)
   942  
   943  	case ORETJMP:
   944  		mode.Fprintf(s, "retjmp %v", n.Sym)
   945  
   946  	case OINLMARK:
   947  		mode.Fprintf(s, "inlmark %d", n.Xoffset)
   948  
   949  	case OGO:
   950  		mode.Fprintf(s, "go %v", n.Left)
   951  
   952  	case ODEFER:
   953  		mode.Fprintf(s, "defer %v", n.Left)
   954  
   955  	case OIF:
   956  		if simpleinit {
   957  			mode.Fprintf(s, "if %v; %v { %v }", n.Ninit.First(), n.Left, n.Nbody)
   958  		} else {
   959  			mode.Fprintf(s, "if %v { %v }", n.Left, n.Nbody)
   960  		}
   961  		if n.Rlist.Len() != 0 {
   962  			mode.Fprintf(s, " else { %v }", n.Rlist)
   963  		}
   964  
   965  	case OFOR, OFORUNTIL:
   966  		opname := "for"
   967  		if n.Op == OFORUNTIL {
   968  			opname = "foruntil"
   969  		}
   970  		if mode == FErr { // TODO maybe only if FmtShort, same below
   971  			fmt.Fprintf(s, "%s loop", opname)
   972  			break
   973  		}
   974  
   975  		fmt.Fprint(s, opname)
   976  		if simpleinit {
   977  			mode.Fprintf(s, " %v;", n.Ninit.First())
   978  		} else if n.Right != nil {
   979  			fmt.Fprint(s, " ;")
   980  		}
   981  
   982  		if n.Left != nil {
   983  			mode.Fprintf(s, " %v", n.Left)
   984  		}
   985  
   986  		if n.Right != nil {
   987  			mode.Fprintf(s, "; %v", n.Right)
   988  		} else if simpleinit {
   989  			fmt.Fprint(s, ";")
   990  		}
   991  
   992  		if n.Op == OFORUNTIL && n.List.Len() != 0 {
   993  			mode.Fprintf(s, "; %v", n.List)
   994  		}
   995  
   996  		mode.Fprintf(s, " { %v }", n.Nbody)
   997  
   998  	case ORANGE:
   999  		if mode == FErr {
  1000  			fmt.Fprint(s, "for loop")
  1001  			break
  1002  		}
  1003  
  1004  		if n.List.Len() == 0 {
  1005  			mode.Fprintf(s, "for range %v { %v }", n.Right, n.Nbody)
  1006  			break
  1007  		}
  1008  
  1009  		mode.Fprintf(s, "for %.v = range %v { %v }", n.List, n.Right, n.Nbody)
  1010  
  1011  	case OSELECT, OSWITCH:
  1012  		if mode == FErr {
  1013  			mode.Fprintf(s, "%v statement", n.Op)
  1014  			break
  1015  		}
  1016  
  1017  		mode.Fprintf(s, "%#v", n.Op)
  1018  		if simpleinit {
  1019  			mode.Fprintf(s, " %v;", n.Ninit.First())
  1020  		}
  1021  		if n.Left != nil {
  1022  			mode.Fprintf(s, " %v ", n.Left)
  1023  		}
  1024  
  1025  		mode.Fprintf(s, " { %v }", n.List)
  1026  
  1027  	case OXCASE:
  1028  		if n.List.Len() != 0 {
  1029  			mode.Fprintf(s, "case %.v", n.List)
  1030  		} else {
  1031  			fmt.Fprint(s, "default")
  1032  		}
  1033  		mode.Fprintf(s, ": %v", n.Nbody)
  1034  
  1035  	case OCASE:
  1036  		switch {
  1037  		case n.Left != nil:
  1038  			// single element
  1039  			mode.Fprintf(s, "case %v", n.Left)
  1040  		case n.List.Len() > 0:
  1041  			// range
  1042  			if n.List.Len() != 2 {
  1043  				Fatalf("bad OCASE list length %d", n.List.Len())
  1044  			}
  1045  			mode.Fprintf(s, "case %v..%v", n.List.First(), n.List.Second())
  1046  		default:
  1047  			fmt.Fprint(s, "default")
  1048  		}
  1049  		mode.Fprintf(s, ": %v", n.Nbody)
  1050  
  1051  	case OBREAK, OCONTINUE, OGOTO, OFALL:
  1052  		if n.Sym != nil {
  1053  			mode.Fprintf(s, "%#v %v", n.Op, n.Sym)
  1054  		} else {
  1055  			mode.Fprintf(s, "%#v", n.Op)
  1056  		}
  1057  
  1058  	case OEMPTY:
  1059  		break
  1060  
  1061  	case OLABEL:
  1062  		mode.Fprintf(s, "%v: ", n.Sym)
  1063  	}
  1064  
  1065  	if extrablock {
  1066  		fmt.Fprint(s, "}")
  1067  	}
  1068  }
  1069  
  1070  var opprec = []int{
  1071  	OALIGNOF:     8,
  1072  	OAPPEND:      8,
  1073  	OBYTES2STR:   8,
  1074  	OARRAYLIT:    8,
  1075  	OSLICELIT:    8,
  1076  	ORUNES2STR:   8,
  1077  	OCALLFUNC:    8,
  1078  	OCALLINTER:   8,
  1079  	OCALLMETH:    8,
  1080  	OCALL:        8,
  1081  	OCAP:         8,
  1082  	OCLOSE:       8,
  1083  	OCONVIFACE:   8,
  1084  	OCONVNOP:     8,
  1085  	OCONV:        8,
  1086  	OCOPY:        8,
  1087  	ODELETE:      8,
  1088  	OGETG:        8,
  1089  	OLEN:         8,
  1090  	OLITERAL:     8,
  1091  	OMAKESLICE:   8,
  1092  	OMAKE:        8,
  1093  	OMAPLIT:      8,
  1094  	ONAME:        8,
  1095  	ONEW:         8,
  1096  	ONONAME:      8,
  1097  	OOFFSETOF:    8,
  1098  	OPACK:        8,
  1099  	OPANIC:       8,
  1100  	OPAREN:       8,
  1101  	OPRINTN:      8,
  1102  	OPRINT:       8,
  1103  	ORUNESTR:     8,
  1104  	OSIZEOF:      8,
  1105  	OSTR2BYTES:   8,
  1106  	OSTR2RUNES:   8,
  1107  	OSTRUCTLIT:   8,
  1108  	OTARRAY:      8,
  1109  	OTCHAN:       8,
  1110  	OTFUNC:       8,
  1111  	OTINTER:      8,
  1112  	OTMAP:        8,
  1113  	OTSTRUCT:     8,
  1114  	OINDEXMAP:    8,
  1115  	OINDEX:       8,
  1116  	OSLICE:       8,
  1117  	OSLICESTR:    8,
  1118  	OSLICEARR:    8,
  1119  	OSLICE3:      8,
  1120  	OSLICE3ARR:   8,
  1121  	OSLICEHEADER: 8,
  1122  	ODOTINTER:    8,
  1123  	ODOTMETH:     8,
  1124  	ODOTPTR:      8,
  1125  	ODOTTYPE2:    8,
  1126  	ODOTTYPE:     8,
  1127  	ODOT:         8,
  1128  	OXDOT:        8,
  1129  	OCALLPART:    8,
  1130  	OPLUS:        7,
  1131  	ONOT:         7,
  1132  	OBITNOT:      7,
  1133  	ONEG:         7,
  1134  	OADDR:        7,
  1135  	ODEREF:       7,
  1136  	ORECV:        7,
  1137  	OMUL:         6,
  1138  	ODIV:         6,
  1139  	OMOD:         6,
  1140  	OLSH:         6,
  1141  	ORSH:         6,
  1142  	OAND:         6,
  1143  	OANDNOT:      6,
  1144  	OADD:         5,
  1145  	OSUB:         5,
  1146  	OOR:          5,
  1147  	OXOR:         5,
  1148  	OEQ:          4,
  1149  	OLT:          4,
  1150  	OLE:          4,
  1151  	OGE:          4,
  1152  	OGT:          4,
  1153  	ONE:          4,
  1154  	OSEND:        3,
  1155  	OANDAND:      2,
  1156  	OOROR:        1,
  1157  
  1158  	// Statements handled by stmtfmt
  1159  	OAS:         -1,
  1160  	OAS2:        -1,
  1161  	OAS2DOTTYPE: -1,
  1162  	OAS2FUNC:    -1,
  1163  	OAS2MAPR:    -1,
  1164  	OAS2RECV:    -1,
  1165  	OASOP:       -1,
  1166  	OBREAK:      -1,
  1167  	OCASE:       -1,
  1168  	OCONTINUE:   -1,
  1169  	ODCL:        -1,
  1170  	ODCLFIELD:   -1,
  1171  	ODEFER:      -1,
  1172  	OEMPTY:      -1,
  1173  	OFALL:       -1,
  1174  	OFOR:        -1,
  1175  	OFORUNTIL:   -1,
  1176  	OGOTO:       -1,
  1177  	OIF:         -1,
  1178  	OLABEL:      -1,
  1179  	OGO:         -1,
  1180  	ORANGE:      -1,
  1181  	ORETURN:     -1,
  1182  	OSELECT:     -1,
  1183  	OSWITCH:     -1,
  1184  	OXCASE:      -1,
  1185  
  1186  	OEND: 0,
  1187  }
  1188  
  1189  func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
  1190  	for n != nil && n.Implicit() && (n.Op == ODEREF || n.Op == OADDR) {
  1191  		n = n.Left
  1192  	}
  1193  
  1194  	if n == nil {
  1195  		fmt.Fprint(s, "<N>")
  1196  		return
  1197  	}
  1198  
  1199  	nprec := opprec[n.Op]
  1200  	if n.Op == OTYPE && n.Sym != nil {
  1201  		nprec = 8
  1202  	}
  1203  
  1204  	if prec > nprec {
  1205  		mode.Fprintf(s, "(%v)", n)
  1206  		return
  1207  	}
  1208  
  1209  	switch n.Op {
  1210  	case OPAREN:
  1211  		mode.Fprintf(s, "(%v)", n.Left)
  1212  
  1213  	case ODDDARG:
  1214  		fmt.Fprint(s, "... argument")
  1215  
  1216  	case OLITERAL: // this is a bit of a mess
  1217  		if mode == FErr {
  1218  			if n.Orig != nil && n.Orig != n {
  1219  				n.Orig.exprfmt(s, prec, mode)
  1220  				return
  1221  			}
  1222  			if n.Sym != nil {
  1223  				fmt.Fprint(s, smodeString(n.Sym, mode))
  1224  				return
  1225  			}
  1226  		}
  1227  		if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
  1228  			n.Orig.exprfmt(s, prec, mode)
  1229  			return
  1230  		}
  1231  		if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != types.Idealbool && n.Type != types.Idealstring {
  1232  			// Need parens when type begins with what might
  1233  			// be misinterpreted as a unary operator: * or <-.
  1234  			if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == types.Crecv) {
  1235  				mode.Fprintf(s, "(%v)(%v)", n.Type, n.Val())
  1236  				return
  1237  			} else {
  1238  				mode.Fprintf(s, "%v(%v)", n.Type, n.Val())
  1239  				return
  1240  			}
  1241  		}
  1242  
  1243  		mode.Fprintf(s, "%v", n.Val())
  1244  
  1245  	// Special case: name used as local variable in export.
  1246  	// _ becomes ~b%d internally; print as _ for export
  1247  	case ONAME:
  1248  		if mode == FErr && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
  1249  			fmt.Fprint(s, "_")
  1250  			return
  1251  		}
  1252  		fallthrough
  1253  	case OPACK, ONONAME:
  1254  		fmt.Fprint(s, smodeString(n.Sym, mode))
  1255  
  1256  	case OTYPE:
  1257  		if n.Type == nil && n.Sym != nil {
  1258  			fmt.Fprint(s, smodeString(n.Sym, mode))
  1259  			return
  1260  		}
  1261  		mode.Fprintf(s, "%v", n.Type)
  1262  
  1263  	case OTARRAY:
  1264  		if n.Left != nil {
  1265  			mode.Fprintf(s, "[%v]%v", n.Left, n.Right)
  1266  			return
  1267  		}
  1268  		mode.Fprintf(s, "[]%v", n.Right) // happens before typecheck
  1269  
  1270  	case OTMAP:
  1271  		mode.Fprintf(s, "map[%v]%v", n.Left, n.Right)
  1272  
  1273  	case OTCHAN:
  1274  		switch n.TChanDir() {
  1275  		case types.Crecv:
  1276  			mode.Fprintf(s, "<-chan %v", n.Left)
  1277  
  1278  		case types.Csend:
  1279  			mode.Fprintf(s, "chan<- %v", n.Left)
  1280  
  1281  		default:
  1282  			if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && n.Left.TChanDir() == types.Crecv {
  1283  				mode.Fprintf(s, "chan (%v)", n.Left)
  1284  			} else {
  1285  				mode.Fprintf(s, "chan %v", n.Left)
  1286  			}
  1287  		}
  1288  
  1289  	case OTSTRUCT:
  1290  		fmt.Fprint(s, "<struct>")
  1291  
  1292  	case OTINTER:
  1293  		fmt.Fprint(s, "<inter>")
  1294  
  1295  	case OTFUNC:
  1296  		fmt.Fprint(s, "<func>")
  1297  
  1298  	case OCLOSURE:
  1299  		if mode == FErr {
  1300  			fmt.Fprint(s, "func literal")
  1301  			return
  1302  		}
  1303  		if n.Nbody.Len() != 0 {
  1304  			mode.Fprintf(s, "%v { %v }", n.Type, n.Nbody)
  1305  			return
  1306  		}
  1307  		mode.Fprintf(s, "%v { %v }", n.Type, n.Func.Closure.Nbody)
  1308  
  1309  	case OCOMPLIT:
  1310  		if mode == FErr {
  1311  			if n.Right != nil && n.Right.Type != nil && !n.Implicit() {
  1312  				if n.Right.Implicit() && n.Right.Type.IsPtr() {
  1313  					mode.Fprintf(s, "&%v literal", n.Right.Type.Elem())
  1314  					return
  1315  				}
  1316  				mode.Fprintf(s, "%v literal", n.Right.Type)
  1317  				return
  1318  			}
  1319  
  1320  			fmt.Fprint(s, "composite literal")
  1321  			return
  1322  		}
  1323  		mode.Fprintf(s, "(%v{ %.v })", n.Right, n.List)
  1324  
  1325  	case OPTRLIT:
  1326  		mode.Fprintf(s, "&%v", n.Left)
  1327  
  1328  	case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
  1329  		if mode == FErr {
  1330  			mode.Fprintf(s, "%v literal", n.Type)
  1331  			return
  1332  		}
  1333  		mode.Fprintf(s, "(%v{ %.v })", n.Type, n.List)
  1334  
  1335  	case OKEY:
  1336  		if n.Left != nil && n.Right != nil {
  1337  			mode.Fprintf(s, "%v:%v", n.Left, n.Right)
  1338  			return
  1339  		}
  1340  
  1341  		if n.Left == nil && n.Right != nil {
  1342  			mode.Fprintf(s, ":%v", n.Right)
  1343  			return
  1344  		}
  1345  		if n.Left != nil && n.Right == nil {
  1346  			mode.Fprintf(s, "%v:", n.Left)
  1347  			return
  1348  		}
  1349  		fmt.Fprint(s, ":")
  1350  
  1351  	case OSTRUCTKEY:
  1352  		mode.Fprintf(s, "%v:%v", n.Sym, n.Left)
  1353  
  1354  	case OCALLPART:
  1355  		n.Left.exprfmt(s, nprec, mode)
  1356  		if n.Right == nil || n.Right.Sym == nil {
  1357  			fmt.Fprint(s, ".<nil>")
  1358  			return
  1359  		}
  1360  		mode.Fprintf(s, ".%0S", n.Right.Sym)
  1361  
  1362  	case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
  1363  		n.Left.exprfmt(s, nprec, mode)
  1364  		if n.Sym == nil {
  1365  			fmt.Fprint(s, ".<nil>")
  1366  			return
  1367  		}
  1368  		mode.Fprintf(s, ".%0S", n.Sym)
  1369  
  1370  	case ODOTTYPE, ODOTTYPE2:
  1371  		n.Left.exprfmt(s, nprec, mode)
  1372  		if n.Right != nil {
  1373  			mode.Fprintf(s, ".(%v)", n.Right)
  1374  			return
  1375  		}
  1376  		mode.Fprintf(s, ".(%v)", n.Type)
  1377  
  1378  	case OINDEX, OINDEXMAP:
  1379  		n.Left.exprfmt(s, nprec, mode)
  1380  		mode.Fprintf(s, "[%v]", n.Right)
  1381  
  1382  	case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
  1383  		n.Left.exprfmt(s, nprec, mode)
  1384  		fmt.Fprint(s, "[")
  1385  		low, high, max := n.SliceBounds()
  1386  		if low != nil {
  1387  			fmt.Fprint(s, low.modeString(mode))
  1388  		}
  1389  		fmt.Fprint(s, ":")
  1390  		if high != nil {
  1391  			fmt.Fprint(s, high.modeString(mode))
  1392  		}
  1393  		if n.Op.IsSlice3() {
  1394  			fmt.Fprint(s, ":")
  1395  			if max != nil {
  1396  				fmt.Fprint(s, max.modeString(mode))
  1397  			}
  1398  		}
  1399  		fmt.Fprint(s, "]")
  1400  
  1401  	case OSLICEHEADER:
  1402  		if n.List.Len() != 2 {
  1403  			Fatalf("bad OSLICEHEADER list length %d", n.List.Len())
  1404  		}
  1405  		mode.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left, n.List.First(), n.List.Second())
  1406  
  1407  	case OCOPY:
  1408  		mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
  1409  
  1410  	case OCOMPLEX:
  1411  		if n.List.Len() == 1 {
  1412  			mode.Fprintf(s, "%#v(%v)", n.Op, n.List.First())
  1413  		} else {
  1414  			mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
  1415  		}
  1416  
  1417  	case OCONV,
  1418  		OCONVIFACE,
  1419  		OCONVNOP,
  1420  		OBYTES2STR,
  1421  		ORUNES2STR,
  1422  		OSTR2BYTES,
  1423  		OSTR2RUNES,
  1424  		ORUNESTR:
  1425  		if n.Type == nil || n.Type.Sym == nil {
  1426  			mode.Fprintf(s, "(%v)", n.Type)
  1427  		} else {
  1428  			mode.Fprintf(s, "%v", n.Type)
  1429  		}
  1430  		if n.Left != nil {
  1431  			mode.Fprintf(s, "(%v)", n.Left)
  1432  		} else {
  1433  			mode.Fprintf(s, "(%.v)", n.List)
  1434  		}
  1435  
  1436  	case OREAL,
  1437  		OIMAG,
  1438  		OAPPEND,
  1439  		OCAP,
  1440  		OCLOSE,
  1441  		ODELETE,
  1442  		OLEN,
  1443  		OMAKE,
  1444  		ONEW,
  1445  		OPANIC,
  1446  		ORECOVER,
  1447  		OALIGNOF,
  1448  		OOFFSETOF,
  1449  		OSIZEOF,
  1450  		OPRINT,
  1451  		OPRINTN:
  1452  		if n.Left != nil {
  1453  			mode.Fprintf(s, "%#v(%v)", n.Op, n.Left)
  1454  			return
  1455  		}
  1456  		if n.IsDDD() {
  1457  			mode.Fprintf(s, "%#v(%.v...)", n.Op, n.List)
  1458  			return
  1459  		}
  1460  		mode.Fprintf(s, "%#v(%.v)", n.Op, n.List)
  1461  
  1462  	case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
  1463  		n.Left.exprfmt(s, nprec, mode)
  1464  		if n.IsDDD() {
  1465  			mode.Fprintf(s, "(%.v...)", n.List)
  1466  			return
  1467  		}
  1468  		mode.Fprintf(s, "(%.v)", n.List)
  1469  
  1470  	case OMAKEMAP, OMAKECHAN, OMAKESLICE:
  1471  		if n.List.Len() != 0 { // pre-typecheck
  1472  			mode.Fprintf(s, "make(%v, %.v)", n.Type, n.List)
  1473  			return
  1474  		}
  1475  		if n.Right != nil {
  1476  			mode.Fprintf(s, "make(%v, %v, %v)", n.Type, n.Left, n.Right)
  1477  			return
  1478  		}
  1479  		if n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()) {
  1480  			mode.Fprintf(s, "make(%v, %v)", n.Type, n.Left)
  1481  			return
  1482  		}
  1483  		mode.Fprintf(s, "make(%v)", n.Type)
  1484  
  1485  	case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
  1486  		// Unary
  1487  		mode.Fprintf(s, "%#v", n.Op)
  1488  		if n.Left != nil && n.Left.Op == n.Op {
  1489  			fmt.Fprint(s, " ")
  1490  		}
  1491  		n.Left.exprfmt(s, nprec+1, mode)
  1492  
  1493  		// Binary
  1494  	case OADD,
  1495  		OAND,
  1496  		OANDAND,
  1497  		OANDNOT,
  1498  		ODIV,
  1499  		OEQ,
  1500  		OGE,
  1501  		OGT,
  1502  		OLE,
  1503  		OLT,
  1504  		OLSH,
  1505  		OMOD,
  1506  		OMUL,
  1507  		ONE,
  1508  		OOR,
  1509  		OOROR,
  1510  		ORSH,
  1511  		OSEND,
  1512  		OSUB,
  1513  		OXOR:
  1514  		n.Left.exprfmt(s, nprec, mode)
  1515  		mode.Fprintf(s, " %#v ", n.Op)
  1516  		n.Right.exprfmt(s, nprec+1, mode)
  1517  
  1518  	case OADDSTR:
  1519  		for i, n1 := range n.List.Slice() {
  1520  			if i != 0 {
  1521  				fmt.Fprint(s, " + ")
  1522  			}
  1523  			n1.exprfmt(s, nprec, mode)
  1524  		}
  1525  
  1526  	default:
  1527  		mode.Fprintf(s, "<node %v>", n.Op)
  1528  	}
  1529  }
  1530  
  1531  func (n *Node) nodefmt(s fmt.State, flag FmtFlag, mode fmtMode) {
  1532  	t := n.Type
  1533  
  1534  	// We almost always want the original.
  1535  	// TODO(gri) Why the special case for OLITERAL?
  1536  	if n.Op != OLITERAL && n.Orig != nil {
  1537  		n = n.Orig
  1538  	}
  1539  
  1540  	if flag&FmtLong != 0 && t != nil {
  1541  		if t.Etype == TNIL {
  1542  			fmt.Fprint(s, "nil")
  1543  		} else {
  1544  			mode.Fprintf(s, "%v (type %v)", n, t)
  1545  		}
  1546  		return
  1547  	}
  1548  
  1549  	// TODO inlining produces expressions with ninits. we can't print these yet.
  1550  
  1551  	if opprec[n.Op] < 0 {
  1552  		n.stmtfmt(s, mode)
  1553  		return
  1554  	}
  1555  
  1556  	n.exprfmt(s, 0, mode)
  1557  }
  1558  
  1559  func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) {
  1560  	recur := flag&FmtShort == 0
  1561  
  1562  	if recur {
  1563  		indent(s)
  1564  		if dumpdepth > 40 {
  1565  			fmt.Fprint(s, "...")
  1566  			return
  1567  		}
  1568  
  1569  		if n.Ninit.Len() != 0 {
  1570  			mode.Fprintf(s, "%v-init%v", n.Op, n.Ninit)
  1571  			indent(s)
  1572  		}
  1573  	}
  1574  
  1575  	switch n.Op {
  1576  	default:
  1577  		mode.Fprintf(s, "%v%j", n.Op, n)
  1578  
  1579  	case OINDREGSP:
  1580  		mode.Fprintf(s, "%v-SP%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  }