exp/template: allow variables as template names.
Just an oversight it wasn't already there.
Thanks to islandberry@live.com for pointing out the omission.

R=golang-dev, dsymonds
CC=golang-dev, islandberry
https://golang.org/cl/4703043
diff --git a/src/pkg/exp/template/parse.go b/src/pkg/exp/template/parse.go
index 774a7dd..91d19e5 100644
--- a/src/pkg/exp/template/parse.go
+++ b/src/pkg/exp/template/parse.go
@@ -33,11 +33,6 @@
 	return t.name
 }
 
-// popVars trims the variable list to the specified length
-func (t *Template) popVars(n int) {
-	t.vars = t.vars[:n]
-}
-
 // next returns the next token.
 func (t *Template) next() item {
 	if t.peekCount > 0 {
@@ -814,6 +809,8 @@
 		name = newIdentifier(token.val)
 	case itemDot:
 		name = newDot()
+	case itemVariable:
+		name = t.useVar(token.val)
 	case itemField:
 		name = newField(token.val)
 	case itemString, itemRawString:
@@ -857,18 +854,7 @@
 		case itemDot:
 			cmd.append(newDot())
 		case itemVariable:
-			v := newVariable(token.val)
-			found := false
-			for _, varName := range t.vars {
-				if varName == v.ident[0] {
-					found = true
-					break
-				}
-			}
-			if !found {
-				t.errorf("undefined variable %q", token.val)
-			}
-			cmd.append(v)
+			cmd.append(t.useVar(token.val))
 		case itemField:
 			cmd.append(newField(token.val))
 		case itemBool:
@@ -894,3 +880,21 @@
 	}
 	return cmd
 }
+
+// popVars trims the variable list to the specified length
+func (t *Template) popVars(n int) {
+	t.vars = t.vars[:n]
+}
+
+// useVar returns a node for a variable reference. It errors if the
+// variable is not defined.
+func (t *Template) useVar(name string) node {
+	v := newVariable(name)
+	for _, varName := range t.vars {
+		if varName == v.ident[0] {
+			return v
+		}
+	}
+	t.errorf("undefined variable %q", v.ident[0])
+	return nil
+}
diff --git a/src/pkg/exp/template/parse_test.go b/src/pkg/exp/template/parse_test.go
index 2a2fa64..10be3cb 100644
--- a/src/pkg/exp/template/parse_test.go
+++ b/src/pkg/exp/template/parse_test.go
@@ -211,6 +211,8 @@
 		`[({{with [(command: [F=[X]])]}} [(text: "hello")])]`},
 	{"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
 		`[({{with [(command: [F=[X]])]}} [(text: "hello")] {{else}} [(text: "goodbye")])]`},
+	{"variable in template", "{{with $v := `hi`}}{{template $v}}{{end}}", noError,
+		"[({{with [$v] := [(command: [S=`hi`])]}} [{{template V=[$v]}}])]"},
 	// Errors.
 	{"unclosed action", "hello{{range", hasError, ""},
 	{"unmatched end", "{{end}}", hasError, ""},
@@ -219,6 +221,7 @@
 	{"undefined function", "hello{{undefined}}", hasError, ""},
 	{"undefined variable", "{{$x}}", hasError, ""},
 	{"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""},
+	{"variable undefined in template", "{{template $v}}", hasError, ""},
 	{"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""},
 }
 
diff --git a/src/pkg/exp/template/set_test.go b/src/pkg/exp/template/set_test.go
index 99310b6..83088af 100644
--- a/src/pkg/exp/template/set_test.go
+++ b/src/pkg/exp/template/set_test.go
@@ -84,6 +84,7 @@
 	{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
 	{"invoke template by field", `{{template .X}}`, "TEXT", tVal, true},
 	{"invoke template by template", `{{template .Tmpl}}`, "test template", tVal, true},
+	{"invoke template by variable", `{{with $t := "x"}}{{template $t}}{{end}}`, "TEXT", tVal, true},
 	{"invalid: invoke template by []int", `{{template .SI}}`, "", tVal, false},
 
 	// User-defined function: test argument evaluator.