Home | History | Annotate | Download | only in gc
      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 }
   1870