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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [old/] [template/] [execute.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 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
// Code to execute a parsed template.
6
 
7
package template
8
 
9
import (
10
        "bytes"
11
        "io"
12
        "reflect"
13
        "strings"
14
)
15
 
16
// Internal state for executing a Template.  As we evaluate the struct,
17
// the data item descends into the fields associated with sections, etc.
18
// Parent is used to walk upwards to find variables higher in the tree.
19
type state struct {
20
        parent *state          // parent in hierarchy
21
        data   reflect.Value   // the driver data for this section etc.
22
        wr     io.Writer       // where to send output
23
        buf    [2]bytes.Buffer // alternating buffers used when chaining formatters
24
}
25
 
26
func (parent *state) clone(data reflect.Value) *state {
27
        return &state{parent: parent, data: data, wr: parent.wr}
28
}
29
 
30
// Evaluate interfaces and pointers looking for a value that can look up the name, via a
31
// struct field, method, or map key, and return the result of the lookup.
32
func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value {
33
        for v.IsValid() {
34
                typ := v.Type()
35
                if n := v.Type().NumMethod(); n > 0 {
36
                        for i := 0; i < n; i++ {
37
                                m := typ.Method(i)
38
                                mtyp := m.Type
39
                                if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 {
40
                                        if !isExported(name) {
41
                                                t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
42
                                        }
43
                                        return v.Method(i).Call(nil)[0]
44
                                }
45
                        }
46
                }
47
                switch av := v; av.Kind() {
48
                case reflect.Ptr:
49
                        v = av.Elem()
50
                case reflect.Interface:
51
                        v = av.Elem()
52
                case reflect.Struct:
53
                        if !isExported(name) {
54
                                t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
55
                        }
56
                        return av.FieldByName(name)
57
                case reflect.Map:
58
                        if v := av.MapIndex(reflect.ValueOf(name)); v.IsValid() {
59
                                return v
60
                        }
61
                        return reflect.Zero(typ.Elem())
62
                default:
63
                        return reflect.Value{}
64
                }
65
        }
66
        return v
67
}
68
 
69
// indirectPtr returns the item numLevels levels of indirection below the value.
70
// It is forgiving: if the value is not a pointer, it returns it rather than giving
71
// an error.  If the pointer is nil, it is returned as is.
72
func indirectPtr(v reflect.Value, numLevels int) reflect.Value {
73
        for i := numLevels; v.IsValid() && i > 0; i++ {
74
                if p := v; p.Kind() == reflect.Ptr {
75
                        if p.IsNil() {
76
                                return v
77
                        }
78
                        v = p.Elem()
79
                } else {
80
                        break
81
                }
82
        }
83
        return v
84
}
85
 
86
// Walk v through pointers and interfaces, extracting the elements within.
87
func indirect(v reflect.Value) reflect.Value {
88
loop:
89
        for v.IsValid() {
90
                switch av := v; av.Kind() {
91
                case reflect.Ptr:
92
                        v = av.Elem()
93
                case reflect.Interface:
94
                        v = av.Elem()
95
                default:
96
                        break loop
97
                }
98
        }
99
        return v
100
}
101
 
102
// If the data for this template is a struct, find the named variable.
103
// Names of the form a.b.c are walked down the data tree.
104
// The special name "@" (the "cursor") denotes the current data.
105
// The value coming in (st.data) might need indirecting to reach
106
// a struct while the return value is not indirected - that is,
107
// it represents the actual named field. Leading stars indicate
108
// levels of indirection to be applied to the value.
109
func (t *Template) findVar(st *state, s string) reflect.Value {
110
        data := st.data
111
        flattenedName := strings.TrimLeft(s, "*")
112
        numStars := len(s) - len(flattenedName)
113
        s = flattenedName
114
        if s == "@" {
115
                return indirectPtr(data, numStars)
116
        }
117
        for _, elem := range strings.Split(s, ".") {
118
                // Look up field; data must be a struct or map.
119
                data = t.lookup(st, data, elem)
120
                if !data.IsValid() {
121
                        return reflect.Value{}
122
                }
123
        }
124
        return indirectPtr(data, numStars)
125
}
126
 
127
// Is there no data to look at?
128
func empty(v reflect.Value) bool {
129
        v = indirect(v)
130
        if !v.IsValid() {
131
                return true
132
        }
133
        switch v.Kind() {
134
        case reflect.Bool:
135
                return v.Bool() == false
136
        case reflect.String:
137
                return v.String() == ""
138
        case reflect.Struct:
139
                return false
140
        case reflect.Map:
141
                return false
142
        case reflect.Array:
143
                return v.Len() == 0
144
        case reflect.Slice:
145
                return v.Len() == 0
146
        }
147
        return false
148
}
149
 
150
// Look up a variable or method, up through the parent if necessary.
151
func (t *Template) varValue(name string, st *state) reflect.Value {
152
        field := t.findVar(st, name)
153
        if !field.IsValid() {
154
                if st.parent == nil {
155
                        t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type())
156
                }
157
                return t.varValue(name, st.parent)
158
        }
159
        return field
160
}
161
 
162
func (t *Template) format(wr io.Writer, fmt string, val []interface{}, v *variableElement, st *state) {
163
        fn := t.formatter(fmt)
164
        if fn == nil {
165
                t.execError(st, v.linenum, "missing formatter %s for variable", fmt)
166
        }
167
        fn(wr, fmt, val...)
168
}
169
 
170
// Evaluate a variable, looking up through the parent if necessary.
171
// If it has a formatter attached ({var|formatter}) run that too.
172
func (t *Template) writeVariable(v *variableElement, st *state) {
173
        // Resolve field names
174
        val := make([]interface{}, len(v.args))
175
        for i, arg := range v.args {
176
                if name, ok := arg.(fieldName); ok {
177
                        val[i] = t.varValue(string(name), st).Interface()
178
                } else {
179
                        val[i] = arg
180
                }
181
        }
182
        for i, fmt := range v.fmts[:len(v.fmts)-1] {
183
                b := &st.buf[i&1]
184
                b.Reset()
185
                t.format(b, fmt, val, v, st)
186
                val = val[0:1]
187
                val[0] = b.Bytes()
188
        }
189
        t.format(st.wr, v.fmts[len(v.fmts)-1], val, v, st)
190
}
191
 
192
// Execute element i.  Return next index to execute.
193
func (t *Template) executeElement(i int, st *state) int {
194
        switch elem := t.elems[i].(type) {
195
        case *textElement:
196
                st.wr.Write(elem.text)
197
                return i + 1
198
        case *literalElement:
199
                st.wr.Write(elem.text)
200
                return i + 1
201
        case *variableElement:
202
                t.writeVariable(elem, st)
203
                return i + 1
204
        case *sectionElement:
205
                t.executeSection(elem, st)
206
                return elem.end
207
        case *repeatedElement:
208
                t.executeRepeated(elem, st)
209
                return elem.end
210
        }
211
        e := t.elems[i]
212
        t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.ValueOf(e).Interface(), e)
213
        return 0
214
}
215
 
216
// Execute the template.
217
func (t *Template) execute(start, end int, st *state) {
218
        for i := start; i < end; {
219
                i = t.executeElement(i, st)
220
        }
221
}
222
 
223
// Execute a .section
224
func (t *Template) executeSection(s *sectionElement, st *state) {
225
        // Find driver data for this section.  It must be in the current struct.
226
        field := t.varValue(s.field, st)
227
        if !field.IsValid() {
228
                t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, st.data.Type())
229
        }
230
        st = st.clone(field)
231
        start, end := s.start, s.or
232
        if !empty(field) {
233
                // Execute the normal block.
234
                if end < 0 {
235
                        end = s.end
236
                }
237
        } else {
238
                // Execute the .or block.  If it's missing, do nothing.
239
                start, end = s.or, s.end
240
                if start < 0 {
241
                        return
242
                }
243
        }
244
        for i := start; i < end; {
245
                i = t.executeElement(i, st)
246
        }
247
}
248
 
249
// Return the result of calling the Iter method on v, or nil.
250
func iter(v reflect.Value) reflect.Value {
251
        for j := 0; j < v.Type().NumMethod(); j++ {
252
                mth := v.Type().Method(j)
253
                fv := v.Method(j)
254
                ft := fv.Type()
255
                // TODO(rsc): NumIn() should return 0 here, because ft is from a curried FuncValue.
256
                if mth.Name != "Iter" || ft.NumIn() != 1 || ft.NumOut() != 1 {
257
                        continue
258
                }
259
                ct := ft.Out(0)
260
                if ct.Kind() != reflect.Chan ||
261
                        ct.ChanDir()&reflect.RecvDir == 0 {
262
                        continue
263
                }
264
                return fv.Call(nil)[0]
265
        }
266
        return reflect.Value{}
267
}
268
 
269
// Execute a .repeated section
270
func (t *Template) executeRepeated(r *repeatedElement, st *state) {
271
        // Find driver data for this section.  It must be in the current struct.
272
        field := t.varValue(r.field, st)
273
        if !field.IsValid() {
274
                t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, st.data.Type())
275
        }
276
        field = indirect(field)
277
 
278
        start, end := r.start, r.or
279
        if end < 0 {
280
                end = r.end
281
        }
282
        if r.altstart >= 0 {
283
                end = r.altstart
284
        }
285
        first := true
286
 
287
        // Code common to all the loops.
288
        loopBody := func(newst *state) {
289
                // .alternates between elements
290
                if !first && r.altstart >= 0 {
291
                        for i := r.altstart; i < r.altend; {
292
                                i = t.executeElement(i, newst)
293
                        }
294
                }
295
                first = false
296
                for i := start; i < end; {
297
                        i = t.executeElement(i, newst)
298
                }
299
        }
300
 
301
        if array := field; array.Kind() == reflect.Array || array.Kind() == reflect.Slice {
302
                for j := 0; j < array.Len(); j++ {
303
                        loopBody(st.clone(array.Index(j)))
304
                }
305
        } else if m := field; m.Kind() == reflect.Map {
306
                for _, key := range m.MapKeys() {
307
                        loopBody(st.clone(m.MapIndex(key)))
308
                }
309
        } else if ch := iter(field); ch.IsValid() {
310
                for {
311
                        e, ok := ch.Recv()
312
                        if !ok {
313
                                break
314
                        }
315
                        loopBody(st.clone(e))
316
                }
317
        } else {
318
                t.execError(st, r.linenum, ".repeated: cannot repeat %s (type %s)",
319
                        r.field, field.Type())
320
        }
321
 
322
        if first {
323
                // Empty. Execute the .or block, once.  If it's missing, do nothing.
324
                start, end := r.or, r.end
325
                if start >= 0 {
326
                        newst := st.clone(field)
327
                        for i := start; i < end; {
328
                                i = t.executeElement(i, newst)
329
                        }
330
                }
331
                return
332
        }
333
}
334
 
335
// A valid delimiter must contain no space and be non-empty.
336
func validDelim(d []byte) bool {
337
        if len(d) == 0 {
338
                return false
339
        }
340
        for _, c := range d {
341
                if isSpace(c) {
342
                        return false
343
                }
344
        }
345
        return true
346
}

powered by: WebSVN 2.1.0

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