-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdata.go
160 lines (139 loc) · 4.52 KB
/
data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package exprel
import (
"context"
"strconv"
)
// Func is a function that can be executed from an Expression.
type Func = func(call *Call) (interface{}, error)
// Call contains information about an expression function call.
type Call struct {
// The name used to invoke the function.
Name string
// The arguments passed to the function.
Values []interface{}
ctx context.Context
}
// Context returns the context for the current function call.
func (c *Call) Context() context.Context {
return c.ctx
}
// String returns the ith argument, iff it is a string. Otherwise, the function
// panics with a *RuntimeError.
func (c *Call) String(i int) string {
if len(c.Values) <= i {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be string"})
}
value, ok := c.Values[i].(string)
if !ok {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be string"})
}
return value
}
// OptString returns the ith argument, iff it is a string. If the ith argument
// does not exist, def is returned. If the ith argument is not a string, the
// function panics with a *RuntimeError.
func (c *Call) OptString(i int, def string) string {
if len(c.Values) <= i {
return def
}
value, ok := c.Values[i].(string)
if !ok {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be string"})
}
return value
}
// Number returns the ith argument, iff it is a float64. Otherwise, the
// function panics with a *RuntimeError.
func (c *Call) Number(i int) float64 {
if len(c.Values) <= i {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be number"})
}
value, ok := c.Values[i].(float64)
if !ok {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be number"})
}
return value
}
// OptNumber returns the ith argument, iff it is a float64. If the ith argument
// does not exist, def is returned. If the ith argument is not a number, the
// function panics with a *RuntimeError.
func (c *Call) OptNumber(i int, def float64) float64 {
if len(c.Values) <= i {
return def
}
value, ok := c.Values[i].(float64)
if !ok {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be number"})
}
return value
}
// Boolean returns the ith argument, iff it is a bool. Otherwise, the function
// panics with a *RuntimeError.
func (c *Call) Boolean(i int) bool {
if len(c.Values) <= i {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be bool"})
}
value, ok := c.Values[i].(bool)
if !ok {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be bool"})
}
return value
}
// OptBoolean returns the ith argument, iff it is a bool. If the ith argument
// does not exist, def is returned. If the ith argument is not a bool, the
// function panics with a *RuntimeError.
func (c *Call) OptBoolean(i int, def bool) bool {
if len(c.Values) <= i {
return def
}
value, ok := c.Values[i].(bool)
if !ok {
panic(&RuntimeError{Message: c.Name + " expects argument " + strconv.Itoa(i) + " to be bool"})
}
return value
}
// Source is a source of data for an expression. Get is called when an
// identifier needs to be evaluated.
type Source interface {
Get(ctx context.Context, name string) (value interface{}, ok bool)
}
// EmptySource is a Source that contains no values.
var EmptySource Source = emptySource{}
type emptySource struct{}
func (emptySource) Get(ctx context.Context, name string) (interface{}, bool) {
return nil, false
}
// SourceFunc is a Source that looks up an identifier via a function.
type SourceFunc func(ctx context.Context, name string) (value interface{}, ok bool)
// Get implements Source.
func (f SourceFunc) Get(ctx context.Context, name string) (interface{}, bool) {
return f(ctx, name)
}
// SourceMap is a Source that looks up an identifier in a map.
type SourceMap map[string]interface{}
// Get implements Source.
func (m SourceMap) Get(ctx context.Context, name string) (interface{}, bool) {
value, ok := m[name]
if !ok {
return nil, false
}
switch value.(type) {
case bool, string, float64, Func:
return value, true
default:
return nil, false
}
}
// Sources is a slice of sources. The first Source, in order, to return ok,
// will have its value returned.
type Sources []Source
// Get implements Source.
func (s Sources) Get(ctx context.Context, name string) (interface{}, bool) {
for _, s := range s {
value, ok := s.Get(ctx, name)
if ok {
return value, true
}
}
return nil, false
}