Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
c756a195
Commit
c756a195
authored
Jun 29, 2011
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
exp/template: boolean constants
R=rsc CC=golang-dev
https://golang.org/cl/4628073
parent
7e1a3e9f
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
55 additions
and
9 deletions
+55
-9
exec.go
src/pkg/exp/template/exec.go
+12
-1
exec_test.go
src/pkg/exp/template/exec_test.go
+11
-8
lex.go
src/pkg/exp/template/lex.go
+4
-0
lex_test.go
src/pkg/exp/template/lex_test.go
+7
-0
parse.go
src/pkg/exp/template/parse.go
+19
-0
parse_test.go
src/pkg/exp/template/parse_test.go
+2
-0
No files found.
src/pkg/exp/template/exec.go
View file @
c756a195
...
...
@@ -224,7 +224,8 @@ func (s *state) evalArg(data reflect.Value, typ reflect.Type, n node) reflect.Va
return
value
}
switch
typ
.
Kind
()
{
// TODO: boolean
case
reflect
.
Bool
:
return
s
.
evalBool
(
data
,
typ
,
n
)
case
reflect
.
String
:
return
s
.
evalString
(
data
,
typ
,
n
)
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
...
...
@@ -240,6 +241,16 @@ func (s *state) evalArg(data reflect.Value, typ reflect.Type, n node) reflect.Va
panic
(
"not reached"
)
}
func
(
s
*
state
)
evalBool
(
v
reflect
.
Value
,
typ
reflect
.
Type
,
n
node
)
reflect
.
Value
{
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"
)
}
func
(
s
*
state
)
evalString
(
v
reflect
.
Value
,
typ
reflect
.
Type
,
n
node
)
reflect
.
Value
{
if
n
,
ok
:=
n
.
(
*
stringNode
);
ok
{
value
:=
reflect
.
New
(
typ
)
.
Elem
()
...
...
src/pkg/exp/template/exec_test.go
View file @
c756a195
...
...
@@ -24,6 +24,7 @@ type T struct {
// Slices
SI
[]
int
SEmpty
[]
int
SB
[]
bool
// Maps
MSI
map
[
string
]
int
MSIEmpty
map
[
string
]
int
...
...
@@ -63,11 +64,11 @@ func (t *T) MSort(m map[string]int) []string {
}
// EPERM returns a value and an os.Error according to its argument.
func
(
t
*
T
)
EPERM
(
a
int
)
(
int
,
os
.
Error
)
{
if
a
==
0
{
return
0
,
os
.
EPERM
func
(
t
*
T
)
EPERM
(
error
bool
)
(
bool
,
os
.
Error
)
{
if
error
{
return
true
,
os
.
EPERM
}
return
a
,
nil
return
false
,
nil
}
type
U
struct
{
...
...
@@ -80,6 +81,7 @@ var tVal = &T{
X
:
"x"
,
U
:
&
U
{
"v"
},
SI
:
[]
int
{
3
,
4
,
5
},
SB
:
[]
bool
{
true
,
false
},
MSI
:
map
[
string
]
int
{
"one"
:
1
,
"two"
:
2
,
"three"
:
3
},
}
...
...
@@ -106,13 +108,14 @@ var execTests = []execTest{
{
"range empty no else"
,
"{{range .SEmpty}}-{{.}}-{{end}}"
,
""
,
tVal
,
true
},
{
"range []int else"
,
"{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}"
,
"-3--4--5-"
,
tVal
,
true
},
{
"range empty else"
,
"{{range .SEmpty}}-{{.}}-{{else}}EMPTY{{end}}"
,
"EMPTY"
,
tVal
,
true
},
{
"range []bool"
,
"{{range .SB}}-{{.}}-{{end}}"
,
"-true--false-"
,
tVal
,
true
},
{
"range []int method"
,
"{{range .SI | .MAdd .I}}-{{.}}-{{end}}"
,
"-20--21--22-"
,
tVal
,
true
},
{
"range map"
,
"{{range .MSI | .MSort}}-{{.}}-{{end}}"
,
"-one--three--two-"
,
tVal
,
true
},
{
"range empty map no else"
,
"{{range .MSIEmpty}}-{{.}}-{{end}}"
,
""
,
tVal
,
true
},
{
"range map else"
,
"{{range .MSI | .MSort}}-{{.}}-{{else}}EMPTY{{end}}"
,
"-one--three--two-"
,
tVal
,
true
},
{
"range empty map else"
,
"{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}"
,
"EMPTY"
,
tVal
,
true
},
{
"error method,
no error"
,
"{{.EPERM 1}}"
,
"1"
,
tVal
,
tru
e
},
{
"error method,
error"
,
"{{.EPERM 0}}"
,
"1"
,
tVal
,
fals
e
},
{
"error method,
error"
,
"{{.EPERM true}}"
,
""
,
tVal
,
fals
e
},
{
"error method,
no error"
,
"{{.EPERM false}}"
,
"false"
,
tVal
,
tru
e
},
}
func
TestExecute
(
t
*
testing
.
T
)
{
...
...
@@ -147,7 +150,7 @@ func TestExecute(t *testing.T) {
func
TestExecuteError
(
t
*
testing
.
T
)
{
b
:=
new
(
bytes
.
Buffer
)
tmpl
:=
New
(
"error"
)
err
:=
tmpl
.
Parse
(
"{{.EPERM
0
}}"
)
err
:=
tmpl
.
Parse
(
"{{.EPERM
true
}}"
)
if
err
!=
nil
{
t
.
Fatalf
(
"parse error: %s"
,
err
)
}
...
...
@@ -155,6 +158,6 @@ func TestExecuteError(t *testing.T) {
if
err
==
nil
{
t
.
Errorf
(
"expected error; got none"
)
}
else
if
!
strings
.
Contains
(
err
.
String
(),
os
.
EPERM
.
String
())
{
t
.
Errorf
(
"expected os.EPERM; got %s
%s
"
,
err
)
t
.
Errorf
(
"expected os.EPERM; got %s"
,
err
)
}
}
src/pkg/exp/template/lex.go
View file @
c756a195
...
...
@@ -35,6 +35,7 @@ type itemType int
const
(
itemError
itemType
=
iota
// error occurred; value is text of error
itemBool
// boolean constant
itemDot
// the cursor, spelled '.'.
itemEOF
itemElse
// else keyword
...
...
@@ -55,6 +56,7 @@ const (
// Make the types prettyprint.
var
itemName
=
map
[
itemType
]
string
{
itemError
:
"error"
,
itemBool
:
"bool"
,
itemDot
:
"."
,
itemEOF
:
"EOF"
,
itemElse
:
"else"
,
...
...
@@ -284,6 +286,8 @@ Loop:
l
.
emit
(
key
[
word
])
case
word
[
0
]
==
'.'
:
l
.
emit
(
itemField
)
case
word
==
"true"
,
word
==
"false"
:
l
.
emit
(
itemBool
)
default
:
l
.
emit
(
itemIdentifier
)
}
...
...
src/pkg/exp/template/lex_test.go
View file @
c756a195
...
...
@@ -46,6 +46,13 @@ var lexTests = []lexTest{
tRight
,
tEOF
,
}},
{
"bools"
,
"{{true false}}"
,
[]
item
{
tLeft
,
{
itemBool
,
"true"
},
{
itemBool
,
"false"
},
tRight
,
tEOF
,
}},
{
"dot"
,
"{{.}}"
,
[]
item
{
tLeft
,
{
itemDot
,
"."
},
...
...
src/pkg/exp/template/parse.go
View file @
c756a195
...
...
@@ -198,6 +198,23 @@ func (f *fieldNode) String() string {
return
fmt
.
Sprintf
(
"F=%s"
,
f
.
ident
)
}
// boolNode holds a boolean constant.
type
boolNode
struct
{
nodeType
true
bool
}
func
newBool
(
true
bool
)
*
boolNode
{
return
&
boolNode
{
nodeType
:
nodeString
,
true
:
true
}
}
func
(
b
*
boolNode
)
String
()
string
{
if
b
.
true
{
return
fmt
.
Sprintf
(
"B=true"
)
}
return
fmt
.
Sprintf
(
"B=false"
)
}
// numberNode holds a number, signed or unsigned, integer, floating, or imaginary.
// The value is parsed and stored under all the types that can represent the value.
// This simulates in a small amount of code the behavior of Go's ideal constants.
...
...
@@ -534,6 +551,8 @@ Loop:
cmd
.
append
(
newDot
())
case
itemField
:
cmd
.
append
(
newField
(
token
.
val
))
case
itemBool
:
cmd
.
append
(
newBool
(
token
.
val
==
"true"
))
case
itemNumber
:
if
len
(
cmd
.
args
)
==
0
{
t
.
errorf
(
"command cannot be %q"
,
token
.
val
)
...
...
src/pkg/exp/template/parse_test.go
View file @
c756a195
...
...
@@ -151,6 +151,8 @@ var parseTests = []parseTest{
`[({{range [(command: [F=[X]]) (command: [F=[M]])]}} [(text: "true")] {{else}} [(text: "false")])]`
},
{
"range []int"
,
"{{range .SI}}{{.}}{{end}}"
,
noError
,
`[({{range [(command: [F=[SI]])]}} [(action: [(command: [{{<.>}}])])])]`
},
{
"constants"
,
"{{range .SI 1 -3.2i true false }}{{end}}"
,
noError
,
`[({{range [(command: [F=[SI] N=1 N=-3.2i B=true B=false])]}} [])]`
},
// Errors.
{
"unclosed action"
,
"hello{{range"
,
hasError
,
""
},
{
"missing end"
,
"hello{{range .x}}"
,
hasError
,
""
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment