From: Robert Griesemer Date: Tue, 30 Aug 2016 21:13:41 +0000 (-0700) Subject: cmd/compile: implement fmt.Formatter for *Node formats %s, %v, %j X-Git-Tag: go1.8beta1~1441 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=adcd34c732d01d60ca336627fc0fd7647d46a0c1;p=gostls13.git cmd/compile: implement fmt.Formatter for *Node formats %s, %v, %j Change-Id: I44ee5843bb9dfd65b9a18091f365355e84888f21 Reviewed-on: https://go-review.googlesource.com/28330 Reviewed-by: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 0fd514fbaf..86d05d3db2 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -998,10 +998,10 @@ func escassign(e *EscState, dst, src *Node, step *EscStep) { } if Debug['m'] > 2 { - fmt.Printf("%v:[%d] %v escassign: %v(%v)[%v] = %v(%v)[%v]\n", + fmt.Printf("%v:[%d] %v escassign: %v(%0j)[%v] = %v(%0j)[%v]\n", linestr(lineno), e.loopdepth, funcSym(Curfn), - Nconv(dst, FmtShort), jconv(dst, FmtShort), dst.Op, - Nconv(src, FmtShort), jconv(src, FmtShort), src.Op) + Nconv(dst, FmtShort), dst, dst.Op, + Nconv(src, FmtShort), src, src.Op) } setlineno(dst) @@ -1756,8 +1756,8 @@ func escwalkBody(e *EscState, level Level, dst *Node, src *Node, step *EscStep, } if Debug['m'] > 2 { - fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %v(%v) scope:%v[%d] extraloopdepth=%v\n", - level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", src.Op, Nconv(src, FmtShort), jconv(src, FmtShort), e.curfnSym(src), srcE.Escloopdepth, extraloopdepth) + fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %v(%0j) scope:%v[%d] extraloopdepth=%v\n", + level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", src.Op, Nconv(src, FmtShort), src, e.curfnSym(src), srcE.Escloopdepth, extraloopdepth) } e.pdepth++ diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index 8f8976c97c..816ccce1c2 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -17,17 +17,48 @@ import ( // See the respective function's documentation for details. type FmtFlag int -const ( - FmtLeft FmtFlag = 1 << iota // "-" - FmtSharp // "#" - FmtSign // "+" - FmtUnsigned // "u" - FmtShort // "h" - FmtLong // "l" - FmtComma // "," - FmtByte // "hh" +const ( // fmt.Format flag/width/prec + FmtLeft FmtFlag = 1 << iota // "-" => '-' + FmtSharp // "#" => '#' + FmtSign // "+" => '+' + FmtUnsigned // "u" => ' ' + FmtShort // "h" => hasWidth && width == 1 + FmtLong // "l" => hasWidth && width == 2 + FmtComma // "," => '.' (== hasPrec) + FmtByte // "hh" => '0' ) +func fmtFlag(s fmt.State) FmtFlag { + var flag FmtFlag + if s.Flag('-') { + flag |= FmtLeft + } + if s.Flag('#') { + flag |= FmtSharp + } + if s.Flag('+') { + flag |= FmtSign + } + if s.Flag(' ') { + flag |= FmtUnsigned + } + if w, ok := s.Width(); ok { + switch w { + case 1: + flag |= FmtShort + case 2: + flag |= FmtLong + } + } + if _, ok := s.Precision(); ok { + flag |= FmtComma + } + if s.Flag('0') { + flag |= FmtByte + } + return flag +} + // // Format conversions // %L int Line numbers @@ -213,49 +244,60 @@ var classnames = []string{ "PFUNC", } -// Node details -func jconv(n *Node, flag FmtFlag) string { - var p printer +func (n *Node) Format(s fmt.State, format rune) { + switch format { + case 's', 'v': + fmt.Fprint(s, Nconv(n, fmtFlag(s))) - c := flag & FmtShort + case 'j': + n.jconv(s) + + default: + fmt.Fprintf(s, "%%!%c(*Node=%p)", format, n) + } +} + +// Node details +func (n *Node) jconv(s fmt.State) { + c := fmtFlag(s) & FmtShort if c == 0 && n.Ullman != 0 { - p.f(" u(%d)", n.Ullman) + fmt.Fprintf(s, " u(%d)", n.Ullman) } if c == 0 && n.Addable { - p.f(" a(%v)", n.Addable) + fmt.Fprintf(s, " a(%v)", n.Addable) } if c == 0 && n.Name != nil && n.Name.Vargen != 0 { - p.f(" g(%d)", n.Name.Vargen) + fmt.Fprintf(s, " g(%d)", n.Name.Vargen) } if n.Lineno != 0 { - p.f(" l(%d)", n.Lineno) + fmt.Fprintf(s, " l(%d)", n.Lineno) } if c == 0 && n.Xoffset != BADWIDTH { - p.f(" x(%d%+d)", n.Xoffset, stkdelta[n]) + fmt.Fprintf(s, " x(%d%+d)", n.Xoffset, stkdelta[n]) } if n.Class != 0 { if int(n.Class) < len(classnames) { - p.f(" class(%s)", classnames[n.Class]) + fmt.Fprintf(s, " class(%s)", classnames[n.Class]) } else { - p.f(" class(%d?)", n.Class) + fmt.Fprintf(s, " class(%d?)", n.Class) } } if n.Colas { - p.f(" colas(%v)", n.Colas) + fmt.Fprintf(s, " colas(%v)", n.Colas) } if n.Name != nil && n.Name.Funcdepth != 0 { - p.f(" f(%d)", n.Name.Funcdepth) + fmt.Fprintf(s, " f(%d)", n.Name.Funcdepth) } if n.Func != nil && n.Func.Depth != 0 { - p.f(" ff(%d)", n.Func.Depth) + fmt.Fprintf(s, " ff(%d)", n.Func.Depth) } switch n.Esc { @@ -263,66 +305,64 @@ func jconv(n *Node, flag FmtFlag) string { break case EscHeap: - p.s(" esc(h)") + fmt.Fprint(s, " esc(h)") case EscScope: - p.s(" esc(s)") + fmt.Fprint(s, " esc(s)") case EscNone: - p.s(" esc(no)") + fmt.Fprint(s, " esc(no)") case EscNever: if c == 0 { - p.s(" esc(N)") + fmt.Fprint(s, " esc(N)") } default: - p.f(" esc(%d)", n.Esc) + fmt.Fprintf(s, " esc(%d)", n.Esc) } if e, ok := n.Opt().(*NodeEscState); ok && e.Escloopdepth != 0 { - p.f(" ld(%d)", e.Escloopdepth) + fmt.Fprintf(s, " ld(%d)", e.Escloopdepth) } if c == 0 && n.Typecheck != 0 { - p.f(" tc(%d)", n.Typecheck) + fmt.Fprintf(s, " tc(%d)", n.Typecheck) } if c == 0 && n.IsStatic { - p.s(" static") + fmt.Fprint(s, " static") } if n.Isddd { - p.f(" isddd(%v)", n.Isddd) + fmt.Fprintf(s, " isddd(%v)", n.Isddd) } if n.Implicit { - p.f(" implicit(%v)", n.Implicit) + fmt.Fprintf(s, " implicit(%v)", n.Implicit) } if n.Embedded != 0 { - p.f(" embedded(%d)", n.Embedded) + fmt.Fprintf(s, " embedded(%d)", n.Embedded) } if n.Addrtaken { - p.s(" addrtaken") + fmt.Fprint(s, " addrtaken") } if n.Assigned { - p.s(" assigned") + fmt.Fprint(s, " assigned") } if n.Bounded { - p.s(" bounded") + fmt.Fprint(s, " bounded") } if n.NonNil { - p.s(" nonnil") + fmt.Fprint(s, " nonnil") } if c == 0 && n.Used { - p.f(" used(%v)", n.Used) + fmt.Fprintf(s, " used(%v)", n.Used) } - - return p.String() } // Fmt "%V": Values @@ -1404,19 +1444,19 @@ func (p *printer) nodedump(n *Node, flag FmtFlag) *printer { switch n.Op { default: - p.f("%v%v", n.Op, jconv(n, 0)) + p.f("%v%j", n.Op, n) case OREGISTER, OINDREG: - p.f("%v-%v%v", n.Op, obj.Rconv(int(n.Reg)), jconv(n, 0)) + p.f("%v-%v%j", n.Op, obj.Rconv(int(n.Reg)), n) case OLITERAL: - p.f("%v-%v%v", n.Op, vconv(n.Val(), 0), jconv(n, 0)) + p.f("%v-%v%j", n.Op, vconv(n.Val(), 0), n) case ONAME, ONONAME: if n.Sym != nil { - p.f("%v-%v%v", n.Op, n.Sym, jconv(n, 0)) + p.f("%v-%v%j", n.Op, n.Sym, n) } else { - p.f("%v%v", n.Op, jconv(n, 0)) + p.f("%v%j", n.Op, n) } if recur && n.Type == nil && n.Name != nil && n.Name.Param != nil && n.Name.Param.Ntype != nil { p.indent() @@ -1424,10 +1464,10 @@ func (p *printer) nodedump(n *Node, flag FmtFlag) *printer { } case OASOP: - p.f("%v-%v%v", n.Op, Op(n.Etype), jconv(n, 0)) + p.f("%v-%v%j", n.Op, Op(n.Etype), n) case OTYPE: - p.f("%v %v%v type=%v", n.Op, n.Sym, jconv(n, 0), n.Type) + p.f("%v %v%j type=%v", n.Op, n.Sym, n, n.Type) if recur && n.Type == nil && n.Name.Param.Ntype != nil { p.indent() p.f("%v-ntype%v", n.Op, n.Name.Param.Ntype)