terraform/config/lang/builtins.go

187 lines
4.4 KiB
Go
Raw Normal View History

package lang
import (
"strconv"
"github.com/hashicorp/terraform/config/lang/ast"
)
2015-01-14 21:02:26 +01:00
// NOTE: All builtins are tested in engine_test.go
2015-01-15 06:48:20 +01:00
func registerBuiltins(scope *ast.BasicScope) *ast.BasicScope {
if scope == nil {
scope = new(ast.BasicScope)
}
if scope.FuncMap == nil {
2015-01-15 05:58:46 +01:00
scope.FuncMap = make(map[string]ast.Function)
}
2015-02-26 23:26:14 +01:00
// Implicit conversions
scope.FuncMap["__builtin_FloatToInt"] = builtinFloatToInt()
scope.FuncMap["__builtin_FloatToString"] = builtinFloatToString()
scope.FuncMap["__builtin_IntToFloat"] = builtinIntToFloat()
scope.FuncMap["__builtin_IntToString"] = builtinIntToString()
2015-01-14 21:02:26 +01:00
scope.FuncMap["__builtin_StringToInt"] = builtinStringToInt()
2015-02-26 23:26:14 +01:00
// Math operations
scope.FuncMap["__builtin_UnaryIntMath"] = builtinUnaryIntMath()
scope.FuncMap["__builtin_UnaryFloatMath"] = builtinUnaryFloatMath()
2015-02-26 23:26:14 +01:00
scope.FuncMap["__builtin_IntMath"] = builtinIntMath()
scope.FuncMap["__builtin_FloatMath"] = builtinFloatMath()
2015-01-15 06:48:20 +01:00
return scope
}
func builtinUnaryIntMath() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
Variadic: false,
ReturnType: ast.TypeInt,
Callback: func(args []interface{}) (interface{}, error) {
op := args[0].(ast.ArithmeticOp)
result := args[1].(int)
switch op {
case ast.ArithmeticOpAdd:
result = result
case ast.ArithmeticOpSub:
result = -result
}
return result, nil
},
}
}
func builtinUnaryFloatMath() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeFloat},
Variadic: false,
ReturnType: ast.TypeFloat,
Callback: func(args []interface{}) (interface{}, error) {
op := args[0].(ast.ArithmeticOp)
result := args[1].(float64)
switch op {
case ast.ArithmeticOpAdd:
result = result
case ast.ArithmeticOpSub:
result = -result
}
return result, nil
},
}
}
2015-02-26 23:26:14 +01:00
func builtinFloatMath() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
Variadic: true,
VariadicType: ast.TypeFloat,
ReturnType: ast.TypeFloat,
Callback: func(args []interface{}) (interface{}, error) {
op := args[0].(ast.ArithmeticOp)
result := args[1].(float64)
for _, raw := range args[2:] {
arg := raw.(float64)
switch op {
case ast.ArithmeticOpAdd:
result += arg
case ast.ArithmeticOpSub:
result -= arg
case ast.ArithmeticOpMul:
result *= arg
case ast.ArithmeticOpDiv:
result /= arg
}
}
return result, nil
},
}
}
func builtinIntMath() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
Variadic: true,
VariadicType: ast.TypeInt,
ReturnType: ast.TypeInt,
Callback: func(args []interface{}) (interface{}, error) {
op := args[0].(ast.ArithmeticOp)
result := args[1].(int)
for _, raw := range args[2:] {
arg := raw.(int)
switch op {
case ast.ArithmeticOpAdd:
result += arg
case ast.ArithmeticOpSub:
result -= arg
case ast.ArithmeticOpMul:
result *= arg
case ast.ArithmeticOpDiv:
result /= arg
2015-02-27 00:17:37 +01:00
case ast.ArithmeticOpMod:
result = result % arg
2015-02-26 23:26:14 +01:00
}
}
return result, nil
},
}
}
func builtinFloatToInt() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeFloat},
ReturnType: ast.TypeInt,
Callback: func(args []interface{}) (interface{}, error) {
return int(args[0].(float64)), nil
},
}
}
func builtinFloatToString() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeFloat},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
return strconv.FormatFloat(
args[0].(float64), 'g', -1, 64), nil
},
}
}
func builtinIntToFloat() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
ReturnType: ast.TypeFloat,
Callback: func(args []interface{}) (interface{}, error) {
return float64(args[0].(int)), nil
},
}
}
2015-01-15 05:58:46 +01:00
func builtinIntToString() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeInt},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
return strconv.FormatInt(int64(args[0].(int)), 10), nil
},
}
}
2015-01-14 21:02:26 +01:00
2015-01-15 05:58:46 +01:00
func builtinStringToInt() ast.Function {
return ast.Function{
2015-01-14 21:02:26 +01:00
ArgTypes: []ast.Type{ast.TypeInt},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
v, err := strconv.ParseInt(args[0].(string), 0, 0)
if err != nil {
return nil, err
}
return int(v), nil
},
}
}