1// 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
7package template
8
9import (
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.
19type 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
26func (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.
32func (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.
72func 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.
87func indirect(v reflect.Value) reflect.Value {
88loop:
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.
109func (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?
128func 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.
151func (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
162func (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.
172func (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.
193func (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.
217func (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
224func (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.
250func 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
270func (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.
336func 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}
347