Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(793)

Side by Side Diff: src/pkg/exp/template/exec.go

Issue 4643068: code review 4643068: exp/template: functions (Closed)
Patch Set: diff -r 67b160cd5fa4 https://go.googlecode.com/hg/ Created 13 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package template 5 package template
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "io" 9 "io"
10 "os" 10 "os"
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 func (s *state) evalPipeline(data reflect.Value, pipe []*commandNode) reflect.Va lue { 167 func (s *state) evalPipeline(data reflect.Value, pipe []*commandNode) reflect.Va lue {
168 value := reflect.Value{} 168 value := reflect.Value{}
169 for _, cmd := range pipe { 169 for _, cmd := range pipe {
170 value = s.evalCommand(data, cmd, value) // previous value is thi s one's final arg. 170 value = s.evalCommand(data, cmd, value) // previous value is thi s one's final arg.
171 } 171 }
172 return value 172 return value
173 } 173 }
174 174
175 func (s *state) evalCommand(data reflect.Value, cmd *commandNode, final reflect. Value) reflect.Value { 175 func (s *state) evalCommand(data reflect.Value, cmd *commandNode, final reflect. Value) reflect.Value {
176 firstWord := cmd.args[0] 176 firstWord := cmd.args[0]
177 » if field, ok := firstWord.(*fieldNode); ok { 177 » switch n := firstWord.(type) {
178 » » return s.evalFieldNode(data, field, cmd.args, final) 178 » case *fieldNode:
179 » » return s.evalFieldNode(data, n, cmd.args, final)
180 » case *identifierNode:
181 » » return s.evalFieldOrCall(data, n.ident, cmd.args, final)
179 } 182 }
180 if len(cmd.args) > 1 || final.IsValid() { 183 if len(cmd.args) > 1 || final.IsValid() {
181 // TODO: functions 184 // TODO: functions
182 s.errorf("can't give argument to non-method %s", cmd.args[0]) 185 s.errorf("can't give argument to non-method %s", cmd.args[0])
183 } 186 }
184 switch word := cmd.args[0].(type) { 187 switch word := cmd.args[0].(type) {
185 case *dotNode: 188 case *dotNode:
186 return data 189 return data
187 case *boolNode: 190 case *boolNode:
188 return reflect.ValueOf(word.true) 191 return reflect.ValueOf(word.true)
(...skipping 19 matching lines...) Expand all
208 panic("not reached") 211 panic("not reached")
209 } 212 }
210 213
211 func (s *state) evalFieldNode(data reflect.Value, field *fieldNode, args []node, final reflect.Value) reflect.Value { 214 func (s *state) evalFieldNode(data reflect.Value, field *fieldNode, args []node, final reflect.Value) reflect.Value {
212 // Up to the last entry, it must be a field. 215 // Up to the last entry, it must be a field.
213 n := len(field.ident) 216 n := len(field.ident)
214 for i := 0; i < n-1; i++ { 217 for i := 0; i < n-1; i++ {
215 data = s.evalField(data, field.ident[i]) 218 data = s.evalField(data, field.ident[i])
216 } 219 }
217 // Now it can be a field or method and if a method, gets arguments. 220 // Now it can be a field or method and if a method, gets arguments.
218 » return s.evalMethodOrField(data, field.ident[n-1], args, final) 221 » return s.evalFieldOrCall(data, field.ident[n-1], args, final)
219 } 222 }
220 223
221 func (s *state) evalField(data reflect.Value, fieldName string) reflect.Value { 224 func (s *state) evalField(data reflect.Value, fieldName string) reflect.Value {
222 for data.Kind() == reflect.Ptr { 225 for data.Kind() == reflect.Ptr {
223 data = reflect.Indirect(data) 226 data = reflect.Indirect(data)
224 } 227 }
225 switch data.Kind() { 228 switch data.Kind() {
226 case reflect.Struct: 229 case reflect.Struct:
227 // Is it a field? 230 // Is it a field?
228 field := data.FieldByName(fieldName) 231 field := data.FieldByName(fieldName)
229 // TODO: look higher up the tree if we can't find it here. Also unexported fields 232 // TODO: look higher up the tree if we can't find it here. Also unexported fields
230 // might succeed higher up, as map keys. 233 // might succeed higher up, as map keys.
231 if field.IsValid() && field.Type().PkgPath() == "" { // valid an d exported 234 if field.IsValid() && field.Type().PkgPath() == "" { // valid an d exported
232 return field 235 return field
233 } 236 }
234 s.errorf("%s has no field %s", data.Type(), fieldName) 237 s.errorf("%s has no field %s", data.Type(), fieldName)
235 default: 238 default:
236 s.errorf("can't evaluate field %s of type %s", fieldName, data.T ype()) 239 s.errorf("can't evaluate field %s of type %s", fieldName, data.T ype())
237 } 240 }
238 panic("not reached") 241 panic("not reached")
239 } 242 }
240 243
241 func (s *state) evalMethodOrField(data reflect.Value, fieldName string, args []n ode, final reflect.Value) reflect.Value { 244 func (s *state) evalFieldOrCall(data reflect.Value, fieldName string, args []nod e, final reflect.Value) reflect.Value {
245 » // Is it a function?
246 » if function, ok := findFunction(fieldName, s.tmpl, s.set); ok {
247 » » return s.evalCall(data, function, fieldName, false, args, final)
248 » }
242 ptr := data 249 ptr := data
243 for data.Kind() == reflect.Ptr { 250 for data.Kind() == reflect.Ptr {
244 ptr, data = data, reflect.Indirect(data) 251 ptr, data = data, reflect.Indirect(data)
245 } 252 }
246 // Is it a method? We use the pointer because it has value methods too. 253 // Is it a method? We use the pointer because it has value methods too.
247 if method, ok := ptr.Type().MethodByName(fieldName); ok { 254 if method, ok := ptr.Type().MethodByName(fieldName); ok {
248 » » return s.evalMethod(ptr, method, args, final) 255 » » return s.evalCall(ptr, method.Func, fieldName, true, args, final )
249 } 256 }
250 if len(args) > 1 || final.IsValid() { 257 if len(args) > 1 || final.IsValid() {
251 s.errorf("%s is not a method but has arguments", fieldName) 258 s.errorf("%s is not a method but has arguments", fieldName)
252 } 259 }
253 switch data.Kind() { 260 switch data.Kind() {
254 case reflect.Struct: 261 case reflect.Struct:
255 return s.evalField(data, fieldName) 262 return s.evalField(data, fieldName)
256 default: 263 default:
257 s.errorf("can't handle evaluation of field %s of type %s", field Name, data.Type()) 264 s.errorf("can't handle evaluation of field %s of type %s", field Name, data.Type())
258 } 265 }
259 panic("not reached") 266 panic("not reached")
260 } 267 }
261 268
262 var ( 269 var (
263 osErrorType = reflect.TypeOf(new(os.Error)).Elem() 270 osErrorType = reflect.TypeOf(new(os.Error)).Elem()
264 ) 271 )
265 272
266 func (s *state) evalMethod(v reflect.Value, method reflect.Method, args []node, final reflect.Value) reflect.Value { 273 func (s *state) evalCall(v, fun reflect.Value, name string, isMethod bool, args []node, final reflect.Value) reflect.Value {
267 » typ := method.Type 274 » typ := fun.Type()
268 » fun := method.Func 275 » if !isMethod && len(args) > 0 { // Args will be nil if it's a niladic ca ll in an argument list
276 » » args = args[1:] // first arg is name of function; not used in ca ll.
277 » }
269 numIn := len(args) 278 numIn := len(args)
270 if final.IsValid() { 279 if final.IsValid() {
271 numIn++ 280 numIn++
272 } 281 }
273 » if !typ.IsVariadic() && numIn < typ.NumIn()-1 || !typ.IsVariadic() && nu mIn != typ.NumIn() { 282 » numFixed := len(args)
274 » » s.errorf("wrong number of args for %s: want %d got %d", method.N ame, typ.NumIn(), len(args)) 283 » if typ.IsVariadic() {
284 » » numFixed = typ.NumIn() - 1 // last arg is the variadic one.
285 » » if numIn < numFixed {
286 » » » s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
287 » » }
288 » } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.Num In() {
289 » » s.errorf("wrong number of args for %s: want %d got %d", name, ty p.NumIn(), len(args))
275 } 290 }
276 » // We allow methods with 1 result or 2 results where the second is an os .Error. 291 » // We allow functions with 1 result or 2 results where the second is an os.Error.
277 switch { 292 switch {
278 case typ.NumOut() == 1: 293 case typ.NumOut() == 1:
279 case typ.NumOut() == 2 && typ.Out(1) == osErrorType: 294 case typ.NumOut() == 2 && typ.Out(1) == osErrorType:
dsymonds 2011/07/05 04:17:04 This checking could be replicated in addFuncs so t
280 default: 295 default:
281 » » s.errorf("can't handle multiple results from method %q", method. Name) 296 » » s.errorf("can't handle multiple results from method/function %q" , name)
282 } 297 }
283 // Build the arg list. 298 // Build the arg list.
284 argv := make([]reflect.Value, numIn) 299 argv := make([]reflect.Value, numIn)
285 // First arg is the receiver. 300 // First arg is the receiver.
286 » argv[0] = v 301 » i := 0
287 » // Others must be evaluated. 302 » if isMethod {
288 » for i := 1; i < len(args); i++ { 303 » » argv[0] = v
304 » » i++
305 » }
306 » // Others must be evaluated. Fixed args first.
307 » for ; i < numFixed; i++ {
289 argv[i] = s.evalArg(v, typ.In(i), args[i]) 308 argv[i] = s.evalArg(v, typ.In(i), args[i])
290 } 309 }
310 // And now the ... args.
311 if typ.IsVariadic() {
312 argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice .
313 for ; i < len(args); i++ {
314 argv[i] = s.evalArg(v, argType, args[i])
315 }
316 }
291 // Add final value if necessary. 317 // Add final value if necessary.
292 if final.IsValid() { 318 if final.IsValid() {
293 argv[len(args)] = final 319 argv[len(args)] = final
294 } 320 }
295 result := fun.Call(argv) 321 result := fun.Call(argv)
296 // If we have an os.Error that is not nil, stop execution and return tha t error to the caller. 322 // If we have an os.Error that is not nil, stop execution and return tha t error to the caller.
297 if len(result) == 2 && !result[1].IsNil() { 323 if len(result) == 2 && !result[1].IsNil() {
298 s.error(result[1].Interface().(os.Error)) 324 s.error(result[1].Interface().(os.Error))
299 } 325 }
300 return result[0] 326 return result[0]
301 } 327 }
302 328
303 func (s *state) evalArg(data reflect.Value, typ reflect.Type, n node) reflect.Va lue { 329 func (s *state) evalArg(data reflect.Value, typ reflect.Type, n node) reflect.Va lue {
304 if field, ok := n.(*fieldNode); ok { 330 if field, ok := n.(*fieldNode); ok {
305 value := s.evalFieldNode(data, field, []node{n}, reflect.Value{} ) 331 value := s.evalFieldNode(data, field, []node{n}, reflect.Value{} )
306 if !value.Type().AssignableTo(typ) { 332 if !value.Type().AssignableTo(typ) {
307 s.errorf("wrong type for value; expected %s; got %s", ty p, value.Type()) 333 s.errorf("wrong type for value; expected %s; got %s", ty p, value.Type())
308 } 334 }
309 return value 335 return value
310 } 336 }
311 switch typ.Kind() { 337 switch typ.Kind() {
312 case reflect.Bool: 338 case reflect.Bool:
313 » » return s.evalBool(data, typ, n) 339 » » return s.evalBool(typ, n)
314 case reflect.String: 340 case reflect.String:
315 » » return s.evalString(data, typ, n) 341 » » return s.evalString(typ, n)
316 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64: 342 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.In t64:
317 » » return s.evalInteger(data, typ, n) 343 » » return s.evalInteger(typ, n)
318 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflec t.Uint64, reflect.Uintptr: 344 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflec t.Uint64, reflect.Uintptr:
319 » » return s.evalUnsignedInteger(data, typ, n) 345 » » return s.evalUnsignedInteger(typ, n)
320 case reflect.Float32, reflect.Float64: 346 case reflect.Float32, reflect.Float64:
321 » » return s.evalFloat(data, typ, n) 347 » » return s.evalFloat(typ, n)
322 case reflect.Complex64, reflect.Complex128: 348 case reflect.Complex64, reflect.Complex128:
323 » » return s.evalComplex(data, typ, n) 349 » » return s.evalComplex(typ, n)
350 » case reflect.Interface:
351 » » if typ.NumMethod() == 0 {
352 » » » return s.evalEmptyInterface(data, typ, n)
353 » » }
324 } 354 }
325 » s.errorf("can't handle node %s for method arg of type %s", n, typ) 355 » s.errorf("can't handle %s for arg of type %s", n, typ)
326 panic("not reached") 356 panic("not reached")
327 } 357 }
328 358
329 func (s *state) evalBool(v reflect.Value, typ reflect.Type, n node) reflect.Valu e { 359 func (s *state) evalBool(typ reflect.Type, n node) reflect.Value {
330 if n, ok := n.(*boolNode); ok { 360 if n, ok := n.(*boolNode); ok {
331 value := reflect.New(typ).Elem() 361 value := reflect.New(typ).Elem()
332 value.SetBool(n.true) 362 value.SetBool(n.true)
333 return value 363 return value
334 } 364 }
335 s.errorf("expected bool; found %s", n) 365 s.errorf("expected bool; found %s", n)
336 panic("not reached") 366 panic("not reached")
337 } 367 }
338 368
339 func (s *state) evalString(v reflect.Value, typ reflect.Type, n node) reflect.Va lue { 369 func (s *state) evalString(typ reflect.Type, n node) reflect.Value {
340 if n, ok := n.(*stringNode); ok { 370 if n, ok := n.(*stringNode); ok {
341 value := reflect.New(typ).Elem() 371 value := reflect.New(typ).Elem()
342 value.SetString(n.text) 372 value.SetString(n.text)
343 return value 373 return value
344 } 374 }
345 s.errorf("expected string; found %s", n) 375 s.errorf("expected string; found %s", n)
346 panic("not reached") 376 panic("not reached")
347 } 377 }
348 378
349 func (s *state) evalInteger(v reflect.Value, typ reflect.Type, n node) reflect.V alue { 379 func (s *state) evalInteger(typ reflect.Type, n node) reflect.Value {
350 if n, ok := n.(*numberNode); ok && n.isInt { 380 if n, ok := n.(*numberNode); ok && n.isInt {
351 value := reflect.New(typ).Elem() 381 value := reflect.New(typ).Elem()
352 value.SetInt(n.int64) 382 value.SetInt(n.int64)
353 return value 383 return value
354 } 384 }
355 s.errorf("expected integer; found %s", n) 385 s.errorf("expected integer; found %s", n)
356 panic("not reached") 386 panic("not reached")
357 } 387 }
358 388
359 func (s *state) evalUnsignedInteger(v reflect.Value, typ reflect.Type, n node) r eflect.Value { 389 func (s *state) evalUnsignedInteger(typ reflect.Type, n node) reflect.Value {
360 if n, ok := n.(*numberNode); ok && n.isUint { 390 if n, ok := n.(*numberNode); ok && n.isUint {
361 value := reflect.New(typ).Elem() 391 value := reflect.New(typ).Elem()
362 value.SetUint(n.uint64) 392 value.SetUint(n.uint64)
363 return value 393 return value
364 } 394 }
365 s.errorf("expected unsigned integer; found %s", n) 395 s.errorf("expected unsigned integer; found %s", n)
366 panic("not reached") 396 panic("not reached")
367 } 397 }
368 398
369 func (s *state) evalFloat(v reflect.Value, typ reflect.Type, n node) reflect.Val ue { 399 func (s *state) evalFloat(typ reflect.Type, n node) reflect.Value {
370 if n, ok := n.(*numberNode); ok && n.isFloat { 400 if n, ok := n.(*numberNode); ok && n.isFloat {
371 value := reflect.New(typ).Elem() 401 value := reflect.New(typ).Elem()
372 value.SetFloat(n.float64) 402 value.SetFloat(n.float64)
373 return value 403 return value
374 } 404 }
375 s.errorf("expected float; found %s", n) 405 s.errorf("expected float; found %s", n)
376 panic("not reached") 406 panic("not reached")
377 } 407 }
378 408
379 func (s *state) evalComplex(v reflect.Value, typ reflect.Type, n node) reflect.V alue { 409 func (s *state) evalComplex(typ reflect.Type, n node) reflect.Value {
380 if n, ok := n.(*numberNode); ok && n.isComplex { 410 if n, ok := n.(*numberNode); ok && n.isComplex {
381 value := reflect.New(typ).Elem() 411 value := reflect.New(typ).Elem()
382 value.SetComplex(n.complex128) 412 value.SetComplex(n.complex128)
383 return value 413 return value
384 } 414 }
385 s.errorf("expected complex; found %s", n) 415 s.errorf("expected complex; found %s", n)
386 panic("not reached") 416 panic("not reached")
387 } 417 }
388 418
419 func (s *state) evalEmptyInterface(data reflect.Value, typ reflect.Type, n node) reflect.Value {
420 switch n := n.(type) {
421 case *boolNode:
422 return reflect.ValueOf(n.true)
423 case *fieldNode:
424 return s.evalFieldNode(data, n, nil, reflect.Value{})
425 case *identifierNode:
426 return s.evalFieldOrCall(data, n.ident, nil, reflect.Value{})
427 case *numberNode:
428 if n.isComplex {
429 return reflect.ValueOf(n.complex128)
430 }
431 if n.isInt {
432 return reflect.ValueOf(n.int64)
433 }
434 if n.isUint {
435 return reflect.ValueOf(n.uint64)
436 }
437 if n.isFloat {
438 return reflect.ValueOf(n.float64)
439 }
440 case *stringNode:
441 return reflect.ValueOf(n.text)
442 }
443 s.errorf("can't handle assignment of %s to empty interface argument", n)
444 panic("not reached")
445 }
446
389 // printValue writes the textual representation of the value to the output of 447 // printValue writes the textual representation of the value to the output of
390 // the template. 448 // the template.
391 func (s *state) printValue(n node, v reflect.Value) { 449 func (s *state) printValue(n node, v reflect.Value) {
392 if !v.IsValid() { 450 if !v.IsValid() {
393 return 451 return
394 } 452 }
395 switch v.Kind() { 453 switch v.Kind() {
396 case reflect.Ptr: 454 case reflect.Ptr:
397 if v.IsNil() { 455 if v.IsNil() {
398 s.errorf("%s: nil value", n) 456 s.errorf("%s: nil value", n)
399 } 457 }
400 case reflect.Chan, reflect.Func, reflect.Interface: 458 case reflect.Chan, reflect.Func, reflect.Interface:
401 s.errorf("can't print %s of type %s", n, v.Type()) 459 s.errorf("can't print %s of type %s", n, v.Type())
402 } 460 }
403 fmt.Fprint(s.wr, v.Interface()) 461 fmt.Fprint(s.wr, v.Interface())
404 } 462 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b