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