diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hil/builtins.go')
-rw-r--r-- | vendor/github.com/hashicorp/hil/builtins.go | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hil/builtins.go b/vendor/github.com/hashicorp/hil/builtins.go new file mode 100644 index 0000000..909c788 --- /dev/null +++ b/vendor/github.com/hashicorp/hil/builtins.go | |||
@@ -0,0 +1,331 @@ | |||
1 | package hil | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "strconv" | ||
6 | |||
7 | "github.com/hashicorp/hil/ast" | ||
8 | ) | ||
9 | |||
10 | // NOTE: All builtins are tested in engine_test.go | ||
11 | |||
12 | func registerBuiltins(scope *ast.BasicScope) *ast.BasicScope { | ||
13 | if scope == nil { | ||
14 | scope = new(ast.BasicScope) | ||
15 | } | ||
16 | if scope.FuncMap == nil { | ||
17 | scope.FuncMap = make(map[string]ast.Function) | ||
18 | } | ||
19 | |||
20 | // Implicit conversions | ||
21 | scope.FuncMap["__builtin_BoolToString"] = builtinBoolToString() | ||
22 | scope.FuncMap["__builtin_FloatToInt"] = builtinFloatToInt() | ||
23 | scope.FuncMap["__builtin_FloatToString"] = builtinFloatToString() | ||
24 | scope.FuncMap["__builtin_IntToFloat"] = builtinIntToFloat() | ||
25 | scope.FuncMap["__builtin_IntToString"] = builtinIntToString() | ||
26 | scope.FuncMap["__builtin_StringToInt"] = builtinStringToInt() | ||
27 | scope.FuncMap["__builtin_StringToFloat"] = builtinStringToFloat() | ||
28 | scope.FuncMap["__builtin_StringToBool"] = builtinStringToBool() | ||
29 | |||
30 | // Math operations | ||
31 | scope.FuncMap["__builtin_IntMath"] = builtinIntMath() | ||
32 | scope.FuncMap["__builtin_FloatMath"] = builtinFloatMath() | ||
33 | scope.FuncMap["__builtin_BoolCompare"] = builtinBoolCompare() | ||
34 | scope.FuncMap["__builtin_FloatCompare"] = builtinFloatCompare() | ||
35 | scope.FuncMap["__builtin_IntCompare"] = builtinIntCompare() | ||
36 | scope.FuncMap["__builtin_StringCompare"] = builtinStringCompare() | ||
37 | scope.FuncMap["__builtin_Logical"] = builtinLogical() | ||
38 | return scope | ||
39 | } | ||
40 | |||
41 | func builtinFloatMath() ast.Function { | ||
42 | return ast.Function{ | ||
43 | ArgTypes: []ast.Type{ast.TypeInt}, | ||
44 | Variadic: true, | ||
45 | VariadicType: ast.TypeFloat, | ||
46 | ReturnType: ast.TypeFloat, | ||
47 | Callback: func(args []interface{}) (interface{}, error) { | ||
48 | op := args[0].(ast.ArithmeticOp) | ||
49 | result := args[1].(float64) | ||
50 | for _, raw := range args[2:] { | ||
51 | arg := raw.(float64) | ||
52 | switch op { | ||
53 | case ast.ArithmeticOpAdd: | ||
54 | result += arg | ||
55 | case ast.ArithmeticOpSub: | ||
56 | result -= arg | ||
57 | case ast.ArithmeticOpMul: | ||
58 | result *= arg | ||
59 | case ast.ArithmeticOpDiv: | ||
60 | result /= arg | ||
61 | } | ||
62 | } | ||
63 | |||
64 | return result, nil | ||
65 | }, | ||
66 | } | ||
67 | } | ||
68 | |||
69 | func builtinIntMath() ast.Function { | ||
70 | return ast.Function{ | ||
71 | ArgTypes: []ast.Type{ast.TypeInt}, | ||
72 | Variadic: true, | ||
73 | VariadicType: ast.TypeInt, | ||
74 | ReturnType: ast.TypeInt, | ||
75 | Callback: func(args []interface{}) (interface{}, error) { | ||
76 | op := args[0].(ast.ArithmeticOp) | ||
77 | result := args[1].(int) | ||
78 | for _, raw := range args[2:] { | ||
79 | arg := raw.(int) | ||
80 | switch op { | ||
81 | case ast.ArithmeticOpAdd: | ||
82 | result += arg | ||
83 | case ast.ArithmeticOpSub: | ||
84 | result -= arg | ||
85 | case ast.ArithmeticOpMul: | ||
86 | result *= arg | ||
87 | case ast.ArithmeticOpDiv: | ||
88 | if arg == 0 { | ||
89 | return nil, errors.New("divide by zero") | ||
90 | } | ||
91 | |||
92 | result /= arg | ||
93 | case ast.ArithmeticOpMod: | ||
94 | if arg == 0 { | ||
95 | return nil, errors.New("divide by zero") | ||
96 | } | ||
97 | |||
98 | result = result % arg | ||
99 | } | ||
100 | } | ||
101 | |||
102 | return result, nil | ||
103 | }, | ||
104 | } | ||
105 | } | ||
106 | |||
107 | func builtinBoolCompare() ast.Function { | ||
108 | return ast.Function{ | ||
109 | ArgTypes: []ast.Type{ast.TypeInt, ast.TypeBool, ast.TypeBool}, | ||
110 | Variadic: false, | ||
111 | ReturnType: ast.TypeBool, | ||
112 | Callback: func(args []interface{}) (interface{}, error) { | ||
113 | op := args[0].(ast.ArithmeticOp) | ||
114 | lhs := args[1].(bool) | ||
115 | rhs := args[2].(bool) | ||
116 | |||
117 | switch op { | ||
118 | case ast.ArithmeticOpEqual: | ||
119 | return lhs == rhs, nil | ||
120 | case ast.ArithmeticOpNotEqual: | ||
121 | return lhs != rhs, nil | ||
122 | default: | ||
123 | return nil, errors.New("invalid comparison operation") | ||
124 | } | ||
125 | }, | ||
126 | } | ||
127 | } | ||
128 | |||
129 | func builtinFloatCompare() ast.Function { | ||
130 | return ast.Function{ | ||
131 | ArgTypes: []ast.Type{ast.TypeInt, ast.TypeFloat, ast.TypeFloat}, | ||
132 | Variadic: false, | ||
133 | ReturnType: ast.TypeBool, | ||
134 | Callback: func(args []interface{}) (interface{}, error) { | ||
135 | op := args[0].(ast.ArithmeticOp) | ||
136 | lhs := args[1].(float64) | ||
137 | rhs := args[2].(float64) | ||
138 | |||
139 | switch op { | ||
140 | case ast.ArithmeticOpEqual: | ||
141 | return lhs == rhs, nil | ||
142 | case ast.ArithmeticOpNotEqual: | ||
143 | return lhs != rhs, nil | ||
144 | case ast.ArithmeticOpLessThan: | ||
145 | return lhs < rhs, nil | ||
146 | case ast.ArithmeticOpLessThanOrEqual: | ||
147 | return lhs <= rhs, nil | ||
148 | case ast.ArithmeticOpGreaterThan: | ||
149 | return lhs > rhs, nil | ||
150 | case ast.ArithmeticOpGreaterThanOrEqual: | ||
151 | return lhs >= rhs, nil | ||
152 | default: | ||
153 | return nil, errors.New("invalid comparison operation") | ||
154 | } | ||
155 | }, | ||
156 | } | ||
157 | } | ||
158 | |||
159 | func builtinIntCompare() ast.Function { | ||
160 | return ast.Function{ | ||
161 | ArgTypes: []ast.Type{ast.TypeInt, ast.TypeInt, ast.TypeInt}, | ||
162 | Variadic: false, | ||
163 | ReturnType: ast.TypeBool, | ||
164 | Callback: func(args []interface{}) (interface{}, error) { | ||
165 | op := args[0].(ast.ArithmeticOp) | ||
166 | lhs := args[1].(int) | ||
167 | rhs := args[2].(int) | ||
168 | |||
169 | switch op { | ||
170 | case ast.ArithmeticOpEqual: | ||
171 | return lhs == rhs, nil | ||
172 | case ast.ArithmeticOpNotEqual: | ||
173 | return lhs != rhs, nil | ||
174 | case ast.ArithmeticOpLessThan: | ||
175 | return lhs < rhs, nil | ||
176 | case ast.ArithmeticOpLessThanOrEqual: | ||
177 | return lhs <= rhs, nil | ||
178 | case ast.ArithmeticOpGreaterThan: | ||
179 | return lhs > rhs, nil | ||
180 | case ast.ArithmeticOpGreaterThanOrEqual: | ||
181 | return lhs >= rhs, nil | ||
182 | default: | ||
183 | return nil, errors.New("invalid comparison operation") | ||
184 | } | ||
185 | }, | ||
186 | } | ||
187 | } | ||
188 | |||
189 | func builtinStringCompare() ast.Function { | ||
190 | return ast.Function{ | ||
191 | ArgTypes: []ast.Type{ast.TypeInt, ast.TypeString, ast.TypeString}, | ||
192 | Variadic: false, | ||
193 | ReturnType: ast.TypeBool, | ||
194 | Callback: func(args []interface{}) (interface{}, error) { | ||
195 | op := args[0].(ast.ArithmeticOp) | ||
196 | lhs := args[1].(string) | ||
197 | rhs := args[2].(string) | ||
198 | |||
199 | switch op { | ||
200 | case ast.ArithmeticOpEqual: | ||
201 | return lhs == rhs, nil | ||
202 | case ast.ArithmeticOpNotEqual: | ||
203 | return lhs != rhs, nil | ||
204 | default: | ||
205 | return nil, errors.New("invalid comparison operation") | ||
206 | } | ||
207 | }, | ||
208 | } | ||
209 | } | ||
210 | |||
211 | func builtinLogical() ast.Function { | ||
212 | return ast.Function{ | ||
213 | ArgTypes: []ast.Type{ast.TypeInt}, | ||
214 | Variadic: true, | ||
215 | VariadicType: ast.TypeBool, | ||
216 | ReturnType: ast.TypeBool, | ||
217 | Callback: func(args []interface{}) (interface{}, error) { | ||
218 | op := args[0].(ast.ArithmeticOp) | ||
219 | result := args[1].(bool) | ||
220 | for _, raw := range args[2:] { | ||
221 | arg := raw.(bool) | ||
222 | switch op { | ||
223 | case ast.ArithmeticOpLogicalOr: | ||
224 | result = result || arg | ||
225 | case ast.ArithmeticOpLogicalAnd: | ||
226 | result = result && arg | ||
227 | default: | ||
228 | return nil, errors.New("invalid logical operator") | ||
229 | } | ||
230 | } | ||
231 | |||
232 | return result, nil | ||
233 | }, | ||
234 | } | ||
235 | } | ||
236 | |||
237 | func builtinFloatToInt() ast.Function { | ||
238 | return ast.Function{ | ||
239 | ArgTypes: []ast.Type{ast.TypeFloat}, | ||
240 | ReturnType: ast.TypeInt, | ||
241 | Callback: func(args []interface{}) (interface{}, error) { | ||
242 | return int(args[0].(float64)), nil | ||
243 | }, | ||
244 | } | ||
245 | } | ||
246 | |||
247 | func builtinFloatToString() ast.Function { | ||
248 | return ast.Function{ | ||
249 | ArgTypes: []ast.Type{ast.TypeFloat}, | ||
250 | ReturnType: ast.TypeString, | ||
251 | Callback: func(args []interface{}) (interface{}, error) { | ||
252 | return strconv.FormatFloat( | ||
253 | args[0].(float64), 'g', -1, 64), nil | ||
254 | }, | ||
255 | } | ||
256 | } | ||
257 | |||
258 | func builtinIntToFloat() ast.Function { | ||
259 | return ast.Function{ | ||
260 | ArgTypes: []ast.Type{ast.TypeInt}, | ||
261 | ReturnType: ast.TypeFloat, | ||
262 | Callback: func(args []interface{}) (interface{}, error) { | ||
263 | return float64(args[0].(int)), nil | ||
264 | }, | ||
265 | } | ||
266 | } | ||
267 | |||
268 | func builtinIntToString() ast.Function { | ||
269 | return ast.Function{ | ||
270 | ArgTypes: []ast.Type{ast.TypeInt}, | ||
271 | ReturnType: ast.TypeString, | ||
272 | Callback: func(args []interface{}) (interface{}, error) { | ||
273 | return strconv.FormatInt(int64(args[0].(int)), 10), nil | ||
274 | }, | ||
275 | } | ||
276 | } | ||
277 | |||
278 | func builtinStringToInt() ast.Function { | ||
279 | return ast.Function{ | ||
280 | ArgTypes: []ast.Type{ast.TypeInt}, | ||
281 | ReturnType: ast.TypeString, | ||
282 | Callback: func(args []interface{}) (interface{}, error) { | ||
283 | v, err := strconv.ParseInt(args[0].(string), 0, 0) | ||
284 | if err != nil { | ||
285 | return nil, err | ||
286 | } | ||
287 | |||
288 | return int(v), nil | ||
289 | }, | ||
290 | } | ||
291 | } | ||
292 | |||
293 | func builtinStringToFloat() ast.Function { | ||
294 | return ast.Function{ | ||
295 | ArgTypes: []ast.Type{ast.TypeString}, | ||
296 | ReturnType: ast.TypeFloat, | ||
297 | Callback: func(args []interface{}) (interface{}, error) { | ||
298 | v, err := strconv.ParseFloat(args[0].(string), 64) | ||
299 | if err != nil { | ||
300 | return nil, err | ||
301 | } | ||
302 | |||
303 | return v, nil | ||
304 | }, | ||
305 | } | ||
306 | } | ||
307 | |||
308 | func builtinBoolToString() ast.Function { | ||
309 | return ast.Function{ | ||
310 | ArgTypes: []ast.Type{ast.TypeBool}, | ||
311 | ReturnType: ast.TypeString, | ||
312 | Callback: func(args []interface{}) (interface{}, error) { | ||
313 | return strconv.FormatBool(args[0].(bool)), nil | ||
314 | }, | ||
315 | } | ||
316 | } | ||
317 | |||
318 | func builtinStringToBool() ast.Function { | ||
319 | return ast.Function{ | ||
320 | ArgTypes: []ast.Type{ast.TypeString}, | ||
321 | ReturnType: ast.TypeBool, | ||
322 | Callback: func(args []interface{}) (interface{}, error) { | ||
323 | v, err := strconv.ParseBool(args[0].(string)) | ||
324 | if err != nil { | ||
325 | return nil, err | ||
326 | } | ||
327 | |||
328 | return v, nil | ||
329 | }, | ||
330 | } | ||
331 | } | ||