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 (
|
|
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 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)"
|
|
|
|
|
//
|
|
|
|
|
// %H NodeList* NodeLists
|
|
|
|
|
// Flags: those of %N
|
|
|
|
|
// ',' separate items with ',' instead of ';'
|
|
|
|
|
//
|
|
|
|
|
// %Z Strlit* String literals
|
|
|
|
|
//
|
|
|
|
|
// In mparith1.c:
|
|
|
|
|
// %B Mpint* Big integers
|
|
|
|
|
// %F Mpflt* Big floats
|
|
|
|
|
//
|
|
|
|
|
// %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
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
// recursions of %N, %T and %S, but not the h and l flags. The u flag is
|
|
|
|
|
// 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)
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
func setfmode(flags *int) int {
|
2015-02-23 16:07:24 -05:00
|
|
|
fm := fmtmode
|
2015-02-13 14:40:36 -05:00
|
|
|
if *flags&obj.FmtSign != 0 {
|
|
|
|
|
fmtmode = FDbg
|
|
|
|
|
} else if *flags&obj.FmtSharp != 0 {
|
|
|
|
|
fmtmode = FExp
|
|
|
|
|
} else if *flags&obj.FmtLeft != 0 {
|
|
|
|
|
fmtmode = FTypeId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*flags &^= (obj.FmtSharp | obj.FmtLeft | obj.FmtSign)
|
|
|
|
|
return fm
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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: "^",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%O": Node opcodes
|
|
|
|
|
func Oconv(o int, flag int) string {
|
|
|
|
|
if (flag&obj.FmtSharp != 0 /*untyped*/) || fmtmode != FDbg {
|
|
|
|
|
if o >= 0 && o < len(goopnames) && goopnames[o] != "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += goopnames[o]
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if o >= 0 && o < len(opnames) && opnames[o] != "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += opnames[o]
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("O-%d", o)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var classnames = []string{
|
|
|
|
|
"Pxxx",
|
|
|
|
|
"PEXTERN",
|
|
|
|
|
"PAUTO",
|
|
|
|
|
"PPARAM",
|
|
|
|
|
"PPARAMOUT",
|
|
|
|
|
"PPARAMREF",
|
|
|
|
|
"PFUNC",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%J": Node details.
|
|
|
|
|
func Jconv(n *Node, flag int) string {
|
|
|
|
|
var fp string
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
c := flag & obj.FmtShort
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Ullman != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" u(%d)", n.Ullman)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Addable != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" a(%d)", n.Addable)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Vargen != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" g(%d)", n.Vargen)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Lineno != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" l(%d)", n.Lineno)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Xoffset != BADWIDTH {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" x(%d%+d)", n.Xoffset, n.Stkdelta)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
fp += fmt.Sprintf(" class(%s%s)", classnames[n.Class&^PHEAP], s)
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf(" class(%d?%s)", n.Class&^PHEAP, s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Colas != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" colas(%d)", n.Colas)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Funcdepth != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" f(%d)", n.Funcdepth)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Esc {
|
|
|
|
|
case EscUnknown:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case EscHeap:
|
|
|
|
|
fp += fmt.Sprintf(" esc(h)")
|
|
|
|
|
|
|
|
|
|
case EscScope:
|
|
|
|
|
fp += fmt.Sprintf(" esc(s)")
|
|
|
|
|
|
|
|
|
|
case EscNone:
|
|
|
|
|
fp += fmt.Sprintf(" esc(no)")
|
|
|
|
|
|
|
|
|
|
case EscNever:
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" esc(N)")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
fp += fmt.Sprintf(" esc(%d)", n.Esc)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Escloopdepth != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" ld(%d)", n.Escloopdepth)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Typecheck != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" tc(%d)", n.Typecheck)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Dodata != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" dd(%d)", n.Dodata)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Isddd != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" isddd(%d)", n.Isddd)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Implicit != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" implicit(%d)", n.Implicit)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Embedded != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" embedded(%d)", n.Embedded)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Addrtaken != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" addrtaken")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Assigned != 0 {
|
|
|
|
|
fp += fmt.Sprintf(" assigned")
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if c == 0 && n.Used != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" used(%d)", n.Used)
|
|
|
|
|
}
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%V": Values
|
|
|
|
|
func Vconv(v *Val, flag int) string {
|
|
|
|
|
switch v.Ctype {
|
|
|
|
|
case CTINT:
|
|
|
|
|
if (flag&obj.FmtSharp != 0 /*untyped*/) || fmtmode == FExp {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Bconv(v.U.Xval, obj.FmtSharp))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Bconv(v.U.Xval, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case CTRUNE:
|
2015-02-23 16:07:24 -05:00
|
|
|
x := Mpgetfix(v.U.Xval)
|
2015-02-13 14:40:36 -05:00
|
|
|
if ' ' <= x && x < 0x80 && x != '\\' && x != '\'' {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("'%c'", int(x))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
if 0 <= x && x < 1<<16 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("'\\u%04x'", uint(int(x)))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
if 0 <= x && x <= utf8.MaxRune {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("'\\U%08x'", uint64(x))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("('\\x00' + %v)", Bconv(v.U.Xval, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case CTFLT:
|
|
|
|
|
if (flag&obj.FmtSharp != 0 /*untyped*/) || fmtmode == FExp {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Fconv(v.U.Fval, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Fconv(v.U.Fval, obj.FmtSharp))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case CTCPLX:
|
|
|
|
|
if (flag&obj.FmtSharp != 0 /*untyped*/) || fmtmode == FExp {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("(%v+%vi)", Fconv(&v.U.Cval.Real, 0), Fconv(&v.U.Cval.Imag, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
if mpcmpfltc(&v.U.Cval.Real, 0) == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%vi", Fconv(&v.U.Cval.Imag, obj.FmtSharp))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
if mpcmpfltc(&v.U.Cval.Imag, 0) == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Fconv(&v.U.Cval.Real, obj.FmtSharp))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
if mpcmpfltc(&v.U.Cval.Imag, 0) < 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("(%v%vi)", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("(%v+%vi)", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case CTSTR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("\"%v\"", Zconv(v.U.Sval, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case CTBOOL:
|
|
|
|
|
if v.U.Bval != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "true"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "false"
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case CTNIL:
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "nil"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("<ctype=%d>", v.Ctype)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%Z": escaped string literals
|
|
|
|
|
func Zconv(sp *Strlit, flag int) string {
|
|
|
|
|
if sp == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<nil>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: Keep in sync with ../ld/go.c:/^Zconv.
|
2015-02-23 16:07:24 -05:00
|
|
|
s := sp.S
|
|
|
|
|
var n int
|
|
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
for i := 0; i < len(s); i += n {
|
|
|
|
|
var r rune
|
|
|
|
|
r, n = utf8.DecodeRuneInString(s[i:])
|
|
|
|
|
switch r {
|
|
|
|
|
case utf8.RuneError:
|
|
|
|
|
if n == 1 {
|
|
|
|
|
fp += fmt.Sprintf("\\x%02x", s[i])
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// fall through
|
|
|
|
|
default:
|
|
|
|
|
if r < ' ' {
|
|
|
|
|
fp += fmt.Sprintf("\\x%02x", r)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp += string(r)
|
|
|
|
|
|
|
|
|
|
case '\t':
|
|
|
|
|
fp += "\\t"
|
|
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
|
fp += "\\n"
|
|
|
|
|
|
|
|
|
|
case '"',
|
|
|
|
|
'\\':
|
|
|
|
|
fp += `\` + string(r)
|
|
|
|
|
|
|
|
|
|
case 0xFEFF: // BOM, basically disallowed in source code
|
|
|
|
|
fp += "\\uFEFF"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
s%,%,\n%g
|
|
|
|
|
s%\n+%\n%g
|
|
|
|
|
s%^[ ]*T%%g
|
|
|
|
|
s%,.*%%g
|
|
|
|
|
s%.+% [T&] = "&",%g
|
|
|
|
|
s%^ ........*\]%&~%g
|
|
|
|
|
s%~ %%g
|
|
|
|
|
*/
|
|
|
|
|
var etnames = []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",
|
|
|
|
|
TPTR32: "PTR32",
|
|
|
|
|
TPTR64: "PTR64",
|
|
|
|
|
TFUNC: "FUNC",
|
|
|
|
|
TARRAY: "ARRAY",
|
|
|
|
|
TSTRUCT: "STRUCT",
|
|
|
|
|
TCHAN: "CHAN",
|
|
|
|
|
TMAP: "MAP",
|
|
|
|
|
TINTER: "INTER",
|
|
|
|
|
TFORW: "FORW",
|
|
|
|
|
TFIELD: "FIELD",
|
|
|
|
|
TSTRING: "STRING",
|
|
|
|
|
TANY: "ANY",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%E": etype
|
|
|
|
|
func Econv(et int, flag int) string {
|
|
|
|
|
if et >= 0 && et < len(etnames) && etnames[et] != "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += etnames[et]
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("E-%d", et)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%S": syms
|
|
|
|
|
func symfmt(s *Sym, flag int) string {
|
2015-02-17 22:13:49 -05:00
|
|
|
if s.Pkg != nil && flag&obj.FmtShort == 0 /*untyped*/ {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch fmtmode {
|
|
|
|
|
case FErr: // This is for the user
|
|
|
|
|
if s.Pkg == localpkg {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += s.Name
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the name was used by multiple packages, display the full path,
|
|
|
|
|
if s.Pkg.Name != "" && Pkglookup(s.Pkg.Name, nil).Npkg > 1 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("\"%v\".%s", Zconv(s.Pkg.Path, 0), s.Name)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name)
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case FDbg:
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name)
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case FTypeId:
|
|
|
|
|
if flag&obj.FmtUnsigned != 0 /*untyped*/ {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%s.%s", s.Pkg.Name, s.Name)
|
|
|
|
|
return fp // dcommontype, typehash
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%s.%s", s.Pkg.Prefix, s.Name)
|
|
|
|
|
return fp // (methodsym), typesym, weaksym
|
|
|
|
|
|
|
|
|
|
case FExp:
|
|
|
|
|
if s.Name != "" && s.Name[0] == '.' {
|
|
|
|
|
Fatal("exporting synthetic symbol %s", s.Name)
|
|
|
|
|
}
|
|
|
|
|
if s.Pkg != builtinpkg {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("@\"%v\".%s", Zconv(s.Pkg.Path, 0), s.Name)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if flag&obj.FmtByte != 0 /*untyped*/ { // FmtByte (hh) implies FmtShort (h)
|
|
|
|
|
|
|
|
|
|
// 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-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("@\"%v\".%s", Zconv(s.Pkg.Path, 0), p)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += p
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += s.Name
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func typefmt(t *Type, flag int) string {
|
|
|
|
|
if t == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<T>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t == bytetype || t == runetype {
|
|
|
|
|
// in %-T mode collapse rune and byte with their originals.
|
|
|
|
|
if fmtmode != FTypeId {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Sconv(t.Sym, obj.FmtShort))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
t = Types[t.Etype]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t == errortype {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "error"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unless the 'l' flag was specified, if the type has a name, just print that name.
|
2015-02-17 22:13:49 -05:00
|
|
|
if flag&obj.FmtLong == 0 /*untyped*/ && t.Sym != nil && t.Etype != TFIELD && t != Types[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch fmtmode {
|
|
|
|
|
case FTypeId:
|
|
|
|
|
if flag&obj.FmtShort != 0 /*untyped*/ {
|
|
|
|
|
if t.Vargen != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v·%d", Sconv(t.Sym, obj.FmtShort), t.Vargen)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Sconv(t.Sym, obj.FmtShort))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if flag&obj.FmtUnsigned != 0 /*untyped*/ {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Sconv(t.Sym, obj.FmtUnsigned))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// fallthrough
|
|
|
|
|
case FExp:
|
|
|
|
|
if t.Sym.Pkg == localpkg && t.Vargen != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v·%d", Sconv(t.Sym, 0), t.Vargen)
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf("%v", Sconv(t.Sym, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
|
|
|
|
|
if fmtmode == FErr && (t == idealbool || t == idealstring) {
|
|
|
|
|
fp += "untyped "
|
|
|
|
|
}
|
|
|
|
|
fp += basicnames[t.Etype]
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if fmtmode == FDbg {
|
|
|
|
|
fp += fmt.Sprintf("%v-", Econv(int(t.Etype), 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch t.Etype {
|
|
|
|
|
case TPTR32,
|
|
|
|
|
TPTR64:
|
|
|
|
|
if fmtmode == FTypeId && (flag&obj.FmtShort != 0 /*untyped*/) {
|
|
|
|
|
fp += fmt.Sprintf("*%v", Tconv(t.Type, obj.FmtShort))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
fp += fmt.Sprintf("*%v", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TARRAY:
|
|
|
|
|
if t.Bound >= 0 {
|
|
|
|
|
fp += fmt.Sprintf("[%d]%v", t.Bound, Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
if t.Bound == -100 {
|
|
|
|
|
fp += fmt.Sprintf("[...]%v", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
fp += fmt.Sprintf("[]%v", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TCHAN:
|
|
|
|
|
switch t.Chan {
|
|
|
|
|
case Crecv:
|
|
|
|
|
fp += fmt.Sprintf("<-chan %v", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case Csend:
|
|
|
|
|
fp += fmt.Sprintf("chan<- %v", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Type != nil && t.Type.Etype == TCHAN && t.Type.Sym == nil && t.Type.Chan == Crecv {
|
|
|
|
|
fp += fmt.Sprintf("chan (%v)", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
fp += fmt.Sprintf("chan %v", Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TMAP:
|
|
|
|
|
fp += fmt.Sprintf("map[%v]%v", Tconv(t.Down, 0), Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TINTER:
|
|
|
|
|
fp += "interface {"
|
2015-02-23 16:07:24 -05:00
|
|
|
for t1 := t.Type; t1 != nil; t1 = t1.Down {
|
2015-02-13 14:40:36 -05:00
|
|
|
if exportname(t1.Sym.Name) {
|
|
|
|
|
if t1.Down != nil {
|
|
|
|
|
fp += fmt.Sprintf(" %v%v;", Sconv(t1.Sym, obj.FmtShort), Tconv(t1.Type, obj.FmtShort))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf(" %v%v ", Sconv(t1.Sym, obj.FmtShort), Tconv(t1.Type, obj.FmtShort))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// non-exported method names must be qualified
|
|
|
|
|
if t1.Down != nil {
|
|
|
|
|
fp += fmt.Sprintf(" %v%v;", Sconv(t1.Sym, obj.FmtUnsigned), Tconv(t1.Type, obj.FmtShort))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf(" %v%v ", Sconv(t1.Sym, obj.FmtUnsigned), Tconv(t1.Type, obj.FmtShort))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp += "}"
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TFUNC:
|
|
|
|
|
if flag&obj.FmtShort != 0 /*untyped*/ {
|
|
|
|
|
fp += fmt.Sprintf("%v", Tconv(getinargx(t), 0))
|
|
|
|
|
} else {
|
|
|
|
|
if t.Thistuple != 0 {
|
|
|
|
|
fp += fmt.Sprintf("method%v func%v", Tconv(getthisx(t), 0), Tconv(getinargx(t), 0))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf("func%v", Tconv(getinargx(t), 0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch t.Outtuple {
|
|
|
|
|
case 0:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
if fmtmode != FExp {
|
|
|
|
|
fp += fmt.Sprintf(" %v", Tconv(getoutargx(t).Type.Type, 0)) // struct->field->field's type
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
fp += fmt.Sprintf(" %v", Tconv(getoutargx(t), 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
|
|
|
|
// This avoids a recursive print that generates very long names.
|
|
|
|
|
case TSTRUCT:
|
|
|
|
|
if t.Map != nil {
|
|
|
|
|
if t.Map.Bucket == t {
|
|
|
|
|
fp += fmt.Sprintf("map.bucket[%v]%v", Tconv(t.Map.Down, 0), Tconv(t.Map.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Map.Hmap == t {
|
|
|
|
|
fp += fmt.Sprintf("map.hdr[%v]%v", Tconv(t.Map.Down, 0), Tconv(t.Map.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Map.Hiter == t {
|
|
|
|
|
fp += fmt.Sprintf("map.iter[%v]%v", Tconv(t.Map.Down, 0), Tconv(t.Map.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Yyerror("unknown internal map type")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Funarg != 0 {
|
|
|
|
|
fp += "("
|
|
|
|
|
if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
|
2015-02-23 16:07:24 -05:00
|
|
|
for t1 := t.Type; t1 != nil; t1 = t1.Down {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t1.Down != nil {
|
|
|
|
|
fp += fmt.Sprintf("%v, ", Tconv(t1, obj.FmtShort))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf("%v", Tconv(t1, obj.FmtShort))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
for t1 := t.Type; t1 != nil; t1 = t1.Down {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t1.Down != nil {
|
|
|
|
|
fp += fmt.Sprintf("%v, ", Tconv(t1, 0))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf("%v", Tconv(t1, 0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp += ")"
|
|
|
|
|
} else {
|
|
|
|
|
fp += "struct {"
|
2015-02-23 16:07:24 -05:00
|
|
|
for t1 := t.Type; t1 != nil; t1 = t1.Down {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t1.Down != nil {
|
|
|
|
|
fp += fmt.Sprintf(" %v;", Tconv(t1, obj.FmtLong))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf(" %v ", Tconv(t1, obj.FmtLong))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fp += "}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TFIELD:
|
2015-02-17 22:13:49 -05:00
|
|
|
if flag&obj.FmtShort == 0 /*untyped*/ {
|
2015-02-23 16:07:24 -05:00
|
|
|
s := t.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// 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) && t.Nname != nil {
|
|
|
|
|
if t.Nname.Orig != nil {
|
|
|
|
|
s = t.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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if s != nil && t.Embedded == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t.Funarg != 0 {
|
|
|
|
|
fp += fmt.Sprintf("%v ", Nconv(t.Nname, 0))
|
|
|
|
|
} else if flag&obj.FmtLong != 0 /*untyped*/ {
|
|
|
|
|
fp += fmt.Sprintf("%v ", Sconv(s, obj.FmtShort|obj.FmtByte)) // qualify non-exported names (used on structs, not on funarg)
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf("%v ", Sconv(s, 0))
|
|
|
|
|
}
|
|
|
|
|
} else if fmtmode == FExp {
|
|
|
|
|
// TODO(rsc) this breaks on the eliding of unused arguments in the backend
|
|
|
|
|
// when this is fixed, the special case in dcl.c checkarglist can go.
|
|
|
|
|
//if(t->funarg)
|
|
|
|
|
// fmtstrcpy(fp, "_ ");
|
|
|
|
|
//else
|
|
|
|
|
if t.Embedded != 0 && s.Pkg != nil && len(s.Pkg.Path.S) > 0 {
|
|
|
|
|
fp += fmt.Sprintf("@\"%v\".? ", Zconv(s.Pkg.Path, 0))
|
|
|
|
|
} else {
|
|
|
|
|
fp += "? "
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Isddd != 0 {
|
|
|
|
|
fp += fmt.Sprintf("...%v", Tconv(t.Type.Type, 0))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf("%v", Tconv(t.Type, 0))
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if flag&obj.FmtShort == 0 /*untyped*/ && t.Note != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += fmt.Sprintf(" \"%v\"", Zconv(t.Note, 0))
|
|
|
|
|
}
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TFORW:
|
|
|
|
|
if t.Sym != nil {
|
|
|
|
|
fp += fmt.Sprintf("undefined %v", Sconv(t.Sym, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
fp += "undefined"
|
|
|
|
|
return fp
|
|
|
|
|
|
|
|
|
|
case TUNSAFEPTR:
|
|
|
|
|
if fmtmode == FExp {
|
|
|
|
|
fp += fmt.Sprintf("@\"unsafe\".Pointer")
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
fp += fmt.Sprintf("unsafe.Pointer")
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if fmtmode == FExp {
|
|
|
|
|
Fatal("missing %v case during export", Econv(int(t.Etype), 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't know how to handle - fall back to detailed prints.
|
|
|
|
|
fp += fmt.Sprintf("%v <%v> %v", Econv(int(t.Etype), 0), Sconv(t.Sym, 0), Tconv(t.Type, 0))
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Statements which may be rendered with a simplestmt as init.
|
2015-02-17 22:13:49 -05:00
|
|
|
func stmtwithinit(op int) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch op {
|
|
|
|
|
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
|
|
|
|
|
// and inlining. If it doesn't fit the syntax, emit an enclosing
|
|
|
|
|
// block starting with the init statements.
|
|
|
|
|
|
|
|
|
|
// if we can just say "for" n->ninit; ... then do so
|
2015-02-23 16:07:24 -05:00
|
|
|
simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(int(n.Op))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// otherwise, print the inits as separate statements
|
2015-02-23 16:07:24 -05:00
|
|
|
complexinit := n.Ninit != nil && !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-02-23 16:07:24 -05:00
|
|
|
extrablock := complexinit && stmtwithinit(int(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-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf(" %v; ", Hconv(n.Ninit, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case ODCL:
|
|
|
|
|
if fmtmode == FExp {
|
|
|
|
|
switch n.Left.Class &^ PHEAP {
|
|
|
|
|
case PPARAM,
|
|
|
|
|
PPARAMOUT,
|
|
|
|
|
PAUTO:
|
|
|
|
|
f += fmt.Sprintf("var %v %v", Nconv(n.Left, 0), Tconv(n.Left.Type, 0))
|
|
|
|
|
goto ret
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf("var %v %v", Sconv(n.Left.Sym, 0), Tconv(n.Left.Type, 0))
|
|
|
|
|
|
|
|
|
|
case ODCLFIELD:
|
|
|
|
|
if n.Left != nil {
|
|
|
|
|
f += fmt.Sprintf("%v %v", Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("%v", Nconv(n.Right, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't export "v = <N>" initializing statements, hope they're always
|
|
|
|
|
// preceded by the DCL which will be re-parsed and typecheck to reproduce
|
|
|
|
|
// the "v = <N>" again.
|
|
|
|
|
case OAS:
|
|
|
|
|
if fmtmode == FExp && n.Right == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Colas != 0 && !complexinit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v := %v", Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("%v = %v", Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OASOP:
|
|
|
|
|
if n.Implicit != 0 {
|
|
|
|
|
if n.Etype == OADD {
|
|
|
|
|
f += fmt.Sprintf("%v++", Nconv(n.Left, 0))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("%v--", Nconv(n.Left, 0))
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf("%v %v= %v", Nconv(n.Left, 0), Oconv(int(n.Etype), obj.FmtSharp), Nconv(n.Right, 0))
|
|
|
|
|
|
|
|
|
|
case OAS2:
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Colas != 0 && !complexinit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v := %v", Hconv(n.List, obj.FmtComma), Hconv(n.Rlist, obj.FmtComma))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// fallthrough
|
|
|
|
|
case OAS2DOTTYPE,
|
|
|
|
|
OAS2FUNC,
|
|
|
|
|
OAS2MAPR,
|
|
|
|
|
OAS2RECV:
|
|
|
|
|
f += fmt.Sprintf("%v = %v", Hconv(n.List, obj.FmtComma), Hconv(n.Rlist, obj.FmtComma))
|
|
|
|
|
|
|
|
|
|
case ORETURN:
|
|
|
|
|
f += fmt.Sprintf("return %v", Hconv(n.List, obj.FmtComma))
|
|
|
|
|
|
|
|
|
|
case ORETJMP:
|
|
|
|
|
f += fmt.Sprintf("retjmp %v", Sconv(n.Sym, 0))
|
|
|
|
|
|
|
|
|
|
case OPROC:
|
|
|
|
|
f += fmt.Sprintf("go %v", Nconv(n.Left, 0))
|
|
|
|
|
|
|
|
|
|
case ODEFER:
|
|
|
|
|
f += fmt.Sprintf("defer %v", Nconv(n.Left, 0))
|
|
|
|
|
|
|
|
|
|
case OIF:
|
2015-02-17 22:13:49 -05:00
|
|
|
if simpleinit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("if %v; %v { %v }", Nconv(n.Ninit.N, 0), Nconv(n.Ntest, 0), Hconv(n.Nbody, 0))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("if %v { %v }", Nconv(n.Ntest, 0), Hconv(n.Nbody, 0))
|
|
|
|
|
}
|
|
|
|
|
if n.Nelse != nil {
|
|
|
|
|
f += fmt.Sprintf(" else { %v }", Hconv(n.Nelse, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf(" %v;", Nconv(n.Ninit.N, 0))
|
|
|
|
|
} else if n.Nincr != nil {
|
|
|
|
|
f += " ;"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Ntest != nil {
|
|
|
|
|
f += fmt.Sprintf(" %v", Nconv(n.Ntest, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Nincr != nil {
|
|
|
|
|
f += fmt.Sprintf("; %v", Nconv(n.Nincr, 0))
|
2015-02-17 22:13:49 -05:00
|
|
|
} else if simpleinit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += ";"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf(" { %v }", Hconv(n.Nbody, 0))
|
|
|
|
|
|
|
|
|
|
case ORANGE:
|
|
|
|
|
if fmtmode == FErr {
|
|
|
|
|
f += "for loop"
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.List == nil {
|
|
|
|
|
f += fmt.Sprintf("for range %v { %v }", Nconv(n.Right, 0), Hconv(n.Nbody, 0))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf("for %v = range %v { %v }", Hconv(n.List, obj.FmtComma), Nconv(n.Right, 0), Hconv(n.Nbody, 0))
|
|
|
|
|
|
|
|
|
|
case OSELECT,
|
|
|
|
|
OSWITCH:
|
|
|
|
|
if fmtmode == FErr {
|
|
|
|
|
f += fmt.Sprintf("%v statement", Oconv(int(n.Op), 0))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf("%v", Oconv(int(n.Op), obj.FmtSharp))
|
2015-02-17 22:13:49 -05:00
|
|
|
if simpleinit {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf(" %v;", Nconv(n.Ninit.N, 0))
|
|
|
|
|
}
|
|
|
|
|
if n.Ntest != nil {
|
|
|
|
|
f += fmt.Sprintf("%v", Nconv(n.Ntest, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf(" { %v }", Hconv(n.List, 0))
|
|
|
|
|
|
|
|
|
|
case OCASE,
|
|
|
|
|
OXCASE:
|
|
|
|
|
if n.List != nil {
|
|
|
|
|
f += fmt.Sprintf("case %v: %v", Hconv(n.List, obj.FmtComma), Hconv(n.Nbody, 0))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("default: %v", Hconv(n.Nbody, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OBREAK,
|
|
|
|
|
OCONTINUE,
|
|
|
|
|
OGOTO,
|
|
|
|
|
OFALL,
|
|
|
|
|
OXFALL:
|
|
|
|
|
if n.Left != nil {
|
|
|
|
|
f += fmt.Sprintf("%v %v", Oconv(int(n.Op), obj.FmtSharp), Nconv(n.Left, 0))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("%v", Oconv(int(n.Op), obj.FmtSharp))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OEMPTY:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case OLABEL:
|
|
|
|
|
f += fmt.Sprintf("%v: ", Nconv(n.Left, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
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 {
|
|
|
|
|
for n != nil && n.Implicit != 0 && (n.Op == OIND || n.Op == OADDR) {
|
|
|
|
|
n = n.Left
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "<N>"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
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-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v)", Nconv(n, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case OPAREN:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v)", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case ODDDARG:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("... argument")
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OREGISTER:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v", Ctxt.Rconv(int(n.Val.U.Reg)))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OLITERAL: // this is a bit of a mess
|
2014-12-09 06:52:17 -08:00
|
|
|
if n.Orig != nil && n.Orig != n {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2014-12-09 06:52:17 -08:00
|
|
|
f += exprfmt(n.Orig, prec)
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
}
|
2014-12-09 06:52:17 -08:00
|
|
|
if fmtmode == FErr && n.Sym != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2014-12-09 06:52:17 -08:00
|
|
|
f += fmt.Sprintf("%v", Sconv(n.Sym, 0))
|
2015-02-13 14:40:36 -05:00
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if n.Type != nil && n.Type != Types[n.Type.Etype] && n.Type != idealbool && n.Type != idealstring {
|
|
|
|
|
// Need parens when type begins with what might
|
|
|
|
|
// be misinterpreted as a unary operator: * or <-.
|
|
|
|
|
if Isptr[n.Type.Etype] != 0 || (n.Type.Etype == TCHAN && n.Type.Chan == Crecv) {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v)(%v)", Tconv(n.Type, 0), Vconv(&n.Val, 0))
|
|
|
|
|
return f
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v)", Tconv(n.Type, 0), Vconv(&n.Val, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v", Vconv(&n.Val, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
// Special case: name used as local variable in export.
|
|
|
|
|
// _ becomes ~b%d internally; print as _ for export
|
|
|
|
|
case ONAME:
|
|
|
|
|
if fmtmode == FExp && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("_")
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if fmtmode == FExp && n.Sym != nil && !isblank(n) && n.Vargen > 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v·%d", Sconv(n.Sym, 0), n.Vargen)
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 {
|
|
|
|
|
if Isptr[n.Left.Type.Etype] != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v).%v", Tconv(n.Left.Type, 0), Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte))
|
|
|
|
|
return f
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v.%v", Tconv(n.Left.Type, 0), Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
//fallthrough
|
|
|
|
|
case OPACK,
|
|
|
|
|
ONONAME:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v", Sconv(n.Sym, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OTYPE:
|
|
|
|
|
if n.Type == nil && n.Sym != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v", Sconv(n.Sym, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v", Tconv(n.Type, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OTARRAY:
|
|
|
|
|
if n.Left != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("[]%v", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("[]%v", Nconv(n.Right, 0))
|
|
|
|
|
return f // happens before typecheck
|
|
|
|
|
|
|
|
|
|
case OTMAP:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("map[%v]%v", Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OTCHAN:
|
|
|
|
|
switch n.Etype {
|
|
|
|
|
case Crecv:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("<-chan %v", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case Csend:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("chan<- %v", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && n.Left.Etype == Crecv {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("chan (%v)", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("chan %v", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case OTSTRUCT:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("<struct>")
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OTINTER:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("<inter>")
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OTFUNC:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("<func>")
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OCLOSURE:
|
|
|
|
|
if fmtmode == FErr {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "func literal"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if n.Nbody != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v { %v }", Tconv(n.Type, 0), Hconv(n.Nbody, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v { %v }", Tconv(n.Type, 0), Hconv(n.Closure.Nbody, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OCOMPLIT:
|
2015-02-23 16:07:24 -05:00
|
|
|
ptrlit := n.Right != nil && n.Right.Implicit != 0 && n.Right.Type != nil && Isptr[n.Right.Type.Etype] != 0
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FErr {
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Right != nil && n.Right.Type != nil && n.Implicit == 0 {
|
|
|
|
|
if ptrlit {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("&%v literal", Tconv(n.Right.Type.Type, 0))
|
|
|
|
|
return f
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v literal", Tconv(n.Right.Type, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "composite literal"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
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.
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(&%v{ %v })", Tconv(n.Right.Type.Type, 0), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v{ %v })", Nconv(n.Right, 0), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OPTRLIT:
|
|
|
|
|
if fmtmode == FExp && n.Left.Implicit != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("&%v", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OSTRUCTLIT:
|
|
|
|
|
if fmtmode == FExp { // requires special handling of field names
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Implicit != 0 {
|
|
|
|
|
f += "{"
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("(%v{", Tconv(n.Type, 0))
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := n.List; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf(" %v:%v", Sconv(l.N.Left.Sym, obj.FmtShort|obj.FmtByte), Nconv(l.N.Right, 0))
|
|
|
|
|
|
|
|
|
|
if l.Next != nil {
|
|
|
|
|
f += ","
|
|
|
|
|
} else {
|
|
|
|
|
f += " "
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Implicit == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
f += "})"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
f += "}"
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// fallthrough
|
|
|
|
|
|
|
|
|
|
case OARRAYLIT,
|
|
|
|
|
OMAPLIT:
|
|
|
|
|
if fmtmode == FErr {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v literal", Tconv(n.Type, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if fmtmode == FExp && n.Implicit != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("{ %v }", Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v{ %v })", Tconv(n.Type, 0), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OKEY:
|
|
|
|
|
if n.Left != nil && n.Right != nil {
|
|
|
|
|
if fmtmode == FExp && n.Left.Type != nil && n.Left.Type.Etype == TFIELD {
|
|
|
|
|
// requires special handling of field names
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v:%v", Sconv(n.Left.Sym, obj.FmtShort|obj.FmtByte), Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v:%v", Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Left == nil && n.Right != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf(":%v", Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Left != nil && n.Right == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v:", Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += ":"
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OXDOT,
|
|
|
|
|
ODOT,
|
|
|
|
|
ODOTPTR,
|
|
|
|
|
ODOTINTER,
|
|
|
|
|
ODOTMETH,
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
f += fmt.Sprintf(".%v", Sconv(n.Right.Sym, obj.FmtShort|obj.FmtByte))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
f += fmt.Sprintf(".(%v)", Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
f += fmt.Sprintf(".(%v)", Tconv(n.Type, 0))
|
|
|
|
|
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)
|
|
|
|
|
f += fmt.Sprintf("[%v]", Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OCOPY,
|
|
|
|
|
OCOMPLEX:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v, %v)", Oconv(int(n.Op), obj.FmtSharp), Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OCONV,
|
|
|
|
|
OCONVIFACE,
|
|
|
|
|
OCONVNOP,
|
|
|
|
|
OARRAYBYTESTR,
|
|
|
|
|
OARRAYRUNESTR,
|
|
|
|
|
OSTRARRAYBYTE,
|
|
|
|
|
OSTRARRAYRUNE,
|
|
|
|
|
ORUNESTR:
|
|
|
|
|
if n.Type == nil || n.Type.Sym == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("(%v)(%v)", Tconv(n.Type, 0), Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if n.Left != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v)", Tconv(n.Type, 0), Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v)", Tconv(n.Type, 0), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OREAL,
|
|
|
|
|
OIMAG,
|
|
|
|
|
OAPPEND,
|
|
|
|
|
OCAP,
|
|
|
|
|
OCLOSE,
|
|
|
|
|
ODELETE,
|
|
|
|
|
OLEN,
|
|
|
|
|
OMAKE,
|
|
|
|
|
ONEW,
|
|
|
|
|
OPANIC,
|
|
|
|
|
ORECOVER,
|
|
|
|
|
OPRINT,
|
|
|
|
|
OPRINTN:
|
|
|
|
|
if n.Left != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v)", Oconv(int(n.Op), obj.FmtSharp), Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if n.Isddd != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v...)", Oconv(int(n.Op), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v(%v)", Oconv(int(n.Op), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OCALL,
|
|
|
|
|
OCALLFUNC,
|
|
|
|
|
OCALLINTER,
|
|
|
|
|
OCALLMETH:
|
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.Isddd != 0 {
|
|
|
|
|
f += fmt.Sprintf("(%v...)", Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
f += fmt.Sprintf("(%v)", Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OMAKEMAP,
|
|
|
|
|
OMAKECHAN,
|
|
|
|
|
OMAKESLICE:
|
|
|
|
|
if n.List != nil { // pre-typecheck
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("make(%v, %v)", Tconv(n.Type, 0), Hconv(n.List, obj.FmtComma))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
if n.Right != nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("make(%v, %v, %v)", Tconv(n.Type, 0), Nconv(n.Left, 0), Nconv(n.Right, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2014-12-08 19:17:37 -08:00
|
|
|
if n.Left != nil && (n.Op == OMAKESLICE || !isideal(n.Left.Type)) {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("make(%v, %v)", Tconv(n.Type, 0), Nconv(n.Left, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("make(%v)", Tconv(n.Type, 0))
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
// 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 {
|
|
|
|
|
f += fmt.Sprintf("%v ", Oconv(int(n.Op), obj.FmtSharp))
|
|
|
|
|
} else {
|
|
|
|
|
f += fmt.Sprintf("%v", Oconv(int(n.Op), obj.FmtSharp))
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
f += fmt.Sprintf(" %v ", Oconv(int(n.Op), obj.FmtSharp))
|
|
|
|
|
f += exprfmt(n.Right, nprec+1)
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
case OADDSTR:
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
|
|
|
|
for l := n.List; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l != n.List {
|
|
|
|
|
f += fmt.Sprintf(" + ")
|
|
|
|
|
}
|
|
|
|
|
f += exprfmt(l.N, nprec)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
f += fmt.Sprintf(" %v ", Oconv(int(n.Etype), obj.FmtSharp))
|
|
|
|
|
f += exprfmt(n.Right, nprec+1)
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("<node %v>", Oconv(int(n.Op), 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func nodefmt(n *Node, flag int) 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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if flag&obj.FmtLong != 0 /*untyped*/ && t != nil {
|
|
|
|
|
if t.Etype == TNIL {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("nil")
|
|
|
|
|
return f
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += fmt.Sprintf("%v (type %v)", Nconv(n, 0), Tconv(t, 0))
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO inlining produces expressions with ninits. we can't print these yet.
|
|
|
|
|
|
|
|
|
|
if opprec[n.Op] < 0 {
|
|
|
|
|
return stmtfmt(n)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var f string
|
2015-02-13 14:40:36 -05:00
|
|
|
f += exprfmt(n, 0)
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dumpdepth int
|
|
|
|
|
|
|
|
|
|
func indent(s string) string {
|
|
|
|
|
return s + "\n" + strings.Repeat(". ", dumpdepth)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func nodedump(n *Node, flag int) string {
|
|
|
|
|
if n == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
recur := flag&obj.FmtShort == 0 /*untyped*/
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-17 22:13:49 -05:00
|
|
|
if recur {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp = indent(fp)
|
|
|
|
|
if dumpdepth > 10 {
|
|
|
|
|
fp += "..."
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Ninit != nil {
|
|
|
|
|
fp += fmt.Sprintf("%v-init%v", Oconv(int(n.Op), 0), Hconv(n.Ninit, 0))
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fmtprint(fp, "[%p]", n);
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
|
|
|
|
fp += fmt.Sprintf("%v%v", Oconv(int(n.Op), 0), Jconv(n, 0))
|
|
|
|
|
|
|
|
|
|
case OREGISTER,
|
|
|
|
|
OINDREG:
|
|
|
|
|
fp += fmt.Sprintf("%v-%v%v", Oconv(int(n.Op), 0), Ctxt.Rconv(int(n.Val.U.Reg)), Jconv(n, 0))
|
|
|
|
|
|
|
|
|
|
case OLITERAL:
|
|
|
|
|
fp += fmt.Sprintf("%v-%v%v", Oconv(int(n.Op), 0), Vconv(&n.Val, 0), Jconv(n, 0))
|
|
|
|
|
|
|
|
|
|
case ONAME,
|
|
|
|
|
ONONAME:
|
|
|
|
|
if n.Sym != nil {
|
|
|
|
|
fp += fmt.Sprintf("%v-%v%v", Oconv(int(n.Op), 0), Sconv(n.Sym, 0), Jconv(n, 0))
|
|
|
|
|
} else {
|
|
|
|
|
fp += fmt.Sprintf("%v%v", Oconv(int(n.Op), 0), Jconv(n, 0))
|
|
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
if recur && n.Type == nil && n.Ntype != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-ntype%v", Oconv(int(n.Op), 0), Nconv(n.Ntype, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OASOP:
|
|
|
|
|
fp += fmt.Sprintf("%v-%v%v", Oconv(int(n.Op), 0), Oconv(int(n.Etype), 0), Jconv(n, 0))
|
|
|
|
|
|
|
|
|
|
case OTYPE:
|
|
|
|
|
fp += fmt.Sprintf("%v %v%v type=%v", Oconv(int(n.Op), 0), Sconv(n.Sym, 0), Jconv(n, 0), Tconv(n.Type, 0))
|
2015-02-17 22:13:49 -05:00
|
|
|
if recur && n.Type == nil && n.Ntype != nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-ntype%v", Oconv(int(n.Op), 0), Nconv(n.Ntype, 0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Sym != nil && n.Op != ONAME {
|
|
|
|
|
fp += fmt.Sprintf(" %v G%d", Sconv(n.Sym, 0), n.Vargen)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Type != nil {
|
|
|
|
|
fp += fmt.Sprintf(" %v", Tconv(n.Type, 0))
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if recur {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n.Left != nil {
|
|
|
|
|
fp += fmt.Sprintf("%v", Nconv(n.Left, 0))
|
|
|
|
|
}
|
|
|
|
|
if n.Right != nil {
|
|
|
|
|
fp += fmt.Sprintf("%v", Nconv(n.Right, 0))
|
|
|
|
|
}
|
|
|
|
|
if n.List != nil {
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-list%v", Oconv(int(n.Op), 0), Hconv(n.List, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Rlist != nil {
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-rlist%v", Oconv(int(n.Op), 0), Hconv(n.Rlist, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Ntest != nil {
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-test%v", Oconv(int(n.Op), 0), Nconv(n.Ntest, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Nbody != nil {
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-body%v", Oconv(int(n.Op), 0), Hconv(n.Nbody, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Nelse != nil {
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-else%v", Oconv(int(n.Op), 0), Hconv(n.Nelse, 0))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Nincr != nil {
|
|
|
|
|
fp = indent(fp)
|
|
|
|
|
fp += fmt.Sprintf("%v-incr%v", Oconv(int(n.Op), 0), Nconv(n.Nincr, 0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt "%S": syms
|
|
|
|
|
// Flags: "%hS" suppresses qualifying with package
|
|
|
|
|
func Sconv(s *Sym, flag int) string {
|
|
|
|
|
if flag&obj.FmtLong != 0 /*untyped*/ {
|
|
|
|
|
panic("linksymfmt")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<S>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.Name == "_" {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "_"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
|
|
|
|
sm := setfmode(&flag)
|
|
|
|
|
var r int
|
2015-02-13 14:40:36 -05:00
|
|
|
_ = r
|
|
|
|
|
str := symfmt(s, flag)
|
|
|
|
|
flag = sf
|
|
|
|
|
fmtmode = sm
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
func Tconv(t *Type, flag int) string {
|
|
|
|
|
if t == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<T>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Trecur > 4 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<...>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Trecur++
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
|
|
|
|
sm := setfmode(&flag)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
|
|
|
|
|
fmtpkgpfx++
|
|
|
|
|
}
|
|
|
|
|
if fmtpkgpfx != 0 {
|
|
|
|
|
flag |= obj.FmtUnsigned
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var r int
|
2015-02-13 14:40:36 -05:00
|
|
|
_ = r
|
|
|
|
|
str := typefmt(t, flag)
|
|
|
|
|
|
|
|
|
|
if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
|
|
|
|
|
fmtpkgpfx--
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
|
|
|
|
fmtmode = sm
|
|
|
|
|
t.Trecur--
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt '%N': Nodes.
|
|
|
|
|
// Flags: 'l' suffix with "(type %T)" where possible
|
|
|
|
|
// '+h' in debug mode, don't recurse, no multiline output
|
|
|
|
|
func Nconv(n *Node, flag int) string {
|
|
|
|
|
if n == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<N>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
|
|
|
|
sm := setfmode(&flag)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var r int
|
2015-02-13 14:40:36 -05:00
|
|
|
_ = r
|
|
|
|
|
var str string
|
|
|
|
|
switch fmtmode {
|
|
|
|
|
case FErr,
|
|
|
|
|
FExp:
|
|
|
|
|
str = nodefmt(n, flag)
|
|
|
|
|
|
|
|
|
|
case FDbg:
|
|
|
|
|
dumpdepth++
|
|
|
|
|
str = nodedump(n, flag)
|
|
|
|
|
dumpdepth--
|
|
|
|
|
|
|
|
|
|
default:
|
2015-02-23 14:02:27 -05:00
|
|
|
Fatal("unhandled %%N mode")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
|
|
|
|
fmtmode = sm
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fmt '%H': NodeList.
|
|
|
|
|
// Flags: all those of %N plus ',': separate with comma's instead of semicolons.
|
|
|
|
|
func Hconv(l *NodeList, flag int) string {
|
|
|
|
|
if l == nil && fmtmode == FDbg {
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
fp += "<nil>"
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
sf := flag
|
|
|
|
|
sm := setfmode(&flag)
|
|
|
|
|
var r int
|
2015-02-13 14:40:36 -05:00
|
|
|
_ = r
|
2015-02-23 16:07:24 -05:00
|
|
|
sep := "; "
|
2015-02-13 14:40:36 -05:00
|
|
|
if fmtmode == FDbg {
|
|
|
|
|
sep = "\n"
|
|
|
|
|
} else if flag&obj.FmtComma != 0 /*untyped*/ {
|
|
|
|
|
sep = ", "
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var fp string
|
2015-02-13 14:40:36 -05:00
|
|
|
for ; l != nil; l = l.Next {
|
|
|
|
|
fp += fmt.Sprintf("%v", Nconv(l.N, 0))
|
|
|
|
|
if l.Next != nil {
|
|
|
|
|
fp += sep
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flag = sf
|
|
|
|
|
fmtmode = sm
|
|
|
|
|
return fp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func dumplist(s string, l *NodeList) {
|
|
|
|
|
fmt.Printf("%s%v\n", s, Hconv(l, obj.FmtSign))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Dump(s string, n *Node) {
|
|
|
|
|
fmt.Printf("%s [%p]%v\n", s, n, Nconv(n, obj.FmtSign))
|
|
|
|
|
}
|