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