@@ -537,7 +537,7 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer {
537
537
if t == bytetype || t == runetype {
538
538
// in %-T mode collapse rune and byte with their originals.
539
539
if fmtmode != FTypeId {
540
- return p .s ( sconv (t .Sym , FmtShort ) )
540
+ return p .sconv (t .Sym , FmtShort )
541
541
}
542
542
t = Types [t .Etype ]
543
543
}
@@ -554,19 +554,19 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer {
554
554
if t .Vargen != 0 {
555
555
return p .f ("%v·%d" , sconv (t .Sym , FmtShort ), t .Vargen )
556
556
}
557
- return p .s ( sconv (t .Sym , FmtShort ) )
557
+ return p .sconv (t .Sym , FmtShort )
558
558
}
559
559
560
560
if flag & FmtUnsigned != 0 {
561
- return p .s ( sconv (t .Sym , FmtUnsigned ) )
561
+ return p .sconv (t .Sym , FmtUnsigned )
562
562
}
563
563
564
564
if t .Sym .Pkg == localpkg && t .Vargen != 0 {
565
565
return p .f ("%v·%d" , t .Sym , t .Vargen )
566
566
}
567
567
}
568
568
569
- return p .s ( sconv (t .Sym , 0 ) )
569
+ return p .sconv (t .Sym , 0 )
570
570
}
571
571
572
572
if int (t .Etype ) < len (basicnames ) && basicnames [t .Etype ] != "" {
@@ -629,11 +629,11 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer {
629
629
// Wrong interface definitions may have types lacking a symbol.
630
630
break
631
631
case exportname (f .Sym .Name ):
632
- p .s ( sconv (f .Sym , FmtShort ) )
632
+ p .sconv (f .Sym , FmtShort )
633
633
default :
634
- p .s ( sconv (f .Sym , FmtUnsigned ) )
634
+ p .sconv (f .Sym , FmtUnsigned )
635
635
}
636
- p .s ( Tconv (f .Type , FmtShort ) )
636
+ p .Tconv (f .Type , FmtShort )
637
637
}
638
638
if t .NumFields () != 0 {
639
639
p .s (" " )
@@ -646,24 +646,24 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer {
646
646
} else {
647
647
if t .Recv () != nil {
648
648
p .s ("method" )
649
- p .s ( Tconv (t .Recvs (), 0 ) )
649
+ p .Tconv (t .Recvs (), 0 )
650
650
p .s (" " )
651
651
}
652
652
p .s ("func" )
653
653
}
654
- p .s ( Tconv (t .Params (), 0 ) )
654
+ p .Tconv (t .Params (), 0 )
655
655
656
656
switch t .Results ().NumFields () {
657
657
case 0 :
658
658
// nothing to do
659
659
660
660
case 1 :
661
661
p .s (" " )
662
- p .s ( Tconv (t .Results ().Field (0 ).Type , 0 ) ) // struct->field->field's type
662
+ p .Tconv (t .Results ().Field (0 ).Type , 0 ) // struct->field->field's type
663
663
664
664
default :
665
665
p .s (" " )
666
- p .s ( Tconv (t .Results (), 0 ) )
666
+ p .Tconv (t .Results (), 0 )
667
667
}
668
668
return p
669
669
@@ -777,7 +777,7 @@ func (p *printer) stmtfmt(n *Node) *printer {
777
777
if n .Left != nil {
778
778
p .f ("%v %v" , n .Left , n .Right )
779
779
} else {
780
- p .s ( Nconv (n .Right , 0 ) )
780
+ p .Nconv (n .Right , 0 )
781
781
}
782
782
783
783
// Don't export "v = <N>" initializing statements, hope they're always
@@ -1075,7 +1075,7 @@ func (p *printer) exprfmt(n *Node, prec int) *printer {
1075
1075
return p .exprfmt (n .Orig , prec )
1076
1076
}
1077
1077
if n .Sym != nil {
1078
- return p .s ( sconv (n .Sym , 0 ) )
1078
+ return p .sconv (n .Sym , 0 )
1079
1079
}
1080
1080
}
1081
1081
if n .Val ().Ctype () == CTNIL && n .Orig != nil && n .Orig != n {
@@ -1102,13 +1102,13 @@ func (p *printer) exprfmt(n *Node, prec int) *printer {
1102
1102
fallthrough
1103
1103
1104
1104
case OPACK , ONONAME :
1105
- return p .s ( sconv (n .Sym , 0 ) )
1105
+ return p .sconv (n .Sym , 0 )
1106
1106
1107
1107
case OTYPE :
1108
1108
if n .Type == nil && n .Sym != nil {
1109
- return p .s ( sconv (n .Sym , 0 ) )
1109
+ return p .sconv (n .Sym , 0 )
1110
1110
}
1111
- return p .s ( Tconv (n .Type , 0 ) )
1111
+ return p .Tconv (n .Type , 0 )
1112
1112
1113
1113
case OTARRAY :
1114
1114
if n .Left != nil {
@@ -1450,10 +1450,10 @@ func (p *printer) nodedump(n *Node, flag FmtFlag) *printer {
1450
1450
1451
1451
if recur {
1452
1452
if n .Left != nil {
1453
- p .s ( Nconv (n .Left , 0 ) )
1453
+ p .Nconv (n .Left , 0 )
1454
1454
}
1455
1455
if n .Right != nil {
1456
- p .s ( Nconv (n .Right , 0 ) )
1456
+ p .Nconv (n .Right , 0 )
1457
1457
}
1458
1458
if n .List .Len () != 0 {
1459
1459
p .indent ()
@@ -1474,25 +1474,33 @@ func (p *printer) nodedump(n *Node, flag FmtFlag) *printer {
1474
1474
return p
1475
1475
}
1476
1476
1477
+ func (s * Sym ) Print (p * printer ) {
1478
+ p .sconv (s , 0 )
1479
+ }
1480
+
1481
+ var _ Printable = new (Sym ) // verify that Sym implements Printable
1482
+
1477
1483
func (s * Sym ) String () string {
1478
1484
return sconv (s , 0 )
1479
1485
}
1480
1486
1481
1487
// Fmt "%S": syms
1482
1488
// Flags: "%hS" suppresses qualifying with package
1483
1489
func sconv (s * Sym , flag FmtFlag ) string {
1484
- var p printer
1490
+ return new (printer ).sconv (s , flag ).String ()
1491
+ }
1485
1492
1493
+ func (p * printer ) sconv (s * Sym , flag FmtFlag ) * printer {
1486
1494
if flag & FmtLong != 0 {
1487
1495
panic ("linksymfmt" )
1488
1496
}
1489
1497
1490
1498
if s == nil {
1491
- return "<S>"
1499
+ return p . s ( "<S>" )
1492
1500
}
1493
1501
1494
1502
if s .Name == "_" {
1495
- return "_"
1503
+ return p . s ( "_" )
1496
1504
}
1497
1505
1498
1506
sf := flag
@@ -1502,9 +1510,15 @@ func sconv(s *Sym, flag FmtFlag) string {
1502
1510
fmtmode = sm
1503
1511
fmtbody = sb
1504
1512
1505
- return p . String ()
1513
+ return p
1506
1514
}
1507
1515
1516
+ func (t * Type ) Print (p * printer ) {
1517
+ p .Tconv (t , 0 )
1518
+ }
1519
+
1520
+ var _ Printable = new (Type ) // verify Type implements Printable
1521
+
1508
1522
func (t * Type ) String () string {
1509
1523
return Tconv (t , 0 )
1510
1524
}
@@ -1595,14 +1609,16 @@ func Fldconv(f *Field, flag FmtFlag) string {
1595
1609
// 'h' omit 'func' and receiver from function types, short type names
1596
1610
// 'u' package name, not prefix (FTypeId mode, sticky)
1597
1611
func Tconv (t * Type , flag FmtFlag ) string {
1598
- var p printer
1612
+ return new (printer ).Tconv (t , flag ).String ()
1613
+ }
1599
1614
1615
+ func (p * printer ) Tconv (t * Type , flag FmtFlag ) * printer {
1600
1616
if t == nil {
1601
- return "<T>"
1617
+ return p . s ( "<T>" )
1602
1618
}
1603
1619
1604
1620
if t .Trecur > 4 {
1605
- return "<...>"
1621
+ return p . s ( "<...>" )
1606
1622
}
1607
1623
1608
1624
t .Trecur ++
@@ -1627,9 +1643,15 @@ func Tconv(t *Type, flag FmtFlag) string {
1627
1643
fmtmode = sm
1628
1644
t .Trecur --
1629
1645
1630
- return p .String ()
1646
+ return p
1647
+ }
1648
+
1649
+ func (n * Node ) Print (p * printer ) {
1650
+ p .Nconv (n , 0 )
1631
1651
}
1632
1652
1653
+ var _ Printable = new (Node ) // verify that Node implements Printable
1654
+
1633
1655
func (n * Node ) String () string {
1634
1656
return Nconv (n , 0 )
1635
1657
}
@@ -1638,10 +1660,12 @@ func (n *Node) String() string {
1638
1660
// Flags: 'l' suffix with "(type %T)" where possible
1639
1661
// '+h' in debug mode, don't recurse, no multiline output
1640
1662
func Nconv (n * Node , flag FmtFlag ) string {
1641
- var p printer
1663
+ return new (printer ).Nconv (n , flag ).String ()
1664
+ }
1642
1665
1666
+ func (p * printer ) Nconv (n * Node , flag FmtFlag ) * printer {
1643
1667
if n == nil {
1644
- return "<N>"
1668
+ return p . s ( "<N>" )
1645
1669
}
1646
1670
sf := flag
1647
1671
sm , sb := setfmode (& flag )
@@ -1663,20 +1687,28 @@ func Nconv(n *Node, flag FmtFlag) string {
1663
1687
fmtbody = sb
1664
1688
fmtmode = sm
1665
1689
1666
- return p . String ()
1690
+ return p
1667
1691
}
1668
1692
1693
+ func (n Nodes ) Print (p * printer ) {
1694
+ p .hconv (n , 0 )
1695
+ }
1696
+
1697
+ var _ Printable = Nodes {} // verify that Nodes implements Printable
1698
+
1669
1699
func (n Nodes ) String () string {
1670
1700
return hconv (n , 0 )
1671
1701
}
1672
1702
1673
1703
// Fmt '%H': Nodes.
1674
1704
// Flags: all those of %N plus ',': separate with comma's instead of semicolons.
1675
1705
func hconv (l Nodes , flag FmtFlag ) string {
1676
- var p printer
1706
+ return new (printer ).hconv (l , flag ).String ()
1707
+ }
1677
1708
1709
+ func (p * printer ) hconv (l Nodes , flag FmtFlag ) * printer {
1678
1710
if l .Len () == 0 && fmtmode == FDbg {
1679
- return "<nil>"
1711
+ return p . s ( "<nil>" )
1680
1712
}
1681
1713
1682
1714
sf := flag
@@ -1689,7 +1721,7 @@ func hconv(l Nodes, flag FmtFlag) string {
1689
1721
}
1690
1722
1691
1723
for i , n := range l .Slice () {
1692
- p .s ( Nconv (n , 0 ) )
1724
+ p .Nconv (n , 0 )
1693
1725
if i + 1 < l .Len () {
1694
1726
p .s (sep )
1695
1727
}
@@ -1699,7 +1731,7 @@ func hconv(l Nodes, flag FmtFlag) string {
1699
1731
fmtbody = sb
1700
1732
fmtmode = sm
1701
1733
1702
- return p . String ()
1734
+ return p
1703
1735
}
1704
1736
1705
1737
func dumplist (s string , l Nodes ) {
@@ -1715,6 +1747,13 @@ type printer struct {
1715
1747
buf []byte
1716
1748
}
1717
1749
1750
+ // Types that implement the Printable interface print
1751
+ // to a printer directly without first converting to
1752
+ // a string.
1753
+ type Printable interface {
1754
+ Print (* printer )
1755
+ }
1756
+
1718
1757
// printer implements io.Writer.
1719
1758
func (p * printer ) Write (buf []byte ) (n int , err error ) {
1720
1759
p .buf = append (p .buf , buf ... )
@@ -1733,8 +1772,27 @@ func (p *printer) s(s string) *printer {
1733
1772
}
1734
1773
1735
1774
// f prints the formatted arguments to p and returns p.
1775
+ // %v arguments that implement the Printable interface
1776
+ // are printed to p via that interface.
1736
1777
func (p * printer ) f (format string , args ... interface {}) * printer {
1737
- fmt .Fprintf (p , format , args ... )
1778
+ for len (format ) > 0 {
1779
+ i := strings .IndexByte (format , '%' )
1780
+ if i < 0 || i + 1 >= len (format ) || format [i + 1 ] != 'v' || len (args ) == 0 {
1781
+ break // don't be clever, let fmt.Fprintf handle this for now
1782
+ }
1783
+ // found "%v" and at least one argument (and no other %x before)
1784
+ p .s (format [:i ])
1785
+ format = format [i + len ("%v" ):]
1786
+ if a , ok := args [0 ].(Printable ); ok {
1787
+ a .Print (p )
1788
+ } else {
1789
+ fmt .Fprintf (p , "%v" , args [0 ])
1790
+ }
1791
+ args = args [1 :]
1792
+ }
1793
+ if len (format ) > 0 || len (args ) > 0 {
1794
+ fmt .Fprintf (p , format , args ... )
1795
+ }
1738
1796
return p
1739
1797
}
1740
1798
0 commit comments