Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / text / template / exec.go
index aba21ce..b9c03d8 100644 (file)
@@ -20,7 +20,7 @@ import (
 type state struct {
        tmpl *Template
        wr   io.Writer
-       line int        // line number for errors
+       node parse.Node // current node, for errors
        vars []variable // push-down stack of variable values.
 }
 
@@ -63,17 +63,32 @@ func (s *state) varValue(name string) reflect.Value {
 
 var zero reflect.Value
 
+// at marks the state to be on node n, for error reporting.
+func (s *state) at(node parse.Node) {
+       s.node = node
+}
+
+// doublePercent returns the string with %'s replaced by %%, if necessary,
+// so it can be used safely inside a Printf format string.
+func doublePercent(str string) string {
+       if strings.Contains(str, "%") {
+               str = strings.Replace(str, "%", "%%", -1)
+       }
+       return str
+}
+
 // 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)
+       name := doublePercent(s.tmpl.Name())
+       if s.node == nil {
+               format = fmt.Sprintf("template: %s: %s", name, format)
+       } else {
+               location, context := s.tmpl.ErrorContext(s.node)
+               format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
+       }
        panic(fmt.Errorf(format, args...))
 }
 
-// error terminates processing.
-func (s *state) error(err error) {
-       s.errorf("%s", err)
-}
-
 // errRecover is the handler that turns panics into returns from the top
 // level of Parse.
 func errRecover(errp *error) {
@@ -108,7 +123,6 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
        state := &state{
                tmpl: t,
                wr:   wr,
-               line: 1,
                vars: []variable{{"$", value}},
        }
        if t.Tree == nil || t.Root == nil {
@@ -120,38 +134,34 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
 
 // Walk functions step through the major pieces of the template structure,
 // generating output as they go.
-func (s *state) walk(dot reflect.Value, n parse.Node) {
-       switch n := n.(type) {
+func (s *state) walk(dot reflect.Value, node parse.Node) {
+       s.at(node)
+       switch node := node.(type) {
        case *parse.ActionNode:
-               s.line = n.Line
                // Do not pop variables so they persist until next end.
                // Also, if the action declares variables, don't print the result.
-               val := s.evalPipeline(dot, n.Pipe)
-               if len(n.Pipe.Decl) == 0 {
-                       s.printValue(n, val)
+               val := s.evalPipeline(dot, node.Pipe)
+               if len(node.Pipe.Decl) == 0 {
+                       s.printValue(node, val)
                }
        case *parse.IfNode:
-               s.line = n.Line
-               s.walkIfOrWith(parse.NodeIf, dot, n.Pipe, n.List, n.ElseList)
+               s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
        case *parse.ListNode:
-               for _, node := range n.Nodes {
+               for _, node := range node.Nodes {
                        s.walk(dot, node)
                }
        case *parse.RangeNode:
-               s.line = n.Line
-               s.walkRange(dot, n)
+               s.walkRange(dot, node)
        case *parse.TemplateNode:
-               s.line = n.Line
-               s.walkTemplate(dot, n)
+               s.walkTemplate(dot, node)
        case *parse.TextNode:
-               if _, err := s.wr.Write(n.Text); err != nil {
-                       s.error(err)
+               if _, err := s.wr.Write(node.Text); err != nil {
+                       s.errorf("%s", err)
                }
        case *parse.WithNode:
-               s.line = n.Line
-               s.walkIfOrWith(parse.NodeWith, dot, n.Pipe, n.List, n.ElseList)
+               s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
        default:
-               s.errorf("unknown node: %s", n)
+               s.errorf("unknown node: %s", node)
        }
 }
 
@@ -206,6 +216,7 @@ func isTrue(val reflect.Value) (truth, ok bool) {
 }
 
 func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+       s.at(r)
        defer s.pop(s.mark())
        val, _ := indirect(s.evalPipeline(dot, r.Pipe))
        // mark top of stack before any variables in the body are pushed.
@@ -266,6 +277,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
 }
 
 func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+       s.at(t)
        tmpl := s.tmpl.tmpl[t.Name]
        if tmpl == nil {
                s.errorf("template %q not defined", t.Name)
@@ -291,6 +303,7 @@ func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value ref
        if pipe == nil {
                return
        }
+       s.at(pipe)
        for _, cmd := range pipe.Cmds {
                value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
                // If the object has type interface{}, dig down one level to the thing inside.
@@ -315,18 +328,26 @@ func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final ref
        switch n := firstWord.(type) {
        case *parse.FieldNode:
                return s.evalFieldNode(dot, n, cmd.Args, final)
+       case *parse.ChainNode:
+               return s.evalChainNode(dot, n, cmd.Args, final)
        case *parse.IdentifierNode:
                // Must be a function.
-               return s.evalFunction(dot, n.Ident, cmd.Args, final)
+               return s.evalFunction(dot, n, cmd, cmd.Args, final)
+       case *parse.PipeNode:
+               // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
+               return s.evalPipeline(dot, n)
        case *parse.VariableNode:
                return s.evalVariableNode(dot, n, cmd.Args, final)
        }
+       s.at(firstWord)
        s.notAFunction(cmd.Args, final)
        switch word := firstWord.(type) {
        case *parse.BoolNode:
                return reflect.ValueOf(word.True)
        case *parse.DotNode:
                return dot
+       case *parse.NilNode:
+               s.errorf("nil is not a command")
        case *parse.NumberNode:
                return s.idealConstant(word)
        case *parse.StringNode:
@@ -344,6 +365,7 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
        // 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.
+       s.at(constant)
        switch {
        case constant.IsComplex:
                return reflect.ValueOf(constant.Complex128) // incontrovertible.
@@ -362,43 +384,57 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
 }
 
 func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
-       return s.evalFieldChain(dot, dot, field.Ident, args, final)
+       s.at(field)
+       return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
+}
+
+func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
+       s.at(chain)
+       // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
+       pipe := s.evalArg(dot, nil, chain.Node)
+       if len(chain.Field) == 0 {
+               s.errorf("internal error: no fields in evalChainNode")
+       }
+       return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
 }
 
-func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
        // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
-       value := s.varValue(v.Ident[0])
-       if len(v.Ident) == 1 {
+       s.at(variable)
+       value := s.varValue(variable.Ident[0])
+       if len(variable.Ident) == 1 {
                s.notAFunction(args, final)
                return value
        }
-       return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
+       return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
 }
 
 // evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
 // dot is the environment in which to evaluate arguments, while
 // receiver is the value being walked along the chain.
-func (s *state) evalFieldChain(dot, receiver reflect.Value, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
        n := len(ident)
        for i := 0; i < n-1; i++ {
-               receiver = s.evalField(dot, ident[i], nil, zero, receiver)
+               receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
        }
        // Now if it's a method, it gets the arguments.
-       return s.evalField(dot, ident[n-1], args, final, receiver)
+       return s.evalField(dot, ident[n-1], node, args, final, receiver)
 }
 
-func (s *state) evalFunction(dot reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
+       s.at(node)
+       name := node.Ident
        function, ok := findFunction(name, s.tmpl)
        if !ok {
                s.errorf("%q is not a defined function", name)
        }
-       return s.evalCall(dot, function, name, args, final)
+       return s.evalCall(dot, function, cmd, name, args, final)
 }
 
 // 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.
-func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
        if !receiver.IsValid() {
                return zero
        }
@@ -411,26 +447,31 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node
                ptr = ptr.Addr()
        }
        if method := ptr.MethodByName(fieldName); method.IsValid() {
-               return s.evalCall(dot, method, fieldName, args, final)
+               return s.evalCall(dot, method, node, fieldName, args, final)
        }
        hasArgs := len(args) > 1 || final.IsValid()
-       // It's not a method; is it a field of a struct?
+       // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
        receiver, isNil := indirect(receiver)
-       if receiver.Kind() == reflect.Struct {
+       if isNil {
+               s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+       }
+       switch receiver.Kind() {
+       case reflect.Struct:
                tField, ok := receiver.Type().FieldByName(fieldName)
                if ok {
                        field := receiver.FieldByIndex(tField.Index)
-                       if tField.PkgPath == "" { // field is exported
-                               // If it's a function, we must call it.
-                               if hasArgs {
-                                       s.errorf("%s has arguments but cannot be invoked as function", fieldName)
-                               }
-                               return field
+                       if tField.PkgPath != "" { // field is unexported
+                               s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
+                       }
+                       // If it's a function, we must call it.
+                       if hasArgs {
+                               s.errorf("%s has arguments but cannot be invoked as function", fieldName)
                        }
+                       return field
                }
-       }
-       // If it's a map, attempt to use the field name as a key.
-       if receiver.Kind() == reflect.Map {
+               s.errorf("%s is not a field of struct type %s", fieldName, typ)
+       case reflect.Map:
+               // If it's a map, attempt to use the field name as a key.
                nameVal := reflect.ValueOf(fieldName)
                if nameVal.Type().AssignableTo(receiver.Type().Key()) {
                        if hasArgs {
@@ -439,9 +480,6 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node
                        return receiver.MapIndex(nameVal)
                }
        }
-       if isNil {
-               s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
-       }
        s.errorf("can't evaluate field %s in type %s", fieldName, typ)
        panic("not reached")
 }
@@ -454,7 +492,7 @@ var (
 // evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
 // it looks just like a function call.  The arg list, if non-nil, includes (in the manner of the shell), arg[0]
 // as the function itself.
-func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
        if args != nil {
                args = args[1:] // Zeroth arg is function name/node; not passed to function.
        }
@@ -473,7 +511,8 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
                s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
        }
        if !goodFunc(typ) {
-               s.errorf("can't handle multiple results from method/function %q", name)
+               // TODO: This could still be a confusing error; maybe goodFunc should provide info.
+               s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
        }
        // Build the arg list.
        argv := make([]reflect.Value, numIn)
@@ -500,24 +539,31 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
        result := fun.Call(argv)
        // If we have an error that is not nil, stop execution and return that error to the caller.
        if len(result) == 2 && !result[1].IsNil() {
+               s.at(node)
                s.errorf("error calling %s: %s", name, result[1].Interface().(error))
        }
        return result[0]
 }
 
+// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
+func canBeNil(typ reflect.Type) bool {
+       switch typ.Kind() {
+       case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+               return true
+       }
+       return false
+}
+
 // validateType guarantees that the value is valid and assignable to the type.
 func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
        if !value.IsValid() {
-               switch typ.Kind() {
-               case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
+               if typ == nil || canBeNil(typ) {
                        // An untyped nil interface{}. Accept as a proper nil value.
-                       // TODO: Can we delete the other types in this list? Should we?
-                       value = reflect.Zero(typ)
-               default:
-                       s.errorf("invalid value; expected %s", typ)
+                       return reflect.Zero(typ)
                }
+               s.errorf("invalid value; expected %s", typ)
        }
-       if !value.Type().AssignableTo(typ) {
+       if typ != nil && !value.Type().AssignableTo(typ) {
                if value.Kind() == reflect.Interface && !value.IsNil() {
                        value = value.Elem()
                        if value.Type().AssignableTo(typ) {
@@ -542,13 +588,21 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
 }
 
 func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
        switch arg := n.(type) {
        case *parse.DotNode:
                return s.validateType(dot, typ)
+       case *parse.NilNode:
+               if canBeNil(typ) {
+                       return reflect.Zero(typ)
+               }
+               s.errorf("cannot assign nil to %s", typ)
        case *parse.FieldNode:
                return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
        case *parse.VariableNode:
                return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+       case *parse.PipeNode:
+               return s.validateType(s.evalPipeline(dot, arg), typ)
        }
        switch typ.Kind() {
        case reflect.Bool:
@@ -573,6 +627,7 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
 }
 
 func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
        if n, ok := n.(*parse.BoolNode); ok {
                value := reflect.New(typ).Elem()
                value.SetBool(n.True)
@@ -583,6 +638,7 @@ func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
        if n, ok := n.(*parse.StringNode); ok {
                value := reflect.New(typ).Elem()
                value.SetString(n.Text)
@@ -593,6 +649,7 @@ func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
        if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
                value := reflect.New(typ).Elem()
                value.SetInt(n.Int64)
@@ -603,6 +660,7 @@ func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
        if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
                value := reflect.New(typ).Elem()
                value.SetUint(n.Uint64)
@@ -613,6 +671,7 @@ func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Valu
 }
 
 func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
        if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
                value := reflect.New(typ).Elem()
                value.SetFloat(n.Float64)
@@ -633,6 +692,7 @@ func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+       s.at(n)
        switch n := n.(type) {
        case *parse.BoolNode:
                return reflect.ValueOf(n.True)
@@ -641,13 +701,18 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Valu
        case *parse.FieldNode:
                return s.evalFieldNode(dot, n, nil, zero)
        case *parse.IdentifierNode:
-               return s.evalFunction(dot, n.Ident, nil, zero)
+               return s.evalFunction(dot, n, n, nil, zero)
+       case *parse.NilNode:
+               // NilNode is handled in evalArg, the only place that calls here.
+               s.errorf("evalEmptyInterface: nil (can't happen)")
        case *parse.NumberNode:
                return s.idealConstant(n)
        case *parse.StringNode:
                return reflect.ValueOf(n.Text)
        case *parse.VariableNode:
                return s.evalVariableNode(dot, n, nil, zero)
+       case *parse.PipeNode:
+               return s.evalPipeline(dot, n)
        }
        s.errorf("can't handle assignment of %s to empty interface argument", n)
        panic("not reached")
@@ -671,6 +736,7 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
 // printValue writes the textual representation of the value to the output of
 // the template.
 func (s *state) printValue(n parse.Node, v reflect.Value) {
+       s.at(n)
        if v.Kind() == reflect.Ptr {
                v, _ = indirect(v) // fmt.Fprint handles nil.
        }