1
2
3
4
5
6
7 package ast
8
9 import (
10 "fmt"
11 "go/token"
12 "io"
13 "os"
14 "reflect"
15 )
16
17
18 type FieldFilter func(name string, value reflect.Value) bool
19
20
21
22 func NotNilFilter(_ string, v reflect.Value) bool {
23 switch v.Kind() {
24 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
25 return !v.IsNil()
26 }
27 return true
28 }
29
30
31
32
33
34
35
36
37
38
39 func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (n int, err os.Error) {
40
41 p := printer{
42 output: w,
43 fset: fset,
44 filter: f,
45 ptrmap: make(map[interface{}]int),
46 last: '\n',
47 }
48
49
50 defer func() {
51 n = p.written
52 if e := recover(); e != nil {
53 err = e.(localError).err
54 }
55 }()
56
57
58 if x == nil {
59 p.printf("nil\n")
60 return
61 }
62 p.print(reflect.ValueOf(x))
63 p.printf("\n")
64
65 return
66 }
67
68
69
70 func Print(fset *token.FileSet, x interface{}) (int, os.Error) {
71 return Fprint(os.Stdout, fset, x, NotNilFilter)
72 }
73
74 type printer struct {
75 output io.Writer
76 fset *token.FileSet
77 filter FieldFilter
78 ptrmap map[interface{}]int
79 written int
80 indent int
81 last byte
82 line int
83 }
84
85 var indent = []byte(". ")
86
87 func (p *printer) Write(data []byte) (n int, err os.Error) {
88 var m int
89 for i, b := range data {
90
91 if b == '\n' {
92 m, err = p.output.Write(data[n : i+1])
93 n += m
94 if err != nil {
95 return
96 }
97 p.line++
98 } else if p.last == '\n' {
99 _, err = fmt.Fprintf(p.output, "%6d ", p.line)
100 if err != nil {
101 return
102 }
103 for j := p.indent; j > 0; j-- {
104 _, err = p.output.Write(indent)
105 if err != nil {
106 return
107 }
108 }
109 }
110 p.last = b
111 }
112 m, err = p.output.Write(data[n:])
113 n += m
114 return
115 }
116
117
118
119 type localError struct {
120 err os.Error
121 }
122
123
124 func (p *printer) printf(format string, args ...interface{}) {
125 n, err := fmt.Fprintf(p, format, args...)
126 p.written += n
127 if err != nil {
128 panic(localError{err})
129 }
130 }
131
132
133
134
135
136
137
138
139
140
141 func (p *printer) print(x reflect.Value) {
142 if !NotNilFilter("", x) {
143 p.printf("nil")
144 return
145 }
146
147 switch x.Kind() {
148 case reflect.Interface:
149 p.print(x.Elem())
150
151 case reflect.Map:
152 p.printf("%s (len = %d) {\n", x.Type().String(), x.Len())
153 p.indent++
154 for _, key := range x.MapKeys() {
155 p.print(key)
156 p.printf(": ")
157 p.print(x.MapIndex(key))
158 p.printf("\n")
159 }
160 p.indent--
161 p.printf("}")
162
163 case reflect.Ptr:
164 p.printf("*")
165
166
167
168 ptr := x.Interface()
169 if line, exists := p.ptrmap[ptr]; exists {
170 p.printf("(obj @ %d)", line)
171 } else {
172 p.ptrmap[ptr] = p.line
173 p.print(x.Elem())
174 }
175
176 case reflect.Slice:
177 if s, ok := x.Interface().([]byte); ok {
178 p.printf("%#q", s)
179 return
180 }
181 p.printf("%s (len = %d) {\n", x.Type().String(), x.Len())
182 p.indent++
183 for i, n := 0, x.Len(); i < n; i++ {
184 p.printf("%d: ", i)
185 p.print(x.Index(i))
186 p.printf("\n")
187 }
188 p.indent--
189 p.printf("}")
190
191 case reflect.Struct:
192 p.printf("%s {\n", x.Type().String())
193 p.indent++
194 t := x.Type()
195 for i, n := 0, t.NumField(); i < n; i++ {
196 name := t.Field(i).Name
197 value := x.Field(i)
198 if p.filter == nil || p.filter(name, value) {
199 p.printf("%s: ", name)
200 p.print(value)
201 p.printf("\n")
202 }
203 }
204 p.indent--
205 p.printf("}")
206
207 default:
208 v := x.Interface()
209 switch v := v.(type) {
210 case string:
211
212 p.printf("%q", v)
213 return
214 case token.Pos:
215
216 if p.fset != nil {
217 p.printf("%s", p.fset.Position(v))
218 return
219 }
220 }
221
222 p.printf("%v", v)
223 }
224 }