]>
Commit | Line | Data |
---|---|---|
adb0401d ILT |
1 | // Copyright 2011 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 | package template | |
6 | ||
7 | import ( | |
8 | "fmt" | |
9 | "io" | |
adb0401d ILT |
10 | "reflect" |
11 | "runtime" | |
df1304ee | 12 | "sort" |
adb0401d | 13 | "strings" |
9c63abc9 | 14 | "text/template/parse" |
adb0401d ILT |
15 | ) |
16 | ||
17 | // state represents the state of an execution. It's not part of the | |
18 | // template so that multiple executions of the same template | |
19 | // can execute in parallel. | |
20 | type state struct { | |
21 | tmpl *Template | |
22 | wr io.Writer | |
4ccad563 | 23 | node parse.Node // current node, for errors |
adb0401d ILT |
24 | vars []variable // push-down stack of variable values. |
25 | } | |
26 | ||
27 | // variable holds the dynamic value of a variable such as $, $x etc. | |
28 | type variable struct { | |
29 | name string | |
30 | value reflect.Value | |
31 | } | |
32 | ||
33 | // push pushes a new variable on the stack. | |
34 | func (s *state) push(name string, value reflect.Value) { | |
35 | s.vars = append(s.vars, variable{name, value}) | |
36 | } | |
37 | ||
38 | // mark returns the length of the variable stack. | |
39 | func (s *state) mark() int { | |
40 | return len(s.vars) | |
41 | } | |
42 | ||
43 | // pop pops the variable stack up to the mark. | |
44 | func (s *state) pop(mark int) { | |
45 | s.vars = s.vars[0:mark] | |
46 | } | |
47 | ||
48 | // setVar overwrites the top-nth variable on the stack. Used by range iterations. | |
49 | func (s *state) setVar(n int, value reflect.Value) { | |
50 | s.vars[len(s.vars)-n].value = value | |
51 | } | |
52 | ||
53 | // varValue returns the value of the named variable. | |
54 | func (s *state) varValue(name string) reflect.Value { | |
55 | for i := s.mark() - 1; i >= 0; i-- { | |
56 | if s.vars[i].name == name { | |
57 | return s.vars[i].value | |
58 | } | |
59 | } | |
60 | s.errorf("undefined variable: %s", name) | |
61 | return zero | |
62 | } | |
63 | ||
64 | var zero reflect.Value | |
65 | ||
4ccad563 ILT |
66 | // at marks the state to be on node n, for error reporting. |
67 | func (s *state) at(node parse.Node) { | |
68 | s.node = node | |
69 | } | |
70 | ||
71 | // doublePercent returns the string with %'s replaced by %%, if necessary, | |
72 | // so it can be used safely inside a Printf format string. | |
73 | func doublePercent(str string) string { | |
74 | if strings.Contains(str, "%") { | |
75 | str = strings.Replace(str, "%", "%%", -1) | |
76 | } | |
77 | return str | |
78 | } | |
79 | ||
adb0401d ILT |
80 | // errorf formats the error and terminates processing. |
81 | func (s *state) errorf(format string, args ...interface{}) { | |
4ccad563 ILT |
82 | name := doublePercent(s.tmpl.Name()) |
83 | if s.node == nil { | |
84 | format = fmt.Sprintf("template: %s: %s", name, format) | |
85 | } else { | |
86 | location, context := s.tmpl.ErrorContext(s.node) | |
87 | format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format) | |
88 | } | |
adb0401d ILT |
89 | panic(fmt.Errorf(format, args...)) |
90 | } | |
91 | ||
adb0401d ILT |
92 | // errRecover is the handler that turns panics into returns from the top |
93 | // level of Parse. | |
2fd401c8 | 94 | func errRecover(errp *error) { |
adb0401d ILT |
95 | e := recover() |
96 | if e != nil { | |
df1304ee ILT |
97 | switch err := e.(type) { |
98 | case runtime.Error: | |
99 | panic(e) | |
100 | case error: | |
101 | *errp = err | |
102 | default: | |
adb0401d ILT |
103 | panic(e) |
104 | } | |
adb0401d ILT |
105 | } |
106 | } | |
107 | ||
7b1c3dd9 ILT |
108 | // ExecuteTemplate applies the template associated with t that has the given name |
109 | // to the specified data object and writes the output to wr. | |
110 | func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { | |
111 | tmpl := t.tmpl[name] | |
112 | if tmpl == nil { | |
113 | return fmt.Errorf("template: no template %q associated with template %q", name, t.name) | |
114 | } | |
115 | return tmpl.Execute(wr, data) | |
116 | } | |
117 | ||
adb0401d | 118 | // Execute applies a parsed template to the specified data object, |
7b1c3dd9 | 119 | // and writes the output to wr. |
2fd401c8 | 120 | func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { |
adb0401d ILT |
121 | defer errRecover(&err) |
122 | value := reflect.ValueOf(data) | |
123 | state := &state{ | |
124 | tmpl: t, | |
125 | wr: wr, | |
adb0401d ILT |
126 | vars: []variable{{"$", value}}, |
127 | } | |
506cf9aa | 128 | if t.Tree == nil || t.Root == nil { |
df4aa89a | 129 | state.errorf("%q is an incomplete or empty template", t.name) |
adb0401d ILT |
130 | } |
131 | state.walk(value, t.Root) | |
132 | return | |
133 | } | |
134 | ||
135 | // Walk functions step through the major pieces of the template structure, | |
136 | // generating output as they go. | |
4ccad563 ILT |
137 | func (s *state) walk(dot reflect.Value, node parse.Node) { |
138 | s.at(node) | |
139 | switch node := node.(type) { | |
adb0401d | 140 | case *parse.ActionNode: |
adb0401d ILT |
141 | // Do not pop variables so they persist until next end. |
142 | // Also, if the action declares variables, don't print the result. | |
4ccad563 ILT |
143 | val := s.evalPipeline(dot, node.Pipe) |
144 | if len(node.Pipe.Decl) == 0 { | |
145 | s.printValue(node, val) | |
adb0401d ILT |
146 | } |
147 | case *parse.IfNode: | |
4ccad563 | 148 | s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) |
adb0401d | 149 | case *parse.ListNode: |
4ccad563 | 150 | for _, node := range node.Nodes { |
adb0401d ILT |
151 | s.walk(dot, node) |
152 | } | |
153 | case *parse.RangeNode: | |
4ccad563 | 154 | s.walkRange(dot, node) |
adb0401d | 155 | case *parse.TemplateNode: |
4ccad563 | 156 | s.walkTemplate(dot, node) |
adb0401d | 157 | case *parse.TextNode: |
4ccad563 ILT |
158 | if _, err := s.wr.Write(node.Text); err != nil { |
159 | s.errorf("%s", err) | |
adb0401d ILT |
160 | } |
161 | case *parse.WithNode: | |
4ccad563 | 162 | s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList) |
adb0401d | 163 | default: |
4ccad563 | 164 | s.errorf("unknown node: %s", node) |
adb0401d ILT |
165 | } |
166 | } | |
167 | ||
168 | // walkIfOrWith walks an 'if' or 'with' node. The two control structures | |
169 | // are identical in behavior except that 'with' sets dot. | |
170 | func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) { | |
171 | defer s.pop(s.mark()) | |
172 | val := s.evalPipeline(dot, pipe) | |
173 | truth, ok := isTrue(val) | |
174 | if !ok { | |
175 | s.errorf("if/with can't use %v", val) | |
176 | } | |
177 | if truth { | |
178 | if typ == parse.NodeWith { | |
179 | s.walk(val, list) | |
180 | } else { | |
181 | s.walk(dot, list) | |
182 | } | |
183 | } else if elseList != nil { | |
184 | s.walk(dot, elseList) | |
185 | } | |
186 | } | |
187 | ||
188 | // isTrue returns whether the value is 'true', in the sense of not the zero of its type, | |
189 | // and whether the value has a meaningful truth value. | |
190 | func isTrue(val reflect.Value) (truth, ok bool) { | |
191 | if !val.IsValid() { | |
192 | // Something like var x interface{}, never set. It's a form of nil. | |
193 | return false, true | |
194 | } | |
195 | switch val.Kind() { | |
196 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: | |
197 | truth = val.Len() > 0 | |
198 | case reflect.Bool: | |
199 | truth = val.Bool() | |
200 | case reflect.Complex64, reflect.Complex128: | |
201 | truth = val.Complex() != 0 | |
202 | case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: | |
203 | truth = !val.IsNil() | |
204 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |
205 | truth = val.Int() != 0 | |
206 | case reflect.Float32, reflect.Float64: | |
207 | truth = val.Float() != 0 | |
208 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | |
209 | truth = val.Uint() != 0 | |
210 | case reflect.Struct: | |
211 | truth = true // Struct values are always true. | |
212 | default: | |
213 | return | |
214 | } | |
215 | return truth, true | |
216 | } | |
217 | ||
218 | func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { | |
4ccad563 | 219 | s.at(r) |
adb0401d ILT |
220 | defer s.pop(s.mark()) |
221 | val, _ := indirect(s.evalPipeline(dot, r.Pipe)) | |
222 | // mark top of stack before any variables in the body are pushed. | |
223 | mark := s.mark() | |
224 | oneIteration := func(index, elem reflect.Value) { | |
225 | // Set top var (lexically the second if there are two) to the element. | |
226 | if len(r.Pipe.Decl) > 0 { | |
227 | s.setVar(1, elem) | |
228 | } | |
229 | // Set next var (lexically the first if there are two) to the index. | |
230 | if len(r.Pipe.Decl) > 1 { | |
231 | s.setVar(2, index) | |
232 | } | |
233 | s.walk(elem, r.List) | |
234 | s.pop(mark) | |
235 | } | |
236 | switch val.Kind() { | |
237 | case reflect.Array, reflect.Slice: | |
238 | if val.Len() == 0 { | |
239 | break | |
240 | } | |
241 | for i := 0; i < val.Len(); i++ { | |
242 | oneIteration(reflect.ValueOf(i), val.Index(i)) | |
243 | } | |
244 | return | |
245 | case reflect.Map: | |
246 | if val.Len() == 0 { | |
247 | break | |
248 | } | |
df1304ee | 249 | for _, key := range sortKeys(val.MapKeys()) { |
adb0401d ILT |
250 | oneIteration(key, val.MapIndex(key)) |
251 | } | |
252 | return | |
253 | case reflect.Chan: | |
254 | if val.IsNil() { | |
255 | break | |
256 | } | |
257 | i := 0 | |
258 | for ; ; i++ { | |
259 | elem, ok := val.Recv() | |
260 | if !ok { | |
261 | break | |
262 | } | |
263 | oneIteration(reflect.ValueOf(i), elem) | |
264 | } | |
265 | if i == 0 { | |
266 | break | |
267 | } | |
268 | return | |
269 | case reflect.Invalid: | |
270 | break // An invalid value is likely a nil map, etc. and acts like an empty map. | |
271 | default: | |
272 | s.errorf("range can't iterate over %v", val) | |
273 | } | |
274 | if r.ElseList != nil { | |
275 | s.walk(dot, r.ElseList) | |
276 | } | |
277 | } | |
278 | ||
279 | func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) { | |
4ccad563 | 280 | s.at(t) |
7b1c3dd9 | 281 | tmpl := s.tmpl.tmpl[t.Name] |
adb0401d | 282 | if tmpl == nil { |
7b1c3dd9 | 283 | s.errorf("template %q not defined", t.Name) |
adb0401d ILT |
284 | } |
285 | // Variables declared by the pipeline persist. | |
286 | dot = s.evalPipeline(dot, t.Pipe) | |
287 | newState := *s | |
288 | newState.tmpl = tmpl | |
289 | // No dynamic scoping: template invocations inherit no variables. | |
290 | newState.vars = []variable{{"$", dot}} | |
291 | newState.walk(dot, tmpl.Root) | |
292 | } | |
293 | ||
294 | // Eval functions evaluate pipelines, commands, and their elements and extract | |
295 | // values from the data structure by examining fields, calling methods, and so on. | |
296 | // The printing of those values happens only through walk functions. | |
297 | ||
298 | // evalPipeline returns the value acquired by evaluating a pipeline. If the | |
299 | // pipeline has a variable declaration, the variable will be pushed on the | |
300 | // stack. Callers should therefore pop the stack after they are finished | |
301 | // executing commands depending on the pipeline value. | |
302 | func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) { | |
303 | if pipe == nil { | |
304 | return | |
305 | } | |
4ccad563 | 306 | s.at(pipe) |
adb0401d ILT |
307 | for _, cmd := range pipe.Cmds { |
308 | value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg. | |
309 | // If the object has type interface{}, dig down one level to the thing inside. | |
310 | if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 { | |
311 | value = reflect.ValueOf(value.Interface()) // lovely! | |
312 | } | |
313 | } | |
314 | for _, variable := range pipe.Decl { | |
315 | s.push(variable.Ident[0], value) | |
316 | } | |
317 | return value | |
318 | } | |
319 | ||
320 | func (s *state) notAFunction(args []parse.Node, final reflect.Value) { | |
321 | if len(args) > 1 || final.IsValid() { | |
322 | s.errorf("can't give argument to non-function %s", args[0]) | |
323 | } | |
324 | } | |
325 | ||
326 | func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value { | |
327 | firstWord := cmd.Args[0] | |
328 | switch n := firstWord.(type) { | |
329 | case *parse.FieldNode: | |
330 | return s.evalFieldNode(dot, n, cmd.Args, final) | |
4ccad563 ILT |
331 | case *parse.ChainNode: |
332 | return s.evalChainNode(dot, n, cmd.Args, final) | |
adb0401d ILT |
333 | case *parse.IdentifierNode: |
334 | // Must be a function. | |
4ccad563 ILT |
335 | return s.evalFunction(dot, n, cmd, cmd.Args, final) |
336 | case *parse.PipeNode: | |
337 | // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored. | |
338 | return s.evalPipeline(dot, n) | |
adb0401d ILT |
339 | case *parse.VariableNode: |
340 | return s.evalVariableNode(dot, n, cmd.Args, final) | |
341 | } | |
4ccad563 | 342 | s.at(firstWord) |
adb0401d ILT |
343 | s.notAFunction(cmd.Args, final) |
344 | switch word := firstWord.(type) { | |
345 | case *parse.BoolNode: | |
346 | return reflect.ValueOf(word.True) | |
347 | case *parse.DotNode: | |
348 | return dot | |
4ccad563 ILT |
349 | case *parse.NilNode: |
350 | s.errorf("nil is not a command") | |
adb0401d ILT |
351 | case *parse.NumberNode: |
352 | return s.idealConstant(word) | |
353 | case *parse.StringNode: | |
354 | return reflect.ValueOf(word.Text) | |
355 | } | |
356 | s.errorf("can't evaluate command %q", firstWord) | |
357 | panic("not reached") | |
358 | } | |
359 | ||
360 | // idealConstant is called to return the value of a number in a context where | |
361 | // we don't know the type. In that case, the syntax of the number tells us | |
362 | // its type, and we use Go rules to resolve. Note there is no such thing as | |
363 | // a uint ideal constant in this situation - the value must be of int type. | |
364 | func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value { | |
365 | // These are ideal constants but we don't know the type | |
366 | // and we have no context. (If it was a method argument, | |
367 | // we'd know what we need.) The syntax guides us to some extent. | |
4ccad563 | 368 | s.at(constant) |
adb0401d ILT |
369 | switch { |
370 | case constant.IsComplex: | |
371 | return reflect.ValueOf(constant.Complex128) // incontrovertible. | |
372 | case constant.IsFloat && strings.IndexAny(constant.Text, ".eE") >= 0: | |
373 | return reflect.ValueOf(constant.Float64) | |
374 | case constant.IsInt: | |
375 | n := int(constant.Int64) | |
376 | if int64(n) != constant.Int64 { | |
377 | s.errorf("%s overflows int", constant.Text) | |
378 | } | |
379 | return reflect.ValueOf(n) | |
380 | case constant.IsUint: | |
381 | s.errorf("%s overflows int", constant.Text) | |
382 | } | |
383 | return zero | |
384 | } | |
385 | ||
386 | func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value { | |
4ccad563 ILT |
387 | s.at(field) |
388 | return s.evalFieldChain(dot, dot, field, field.Ident, args, final) | |
389 | } | |
390 | ||
391 | func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value { | |
392 | s.at(chain) | |
393 | // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields. | |
394 | pipe := s.evalArg(dot, nil, chain.Node) | |
395 | if len(chain.Field) == 0 { | |
396 | s.errorf("internal error: no fields in evalChainNode") | |
397 | } | |
398 | return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final) | |
adb0401d ILT |
399 | } |
400 | ||
4ccad563 | 401 | func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value { |
adb0401d | 402 | // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields. |
4ccad563 ILT |
403 | s.at(variable) |
404 | value := s.varValue(variable.Ident[0]) | |
405 | if len(variable.Ident) == 1 { | |
9a18821c | 406 | s.notAFunction(args, final) |
adb0401d ILT |
407 | return value |
408 | } | |
4ccad563 | 409 | return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final) |
adb0401d ILT |
410 | } |
411 | ||
412 | // evalFieldChain evaluates .X.Y.Z possibly followed by arguments. | |
413 | // dot is the environment in which to evaluate arguments, while | |
414 | // receiver is the value being walked along the chain. | |
4ccad563 | 415 | func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value { |
adb0401d ILT |
416 | n := len(ident) |
417 | for i := 0; i < n-1; i++ { | |
4ccad563 | 418 | receiver = s.evalField(dot, ident[i], node, nil, zero, receiver) |
adb0401d ILT |
419 | } |
420 | // Now if it's a method, it gets the arguments. | |
4ccad563 | 421 | return s.evalField(dot, ident[n-1], node, args, final, receiver) |
adb0401d ILT |
422 | } |
423 | ||
4ccad563 ILT |
424 | func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value { |
425 | s.at(node) | |
426 | name := node.Ident | |
7b1c3dd9 | 427 | function, ok := findFunction(name, s.tmpl) |
adb0401d ILT |
428 | if !ok { |
429 | s.errorf("%q is not a defined function", name) | |
430 | } | |
4ccad563 | 431 | return s.evalCall(dot, function, cmd, name, args, final) |
adb0401d ILT |
432 | } |
433 | ||
434 | // evalField evaluates an expression like (.Field) or (.Field arg1 arg2). | |
435 | // The 'final' argument represents the return value from the preceding | |
436 | // value of the pipeline, if any. | |
4ccad563 | 437 | func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value { |
adb0401d ILT |
438 | if !receiver.IsValid() { |
439 | return zero | |
440 | } | |
441 | typ := receiver.Type() | |
442 | receiver, _ = indirect(receiver) | |
443 | // Unless it's an interface, need to get to a value of type *T to guarantee | |
444 | // we see all methods of T and *T. | |
445 | ptr := receiver | |
446 | if ptr.Kind() != reflect.Interface && ptr.CanAddr() { | |
447 | ptr = ptr.Addr() | |
448 | } | |
7b1c3dd9 | 449 | if method := ptr.MethodByName(fieldName); method.IsValid() { |
4ccad563 | 450 | return s.evalCall(dot, method, node, fieldName, args, final) |
adb0401d ILT |
451 | } |
452 | hasArgs := len(args) > 1 || final.IsValid() | |
4ccad563 | 453 | // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil. |
adb0401d | 454 | receiver, isNil := indirect(receiver) |
4ccad563 ILT |
455 | if isNil { |
456 | s.errorf("nil pointer evaluating %s.%s", typ, fieldName) | |
457 | } | |
458 | switch receiver.Kind() { | |
459 | case reflect.Struct: | |
adb0401d ILT |
460 | tField, ok := receiver.Type().FieldByName(fieldName) |
461 | if ok { | |
462 | field := receiver.FieldByIndex(tField.Index) | |
4ccad563 ILT |
463 | if tField.PkgPath != "" { // field is unexported |
464 | s.errorf("%s is an unexported field of struct type %s", fieldName, typ) | |
465 | } | |
466 | // If it's a function, we must call it. | |
467 | if hasArgs { | |
468 | s.errorf("%s has arguments but cannot be invoked as function", fieldName) | |
adb0401d | 469 | } |
4ccad563 | 470 | return field |
adb0401d | 471 | } |
4ccad563 ILT |
472 | s.errorf("%s is not a field of struct type %s", fieldName, typ) |
473 | case reflect.Map: | |
474 | // If it's a map, attempt to use the field name as a key. | |
adb0401d ILT |
475 | nameVal := reflect.ValueOf(fieldName) |
476 | if nameVal.Type().AssignableTo(receiver.Type().Key()) { | |
477 | if hasArgs { | |
478 | s.errorf("%s is not a method but has arguments", fieldName) | |
479 | } | |
480 | return receiver.MapIndex(nameVal) | |
481 | } | |
482 | } | |
adb0401d ILT |
483 | s.errorf("can't evaluate field %s in type %s", fieldName, typ) |
484 | panic("not reached") | |
485 | } | |
486 | ||
adb0401d | 487 | var ( |
9c63abc9 | 488 | errorType = reflect.TypeOf((*error)(nil)).Elem() |
adb0401d ILT |
489 | fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() |
490 | ) | |
491 | ||
492 | // evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so | |
493 | // it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0] | |
494 | // as the function itself. | |
4ccad563 | 495 | func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value { |
adb0401d ILT |
496 | if args != nil { |
497 | args = args[1:] // Zeroth arg is function name/node; not passed to function. | |
498 | } | |
499 | typ := fun.Type() | |
500 | numIn := len(args) | |
501 | if final.IsValid() { | |
502 | numIn++ | |
503 | } | |
504 | numFixed := len(args) | |
505 | if typ.IsVariadic() { | |
506 | numFixed = typ.NumIn() - 1 // last arg is the variadic one. | |
507 | if numIn < numFixed { | |
508 | s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args)) | |
509 | } | |
510 | } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() { | |
511 | s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args)) | |
512 | } | |
513 | if !goodFunc(typ) { | |
4ccad563 ILT |
514 | // TODO: This could still be a confusing error; maybe goodFunc should provide info. |
515 | s.errorf("can't call method/function %q with %d results", name, typ.NumOut()) | |
adb0401d ILT |
516 | } |
517 | // Build the arg list. | |
518 | argv := make([]reflect.Value, numIn) | |
519 | // Args must be evaluated. Fixed args first. | |
520 | i := 0 | |
521 | for ; i < numFixed; i++ { | |
522 | argv[i] = s.evalArg(dot, typ.In(i), args[i]) | |
523 | } | |
524 | // Now the ... args. | |
525 | if typ.IsVariadic() { | |
526 | argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice. | |
527 | for ; i < len(args); i++ { | |
528 | argv[i] = s.evalArg(dot, argType, args[i]) | |
529 | } | |
530 | } | |
531 | // Add final value if necessary. | |
532 | if final.IsValid() { | |
33e337e3 ILT |
533 | t := typ.In(typ.NumIn() - 1) |
534 | if typ.IsVariadic() { | |
535 | t = t.Elem() | |
536 | } | |
537 | argv[i] = s.validateType(final, t) | |
adb0401d ILT |
538 | } |
539 | result := fun.Call(argv) | |
2fd401c8 | 540 | // If we have an error that is not nil, stop execution and return that error to the caller. |
adb0401d | 541 | if len(result) == 2 && !result[1].IsNil() { |
4ccad563 | 542 | s.at(node) |
2fd401c8 | 543 | s.errorf("error calling %s: %s", name, result[1].Interface().(error)) |
adb0401d ILT |
544 | } |
545 | return result[0] | |
546 | } | |
547 | ||
4ccad563 ILT |
548 | // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. |
549 | func canBeNil(typ reflect.Type) bool { | |
550 | switch typ.Kind() { | |
551 | case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: | |
552 | return true | |
553 | } | |
554 | return false | |
555 | } | |
556 | ||
adb0401d ILT |
557 | // validateType guarantees that the value is valid and assignable to the type. |
558 | func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value { | |
559 | if !value.IsValid() { | |
4ccad563 | 560 | if typ == nil || canBeNil(typ) { |
df4aa89a | 561 | // An untyped nil interface{}. Accept as a proper nil value. |
4ccad563 | 562 | return reflect.Zero(typ) |
df4aa89a | 563 | } |
4ccad563 | 564 | s.errorf("invalid value; expected %s", typ) |
adb0401d | 565 | } |
4ccad563 | 566 | if typ != nil && !value.Type().AssignableTo(typ) { |
08a680a8 ILT |
567 | if value.Kind() == reflect.Interface && !value.IsNil() { |
568 | value = value.Elem() | |
569 | if value.Type().AssignableTo(typ) { | |
570 | return value | |
571 | } | |
572 | // fallthrough | |
573 | } | |
adb0401d ILT |
574 | // Does one dereference or indirection work? We could do more, as we |
575 | // do with method receivers, but that gets messy and method receivers | |
576 | // are much more constrained, so it makes more sense there than here. | |
577 | // Besides, one is almost always all you need. | |
578 | switch { | |
d8f41257 | 579 | case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ): |
adb0401d ILT |
580 | value = value.Elem() |
581 | case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr(): | |
582 | value = value.Addr() | |
583 | default: | |
584 | s.errorf("wrong type for value; expected %s; got %s", typ, value.Type()) | |
585 | } | |
586 | } | |
587 | return value | |
588 | } | |
589 | ||
590 | func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value { | |
4ccad563 | 591 | s.at(n) |
adb0401d ILT |
592 | switch arg := n.(type) { |
593 | case *parse.DotNode: | |
594 | return s.validateType(dot, typ) | |
4ccad563 ILT |
595 | case *parse.NilNode: |
596 | if canBeNil(typ) { | |
597 | return reflect.Zero(typ) | |
598 | } | |
599 | s.errorf("cannot assign nil to %s", typ) | |
adb0401d ILT |
600 | case *parse.FieldNode: |
601 | return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ) | |
602 | case *parse.VariableNode: | |
603 | return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ) | |
4ccad563 ILT |
604 | case *parse.PipeNode: |
605 | return s.validateType(s.evalPipeline(dot, arg), typ) | |
adb0401d ILT |
606 | } |
607 | switch typ.Kind() { | |
608 | case reflect.Bool: | |
609 | return s.evalBool(typ, n) | |
610 | case reflect.Complex64, reflect.Complex128: | |
611 | return s.evalComplex(typ, n) | |
612 | case reflect.Float32, reflect.Float64: | |
613 | return s.evalFloat(typ, n) | |
614 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |
615 | return s.evalInteger(typ, n) | |
616 | case reflect.Interface: | |
617 | if typ.NumMethod() == 0 { | |
618 | return s.evalEmptyInterface(dot, n) | |
619 | } | |
620 | case reflect.String: | |
621 | return s.evalString(typ, n) | |
622 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | |
623 | return s.evalUnsignedInteger(typ, n) | |
624 | } | |
625 | s.errorf("can't handle %s for arg of type %s", n, typ) | |
626 | panic("not reached") | |
627 | } | |
628 | ||
629 | func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value { | |
4ccad563 | 630 | s.at(n) |
adb0401d ILT |
631 | if n, ok := n.(*parse.BoolNode); ok { |
632 | value := reflect.New(typ).Elem() | |
633 | value.SetBool(n.True) | |
634 | return value | |
635 | } | |
636 | s.errorf("expected bool; found %s", n) | |
637 | panic("not reached") | |
638 | } | |
639 | ||
640 | func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value { | |
4ccad563 | 641 | s.at(n) |
adb0401d ILT |
642 | if n, ok := n.(*parse.StringNode); ok { |
643 | value := reflect.New(typ).Elem() | |
644 | value.SetString(n.Text) | |
645 | return value | |
646 | } | |
647 | s.errorf("expected string; found %s", n) | |
648 | panic("not reached") | |
649 | } | |
650 | ||
651 | func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value { | |
4ccad563 | 652 | s.at(n) |
adb0401d ILT |
653 | if n, ok := n.(*parse.NumberNode); ok && n.IsInt { |
654 | value := reflect.New(typ).Elem() | |
655 | value.SetInt(n.Int64) | |
656 | return value | |
657 | } | |
658 | s.errorf("expected integer; found %s", n) | |
659 | panic("not reached") | |
660 | } | |
661 | ||
662 | func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value { | |
4ccad563 | 663 | s.at(n) |
adb0401d ILT |
664 | if n, ok := n.(*parse.NumberNode); ok && n.IsUint { |
665 | value := reflect.New(typ).Elem() | |
666 | value.SetUint(n.Uint64) | |
667 | return value | |
668 | } | |
669 | s.errorf("expected unsigned integer; found %s", n) | |
670 | panic("not reached") | |
671 | } | |
672 | ||
673 | func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value { | |
4ccad563 | 674 | s.at(n) |
adb0401d ILT |
675 | if n, ok := n.(*parse.NumberNode); ok && n.IsFloat { |
676 | value := reflect.New(typ).Elem() | |
677 | value.SetFloat(n.Float64) | |
678 | return value | |
679 | } | |
680 | s.errorf("expected float; found %s", n) | |
681 | panic("not reached") | |
682 | } | |
683 | ||
684 | func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value { | |
685 | if n, ok := n.(*parse.NumberNode); ok && n.IsComplex { | |
686 | value := reflect.New(typ).Elem() | |
687 | value.SetComplex(n.Complex128) | |
688 | return value | |
689 | } | |
690 | s.errorf("expected complex; found %s", n) | |
691 | panic("not reached") | |
692 | } | |
693 | ||
694 | func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value { | |
4ccad563 | 695 | s.at(n) |
adb0401d ILT |
696 | switch n := n.(type) { |
697 | case *parse.BoolNode: | |
698 | return reflect.ValueOf(n.True) | |
699 | case *parse.DotNode: | |
700 | return dot | |
701 | case *parse.FieldNode: | |
702 | return s.evalFieldNode(dot, n, nil, zero) | |
703 | case *parse.IdentifierNode: | |
4ccad563 ILT |
704 | return s.evalFunction(dot, n, n, nil, zero) |
705 | case *parse.NilNode: | |
706 | // NilNode is handled in evalArg, the only place that calls here. | |
707 | s.errorf("evalEmptyInterface: nil (can't happen)") | |
adb0401d ILT |
708 | case *parse.NumberNode: |
709 | return s.idealConstant(n) | |
710 | case *parse.StringNode: | |
711 | return reflect.ValueOf(n.Text) | |
712 | case *parse.VariableNode: | |
713 | return s.evalVariableNode(dot, n, nil, zero) | |
4ccad563 ILT |
714 | case *parse.PipeNode: |
715 | return s.evalPipeline(dot, n) | |
adb0401d ILT |
716 | } |
717 | s.errorf("can't handle assignment of %s to empty interface argument", n) | |
718 | panic("not reached") | |
719 | } | |
720 | ||
721 | // indirect returns the item at the end of indirection, and a bool to indicate if it's nil. | |
722 | // We indirect through pointers and empty interfaces (only) because | |
723 | // non-empty interfaces have methods we might need. | |
724 | func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { | |
725 | for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { | |
726 | if v.IsNil() { | |
727 | return v, true | |
728 | } | |
729 | if v.Kind() == reflect.Interface && v.NumMethod() > 0 { | |
730 | break | |
731 | } | |
732 | } | |
733 | return v, false | |
734 | } | |
735 | ||
736 | // printValue writes the textual representation of the value to the output of | |
737 | // the template. | |
738 | func (s *state) printValue(n parse.Node, v reflect.Value) { | |
4ccad563 | 739 | s.at(n) |
adb0401d ILT |
740 | if v.Kind() == reflect.Ptr { |
741 | v, _ = indirect(v) // fmt.Fprint handles nil. | |
742 | } | |
743 | if !v.IsValid() { | |
744 | fmt.Fprint(s.wr, "<no value>") | |
745 | return | |
746 | } | |
747 | ||
9c63abc9 ILT |
748 | if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { |
749 | if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) { | |
adb0401d ILT |
750 | v = v.Addr() |
751 | } else { | |
752 | switch v.Kind() { | |
753 | case reflect.Chan, reflect.Func: | |
754 | s.errorf("can't print %s of type %s", n, v.Type()) | |
755 | } | |
756 | } | |
757 | } | |
758 | fmt.Fprint(s.wr, v.Interface()) | |
759 | } | |
df1304ee ILT |
760 | |
761 | // Types to help sort the keys in a map for reproducible output. | |
762 | ||
763 | type rvs []reflect.Value | |
764 | ||
765 | func (x rvs) Len() int { return len(x) } | |
766 | func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | |
767 | ||
768 | type rvInts struct{ rvs } | |
769 | ||
770 | func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() } | |
771 | ||
772 | type rvUints struct{ rvs } | |
773 | ||
774 | func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() } | |
775 | ||
776 | type rvFloats struct{ rvs } | |
777 | ||
778 | func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() } | |
779 | ||
780 | type rvStrings struct{ rvs } | |
781 | ||
782 | func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() } | |
783 | ||
784 | // sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys. | |
785 | func sortKeys(v []reflect.Value) []reflect.Value { | |
786 | if len(v) <= 1 { | |
787 | return v | |
788 | } | |
789 | switch v[0].Kind() { | |
790 | case reflect.Float32, reflect.Float64: | |
791 | sort.Sort(rvFloats{v}) | |
792 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |
793 | sort.Sort(rvInts{v}) | |
794 | case reflect.String: | |
795 | sort.Sort(rvStrings{v}) | |
796 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | |
797 | sort.Sort(rvUints{v}) | |
798 | } | |
799 | return v | |
800 | } |