OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [go/] [ast/] [print.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2010 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
// This file contains printing suppport for ASTs.
6
 
7
package ast
8
 
9
import (
10
        "fmt"
11
        "go/token"
12
        "io"
13
        "os"
14
        "reflect"
15
)
16
 
17
// A FieldFilter may be provided to Fprint to control the output.
18
type FieldFilter func(name string, value reflect.Value) bool
19
 
20
// NotNilFilter returns true for field values that are not nil;
21
// it returns false otherwise.
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
// Fprint prints the (sub-)tree starting at AST node x to w.
31
// If fset != nil, position information is interpreted relative
32
// to that file set. Otherwise positions are printed as integer
33
// values (file set specific offsets).
34
//
35
// A non-nil FieldFilter f may be provided to control the output:
36
// struct fields for which f(fieldname, fieldvalue) is true are
37
// are printed; all others are filtered from the output.
38
//
39
func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) {
40
        // setup printer
41
        p := printer{
42
                output: w,
43
                fset:   fset,
44
                filter: f,
45
                ptrmap: make(map[interface{}]int),
46
                last:   '\n', // force printing of line number on first line
47
        }
48
 
49
        // install error handler
50
        defer func() {
51
                if e := recover(); e != nil {
52
                        err = e.(localError).err // re-panics if it's not a localError
53
                }
54
        }()
55
 
56
        // print x
57
        if x == nil {
58
                p.printf("nil\n")
59
                return
60
        }
61
        p.print(reflect.ValueOf(x))
62
        p.printf("\n")
63
 
64
        return
65
}
66
 
67
// Print prints x to standard output, skipping nil fields.
68
// Print(fset, x) is the same as Fprint(os.Stdout, fset, x, NotNilFilter).
69
func Print(fset *token.FileSet, x interface{}) error {
70
        return Fprint(os.Stdout, fset, x, NotNilFilter)
71
}
72
 
73
type printer struct {
74
        output io.Writer
75
        fset   *token.FileSet
76
        filter FieldFilter
77
        ptrmap map[interface{}]int // *T -> line number
78
        indent int                 // current indentation level
79
        last   byte                // the last byte processed by Write
80
        line   int                 // current line number
81
}
82
 
83
var indent = []byte(".  ")
84
 
85
func (p *printer) Write(data []byte) (n int, err error) {
86
        var m int
87
        for i, b := range data {
88
                // invariant: data[0:n] has been written
89
                if b == '\n' {
90
                        m, err = p.output.Write(data[n : i+1])
91
                        n += m
92
                        if err != nil {
93
                                return
94
                        }
95
                        p.line++
96
                } else if p.last == '\n' {
97
                        _, err = fmt.Fprintf(p.output, "%6d  ", p.line)
98
                        if err != nil {
99
                                return
100
                        }
101
                        for j := p.indent; j > 0; j-- {
102
                                _, err = p.output.Write(indent)
103
                                if err != nil {
104
                                        return
105
                                }
106
                        }
107
                }
108
                p.last = b
109
        }
110
        m, err = p.output.Write(data[n:])
111
        n += m
112
        return
113
}
114
 
115
// localError wraps locally caught errors so we can distinguish
116
// them from genuine panics which we don't want to return as errors.
117
type localError struct {
118
        err error
119
}
120
 
121
// printf is a convenience wrapper that takes care of print errors.
122
func (p *printer) printf(format string, args ...interface{}) {
123
        if _, err := fmt.Fprintf(p, format, args...); err != nil {
124
                panic(localError{err})
125
        }
126
}
127
 
128
// Implementation note: Print is written for AST nodes but could be
129
// used to print arbitrary data structures; such a version should
130
// probably be in a different package.
131
//
132
// Note: This code detects (some) cycles created via pointers but
133
// not cycles that are created via slices or maps containing the
134
// same slice or map. Code for general data structures probably
135
// should catch those as well.
136
 
137
func (p *printer) print(x reflect.Value) {
138
        if !NotNilFilter("", x) {
139
                p.printf("nil")
140
                return
141
        }
142
 
143
        switch x.Kind() {
144
        case reflect.Interface:
145
                p.print(x.Elem())
146
 
147
        case reflect.Map:
148
                p.printf("%s (len = %d) {\n", x.Type(), x.Len())
149
                p.indent++
150
                for _, key := range x.MapKeys() {
151
                        p.print(key)
152
                        p.printf(": ")
153
                        p.print(x.MapIndex(key))
154
                        p.printf("\n")
155
                }
156
                p.indent--
157
                p.printf("}")
158
 
159
        case reflect.Ptr:
160
                p.printf("*")
161
                // type-checked ASTs may contain cycles - use ptrmap
162
                // to keep track of objects that have been printed
163
                // already and print the respective line number instead
164
                ptr := x.Interface()
165
                if line, exists := p.ptrmap[ptr]; exists {
166
                        p.printf("(obj @ %d)", line)
167
                } else {
168
                        p.ptrmap[ptr] = p.line
169
                        p.print(x.Elem())
170
                }
171
 
172
        case reflect.Slice:
173
                if s, ok := x.Interface().([]byte); ok {
174
                        p.printf("%#q", s)
175
                        return
176
                }
177
                p.printf("%s (len = %d) {\n", x.Type(), x.Len())
178
                p.indent++
179
                for i, n := 0, x.Len(); i < n; i++ {
180
                        p.printf("%d: ", i)
181
                        p.print(x.Index(i))
182
                        p.printf("\n")
183
                }
184
                p.indent--
185
                p.printf("}")
186
 
187
        case reflect.Struct:
188
                p.printf("%s {\n", x.Type())
189
                p.indent++
190
                t := x.Type()
191
                for i, n := 0, t.NumField(); i < n; i++ {
192
                        name := t.Field(i).Name
193
                        value := x.Field(i)
194
                        if p.filter == nil || p.filter(name, value) {
195
                                p.printf("%s: ", name)
196
                                p.print(value)
197
                                p.printf("\n")
198
                        }
199
                }
200
                p.indent--
201
                p.printf("}")
202
 
203
        default:
204
                v := x.Interface()
205
                switch v := v.(type) {
206
                case string:
207
                        // print strings in quotes
208
                        p.printf("%q", v)
209
                        return
210
                case token.Pos:
211
                        // position values can be printed nicely if we have a file set
212
                        if p.fset != nil {
213
                                p.printf("%s", p.fset.Position(v))
214
                                return
215
                        }
216
                }
217
                // default
218
                p.printf("%v", v)
219
        }
220
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.