2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2011 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import (
|
2015-03-12 18:45:30 -04:00
|
|
|
"bytes"
|
2015-02-13 14:40:36 -05:00
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"fmt"
|
2015-03-12 18:45:30 -04:00
|
|
|
"strconv"
|
2015-02-13 14:40:36 -05:00
|
|
|
"strings"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
// A FmtFlag value is a set of flags (or 0).
|
|
|
|
|
// They control how the Xconv functions format their values.
|
|
|
|
|
// See the respective function's documentation for details.
|
|
|
|
|
type FmtFlag int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
FmtWidth FmtFlag = 1 << iota
|
|
|
|
|
FmtLeft // "-"
|
|
|
|
|
FmtSharp // "#"
|
|
|
|
|
FmtSign // "+"
|
|
|
|
|
FmtUnsigned // "u"
|
|
|
|
|
FmtShort // "h"
|
|
|
|
|
FmtLong // "l"
|
|
|
|
|
FmtComma // ","
|
|
|
|
|
FmtByte // "hh"
|
|
|
|
|
FmtBody // for printing export bodies
|
|
|
|
|
)
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
//
|
|
|
|
|
// Format conversions
|
|
|
|
|
// %L int Line numbers
|
|
|
|
|
//
|
|
|
|
|
// %E int etype values (aka 'Kind')
|
|
|
|
|
//
|
|
|
|
|
// %O int Node Opcodes
|
|
|
|
|
// Flags: "%#O": print go syntax. (automatic unless fmtmode == FDbg)
|
|
|
|
|
//
|
|
|
|
|
// %J Node* Node details
|
|
|
|
|
// Flags: "%hJ" suppresses things not relevant until walk.
|
|
|
|
|
//
|
|
|
|
|
// %V Val* Constant values
|
|
|
|
|
//
|
|
|
|
|
// %S Sym* Symbols
|
|
|
|
|
// Flags: +,- #: mode (see below)
|
|
|
|
|
// "%hS" unqualified identifier in any mode
|
|
|
|
|
// "%hhS" in export mode: unqualified identifier if exported, qualified if not
|
|
|
|
|
//
|
|
|
|
|
// %T Type* Types
|
|
|
|
|
// Flags: +,- #: mode (see below)
|
|
|
|
|
// 'l' definition instead of name.
|
|
|
|
|
// 'h' omit "func" and receiver in function types
|
|
|
|
|
// 'u' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
|
|
|
|
|
//
|
|
|
|
|
// %N Node* Nodes
|
|
|
|
|
// Flags: +,- #: mode (see below)
|
|
|
|
|
// 'h' (only in +/debug mode) suppress recursion
|
|
|
|
|
// 'l' (only in Error mode) print "foo (type Bar)"
|
|
|
|
|
//
|
2016-03-10 10:00:29 -08:00
|
|
|
// %H Nodes Nodes
|
2015-02-13 14:40:36 -05:00
|
|
|
// Flags: those of %N
|
|
|
|
|
// ',' separate items with ',' instead of ';'
|
|
|
|
|
//
|
2015-10-22 09:51:12 +09:00
|
|
|
// In mparith2.go and mparith3.go:
|
|
|
|
|
// %B Mpint* Big integers
|
|
|
|
|
// %F Mpflt* Big floats
|
2015-02-13 14:40:36 -05:00
|
|
|
//
|
|
|
|
|
// %S, %T and %N obey use the following flags to set the format mode:
|
|
|
|
|
const (
|
|
|
|
|
FErr = iota
|
|
|
|
|
FDbg
|
|
|
|
|
FExp
|
|
|
|
|
FTypeId
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var fmtmode int = FErr
|
|
|
|
|
|
|
|
|
|
var fmtpkgpfx int // %uT stickyness
|
|
|
|
|
|
2015-12-30 19:47:36 -05:00
|
|
|
var fmtbody bool
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
//
|
|
|
|
|
// E.g. for %S: %+S %#S %-S print an identifier properly qualified for debug/export/internal mode.
|
|
|
|
|
//
|
|
|
|
|
// The mode flags +, - and # are sticky, meaning they persist through
|
2016-03-01 23:21:55 +00:00
|
|
|
// recursions of %N, %T and %S, but not the h and l flags. The u flag is
|
2015-02-13 14:40:36 -05:00
|
|
|
// sticky only on %T recursions and only used in %-/Sym mode.
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Useful format combinations:
|
|
|
|
|
//
|
|
|
|
|
// %+N %+H multiline recursive debug dump of node/nodelist
|
|
|
|
|
// %+hN %+hH non recursive debug dump
|
|
|
|
|
//
|
|
|
|
|
// %#N %#T export format
|
|
|
|
|
// %#lT type definition instead of name
|
|
|
|
|
// %#hT omit"func" and receiver in function signature
|
|
|
|
|
//
|
|
|
|
|
// %lN "foo (type Bar)" for error messages
|
|
|
|
|
//
|
|
|
|
|
// %-T type identifiers
|
|
|
|
|
// %-hT type identifiers without "func" and arg names in type signatures (methodsym)
|
|
|
|
|
// %-uT type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
|
|
|
|
|
//
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
func setfmode(flags *FmtFlag) (fm int, fb bool) {
|
2015-12-30 19:47:36 -05:00
|
|
|
fm = fmtmode
|
|
|
|
|
fb = fmtbody
|
2016-03-15 13:06:58 -07:00
|
|
|
if *flags&FmtSign != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtmode = FDbg
|
2016-03-15 13:06:58 -07:00
|
|
|
} else if *flags&FmtSharp != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtmode = FExp
|
2016-03-15 13:06:58 -07:00
|
|
|
} else if *flags&FmtLeft != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtmode = FTypeId
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if *flags&FmtBody != 0 {
|
2015-12-30 19:47:36 -05:00
|
|
|
fmtbody = true
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
*flags &^= (FmtSharp | FmtLeft | FmtSign | FmtBody)
|
2015-12-30 19:47:36 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%L": Linenumbers
|
|
|
|
|
|
|
|
|
|
var goopnames = []string{
|
|
|
|
|
OADDR: "&",
|
|
|
|
|
OADD: "+",
|
|
|
|
|
OADDSTR: "+",
|
|
|
|
|
OANDAND: "&&",
|
|
|
|
|
OANDNOT: "&^",
|
|
|
|
|
OAND: "&",
|
|
|
|
|
OAPPEND: "append",
|
|
|
|
|
OAS: "=",
|
|
|
|
|
OAS2: "=",
|
|
|
|
|
OBREAK: "break",
|
|
|
|
|
OCALL: "function call", // not actual syntax
|
|
|
|
|
OCAP: "cap",
|
|
|
|
|
OCASE: "case",
|
|
|
|
|
OCLOSE: "close",
|
|
|
|
|
OCOMPLEX: "complex",
|
|
|
|
|
OCOM: "^",
|
|
|
|
|
OCONTINUE: "continue",
|
|
|
|
|
OCOPY: "copy",
|
|
|
|
|
ODEC: "--",
|
|
|
|
|
ODELETE: "delete",
|
|
|
|
|
ODEFER: "defer",
|
|
|
|
|
ODIV: "/",
|
|
|
|
|
OEQ: "==",
|
|
|
|
|
OFALL: "fallthrough",
|
|
|
|
|
OFOR: "for",
|
|
|
|
|
OGE: ">=",
|
|
|
|
|
OGOTO: "goto",
|
|
|
|
|
OGT: ">",
|
|
|
|
|
OIF: "if",
|
|
|
|
|
OIMAG: "imag",
|
|
|
|
|
OINC: "++",
|
|
|
|
|
OIND: "*",
|
|
|
|
|
OLEN: "len",
|
|
|
|
|
OLE: "<=",
|
|
|
|
|
OLSH: "<<",
|
|
|
|
|
OLT: "<",
|
|
|
|
|
OMAKE: "make",
|
|
|
|
|
OMINUS: "-",
|
|
|
|
|
OMOD: "%",
|
|
|
|
|
OMUL: "*",
|
|
|
|
|
ONEW: "new",
|
|
|
|
|
ONE: "!=",
|
|
|
|
|
ONOT: "!",
|
|
|
|
|
OOROR: "||",
|
|
|
|
|
OOR: "|",
|
|
|
|
|
OPANIC: "panic",
|
|
|
|
|
OPLUS: "+",
|
|
|
|
|
OPRINTN: "println",
|
|
|
|
|
OPRINT: "print",
|
|
|
|
|
ORANGE: "range",
|
|
|
|
|
OREAL: "real",
|
|
|
|
|
ORECV: "<-",
|
|
|
|
|
ORECOVER: "recover",
|
|
|
|
|
ORETURN: "return",
|
|
|
|
|
ORSH: ">>",
|
|
|
|
|
OSELECT: "select",
|
|
|
|
|
OSEND: "<-",
|
|
|
|
|
OSUB: "-",
|
|
|
|
|
OSWITCH: "switch",
|
|
|
|
|
OXOR: "^",
|
2016-04-01 23:28:14 -05:00
|
|
|
OXFALL: "fallthrough",
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%O": Node opcodes
|
2016-03-15 13:06:58 -07:00
|
|
|
func Oconv(o Op, flag FmtFlag) string {
|
|
|
|
|
if (flag&FmtSharp != 0) || fmtmode != FDbg {
|
2016-03-07 08:23:55 -08:00
|
|
|
if o >= 0 && int(o) < len(goopnames) && goopnames[o] != "" {
|
2015-02-27 22:44:15 +00:00
|
|
|
return goopnames[o]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 08:23:55 -08:00
|
|
|
if o >= 0 && int(o) < len(opnames) && opnames[o] != "" {
|
2015-02-27 22:44:15 +00:00
|
|
|
return opnames[o]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:44:15 +00:00
|
|
|
return fmt.Sprintf("O-%d", o)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var classnames = []string{
|
|
|
|
|
"Pxxx",
|
|
|
|
|
"PEXTERN",
|
|
|
|
|
"PAUTO",
|
|
|
|
|
"PPARAM",
|
|
|
|
|
"PPARAMOUT",
|
|
|
|
|
"PPARAMREF",
|
|
|
|
|
"PFUNC",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%J": Node details.
|
2016-03-15 13:06:58 -07:00
|
|
|
func Jconv(n *Node, flag FmtFlag) string {
|
2015-03-12 18:45:30 -04:00
|
|
|
var buf bytes.Buffer
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
c := flag & FmtShort
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Ullman != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " u(%d)", n.Ullman)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-02 19:58:37 -07:00
|
|
|
if c == 0 && n.Addable {
|
2015-04-17 01:50:16 -04:00
|
|
|
fmt.Fprintf(&buf, " a(%v)", n.Addable)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-26 23:56:14 -04:00
|
|
|
if c == 0 && n.Name != nil && n.Name.Vargen != 0 {
|
|
|
|
|
fmt.Fprintf(&buf, " g(%d)", n.Name.Vargen)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Lineno != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " l(%d)", n.Lineno)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Xoffset != BADWIDTH {
|
2015-05-26 21:30:20 -04:00
|
|
|
fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, stkdelta[n])
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Class != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
s := ""
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Class&PHEAP != 0 {
|
|
|
|
|
s = ",heap"
|
|
|
|
|
}
|
|
|
|
|
if int(n.Class&^PHEAP) < len(classnames) {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " class(%s%s)", classnames[n.Class&^PHEAP], s)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " class(%d?%s)", n.Class&^PHEAP, s)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 19:58:37 -07:00
|
|
|
if n.Colas {
|
2015-04-17 01:50:16 -04:00
|
|
|
fmt.Fprintf(&buf, " colas(%v)", n.Colas)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-27 00:44:05 -04:00
|
|
|
if n.Name != nil && n.Name.Funcdepth != 0 {
|
|
|
|
|
fmt.Fprintf(&buf, " f(%d)", n.Name.Funcdepth)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-06-03 14:16:01 -04:00
|
|
|
if n.Func != nil && n.Func.Depth != 0 {
|
|
|
|
|
fmt.Fprintf(&buf, " ff(%d)", n.Func.Depth)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
switch n.Esc {
|
|
|
|
|
case EscUnknown:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case EscHeap:
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" esc(h)")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case EscScope:
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" esc(s)")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case EscNone:
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" esc(no)")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case EscNever:
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" esc(N)")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " esc(%d)", n.Esc)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
if e, ok := n.Opt().(*NodeEscState); ok && e.Escloopdepth != 0 {
|
2015-05-26 23:42:41 -04:00
|
|
|
fmt.Fprintf(&buf, " ld(%d)", e.Escloopdepth)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Typecheck != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " tc(%d)", n.Typecheck)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Dodata != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " dd(%d)", n.Dodata)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-09 16:24:07 +11:00
|
|
|
if n.Isddd {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " isddd(%v)", n.Isddd)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-06 21:18:41 +11:00
|
|
|
if n.Implicit {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " implicit(%v)", n.Implicit)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Embedded != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " embedded(%d)", n.Embedded)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-05 18:20:54 +11:00
|
|
|
if n.Addrtaken {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" addrtaken")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-06 18:42:58 +11:00
|
|
|
if n.Assigned {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" assigned")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-19 21:06:53 -07:00
|
|
|
if n.Bounded {
|
|
|
|
|
buf.WriteString(" bounded")
|
|
|
|
|
}
|
|
|
|
|
if n.NonNil {
|
|
|
|
|
buf.WriteString(" nonnil")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-06 21:18:41 +11:00
|
|
|
if c == 0 && n.Used {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmt.Fprintf(&buf, " used(%v)", n.Used)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%V": Values
|
2016-03-15 13:06:58 -07:00
|
|
|
func Vconv(v Val, flag FmtFlag) string {
|
2016-04-22 12:27:29 -07:00
|
|
|
switch u := v.U.(type) {
|
|
|
|
|
case *Mpint:
|
|
|
|
|
if !u.Rune {
|
|
|
|
|
if (flag&FmtSharp != 0) || fmtmode == FExp {
|
|
|
|
|
return Bconv(u, FmtSharp)
|
|
|
|
|
}
|
|
|
|
|
return Bconv(u, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-22 12:27:29 -07:00
|
|
|
x := u.Int64()
|
2016-04-10 08:48:55 +02:00
|
|
|
if ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'' {
|
2015-02-27 22:44:15 +00:00
|
|
|
return fmt.Sprintf("'%c'", int(x))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if 0 <= x && x < 1<<16 {
|
2015-02-27 22:44:15 +00:00
|
|
|
return fmt.Sprintf("'\\u%04x'", uint(int(x)))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if 0 <= x && x <= utf8.MaxRune {
|
2015-02-27 22:44:15 +00:00
|
|
|
return fmt.Sprintf("'\\U%08x'", uint64(x))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-22 12:27:29 -07:00
|
|
|
return fmt.Sprintf("('\\x00' + %v)", u)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-04-22 12:27:29 -07:00
|
|
|
case *Mpflt:
|
2016-03-15 13:06:58 -07:00
|
|
|
if (flag&FmtSharp != 0) || fmtmode == FExp {
|
2016-04-22 12:27:29 -07:00
|
|
|
return Fconv(u, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-22 12:27:29 -07:00
|
|
|
return Fconv(u, FmtSharp)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-04-22 12:27:29 -07:00
|
|
|
case *Mpcplx:
|
2016-03-15 13:06:58 -07:00
|
|
|
if (flag&FmtSharp != 0) || fmtmode == FExp {
|
2016-04-22 12:27:29 -07:00
|
|
|
return fmt.Sprintf("(%v+%vi)", &u.Real, &u.Imag)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-20 13:55:42 -07:00
|
|
|
if v.U.(*Mpcplx).Real.CmpFloat64(0) == 0 {
|
2016-04-22 12:27:29 -07:00
|
|
|
return fmt.Sprintf("%vi", Fconv(&u.Imag, FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-20 13:55:42 -07:00
|
|
|
if v.U.(*Mpcplx).Imag.CmpFloat64(0) == 0 {
|
2016-04-22 12:27:29 -07:00
|
|
|
return Fconv(&u.Real, FmtSharp)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-20 13:55:42 -07:00
|
|
|
if v.U.(*Mpcplx).Imag.CmpFloat64(0) < 0 {
|
2016-04-22 12:27:29 -07:00
|
|
|
return fmt.Sprintf("(%v%vi)", Fconv(&u.Real, FmtSharp), Fconv(&u.Imag, FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-22 12:27:29 -07:00
|
|
|
return fmt.Sprintf("(%v+%vi)", Fconv(&u.Real, FmtSharp), Fconv(&u.Imag, FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-04-22 12:27:29 -07:00
|
|
|
case string:
|
|
|
|
|
return strconv.Quote(u)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-04-22 12:27:29 -07:00
|
|
|
case bool:
|
|
|
|
|
if u {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "true"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return "false"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-04-22 12:27:29 -07:00
|
|
|
case *NilVal:
|
2015-03-12 18:45:30 -04:00
|
|
|
return "nil"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-08-28 15:38:20 -07:00
|
|
|
return fmt.Sprintf("<ctype=%d>", v.Ctype())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
s%,%,\n%g
|
|
|
|
|
s%\n+%\n%g
|
|
|
|
|
s%^[ ]*T%%g
|
|
|
|
|
s%,.*%%g
|
|
|
|
|
s%.+% [T&] = "&",%g
|
|
|
|
|
s%^ ........*\]%&~%g
|
|
|
|
|
s%~ %%g
|
|
|
|
|
*/
|
|
|
|
|
var etnames = []string{
|
2016-03-27 15:31:50 -07:00
|
|
|
Txxx: "Txxx",
|
2015-02-13 14:40:36 -05:00
|
|
|
TINT: "INT",
|
|
|
|
|
TUINT: "UINT",
|
|
|
|
|
TINT8: "INT8",
|
|
|
|
|
TUINT8: "UINT8",
|
|
|
|
|
TINT16: "INT16",
|
|
|
|
|
TUINT16: "UINT16",
|
|
|
|
|
TINT32: "INT32",
|
|
|
|
|
TUINT32: "UINT32",
|
|
|
|
|
TINT64: "INT64",
|
|
|
|
|
TUINT64: "UINT64",
|
|
|
|
|
TUINTPTR: "UINTPTR",
|
|
|
|
|
TFLOAT32: "FLOAT32",
|
|
|
|
|
TFLOAT64: "FLOAT64",
|
|
|
|
|
TCOMPLEX64: "COMPLEX64",
|
|
|
|
|
TCOMPLEX128: "COMPLEX128",
|
|
|
|
|
TBOOL: "BOOL",
|
|
|
|
|
TPTR32: "PTR32",
|
|
|
|
|
TPTR64: "PTR64",
|
|
|
|
|
TFUNC: "FUNC",
|
|
|
|
|
TARRAY: "ARRAY",
|
2016-04-18 14:02:08 -07:00
|
|
|
TSLICE: "SLICE",
|
2015-02-13 14:40:36 -05:00
|
|
|
TSTRUCT: "STRUCT",
|
|
|
|
|
TCHAN: "CHAN",
|
|
|
|
|
TMAP: "MAP",
|
|
|
|
|
TINTER: "INTER",
|
|
|
|
|
TFORW: "FORW",
|
|
|
|
|
TSTRING: "STRING",
|
2015-07-22 19:18:35 -07:00
|
|
|
TUNSAFEPTR: "TUNSAFEPTR",
|
2015-02-13 14:40:36 -05:00
|
|
|
TANY: "ANY",
|
2016-03-27 15:31:50 -07:00
|
|
|
TIDEAL: "TIDEAL",
|
|
|
|
|
TNIL: "TNIL",
|
|
|
|
|
TBLANK: "TBLANK",
|
|
|
|
|
TFUNCARGS: "TFUNCARGS",
|
|
|
|
|
TCHANARGS: "TCHANARGS",
|
|
|
|
|
TINTERMETH: "TINTERMETH",
|
|
|
|
|
TDDDFIELD: "TDDDFIELD",
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%E": etype
|
2015-09-24 23:21:18 +02:00
|
|
|
func Econv(et EType) string {
|
|
|
|
|
if int(et) < len(etnames) && etnames[et] != "" {
|
2015-02-27 22:44:15 +00:00
|
|
|
return etnames[et]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-27 22:44:15 +00:00
|
|
|
return fmt.Sprintf("E-%d", et)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-27 15:31:50 -07:00
|
|
|
func (e EType) String() string {
|
|
|
|
|
return Econv(e)
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-22 07:14:10 -07:00
|
|
|
func (o Op) String() string {
|
|
|
|
|
return Oconv(o, 0)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Fmt "%S": syms
|
2016-03-15 13:06:58 -07:00
|
|
|
func symfmt(s *Sym, flag FmtFlag) string {
|
|
|
|
|
if s.Pkg != nil && flag&FmtShort == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch fmtmode {
|
|
|
|
|
case FErr: // This is for the user
|
2016-01-19 14:17:29 -08:00
|
|
|
if s.Pkg == builtinpkg || s.Pkg == localpkg {
|
2015-02-27 22:44:15 +00:00
|
|
|
return s.Name
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the name was used by multiple packages, display the full path,
|
2015-03-02 16:21:15 -05:00
|
|
|
if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 {
|
2015-03-02 16:03:26 -05:00
|
|
|
return fmt.Sprintf("%q.%s", s.Pkg.Path, s.Name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-19 16:34:48 -07:00
|
|
|
return s.Pkg.Name + "." + s.Name
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case FDbg:
|
2016-03-19 16:34:48 -07:00
|
|
|
return s.Pkg.Name + "." + s.Name
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case FTypeId:
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtUnsigned != 0 {
|
2016-03-19 16:34:48 -07:00
|
|
|
return s.Pkg.Name + "." + s.Name // dcommontype, typehash
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-19 16:34:48 -07:00
|
|
|
return s.Pkg.Prefix + "." + s.Name // (methodsym), typesym, weaksym
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case FExp:
|
|
|
|
|
if s.Name != "" && s.Name[0] == '.' {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("exporting synthetic symbol %s", s.Name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if s.Pkg != builtinpkg {
|
2015-03-02 16:03:26 -05:00
|
|
|
return fmt.Sprintf("@%q.%s", s.Pkg.Path, s.Name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtByte != 0 {
|
2015-02-27 22:44:15 +00:00
|
|
|
// FmtByte (hh) implies FmtShort (h)
|
2015-02-13 14:40:36 -05:00
|
|
|
// skip leading "type." in method name
|
2015-02-23 16:07:24 -05:00
|
|
|
p := s.Name
|
2015-02-13 14:40:36 -05:00
|
|
|
if i := strings.LastIndex(s.Name, "."); i >= 0 {
|
|
|
|
|
p = s.Name[i+1:]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// exportname needs to see the name without the prefix too.
|
|
|
|
|
if (fmtmode == FExp && !exportname(p)) || fmtmode == FDbg {
|
2015-03-02 16:03:26 -05:00
|
|
|
return fmt.Sprintf("@%q.%s", s.Pkg.Path, p)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:44:15 +00:00
|
|
|
return p
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:44:15 +00:00
|
|
|
return s.Name
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var basicnames = []string{
|
|
|
|
|
TINT: "int",
|
|
|
|
|
TUINT: "uint",
|
|
|
|
|
TINT8: "int8",
|
|
|
|
|
TUINT8: "uint8",
|
|
|
|
|
TINT16: "int16",
|
|
|
|
|
TUINT16: "uint16",
|
|
|
|
|
TINT32: "int32",
|
|
|
|
|
TUINT32: "uint32",
|
|
|
|
|
TINT64: "int64",
|
|
|
|
|
TUINT64: "uint64",
|
|
|
|
|
TUINTPTR: "uintptr",
|
|
|
|
|
TFLOAT32: "float32",
|
|
|
|
|
TFLOAT64: "float64",
|
|
|
|
|
TCOMPLEX64: "complex64",
|
|
|
|
|
TCOMPLEX128: "complex128",
|
|
|
|
|
TBOOL: "bool",
|
|
|
|
|
TANY: "any",
|
|
|
|
|
TSTRING: "string",
|
|
|
|
|
TNIL: "nil",
|
|
|
|
|
TIDEAL: "untyped number",
|
|
|
|
|
TBLANK: "blank",
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
func typefmt(t *Type, flag FmtFlag) string {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t == nil {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<T>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t == bytetype || t == runetype {
|
|
|
|
|
// in %-T mode collapse rune and byte with their originals.
|
|
|
|
|
if fmtmode != FTypeId {
|
2016-03-15 13:06:58 -07:00
|
|
|
return Sconv(t.Sym, FmtShort)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
t = Types[t.Etype]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t == errortype {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "error"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unless the 'l' flag was specified, if the type has a name, just print that name.
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtLong == 0 && t.Sym != nil && t != Types[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch fmtmode {
|
|
|
|
|
case FTypeId:
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtShort != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t.Vargen != 0 {
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v·%d", Sconv(t.Sym, FmtShort), t.Vargen)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-15 13:06:58 -07:00
|
|
|
return Sconv(t.Sym, FmtShort)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtUnsigned != 0 {
|
|
|
|
|
return Sconv(t.Sym, FmtUnsigned)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case FExp:
|
|
|
|
|
if t.Sym.Pkg == localpkg && t.Vargen != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v·%d", t.Sym, t.Vargen)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-12 18:45:30 -04:00
|
|
|
return Sconv(t.Sym, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
|
2015-03-12 18:45:30 -04:00
|
|
|
prefix := ""
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FErr && (t == idealbool || t == idealstring) {
|
2015-03-12 18:45:30 -04:00
|
|
|
prefix = "untyped "
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return prefix + basicnames[t.Etype]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if fmtmode == FDbg {
|
2015-03-12 18:45:30 -04:00
|
|
|
fmtmode = 0
|
2016-04-22 08:39:56 -07:00
|
|
|
str := t.Etype.String() + "-" + typefmt(t, flag)
|
2015-03-12 18:45:30 -04:00
|
|
|
fmtmode = FDbg
|
|
|
|
|
return str
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch t.Etype {
|
2015-04-01 09:38:44 -07:00
|
|
|
case TPTR32, TPTR64:
|
2016-03-15 13:06:58 -07:00
|
|
|
if fmtmode == FTypeId && (flag&FmtShort != 0) {
|
2016-03-30 10:57:47 -07:00
|
|
|
return "*" + Tconv(t.Elem(), FmtShort)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-30 10:57:47 -07:00
|
|
|
return "*" + t.Elem().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TARRAY:
|
2016-03-27 17:57:42 -07:00
|
|
|
if t.isDDDArray() {
|
2016-03-30 10:57:47 -07:00
|
|
|
return "[...]" + t.Elem().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-18 14:02:08 -07:00
|
|
|
return fmt.Sprintf("[%d]%v", t.NumElem(), t.Elem())
|
|
|
|
|
|
|
|
|
|
case TSLICE:
|
2016-03-30 10:57:47 -07:00
|
|
|
return "[]" + t.Elem().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TCHAN:
|
2016-04-02 16:26:30 -07:00
|
|
|
switch t.ChanDir() {
|
2015-02-13 14:40:36 -05:00
|
|
|
case Crecv:
|
2016-03-30 10:57:47 -07:00
|
|
|
return "<-chan " + t.Elem().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case Csend:
|
2016-03-30 10:57:47 -07:00
|
|
|
return "chan<- " + t.Elem().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-02 16:26:30 -07:00
|
|
|
if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == Crecv {
|
2016-03-30 10:57:47 -07:00
|
|
|
return "chan (" + t.Elem().String() + ")"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-30 10:57:47 -07:00
|
|
|
return "chan " + t.Elem().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TMAP:
|
2016-03-28 21:48:47 -07:00
|
|
|
return "map[" + t.Key().String() + "]" + t.Val().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TINTER:
|
2015-03-12 18:45:30 -04:00
|
|
|
var buf bytes.Buffer
|
|
|
|
|
buf.WriteString("interface {")
|
2016-03-17 00:44:07 -07:00
|
|
|
for i, f := range t.Fields().Slice() {
|
|
|
|
|
if i != 0 {
|
|
|
|
|
buf.WriteString(";")
|
|
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" ")
|
2015-08-29 11:30:10 +00:00
|
|
|
switch {
|
2016-03-17 00:44:07 -07:00
|
|
|
case f.Sym == nil:
|
2015-08-29 11:30:10 +00:00
|
|
|
// Check first that a symbol is defined for this type.
|
|
|
|
|
// Wrong interface definitions may have types lacking a symbol.
|
|
|
|
|
break
|
2016-03-17 00:44:07 -07:00
|
|
|
case exportname(f.Sym.Name):
|
|
|
|
|
buf.WriteString(Sconv(f.Sym, FmtShort))
|
2015-08-29 11:30:10 +00:00
|
|
|
default:
|
2016-03-17 00:44:07 -07:00
|
|
|
buf.WriteString(Sconv(f.Sym, FmtUnsigned))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-17 00:44:07 -07:00
|
|
|
buf.WriteString(Tconv(f.Type, FmtShort))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-17 00:44:07 -07:00
|
|
|
if t.NumFields() != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" ")
|
|
|
|
|
}
|
|
|
|
|
buf.WriteString("}")
|
|
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TFUNC:
|
2015-03-12 18:45:30 -04:00
|
|
|
var buf bytes.Buffer
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtShort != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
// no leading func
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-17 01:47:16 -07:00
|
|
|
if t.Recv() != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString("method")
|
2016-03-09 20:54:59 -08:00
|
|
|
buf.WriteString(Tconv(t.Recvs(), 0))
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" ")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString("func")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-08 16:31:28 -08:00
|
|
|
buf.WriteString(Tconv(t.Params(), 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-17 01:47:16 -07:00
|
|
|
switch t.Results().NumFields() {
|
2015-02-13 14:40:36 -05:00
|
|
|
case 0:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
if fmtmode != FExp {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" ")
|
2016-03-13 23:02:38 -07:00
|
|
|
buf.WriteString(Tconv(t.Results().Field(0).Type, 0)) // struct->field->field's type
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
default:
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" ")
|
2016-03-08 16:31:28 -08:00
|
|
|
buf.WriteString(Tconv(t.Results(), 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TSTRUCT:
|
2016-04-01 20:11:30 -07:00
|
|
|
if m := t.StructType().Map; m != nil {
|
|
|
|
|
mt := m.MapType()
|
2015-03-12 18:45:30 -04:00
|
|
|
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
|
|
|
|
// This avoids a recursive print that generates very long names.
|
2016-04-01 20:11:30 -07:00
|
|
|
if mt.Bucket == t {
|
|
|
|
|
return "map.bucket[" + m.Key().String() + "]" + m.Val().String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-01 20:11:30 -07:00
|
|
|
if mt.Hmap == t {
|
|
|
|
|
return "map.hdr[" + m.Key().String() + "]" + m.Val().String()
|
2016-02-23 07:46:01 +00:00
|
|
|
}
|
|
|
|
|
|
2016-04-01 20:11:30 -07:00
|
|
|
if mt.Hiter == t {
|
|
|
|
|
return "map.iter[" + m.Key().String() + "]" + m.Val().String()
|
2016-02-23 07:46:01 +00:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("unknown internal map type")
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-12 18:45:30 -04:00
|
|
|
var buf bytes.Buffer
|
2016-04-05 16:44:07 -07:00
|
|
|
if t.IsFuncArgStruct() {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString("(")
|
2016-03-17 00:44:07 -07:00
|
|
|
var flag1 FmtFlag
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
|
2016-03-17 00:44:07 -07:00
|
|
|
flag1 = FmtShort
|
|
|
|
|
}
|
|
|
|
|
for i, f := range t.Fields().Slice() {
|
|
|
|
|
if i != 0 {
|
|
|
|
|
buf.WriteString(", ")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-17 00:44:07 -07:00
|
|
|
buf.WriteString(Fldconv(f, flag1))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(")")
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString("struct {")
|
2016-03-17 00:44:07 -07:00
|
|
|
for i, f := range t.Fields().Slice() {
|
|
|
|
|
if i != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(";")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-17 00:44:07 -07:00
|
|
|
buf.WriteString(" ")
|
|
|
|
|
buf.WriteString(Fldconv(f, FmtLong))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-17 00:44:07 -07:00
|
|
|
if t.NumFields() != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(" ")
|
|
|
|
|
}
|
|
|
|
|
buf.WriteString("}")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TFORW:
|
|
|
|
|
if t.Sym != nil {
|
2016-03-19 16:34:48 -07:00
|
|
|
return "undefined " + t.Sym.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return "undefined"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TUNSAFEPTR:
|
|
|
|
|
if fmtmode == FExp {
|
2015-03-12 18:45:30 -04:00
|
|
|
return "@\"unsafe\".Pointer"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return "unsafe.Pointer"
|
2016-03-31 14:46:04 -07:00
|
|
|
|
|
|
|
|
case TDDDFIELD:
|
|
|
|
|
if fmtmode == FExp {
|
|
|
|
|
Fatalf("cannot use TDDDFIELD with old exporter")
|
|
|
|
|
}
|
2016-04-22 08:39:56 -07:00
|
|
|
return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.DDDField())
|
2016-04-08 13:33:43 -04:00
|
|
|
|
|
|
|
|
case Txxx:
|
|
|
|
|
return "Txxx"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if fmtmode == FExp {
|
2016-04-22 08:39:56 -07:00
|
|
|
Fatalf("missing %v case during export", t.Etype)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't know how to handle - fall back to detailed prints.
|
2016-04-22 08:39:56 -07:00
|
|
|
return fmt.Sprintf("%v <%v> %v", t.Etype, t.Sym, t.Elem())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Statements which may be rendered with a simplestmt as init.
|
2015-09-24 23:21:18 +02:00
|
|
|
func stmtwithinit(op Op) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch op {
|
2015-04-01 09:38:44 -07:00
|
|
|
case OIF, OFOR, OSWITCH:
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func stmtfmt(n *Node) string {
|
|
|
|
|
var f string
|
|
|
|
|
|
|
|
|
|
// some statements allow for an init, but at most one,
|
|
|
|
|
// but we may have an arbitrary number added, eg by typecheck
|
2016-03-01 23:21:55 +00:00
|
|
|
// and inlining. If it doesn't fit the syntax, emit an enclosing
|
2015-02-13 14:40:36 -05:00
|
|
|
// block starting with the init statements.
|
|
|
|
|
|
|
|
|
|
// if we can just say "for" n->ninit; ... then do so
|
2016-03-08 15:10:26 -08:00
|
|
|
simpleinit := n.Ninit.Len() == 1 && n.Ninit.First().Ninit.Len() == 0 && stmtwithinit(n.Op)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// otherwise, print the inits as separate statements
|
2016-03-08 15:10:26 -08:00
|
|
|
complexinit := n.Ninit.Len() != 0 && !simpleinit && (fmtmode != FErr)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
|
2015-09-24 23:21:18 +02:00
|
|
|
extrablock := complexinit && stmtwithinit(n.Op)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if extrablock {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "{"
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if complexinit {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf(" %v; ", n.Ninit)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case ODCL:
|
|
|
|
|
if fmtmode == FExp {
|
|
|
|
|
switch n.Left.Class &^ PHEAP {
|
2015-04-01 09:38:44 -07:00
|
|
|
case PPARAM, PPARAMOUT, PAUTO:
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("var %v %v", n.Left, n.Left.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
goto ret
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("var %v %v", n.Left.Sym, n.Left.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ODCLFIELD:
|
|
|
|
|
if n.Left != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("%v %v", n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-03-12 18:45:30 -04:00
|
|
|
f += Nconv(n.Right, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-22 10:04:23 -07:00
|
|
|
// Don't export "v = <N>" initializing statements, hope they're always
|
2016-03-18 17:21:32 -07:00
|
|
|
// preceded by the DCL which will be re-parsed and typechecked to reproduce
|
2015-02-13 14:40:36 -05:00
|
|
|
// the "v = <N>" again.
|
cmd/internal/gc: emit write barriers at lower level
This is primarily preparation for inlining, not an optimization by itself,
but it still helps some.
name old new delta
BenchmarkBinaryTree17 18.2s × (0.99,1.01) 17.9s × (0.99,1.01) -1.57%
BenchmarkFannkuch11 4.44s × (1.00,1.00) 4.42s × (1.00,1.00) -0.40%
BenchmarkFmtFprintfEmpty 119ns × (0.95,1.02) 118ns × (0.96,1.02) ~
BenchmarkFmtFprintfString 501ns × (0.99,1.02) 486ns × (0.99,1.01) -2.89%
BenchmarkFmtFprintfInt 474ns × (0.99,1.00) 457ns × (0.99,1.01) -3.59%
BenchmarkFmtFprintfIntInt 792ns × (1.00,1.00) 768ns × (1.00,1.01) -3.03%
BenchmarkFmtFprintfPrefixedInt 574ns × (1.00,1.01) 584ns × (0.99,1.03) +1.83%
BenchmarkFmtFprintfFloat 749ns × (1.00,1.00) 739ns × (0.99,1.00) -1.34%
BenchmarkFmtManyArgs 2.94µs × (1.00,1.01) 2.77µs × (1.00,1.00) -5.76%
BenchmarkGobDecode 39.5ms × (0.99,1.01) 39.3ms × (0.99,1.01) ~
BenchmarkGobEncode 39.4ms × (1.00,1.01) 39.4ms × (0.99,1.00) ~
BenchmarkGzip 658ms × (1.00,1.01) 661ms × (0.99,1.01) ~
BenchmarkGunzip 142ms × (1.00,1.00) 142ms × (1.00,1.00) +0.22%
BenchmarkHTTPClientServer 134µs × (0.99,1.01) 133µs × (0.98,1.01) ~
BenchmarkJSONEncode 57.1ms × (0.99,1.01) 56.5ms × (0.99,1.01) ~
BenchmarkJSONDecode 141ms × (1.00,1.00) 143ms × (1.00,1.00) +1.09%
BenchmarkMandelbrot200 6.01ms × (1.00,1.00) 6.01ms × (1.00,1.00) ~
BenchmarkGoParse 10.1ms × (0.91,1.09) 9.6ms × (0.94,1.07) ~
BenchmarkRegexpMatchEasy0_32 207ns × (1.00,1.01) 210ns × (1.00,1.00) +1.45%
BenchmarkRegexpMatchEasy0_1K 592ns × (0.99,1.00) 596ns × (0.99,1.01) +0.68%
BenchmarkRegexpMatchEasy1_32 184ns × (0.99,1.01) 184ns × (0.99,1.01) ~
BenchmarkRegexpMatchEasy1_1K 1.01µs × (1.00,1.00) 1.01µs × (0.99,1.01) ~
BenchmarkRegexpMatchMedium_32 327ns × (0.99,1.00) 327ns × (1.00,1.01) ~
BenchmarkRegexpMatchMedium_1K 92.5µs × (1.00,1.00) 93.0µs × (1.00,1.02) +0.48%
BenchmarkRegexpMatchHard_32 4.79µs × (0.95,1.00) 4.76µs × (0.95,1.01) ~
BenchmarkRegexpMatchHard_1K 136µs × (1.00,1.00) 136µs × (1.00,1.01) ~
BenchmarkRevcomp 900ms × (0.99,1.01) 892ms × (1.00,1.01) ~
BenchmarkTemplate 170ms × (0.99,1.01) 175ms × (0.99,1.00) +2.95%
BenchmarkTimeParse 645ns × (1.00,1.00) 638ns × (1.00,1.00) -1.16%
BenchmarkTimeFormat 740ns × (1.00,1.00) 772ns × (1.00,1.00) +4.39%
Change-Id: I0be905e32791e0cb70ff01f169c4b309a971d981
Reviewed-on: https://go-review.googlesource.com/9159
Reviewed-by: Rick Hudson <rlh@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-04-17 00:25:10 -04:00
|
|
|
case OAS, OASWB:
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FExp && n.Right == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 19:58:37 -07:00
|
|
|
if n.Colas && !complexinit {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("%v := %v", n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("%v = %v", n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OASOP:
|
2015-03-06 21:18:41 +11:00
|
|
|
if n.Implicit {
|
2015-09-24 23:21:18 +02:00
|
|
|
if Op(n.Etype) == OADD {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("%v++", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("%v--", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("%v %v= %v", n.Left, Oconv(Op(n.Etype), FmtSharp), n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OAS2:
|
2015-04-02 19:58:37 -07:00
|
|
|
if n.Colas && !complexinit {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("%v := %v", Hconv(n.List, FmtComma), Hconv(n.Rlist, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("%v = %v", Hconv(n.List, FmtComma), Hconv(n.Rlist, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ORETURN:
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("return %v", Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ORETJMP:
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("retjmp %v", n.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OPROC:
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("go %v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ODEFER:
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("defer %v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OIF:
|
2015-02-17 22:13:49 -05:00
|
|
|
if simpleinit {
|
2016-03-08 15:10:26 -08:00
|
|
|
f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.First(), n.Left, n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-05-26 21:30:20 -04:00
|
|
|
f += fmt.Sprintf("if %v { %v }", n.Left, n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Rlist.Len() != 0 {
|
2015-05-22 01:16:52 -04:00
|
|
|
f += fmt.Sprintf(" else { %v }", n.Rlist)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OFOR:
|
|
|
|
|
if fmtmode == FErr { // TODO maybe only if FmtShort, same below
|
|
|
|
|
f += "for loop"
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += "for"
|
2015-02-17 22:13:49 -05:00
|
|
|
if simpleinit {
|
2016-03-08 15:10:26 -08:00
|
|
|
f += fmt.Sprintf(" %v;", n.Ninit.First())
|
2015-05-22 01:16:52 -04:00
|
|
|
} else if n.Right != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += " ;"
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 21:30:20 -04:00
|
|
|
if n.Left != nil {
|
|
|
|
|
f += fmt.Sprintf(" %v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-22 01:16:52 -04:00
|
|
|
if n.Right != nil {
|
|
|
|
|
f += fmt.Sprintf("; %v", n.Right)
|
2015-02-17 22:13:49 -05:00
|
|
|
} else if simpleinit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += ";"
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf(" { %v }", n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ORANGE:
|
|
|
|
|
if fmtmode == FErr {
|
|
|
|
|
f += "for loop"
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.List.Len() == 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("for range %v { %v }", n.Right, n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("for %v = range %v { %v }", Hconv(n.List, FmtComma), n.Right, n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OSELECT, OSWITCH:
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FErr {
|
2016-03-07 08:23:55 -08:00
|
|
|
f += fmt.Sprintf("%v statement", Oconv(n.Op, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
f += Oconv(n.Op, FmtSharp)
|
2015-02-17 22:13:49 -05:00
|
|
|
if simpleinit {
|
2016-03-08 15:10:26 -08:00
|
|
|
f += fmt.Sprintf(" %v;", n.Ninit.First())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 21:30:20 -04:00
|
|
|
if n.Left != nil {
|
2016-03-16 21:29:17 -05:00
|
|
|
f += fmt.Sprintf(" %s ", Nconv(n.Left, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf(" { %v }", n.List)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OCASE, OXCASE:
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.List.Len() != 0 {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("case %v: %v", Hconv(n.List, FmtComma), n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("default: %v", n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OBREAK,
|
|
|
|
|
OCONTINUE,
|
|
|
|
|
OGOTO,
|
|
|
|
|
OFALL,
|
|
|
|
|
OXFALL:
|
|
|
|
|
if n.Left != nil {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("%v %v", Oconv(n.Op, FmtSharp), n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += Oconv(n.Op, FmtSharp)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OEMPTY:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case OLABEL:
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("%v: ", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret:
|
2015-02-17 22:13:49 -05:00
|
|
|
if extrablock {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var opprec = []int{
|
|
|
|
|
OAPPEND: 8,
|
|
|
|
|
OARRAYBYTESTR: 8,
|
|
|
|
|
OARRAYLIT: 8,
|
|
|
|
|
OARRAYRUNESTR: 8,
|
|
|
|
|
OCALLFUNC: 8,
|
|
|
|
|
OCALLINTER: 8,
|
|
|
|
|
OCALLMETH: 8,
|
|
|
|
|
OCALL: 8,
|
|
|
|
|
OCAP: 8,
|
|
|
|
|
OCLOSE: 8,
|
|
|
|
|
OCONVIFACE: 8,
|
|
|
|
|
OCONVNOP: 8,
|
|
|
|
|
OCONV: 8,
|
|
|
|
|
OCOPY: 8,
|
|
|
|
|
ODELETE: 8,
|
2015-04-03 12:23:28 -04:00
|
|
|
OGETG: 8,
|
2015-02-13 14:40:36 -05:00
|
|
|
OLEN: 8,
|
|
|
|
|
OLITERAL: 8,
|
|
|
|
|
OMAKESLICE: 8,
|
|
|
|
|
OMAKE: 8,
|
|
|
|
|
OMAPLIT: 8,
|
|
|
|
|
ONAME: 8,
|
|
|
|
|
ONEW: 8,
|
|
|
|
|
ONONAME: 8,
|
|
|
|
|
OPACK: 8,
|
|
|
|
|
OPANIC: 8,
|
|
|
|
|
OPAREN: 8,
|
|
|
|
|
OPRINTN: 8,
|
|
|
|
|
OPRINT: 8,
|
|
|
|
|
ORUNESTR: 8,
|
|
|
|
|
OSTRARRAYBYTE: 8,
|
|
|
|
|
OSTRARRAYRUNE: 8,
|
|
|
|
|
OSTRUCTLIT: 8,
|
|
|
|
|
OTARRAY: 8,
|
|
|
|
|
OTCHAN: 8,
|
|
|
|
|
OTFUNC: 8,
|
|
|
|
|
OTINTER: 8,
|
|
|
|
|
OTMAP: 8,
|
|
|
|
|
OTSTRUCT: 8,
|
|
|
|
|
OINDEXMAP: 8,
|
|
|
|
|
OINDEX: 8,
|
|
|
|
|
OSLICE: 8,
|
|
|
|
|
OSLICESTR: 8,
|
|
|
|
|
OSLICEARR: 8,
|
|
|
|
|
OSLICE3: 8,
|
|
|
|
|
OSLICE3ARR: 8,
|
|
|
|
|
ODOTINTER: 8,
|
|
|
|
|
ODOTMETH: 8,
|
|
|
|
|
ODOTPTR: 8,
|
|
|
|
|
ODOTTYPE2: 8,
|
|
|
|
|
ODOTTYPE: 8,
|
|
|
|
|
ODOT: 8,
|
|
|
|
|
OXDOT: 8,
|
|
|
|
|
OCALLPART: 8,
|
|
|
|
|
OPLUS: 7,
|
|
|
|
|
ONOT: 7,
|
|
|
|
|
OCOM: 7,
|
|
|
|
|
OMINUS: 7,
|
|
|
|
|
OADDR: 7,
|
|
|
|
|
OIND: 7,
|
|
|
|
|
ORECV: 7,
|
|
|
|
|
OMUL: 6,
|
|
|
|
|
ODIV: 6,
|
|
|
|
|
OMOD: 6,
|
|
|
|
|
OLSH: 6,
|
|
|
|
|
ORSH: 6,
|
|
|
|
|
OAND: 6,
|
|
|
|
|
OANDNOT: 6,
|
|
|
|
|
OADD: 5,
|
|
|
|
|
OSUB: 5,
|
|
|
|
|
OOR: 5,
|
|
|
|
|
OXOR: 5,
|
|
|
|
|
OEQ: 4,
|
|
|
|
|
OLT: 4,
|
|
|
|
|
OLE: 4,
|
|
|
|
|
OGE: 4,
|
|
|
|
|
OGT: 4,
|
|
|
|
|
ONE: 4,
|
|
|
|
|
OCMPSTR: 4,
|
|
|
|
|
OCMPIFACE: 4,
|
|
|
|
|
OSEND: 3,
|
|
|
|
|
OANDAND: 2,
|
|
|
|
|
OOROR: 1,
|
2015-02-20 13:54:45 -05:00
|
|
|
// Statements handled by stmtfmt
|
|
|
|
|
OAS: -1,
|
2015-02-13 14:40:36 -05:00
|
|
|
OAS2: -1,
|
|
|
|
|
OAS2DOTTYPE: -1,
|
|
|
|
|
OAS2FUNC: -1,
|
|
|
|
|
OAS2MAPR: -1,
|
|
|
|
|
OAS2RECV: -1,
|
|
|
|
|
OASOP: -1,
|
|
|
|
|
OBREAK: -1,
|
|
|
|
|
OCASE: -1,
|
|
|
|
|
OCONTINUE: -1,
|
|
|
|
|
ODCL: -1,
|
|
|
|
|
ODCLFIELD: -1,
|
|
|
|
|
ODEFER: -1,
|
|
|
|
|
OEMPTY: -1,
|
|
|
|
|
OFALL: -1,
|
|
|
|
|
OFOR: -1,
|
|
|
|
|
OGOTO: -1,
|
|
|
|
|
OIF: -1,
|
|
|
|
|
OLABEL: -1,
|
|
|
|
|
OPROC: -1,
|
|
|
|
|
ORANGE: -1,
|
|
|
|
|
ORETURN: -1,
|
|
|
|
|
OSELECT: -1,
|
|
|
|
|
OSWITCH: -1,
|
|
|
|
|
OXCASE: -1,
|
|
|
|
|
OXFALL: -1,
|
|
|
|
|
OEND: 0,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func exprfmt(n *Node, prec int) string {
|
2015-03-06 21:18:41 +11:00
|
|
|
for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) {
|
2015-02-13 14:40:36 -05:00
|
|
|
n = n.Left
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n == nil {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<N>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
nprec := opprec[n.Op]
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Op == OTYPE && n.Sym != nil {
|
|
|
|
|
nprec = 8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if prec > nprec {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("(%v)", n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case OPAREN:
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("(%v)", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ODDDARG:
|
2015-03-12 18:45:30 -04:00
|
|
|
return "... argument"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OREGISTER:
|
2015-04-13 10:28:57 -07:00
|
|
|
return obj.Rconv(int(n.Reg))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OLITERAL: // this is a bit of a mess
|
2015-03-03 23:28:00 -05:00
|
|
|
if fmtmode == FErr {
|
|
|
|
|
if n.Orig != nil && n.Orig != n {
|
|
|
|
|
return exprfmt(n.Orig, prec)
|
|
|
|
|
}
|
|
|
|
|
if n.Sym != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
return Sconv(n.Sym, 0)
|
2015-03-03 23:28:00 -05:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-27 00:47:05 -04:00
|
|
|
if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
|
2015-03-03 23:28:00 -05:00
|
|
|
return exprfmt(n.Orig, prec)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-12-14 14:07:21 -05:00
|
|
|
if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != idealbool && n.Type != idealstring {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Need parens when type begins with what might
|
|
|
|
|
// be misinterpreted as a unary operator: * or <-.
|
2016-04-02 16:26:30 -07:00
|
|
|
if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == Crecv) {
|
2015-05-27 00:47:05 -04:00
|
|
|
return fmt.Sprintf("(%v)(%v)", n.Type, Vconv(n.Val(), 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-05-27 00:47:05 -04:00
|
|
|
return fmt.Sprintf("%v(%v)", n.Type, Vconv(n.Val(), 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-27 00:47:05 -04:00
|
|
|
return Vconv(n.Val(), 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-10-22 10:04:23 -07:00
|
|
|
// Special case: name used as local variable in export.
|
2015-02-13 14:40:36 -05:00
|
|
|
// _ becomes ~b%d internally; print as _ for export
|
|
|
|
|
case ONAME:
|
2015-05-09 17:21:42 +00:00
|
|
|
if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
|
2015-02-28 20:31:32 +00:00
|
|
|
return "_"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-26 23:56:14 -04:00
|
|
|
if fmtmode == FExp && n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 {
|
|
|
|
|
return fmt.Sprintf("%v·%d", n.Sym, n.Name.Vargen)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
|
|
|
|
|
// but for export, this should be rendered as (*pkg.T).meth.
|
|
|
|
|
// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
|
|
|
|
|
if fmtmode == FExp && n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
|
2016-03-30 15:09:25 -07:00
|
|
|
if n.Left.Type.IsPtr() {
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("(%v).%v", n.Left.Type, Sconv(n.Right.Sym, FmtShort|FmtByte))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v.%v", n.Left.Type, Sconv(n.Right.Sym, FmtShort|FmtByte))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OPACK, ONONAME:
|
2015-03-12 18:45:30 -04:00
|
|
|
return Sconv(n.Sym, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTYPE:
|
|
|
|
|
if n.Type == nil && n.Sym != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
return Sconv(n.Sym, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return Tconv(n.Type, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTARRAY:
|
|
|
|
|
if n.Left != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("[]%v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-18 17:21:32 -07:00
|
|
|
return fmt.Sprintf("[]%v", n.Right) // happens before typecheck
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTMAP:
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("map[%v]%v", n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTCHAN:
|
2016-04-03 22:58:10 +00:00
|
|
|
switch ChanDir(n.Etype) {
|
2015-02-13 14:40:36 -05:00
|
|
|
case Crecv:
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("<-chan %v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case Csend:
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("chan<- %v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
default:
|
2016-04-03 22:58:10 +00:00
|
|
|
if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && ChanDir(n.Left.Etype) == Crecv {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("chan (%v)", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("chan %v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OTSTRUCT:
|
2015-03-12 18:45:30 -04:00
|
|
|
return "<struct>"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTINTER:
|
2015-03-12 18:45:30 -04:00
|
|
|
return "<inter>"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTFUNC:
|
2015-03-12 18:45:30 -04:00
|
|
|
return "<func>"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCLOSURE:
|
|
|
|
|
if fmtmode == FErr {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "func literal"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-24 13:50:26 -07:00
|
|
|
if n.Nbody.Len() != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v { %v }", n.Type, n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-05-27 00:44:05 -04:00
|
|
|
return fmt.Sprintf("%v { %v }", n.Type, n.Name.Param.Closure.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCOMPLIT:
|
2016-03-30 15:09:25 -07:00
|
|
|
ptrlit := n.Right != nil && n.Right.Implicit && n.Right.Type != nil && n.Right.Type.IsPtr()
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FErr {
|
2015-03-06 21:18:41 +11:00
|
|
|
if n.Right != nil && n.Right.Type != nil && !n.Implicit {
|
2015-02-17 22:13:49 -05:00
|
|
|
if ptrlit {
|
2016-03-30 10:57:47 -07:00
|
|
|
return fmt.Sprintf("&%v literal", n.Right.Type.Elem())
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v literal", n.Right.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:44:15 +00:00
|
|
|
return "composite literal"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if fmtmode == FExp && ptrlit {
|
2015-02-13 14:40:36 -05:00
|
|
|
// typecheck has overwritten OIND by OTYPE with pointer type.
|
2016-03-30 10:57:47 -07:00
|
|
|
return fmt.Sprintf("(&%v{ %v })", n.Right.Type.Elem(), Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("(%v{ %v })", n.Right, Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OPTRLIT:
|
2015-03-06 21:18:41 +11:00
|
|
|
if fmtmode == FExp && n.Left.Implicit {
|
2015-03-12 18:45:30 -04:00
|
|
|
return Nconv(n.Left, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("&%v", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
|
if fmtmode == FExp { // requires special handling of field names
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-03-06 21:18:41 +11:00
|
|
|
if n.Implicit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "{"
|
|
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("(%v{", n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-09 12:39:36 -08:00
|
|
|
for i1, n1 := range n.List.Slice() {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf(" %v:%v", Sconv(n1.Left.Sym, FmtShort|FmtByte), n1.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-09 12:39:36 -08:00
|
|
|
if i1+1 < n.List.Len() {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += ","
|
|
|
|
|
} else {
|
|
|
|
|
f += " "
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-06 21:18:41 +11:00
|
|
|
if !n.Implicit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "})"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
f += "}"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OARRAYLIT, OMAPLIT:
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FErr {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v literal", n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-06 21:18:41 +11:00
|
|
|
if fmtmode == FExp && n.Implicit {
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("{ %v }", Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("(%v{ %v })", n.Type, Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OKEY:
|
|
|
|
|
if n.Left != nil && n.Right != nil {
|
2016-03-14 00:24:43 -07:00
|
|
|
if fmtmode == FExp && n.Left.Type == structkey {
|
2015-02-13 14:40:36 -05:00
|
|
|
// requires special handling of field names
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v:%v", Sconv(n.Left.Sym, FmtShort|FmtByte), n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v:%v", n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Left == nil && n.Right != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf(":%v", n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Left != nil && n.Right == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v:", n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-12 18:45:30 -04:00
|
|
|
return ":"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
case OCALLPART:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Left, nprec)
|
|
|
|
|
if n.Right == nil || n.Right.Sym == nil {
|
|
|
|
|
f += ".<nil>"
|
|
|
|
|
return f
|
|
|
|
|
}
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf(".%v", Sconv(n.Right.Sym, FmtShort|FmtByte))
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
|
|
|
|
var f string
|
|
|
|
|
f += exprfmt(n.Left, nprec)
|
|
|
|
|
if n.Sym == nil {
|
|
|
|
|
f += ".<nil>"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
f += fmt.Sprintf(".%v", Sconv(n.Sym, FmtShort|FmtByte))
|
|
|
|
|
return f
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case ODOTTYPE, ODOTTYPE2:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Left, nprec)
|
|
|
|
|
if n.Right != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf(".(%v)", n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
}
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf(".(%v)", n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OINDEX,
|
|
|
|
|
OINDEXMAP,
|
|
|
|
|
OSLICE,
|
|
|
|
|
OSLICESTR,
|
|
|
|
|
OSLICEARR,
|
|
|
|
|
OSLICE3,
|
|
|
|
|
OSLICE3ARR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Left, nprec)
|
2015-04-17 12:03:22 -04:00
|
|
|
f += fmt.Sprintf("[%v]", n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OCOPY, OCOMPLEX:
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v(%v, %v)", Oconv(n.Op, FmtSharp), n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCONV,
|
|
|
|
|
OCONVIFACE,
|
|
|
|
|
OCONVNOP,
|
|
|
|
|
OARRAYBYTESTR,
|
|
|
|
|
OARRAYRUNESTR,
|
|
|
|
|
OSTRARRAYBYTE,
|
|
|
|
|
OSTRARRAYRUNE,
|
|
|
|
|
ORUNESTR:
|
|
|
|
|
if n.Type == nil || n.Type.Sym == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("(%v)(%v)", n.Type, n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Left != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v(%v)", n.Type, n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v(%v)", n.Type, Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OREAL,
|
|
|
|
|
OIMAG,
|
|
|
|
|
OAPPEND,
|
|
|
|
|
OCAP,
|
|
|
|
|
OCLOSE,
|
|
|
|
|
ODELETE,
|
|
|
|
|
OLEN,
|
|
|
|
|
OMAKE,
|
|
|
|
|
ONEW,
|
|
|
|
|
OPANIC,
|
|
|
|
|
ORECOVER,
|
|
|
|
|
OPRINT,
|
|
|
|
|
OPRINTN:
|
|
|
|
|
if n.Left != nil {
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v(%v)", Oconv(n.Op, FmtSharp), n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-09 16:24:07 +11:00
|
|
|
if n.Isddd {
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v(%v...)", Oconv(n.Op, FmtSharp), Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("%v(%v)", Oconv(n.Op, FmtSharp), Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-03 12:23:28 -04:00
|
|
|
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Left, nprec)
|
2015-03-09 16:24:07 +11:00
|
|
|
if n.Isddd {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("(%v...)", Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
}
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("(%v)", Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OMAKEMAP, OMAKECHAN, OMAKESLICE:
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.List.Len() != 0 { // pre-typecheck
|
2016-03-15 13:06:58 -07:00
|
|
|
return fmt.Sprintf("make(%v, %v)", n.Type, Hconv(n.List, FmtComma))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Right != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("make(%v, %v, %v)", n.Type, n.Left, n.Right)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-01 13:36:24 -07:00
|
|
|
if n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()) {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("make(%v, %v)", n.Type, n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("make(%v)", n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// Unary
|
|
|
|
|
case OPLUS,
|
|
|
|
|
OMINUS,
|
|
|
|
|
OADDR,
|
|
|
|
|
OCOM,
|
|
|
|
|
OIND,
|
|
|
|
|
ONOT,
|
|
|
|
|
ORECV:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Left.Op == n.Op {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf("%v ", Oconv(n.Op, FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-15 13:06:58 -07:00
|
|
|
f += Oconv(n.Op, FmtSharp)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
f += exprfmt(n.Left, nprec+1)
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
// Binary
|
|
|
|
|
case OADD,
|
|
|
|
|
OAND,
|
|
|
|
|
OANDAND,
|
|
|
|
|
OANDNOT,
|
|
|
|
|
ODIV,
|
|
|
|
|
OEQ,
|
|
|
|
|
OGE,
|
|
|
|
|
OGT,
|
|
|
|
|
OLE,
|
|
|
|
|
OLT,
|
|
|
|
|
OLSH,
|
|
|
|
|
OMOD,
|
|
|
|
|
OMUL,
|
|
|
|
|
ONE,
|
|
|
|
|
OOR,
|
|
|
|
|
OOROR,
|
|
|
|
|
ORSH,
|
|
|
|
|
OSEND,
|
|
|
|
|
OSUB,
|
|
|
|
|
OXOR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Left, nprec)
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf(" %v ", Oconv(n.Op, FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Right, nprec+1)
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OADDSTR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2016-03-04 13:16:48 -08:00
|
|
|
i := 0
|
2016-03-08 15:10:26 -08:00
|
|
|
for _, n1 := range n.List.Slice() {
|
2016-03-04 13:16:48 -08:00
|
|
|
if i != 0 {
|
2015-02-28 20:31:32 +00:00
|
|
|
f += " + "
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-08 15:10:26 -08:00
|
|
|
f += exprfmt(n1, nprec)
|
2016-03-04 13:16:48 -08:00
|
|
|
i++
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return f
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OCMPSTR, OCMPIFACE:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Left, nprec)
|
2015-09-24 23:21:18 +02:00
|
|
|
// TODO(marvin): Fix Node.EType type union.
|
2016-03-15 13:06:58 -07:00
|
|
|
f += fmt.Sprintf(" %v ", Oconv(Op(n.Etype), FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n.Right, nprec+1)
|
|
|
|
|
return f
|
2016-03-16 18:44:17 -05:00
|
|
|
|
|
|
|
|
case ODCLCONST:
|
|
|
|
|
// if exporting, DCLCONST should just be removed as its usage
|
|
|
|
|
// has already been replaced with literals
|
|
|
|
|
if fmtbody {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-07 08:23:55 -08:00
|
|
|
return fmt.Sprintf("<node %v>", Oconv(n.Op, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
func nodefmt(n *Node, flag FmtFlag) string {
|
2015-02-23 16:07:24 -05:00
|
|
|
t := n.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// we almost always want the original, except in export mode for literals
|
|
|
|
|
// this saves the importer some work, and avoids us having to redo some
|
|
|
|
|
// special casing for package unsafe
|
|
|
|
|
if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
|
|
|
|
|
n = n.Orig
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtLong != 0 && t != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t.Etype == TNIL {
|
2015-02-28 20:31:32 +00:00
|
|
|
return "nil"
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-04-17 12:03:22 -04:00
|
|
|
return fmt.Sprintf("%v (type %v)", n, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO inlining produces expressions with ninits. we can't print these yet.
|
|
|
|
|
|
|
|
|
|
if opprec[n.Op] < 0 {
|
|
|
|
|
return stmtfmt(n)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:44:15 +00:00
|
|
|
return exprfmt(n, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dumpdepth int
|
|
|
|
|
|
2015-03-12 18:45:30 -04:00
|
|
|
func indent(buf *bytes.Buffer) {
|
|
|
|
|
buf.WriteString("\n")
|
|
|
|
|
for i := 0; i < dumpdepth; i++ {
|
|
|
|
|
buf.WriteString(". ")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
func nodedump(n *Node, flag FmtFlag) string {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
return ""
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
recur := flag&FmtShort == 0
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-12 18:45:30 -04:00
|
|
|
var buf bytes.Buffer
|
2015-02-17 22:13:49 -05:00
|
|
|
if recur {
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2015-02-13 14:40:36 -05:00
|
|
|
if dumpdepth > 10 {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString("...")
|
|
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Ninit.Len() != 0 {
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-init%v", Oconv(n.Op, 0), n.Ninit)
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v%v", Oconv(n.Op, 0), Jconv(n, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OREGISTER, OINDREG:
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-%v%v", Oconv(n.Op, 0), obj.Rconv(int(n.Reg)), Jconv(n, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OLITERAL:
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-%v%v", Oconv(n.Op, 0), Vconv(n.Val(), 0), Jconv(n, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case ONAME, ONONAME:
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Sym != nil {
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-%v%v", Oconv(n.Op, 0), n.Sym, Jconv(n, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v%v", Oconv(n.Op, 0), Jconv(n, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-02-19 12:06:31 -05:00
|
|
|
if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-ntype%v", Oconv(n.Op, 0), n.Name.Param.Ntype)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OASOP:
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-%v%v", Oconv(n.Op, 0), Oconv(Op(n.Etype), 0), Jconv(n, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTYPE:
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v %v%v type=%v", Oconv(n.Op, 0), n.Sym, Jconv(n, 0), n.Type)
|
2015-05-27 00:44:05 -04:00
|
|
|
if recur && n.Type == nil && n.Name.Param.Ntype != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-ntype%v", Oconv(n.Op, 0), n.Name.Param.Ntype)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Sym != nil && n.Op != ONAME {
|
2015-05-27 00:47:05 -04:00
|
|
|
fmt.Fprintf(&buf, " %v", n.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Type != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
fmt.Fprintf(&buf, " %v", n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if recur {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Left != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(Nconv(n.Left, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Right != nil {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(Nconv(n.Right, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.List.Len() != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-list%v", Oconv(n.Op, 0), n.List)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
if n.Rlist.Len() != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-rlist%v", Oconv(n.Op, 0), n.Rlist)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-24 13:50:26 -07:00
|
|
|
if n.Nbody.Len() != 0 {
|
2015-03-12 18:45:30 -04:00
|
|
|
indent(&buf)
|
2016-03-07 08:23:55 -08:00
|
|
|
fmt.Fprintf(&buf, "%v-body%v", Oconv(n.Op, 0), n.Nbody)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-12 18:45:30 -04:00
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-17 11:56:29 -04:00
|
|
|
func (s *Sym) String() string {
|
|
|
|
|
return Sconv(s, 0)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Fmt "%S": syms
|
|
|
|
|
// Flags: "%hS" suppresses qualifying with package
|
2016-03-15 13:06:58 -07:00
|
|
|
func Sconv(s *Sym, flag FmtFlag) string {
|
|
|
|
|
if flag&FmtLong != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
panic("linksymfmt")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s == nil {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<S>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.Name == "_" {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "_"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
2015-12-30 19:47:36 -05:00
|
|
|
sm, sb := setfmode(&flag)
|
2015-02-13 14:40:36 -05:00
|
|
|
str := symfmt(s, flag)
|
|
|
|
|
flag = sf
|
|
|
|
|
fmtmode = sm
|
2015-12-30 19:47:36 -05:00
|
|
|
fmtbody = sb
|
2015-02-13 14:40:36 -05:00
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 11:56:29 -04:00
|
|
|
func (t *Type) String() string {
|
|
|
|
|
return Tconv(t, 0)
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
func Fldconv(f *Field, flag FmtFlag) string {
|
2016-03-14 01:20:49 -07:00
|
|
|
if f == nil {
|
|
|
|
|
return "<T>"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sf := flag
|
|
|
|
|
sm, sb := setfmode(&flag)
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
|
2016-03-14 01:20:49 -07:00
|
|
|
fmtpkgpfx++
|
|
|
|
|
}
|
|
|
|
|
if fmtpkgpfx != 0 {
|
2016-03-15 13:06:58 -07:00
|
|
|
flag |= FmtUnsigned
|
2016-03-14 01:20:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var name string
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtShort == 0 {
|
2016-03-14 01:20:49 -07:00
|
|
|
s := f.Sym
|
|
|
|
|
|
|
|
|
|
// Take the name from the original, lest we substituted it with ~r%d or ~b%d.
|
|
|
|
|
// ~r%d is a (formerly) unnamed result.
|
|
|
|
|
if (fmtmode == FErr || fmtmode == FExp) && f.Nname != nil {
|
|
|
|
|
if f.Nname.Orig != nil {
|
|
|
|
|
s = f.Nname.Orig.Sym
|
|
|
|
|
if s != nil && s.Name[0] == '~' {
|
|
|
|
|
if s.Name[1] == 'r' { // originally an unnamed result
|
|
|
|
|
s = nil
|
|
|
|
|
} else if s.Name[1] == 'b' { // originally the blank identifier _
|
|
|
|
|
s = Lookup("_")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
s = nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s != nil && f.Embedded == 0 {
|
|
|
|
|
if f.Funarg {
|
|
|
|
|
name = Nconv(f.Nname, 0)
|
2016-03-15 13:06:58 -07:00
|
|
|
} else if flag&FmtLong != 0 {
|
|
|
|
|
name = Sconv(s, FmtShort|FmtByte) // qualify non-exported names (used on structs, not on funarg)
|
2016-03-14 01:20:49 -07:00
|
|
|
} else {
|
|
|
|
|
name = Sconv(s, 0)
|
|
|
|
|
}
|
|
|
|
|
} else if fmtmode == FExp {
|
|
|
|
|
if f.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path) > 0 {
|
|
|
|
|
name = fmt.Sprintf("@%q.?", s.Pkg.Path)
|
|
|
|
|
} else {
|
|
|
|
|
name = "?"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var typ string
|
|
|
|
|
if f.Isddd {
|
2016-03-30 10:57:47 -07:00
|
|
|
typ = "..." + Tconv(f.Type.Elem(), 0)
|
2016-03-14 01:20:49 -07:00
|
|
|
} else {
|
|
|
|
|
typ = Tconv(f.Type, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str := typ
|
|
|
|
|
if name != "" {
|
|
|
|
|
str = name + " " + typ
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The fmtbody flag is intended to suppress escape analysis annotations
|
|
|
|
|
// when printing a function type used in a function body.
|
|
|
|
|
// (The escape analysis tags do not apply to func vars.)
|
|
|
|
|
// But it must not suppress struct field tags.
|
|
|
|
|
// See golang.org/issue/13777 and golang.org/issue/14331.
|
2016-03-15 13:06:58 -07:00
|
|
|
if flag&FmtShort == 0 && (!fmtbody || !f.Funarg) && f.Note != nil {
|
2016-03-14 01:20:49 -07:00
|
|
|
str += " " + strconv.Quote(*f.Note)
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
|
2016-03-14 01:20:49 -07:00
|
|
|
fmtpkgpfx--
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
|
|
|
|
fmtbody = sb
|
|
|
|
|
fmtmode = sm
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Fmt "%T": types.
|
|
|
|
|
// Flags: 'l' print definition, not name
|
|
|
|
|
// 'h' omit 'func' and receiver from function types, short type names
|
|
|
|
|
// 'u' package name, not prefix (FTypeId mode, sticky)
|
2016-03-15 13:06:58 -07:00
|
|
|
func Tconv(t *Type, flag FmtFlag) string {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t == nil {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<T>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Trecur > 4 {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<...>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Trecur++
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
2015-12-30 19:47:36 -05:00
|
|
|
sm, sb := setfmode(&flag)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtpkgpfx++
|
|
|
|
|
}
|
|
|
|
|
if fmtpkgpfx != 0 {
|
2016-03-15 13:06:58 -07:00
|
|
|
flag |= FmtUnsigned
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str := typefmt(t, flag)
|
|
|
|
|
|
2016-03-15 13:06:58 -07:00
|
|
|
if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtpkgpfx--
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
2015-12-30 19:47:36 -05:00
|
|
|
fmtbody = sb
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtmode = sm
|
|
|
|
|
t.Trecur--
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 11:56:29 -04:00
|
|
|
func (n *Node) String() string {
|
|
|
|
|
return Nconv(n, 0)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Fmt '%N': Nodes.
|
|
|
|
|
// Flags: 'l' suffix with "(type %T)" where possible
|
|
|
|
|
// '+h' in debug mode, don't recurse, no multiline output
|
2016-03-15 13:06:58 -07:00
|
|
|
func Nconv(n *Node, flag FmtFlag) string {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<N>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
2015-12-30 19:47:36 -05:00
|
|
|
sm, sb := setfmode(&flag)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
var str string
|
|
|
|
|
switch fmtmode {
|
2015-04-01 09:38:44 -07:00
|
|
|
case FErr, FExp:
|
2015-02-13 14:40:36 -05:00
|
|
|
str = nodefmt(n, flag)
|
|
|
|
|
|
|
|
|
|
case FDbg:
|
|
|
|
|
dumpdepth++
|
|
|
|
|
str = nodedump(n, flag)
|
|
|
|
|
dumpdepth--
|
|
|
|
|
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("unhandled %%N mode")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
2015-12-30 19:47:36 -05:00
|
|
|
fmtbody = sb
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtmode = sm
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 14:31:33 -08:00
|
|
|
func (n Nodes) String() string {
|
2016-03-04 13:16:48 -08:00
|
|
|
return Hconv(n, 0)
|
2016-02-27 14:31:33 -08:00
|
|
|
}
|
|
|
|
|
|
2016-03-10 10:00:29 -08:00
|
|
|
// Fmt '%H': Nodes.
|
2015-02-13 14:40:36 -05:00
|
|
|
// Flags: all those of %N plus ',': separate with comma's instead of semicolons.
|
2016-03-15 13:06:58 -07:00
|
|
|
func Hconv(l Nodes, flag FmtFlag) string {
|
2016-03-08 15:10:26 -08:00
|
|
|
if l.Len() == 0 && fmtmode == FDbg {
|
2015-02-27 22:44:15 +00:00
|
|
|
return "<nil>"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
2015-12-30 19:47:36 -05:00
|
|
|
sm, sb := setfmode(&flag)
|
2015-02-23 16:07:24 -05:00
|
|
|
sep := "; "
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FDbg {
|
|
|
|
|
sep = "\n"
|
2016-03-15 13:06:58 -07:00
|
|
|
} else if flag&FmtComma != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
sep = ", "
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-12 18:45:30 -04:00
|
|
|
var buf bytes.Buffer
|
2016-03-09 12:39:36 -08:00
|
|
|
for i, n := range l.Slice() {
|
|
|
|
|
buf.WriteString(Nconv(n, 0))
|
|
|
|
|
if i+1 < l.Len() {
|
2015-03-12 18:45:30 -04:00
|
|
|
buf.WriteString(sep)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
2015-12-30 19:47:36 -05:00
|
|
|
fmtbody = sb
|
2015-02-13 14:40:36 -05:00
|
|
|
fmtmode = sm
|
2015-03-12 18:45:30 -04:00
|
|
|
return buf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-08 10:26:20 -08:00
|
|
|
func dumplist(s string, l Nodes) {
|
2016-03-15 13:06:58 -07:00
|
|
|
fmt.Printf("%s%v\n", s, Hconv(l, FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Dump(s string, n *Node) {
|
2016-03-15 13:06:58 -07:00
|
|
|
fmt.Printf("%s [%p]%v\n", s, n, Nconv(n, FmtSign))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|