github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/cmd/compile/internal/gc/fmt.go (about)

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