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