exec.go 17.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package template

import (
	"fmt"
	"io"
	"os"
	"reflect"
12
	"strings"
Rob Pike's avatar
Rob Pike committed
13 14
	"unicode"
	"utf8"
15 16 17 18 19 20 21 22
)

// state represents the state of an execution. It's not part of the
// template so that multiple executions of the same template
// can execute in parallel.
type state struct {
	tmpl *Template
	wr   io.Writer
23
	set  *Set
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
	line int        // line number for errors
	vars []variable // push-down stack of variable values.
}

// variable holds the dynamic value of a variable such as $, $x etc.
type variable struct {
	name  string
	value reflect.Value
}

// push pushes a new variable on the stack.
func (s *state) push(name string, value reflect.Value) {
	s.vars = append(s.vars, variable{name, value})
}

// mark returns the length of the variable stack.
func (s *state) mark() int {
	return len(s.vars)
}

// pop pops the variable stack up to the mark.
func (s *state) pop(mark int) {
	s.vars = s.vars[0:mark]
}

// setTop overwrites the top variable on the stack. Used by range iterations.
func (s *state) setTop(value reflect.Value) {
	s.vars[len(s.vars)-1].value = value
}

54 55
// varValue returns the value of the named variable.
func (s *state) varValue(name string) reflect.Value {
56 57 58 59 60 61 62
	for i := s.mark() - 1; i >= 0; i-- {
		if s.vars[i].name == name {
			return s.vars[i].value
		}
	}
	s.errorf("undefined variable: %s", name)
	return zero
63 64
}

65 66
var zero reflect.Value

67 68 69 70 71 72 73 74 75 76 77 78 79
// errorf formats the error and terminates processing.
func (s *state) errorf(format string, args ...interface{}) {
	format = fmt.Sprintf("template: %s:%d: %s", s.tmpl.name, s.line, format)
	panic(fmt.Errorf(format, args...))
}

// error terminates processing.
func (s *state) error(err os.Error) {
	s.errorf("%s", err)
}

// Execute applies a parsed template to the specified data object,
// writing the output to wr.
80 81 82 83 84 85 86 87
func (t *Template) Execute(wr io.Writer, data interface{}) os.Error {
	return t.ExecuteInSet(wr, data, nil)
}

// ExecuteInSet applies a parsed template to the specified data object,
// writing the output to wr. Nested template invocations will be resolved
// from the specified set.
func (t *Template) ExecuteInSet(wr io.Writer, data interface{}, set *Set) (err os.Error) {
88
	defer t.recover(&err)
89
	value := reflect.ValueOf(data)
90 91 92
	state := &state{
		tmpl: t,
		wr:   wr,
93
		set:  set,
94
		line: 1,
95
		vars: []variable{{"$", value}},
96 97 98 99
	}
	if t.root == nil {
		state.errorf("must be parsed before execution")
	}
100 101 102 103
	state.walk(value, t.root)
	if state.mark() != 1 {
		t.errorf("internal error: variable stack at %d", state.mark())
	}
104 105 106 107 108
	return
}

// Walk functions step through the major pieces of the template structure,
// generating output as they go.
109
func (s *state) walk(dot reflect.Value, n node) {
110 111 112
	switch n := n.(type) {
	case *actionNode:
		s.line = n.line
113
		defer s.pop(s.mark())
114
		s.printValue(n, s.evalPipeline(dot, n.pipe))
115 116
	case *ifNode:
		s.line = n.line
117
		s.walkIfOrWith(nodeIf, dot, n.pipe, n.list, n.elseList)
118 119
	case *listNode:
		for _, node := range n.nodes {
120
			s.walk(dot, node)
121 122
		}
	case *rangeNode:
Rob Pike's avatar
Rob Pike committed
123
		s.line = n.line
124
		s.walkRange(dot, n)
125 126
	case *templateNode:
		s.line = n.line
127
		s.walkTemplate(dot, n)
128 129 130 131
	case *textNode:
		if _, err := s.wr.Write(n.text); err != nil {
			s.error(err)
		}
132
	case *withNode:
Rob Pike's avatar
Rob Pike committed
133
		s.line = n.line
134
		s.walkIfOrWith(nodeWith, dot, n.pipe, n.list, n.elseList)
135 136 137 138 139
	default:
		s.errorf("unknown node: %s", n)
	}
}

140 141
// walkIfOrWith walks an 'if' or 'with' node. The two control structures
// are identical in behavior except that 'with' sets dot.
142
func (s *state) walkIfOrWith(typ nodeType, dot reflect.Value, pipe *pipeNode, list, elseList *listNode) {
143
	defer s.pop(s.mark())
144
	val := s.evalPipeline(dot, pipe)
145 146 147 148 149 150
	truth, ok := isTrue(val)
	if !ok {
		s.errorf("if/with can't use value of type %T", val.Interface())
	}
	if truth {
		if typ == nodeWith {
151
			s.walk(val, list)
152
		} else {
153
			s.walk(dot, list)
154 155
		}
	} else if elseList != nil {
156
		s.walk(dot, elseList)
157 158 159 160 161 162
	}
}

// isTrue returns whether the value is 'true', in the sense of not the zero of its type,
// and whether the value has a meaningful truth value.
func isTrue(val reflect.Value) (truth, ok bool) {
163 164 165 166 167 168 169 170 171
	switch val.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		truth = val.Len() > 0
	case reflect.Bool:
		truth = val.Bool()
	case reflect.Complex64, reflect.Complex128:
		truth = val.Complex() != 0
	case reflect.Chan, reflect.Func, reflect.Ptr:
		truth = !val.IsNil()
172 173 174 175 176 177
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		truth = val.Int() != 0
	case reflect.Float32, reflect.Float64:
		truth = val.Float() != 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		truth = val.Uint() != 0
178
	default:
179
		return
180
	}
181
	return truth, true
182 183
}

184
func (s *state) walkRange(dot reflect.Value, r *rangeNode) {
185
	defer s.pop(s.mark())
186
	val, _ := indirect(s.evalPipeline(dot, r.pipe))
187 188 189 190 191 192
	switch val.Kind() {
	case reflect.Array, reflect.Slice:
		if val.Len() == 0 {
			break
		}
		for i := 0; i < val.Len(); i++ {
193 194 195 196 197 198
			elem := val.Index(i)
			// Set $x to the element rather than the slice.
			if r.pipe.decl != nil {
				s.setTop(elem)
			}
			s.walk(elem, r.list)
199 200 201 202 203 204 205
		}
		return
	case reflect.Map:
		if val.Len() == 0 {
			break
		}
		for _, key := range val.MapKeys() {
206 207 208 209 210 211
			elem := val.MapIndex(key)
			// Set $x to the key rather than the map.
			if r.pipe.decl != nil {
				s.setTop(elem)
			}
			s.walk(elem, r.list)
212 213 214 215 216 217
		}
		return
	default:
		s.errorf("range can't iterate over value of type %T", val.Interface())
	}
	if r.elseList != nil {
218
		s.walk(dot, r.elseList)
219 220 221
	}
}

222
func (s *state) walkTemplate(dot reflect.Value, t *templateNode) {
223
	// Can't use evalArg because there are two types we expect.
224
	arg := s.evalEmptyInterface(dot, t.name)
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
	if !arg.IsValid() {
		s.errorf("invalid value in template invocation; expected string or *Template")
	}
	var tmpl *Template
	if arg.Type() == reflect.TypeOf((*Template)(nil)) {
		tmpl = arg.Interface().(*Template)
		if tmpl == nil {
			s.errorf("nil template")
		}
	} else {
		s.validateType(arg, reflect.TypeOf(""))
		name := arg.String()
		if s.set == nil {
			s.errorf("no set defined in which to invoke template named %q", name)
		}
		tmpl = s.set.tmpl[name]
		if tmpl == nil {
			s.errorf("template %q not in set", name)
		}
244
	}
245
	defer s.pop(s.mark())
246
	dot = s.evalPipeline(dot, t.pipe)
247 248
	newState := *s
	newState.tmpl = tmpl
249
	// No dynamic scoping: template invocations inherit no variables.
250 251
	newState.vars = []variable{{"$", dot}}
	newState.walk(dot, tmpl.root)
252 253
}

254 255 256 257
// Eval functions evaluate pipelines, commands, and their elements and extract
// values from the data structure by examining fields, calling methods, and so on.
// The printing of those values happens only through walk functions.

258 259 260 261
// evalPipeline returns the value acquired by evaluating a pipeline. If the
// pipeline has a variable declaration, the variable will be pushed on the
// stack. Callers should therefore pop the stack after they are finished
// executing commands depending on the pipeline value.
262
func (s *state) evalPipeline(dot reflect.Value, pipe *pipeNode) (value reflect.Value) {
263 264 265
	if pipe == nil {
		return
	}
266
	for _, cmd := range pipe.cmds {
267
		value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
268 269 270 271
		// If the object has type interface{}, dig down one level to the thing inside.
		if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
			value = reflect.ValueOf(value.Interface()) // lovely!
		}
272
	}
273
	if pipe.decl != nil {
274
		s.push(pipe.decl.ident[0], value)
275
	}
276 277 278
	return value
}

279 280 281 282 283 284
func (s *state) notAFunction(args []node, final reflect.Value) {
	if len(args) > 1 || final.IsValid() {
		s.errorf("can't give argument to non-function %s", args[0])
	}
}

285
func (s *state) evalCommand(dot reflect.Value, cmd *commandNode, final reflect.Value) reflect.Value {
286
	firstWord := cmd.args[0]
Rob Pike's avatar
Rob Pike committed
287 288
	switch n := firstWord.(type) {
	case *fieldNode:
289
		return s.evalFieldNode(dot, n, cmd.args, final)
Rob Pike's avatar
Rob Pike committed
290
	case *identifierNode:
291
		// Must be a function.
292
		return s.evalFunction(dot, n.ident, cmd.args, final)
293
	case *variableNode:
294
		return s.evalVariableNode(dot, n, cmd.args, final)
295
	}
296
	s.notAFunction(cmd.args, final)
297
	switch word := firstWord.(type) {
298 299
	case *boolNode:
		return reflect.ValueOf(word.true)
300
	case *dotNode:
301
		return dot
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
	case *numberNode:
		// These are ideal constants but we don't know the type
		// and we have no context.  (If it was a method argument,
		// we'd know what we need.) The syntax guides us to some extent.
		switch {
		case word.isComplex:
			return reflect.ValueOf(word.complex128) // incontrovertible.
		case word.isFloat && strings.IndexAny(word.text, ".eE") >= 0:
			return reflect.ValueOf(word.float64)
		case word.isInt:
			return reflect.ValueOf(word.int64)
		case word.isUint:
			return reflect.ValueOf(word.uint64)
		}
	case *stringNode:
		return reflect.ValueOf(word.text)
318
	}
319
	s.errorf("can't handle command %q", firstWord)
320 321 322
	panic("not reached")
}

323 324
func (s *state) evalFieldNode(dot reflect.Value, field *fieldNode, args []node, final reflect.Value) reflect.Value {
	return s.evalFieldChain(dot, dot, field.ident, args, final)
325 326
}

327
func (s *state) evalVariableNode(dot reflect.Value, v *variableNode, args []node, final reflect.Value) reflect.Value {
328
	// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
329
	value := s.varValue(v.ident[0])
330
	if len(v.ident) == 1 {
331
		return value
332
	}
333
	return s.evalFieldChain(dot, value, v.ident[1:], args, final)
334 335
}

336
func (s *state) evalFieldChain(dot, receiver reflect.Value, ident []string, args []node, final reflect.Value) reflect.Value {
337
	// Up to the last entry, it must be a field.
338
	n := len(ident)
339
	for i := 0; i < n-1; i++ {
340
		dot = s.evalField(dot, ident[i], nil, zero, zero)
341 342
	}
	// Now it can be a field or method and if a method, gets arguments.
343
	return s.evalField(dot, ident[n-1], args, final, receiver)
344 345
}

346
func (s *state) evalFunction(dot reflect.Value, name string, args []node, final reflect.Value) reflect.Value {
347 348 349 350
	function, ok := findFunction(name, s.tmpl, s.set)
	if !ok {
		s.errorf("%q is not a defined function", name)
	}
351
	return s.evalCall(dot, zero, function, name, args, final)
352 353
}

Rob Pike's avatar
Rob Pike committed
354 355 356 357 358 359
// Is this an exported - upper case - name?
func isExported(name string) bool {
	rune, _ := utf8.DecodeRuneInString(name)
	return unicode.IsUpper(rune)
}

360 361 362 363
// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
// The 'final' argument represents the return value from the preceding
// value of the pipeline, if any.
// If we're in a chain, such as (.X.Y.Z), .X and .Y cannot be methods;
364
// canBeMethod will be true only for the last element of such chains (here .Z).
365 366 367 368 369
func (s *state) evalField(dot reflect.Value, fieldName string, args []node, final reflect.Value,
receiver reflect.Value) reflect.Value {
	typ := dot.Type()
	if receiver.IsValid() {
		receiver, _ = indirect(receiver)
370 371
		// Need to get to a value of type *T to guarantee we see all
		// methods of T and *T.
372
		ptr := receiver
373 374
		if ptr.CanAddr() {
			ptr = ptr.Addr()
375
		}
376
		if method, ok := methodByName(ptr.Type(), fieldName); ok {
377
			return s.evalCall(dot, ptr, method.Func, fieldName, args, final)
378
		}
379 380
	}
	// It's not a method; is it a field of a struct?
381 382 383
	dot, isNil := indirect(dot)
	if dot.Kind() == reflect.Struct {
		field := dot.FieldByName(fieldName)
384 385 386 387 388 389
		if field.IsValid() {
			if len(args) > 1 || final.IsValid() {
				s.errorf("%s is not a method but has arguments", fieldName)
			}
			if isExported(fieldName) { // valid and exported
				return field
390 391
			}
		}
392
	}
393 394 395 396
	if isNil {
		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
	}
	s.errorf("can't handle evaluation of field %s in type %s", fieldName, typ)
397 398 399
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
400 401 402 403 404 405 406 407 408 409
// TODO: delete when reflect's own MethodByName is released.
func methodByName(typ reflect.Type, name string) (reflect.Method, bool) {
	for i := 0; i < typ.NumMethod(); i++ {
		if typ.Method(i).Name == name {
			return typ.Method(i), true
		}
	}
	return reflect.Method{}, false
}

410 411 412 413
var (
	osErrorType = reflect.TypeOf(new(os.Error)).Elem()
)

414
func (s *state) evalCall(dot, receiver, fun reflect.Value, name string, args []node, final reflect.Value) reflect.Value {
Rob Pike's avatar
Rob Pike committed
415
	typ := fun.Type()
416
	isMethod := receiver.IsValid()
Rob Pike's avatar
Rob Pike committed
417 418 419
	if !isMethod && len(args) > 0 { // Args will be nil if it's a niladic call in an argument list
		args = args[1:] // first arg is name of function; not used in call.
	}
420 421 422 423
	numIn := len(args)
	if final.IsValid() {
		numIn++
	}
Rob Pike's avatar
Rob Pike committed
424 425 426 427 428 429 430 431
	numFixed := len(args)
	if typ.IsVariadic() {
		numFixed = typ.NumIn() - 1 // last arg is the variadic one.
		if numIn < numFixed {
			s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
		}
	} else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
		s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
432
	}
Rob Pike's avatar
Rob Pike committed
433 434
	if !goodFunc(typ) {
		s.errorf("can't handle multiple results from method/function %q", name)
435 436 437 438
	}
	// Build the arg list.
	argv := make([]reflect.Value, numIn)
	// First arg is the receiver.
Rob Pike's avatar
Rob Pike committed
439 440
	i := 0
	if isMethod {
441
		argv[0] = receiver
Rob Pike's avatar
Rob Pike committed
442 443 444 445
		i++
	}
	// Others must be evaluated. Fixed args first.
	for ; i < numFixed; i++ {
446
		argv[i] = s.evalArg(dot, typ.In(i), args[i])
447
	}
Rob Pike's avatar
Rob Pike committed
448 449 450 451
	// And now the ... args.
	if typ.IsVariadic() {
		argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
		for ; i < len(args); i++ {
452
			argv[i] = s.evalArg(dot, argType, args[i])
Rob Pike's avatar
Rob Pike committed
453 454
		}
	}
455 456 457 458 459 460 461 462 463 464 465 466
	// Add final value if necessary.
	if final.IsValid() {
		argv[len(args)] = final
	}
	result := fun.Call(argv)
	// If we have an os.Error that is not nil, stop execution and return that error to the caller.
	if len(result) == 2 && !result[1].IsNil() {
		s.error(result[1].Interface().(os.Error))
	}
	return result[0]
}

467
// validateType guarantees that the value is valid and assignable to the type.
468
func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
469 470 471
	if !value.IsValid() {
		s.errorf("invalid value; expected %s", typ)
	}
472 473 474 475 476 477
	if !value.Type().AssignableTo(typ) {
		s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
	}
	return value
}

478
func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n node) reflect.Value {
479 480
	switch arg := n.(type) {
	case *dotNode:
481
		return s.validateType(dot, typ)
482
	case *fieldNode:
483
		return s.validateType(s.evalFieldNode(dot, arg, []node{n}, zero), typ)
484
	case *variableNode:
485
		return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
486 487
	}
	switch typ.Kind() {
Rob Pike's avatar
Rob Pike committed
488
	case reflect.Bool:
Rob Pike's avatar
Rob Pike committed
489
		return s.evalBool(typ, n)
490
	case reflect.Complex64, reflect.Complex128:
Rob Pike's avatar
Rob Pike committed
491
		return s.evalComplex(typ, n)
492 493 494 495
	case reflect.Float32, reflect.Float64:
		return s.evalFloat(typ, n)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return s.evalInteger(typ, n)
Rob Pike's avatar
Rob Pike committed
496 497
	case reflect.Interface:
		if typ.NumMethod() == 0 {
498
			return s.evalEmptyInterface(dot, n)
Rob Pike's avatar
Rob Pike committed
499
		}
500 501 502 503
	case reflect.String:
		return s.evalString(typ, n)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return s.evalUnsignedInteger(typ, n)
504
	}
Rob Pike's avatar
Rob Pike committed
505
	s.errorf("can't handle %s for arg of type %s", n, typ)
506 507 508
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
509
func (s *state) evalBool(typ reflect.Type, n node) reflect.Value {
Rob Pike's avatar
Rob Pike committed
510 511 512 513 514 515 516 517 518
	if n, ok := n.(*boolNode); ok {
		value := reflect.New(typ).Elem()
		value.SetBool(n.true)
		return value
	}
	s.errorf("expected bool; found %s", n)
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
519
func (s *state) evalString(typ reflect.Type, n node) reflect.Value {
520 521 522 523 524 525 526 527 528
	if n, ok := n.(*stringNode); ok {
		value := reflect.New(typ).Elem()
		value.SetString(n.text)
		return value
	}
	s.errorf("expected string; found %s", n)
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
529
func (s *state) evalInteger(typ reflect.Type, n node) reflect.Value {
530 531 532 533 534 535 536 537 538
	if n, ok := n.(*numberNode); ok && n.isInt {
		value := reflect.New(typ).Elem()
		value.SetInt(n.int64)
		return value
	}
	s.errorf("expected integer; found %s", n)
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
539
func (s *state) evalUnsignedInteger(typ reflect.Type, n node) reflect.Value {
540 541 542 543 544 545 546 547 548
	if n, ok := n.(*numberNode); ok && n.isUint {
		value := reflect.New(typ).Elem()
		value.SetUint(n.uint64)
		return value
	}
	s.errorf("expected unsigned integer; found %s", n)
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
549
func (s *state) evalFloat(typ reflect.Type, n node) reflect.Value {
550
	if n, ok := n.(*numberNode); ok && n.isFloat {
551 552 553 554 555 556 557 558
		value := reflect.New(typ).Elem()
		value.SetFloat(n.float64)
		return value
	}
	s.errorf("expected float; found %s", n)
	panic("not reached")
}

Rob Pike's avatar
Rob Pike committed
559
func (s *state) evalComplex(typ reflect.Type, n node) reflect.Value {
560
	if n, ok := n.(*numberNode); ok && n.isComplex {
561
		value := reflect.New(typ).Elem()
562
		value.SetComplex(n.complex128)
563 564 565 566 567 568
		return value
	}
	s.errorf("expected complex; found %s", n)
	panic("not reached")
}

569
func (s *state) evalEmptyInterface(dot reflect.Value, n node) reflect.Value {
Rob Pike's avatar
Rob Pike committed
570 571 572
	switch n := n.(type) {
	case *boolNode:
		return reflect.ValueOf(n.true)
573
	case *dotNode:
574
		return dot
Rob Pike's avatar
Rob Pike committed
575
	case *fieldNode:
576
		return s.evalFieldNode(dot, n, nil, zero)
Rob Pike's avatar
Rob Pike committed
577
	case *identifierNode:
578
		return s.evalFunction(dot, n.ident, nil, zero)
Rob Pike's avatar
Rob Pike committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
	case *numberNode:
		if n.isComplex {
			return reflect.ValueOf(n.complex128)
		}
		if n.isInt {
			return reflect.ValueOf(n.int64)
		}
		if n.isUint {
			return reflect.ValueOf(n.uint64)
		}
		if n.isFloat {
			return reflect.ValueOf(n.float64)
		}
	case *stringNode:
		return reflect.ValueOf(n.text)
594
	case *variableNode:
595
		return s.evalVariableNode(dot, n, nil, zero)
Rob Pike's avatar
Rob Pike committed
596 597 598 599 600
	}
	s.errorf("can't handle assignment of %s to empty interface argument", n)
	panic("not reached")
}

601 602 603 604 605 606 607 608 609 610 611
// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
	for v.Kind() == reflect.Ptr {
		if v.IsNil() {
			return v, true
		}
		v = v.Elem()
	}
	return v, false
}

612 613 614 615
// printValue writes the textual representation of the value to the output of
// the template.
func (s *state) printValue(n node, v reflect.Value) {
	if !v.IsValid() {
616
		fmt.Fprint(s.wr, "<no value>")
617 618 619 620
		return
	}
	switch v.Kind() {
	case reflect.Ptr:
621 622 623 624
		var isNil bool
		if v, isNil = indirect(v); isNil {
			fmt.Fprint(s.wr, "<nil>")
			return
625 626 627 628 629 630
		}
	case reflect.Chan, reflect.Func, reflect.Interface:
		s.errorf("can't print %s of type %s", n, v.Type())
	}
	fmt.Fprint(s.wr, v.Interface())
}