7 "github.com/hashicorp/hil/ast"
10 // NOTE: All builtins are tested in engine_test.go
12 func registerBuiltins(scope *ast.BasicScope) *ast.BasicScope {
14 scope = new(ast.BasicScope)
16 if scope.FuncMap == nil {
17 scope.FuncMap = make(map[string]ast.Function)
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()
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()
41 func builtinFloatMath() ast.Function {
43 ArgTypes: []ast.Type{ast.TypeInt},
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:] {
53 case ast.ArithmeticOpAdd:
55 case ast.ArithmeticOpSub:
57 case ast.ArithmeticOpMul:
59 case ast.ArithmeticOpDiv:
69 func builtinIntMath() ast.Function {
71 ArgTypes: []ast.Type{ast.TypeInt},
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:] {
81 case ast.ArithmeticOpAdd:
83 case ast.ArithmeticOpSub:
85 case ast.ArithmeticOpMul:
87 case ast.ArithmeticOpDiv:
89 return nil, errors.New("divide by zero")
93 case ast.ArithmeticOpMod:
95 return nil, errors.New("divide by zero")
107 func builtinBoolCompare() ast.Function {
109 ArgTypes: []ast.Type{ast.TypeInt, ast.TypeBool, ast.TypeBool},
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)
118 case ast.ArithmeticOpEqual:
119 return lhs == rhs, nil
120 case ast.ArithmeticOpNotEqual:
121 return lhs != rhs, nil
123 return nil, errors.New("invalid comparison operation")
129 func builtinFloatCompare() ast.Function {
131 ArgTypes: []ast.Type{ast.TypeInt, ast.TypeFloat, ast.TypeFloat},
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)
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
153 return nil, errors.New("invalid comparison operation")
159 func builtinIntCompare() ast.Function {
161 ArgTypes: []ast.Type{ast.TypeInt, ast.TypeInt, ast.TypeInt},
163 ReturnType: ast.TypeBool,
164 Callback: func(args []interface{}) (interface{}, error) {
165 op := args[0].(ast.ArithmeticOp)
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
183 return nil, errors.New("invalid comparison operation")
189 func builtinStringCompare() ast.Function {
191 ArgTypes: []ast.Type{ast.TypeInt, ast.TypeString, ast.TypeString},
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)
200 case ast.ArithmeticOpEqual:
201 return lhs == rhs, nil
202 case ast.ArithmeticOpNotEqual:
203 return lhs != rhs, nil
205 return nil, errors.New("invalid comparison operation")
211 func builtinLogical() ast.Function {
213 ArgTypes: []ast.Type{ast.TypeInt},
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:] {
223 case ast.ArithmeticOpLogicalOr:
224 result = result || arg
225 case ast.ArithmeticOpLogicalAnd:
226 result = result && arg
228 return nil, errors.New("invalid logical operator")
237 func builtinFloatToInt() 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
247 func builtinFloatToString() 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
258 func builtinIntToFloat() 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
268 func builtinIntToString() 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
278 func builtinStringToInt() 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)
293 func builtinStringToFloat() 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)
308 func builtinBoolToString() 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
318 func builtinStringToBool() 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))