github.com/franklinhu/terraform@v0.6.9-0.20151202232446-81f7fb1e6f9e/config/lang/builtins.go (about) 1 package lang 2 3 import ( 4 "strconv" 5 6 "github.com/hashicorp/terraform/config/lang/ast" 7 ) 8 9 // NOTE: All builtins are tested in engine_test.go 10 11 func registerBuiltins(scope *ast.BasicScope) *ast.BasicScope { 12 if scope == nil { 13 scope = new(ast.BasicScope) 14 } 15 if scope.FuncMap == nil { 16 scope.FuncMap = make(map[string]ast.Function) 17 } 18 19 // Implicit conversions 20 scope.FuncMap["__builtin_FloatToInt"] = builtinFloatToInt() 21 scope.FuncMap["__builtin_FloatToString"] = builtinFloatToString() 22 scope.FuncMap["__builtin_IntToFloat"] = builtinIntToFloat() 23 scope.FuncMap["__builtin_IntToString"] = builtinIntToString() 24 scope.FuncMap["__builtin_StringToInt"] = builtinStringToInt() 25 26 // Math operations 27 scope.FuncMap["__builtin_IntMath"] = builtinIntMath() 28 scope.FuncMap["__builtin_FloatMath"] = builtinFloatMath() 29 return scope 30 } 31 32 func builtinFloatMath() ast.Function { 33 return ast.Function{ 34 ArgTypes: []ast.Type{ast.TypeInt}, 35 Variadic: true, 36 VariadicType: ast.TypeFloat, 37 ReturnType: ast.TypeFloat, 38 Callback: func(args []interface{}) (interface{}, error) { 39 op := args[0].(ast.ArithmeticOp) 40 result := args[1].(float64) 41 for _, raw := range args[2:] { 42 arg := raw.(float64) 43 switch op { 44 case ast.ArithmeticOpAdd: 45 result += arg 46 case ast.ArithmeticOpSub: 47 result -= arg 48 case ast.ArithmeticOpMul: 49 result *= arg 50 case ast.ArithmeticOpDiv: 51 result /= arg 52 } 53 } 54 55 return result, nil 56 }, 57 } 58 } 59 60 func builtinIntMath() ast.Function { 61 return ast.Function{ 62 ArgTypes: []ast.Type{ast.TypeInt}, 63 Variadic: true, 64 VariadicType: ast.TypeInt, 65 ReturnType: ast.TypeInt, 66 Callback: func(args []interface{}) (interface{}, error) { 67 op := args[0].(ast.ArithmeticOp) 68 result := args[1].(int) 69 for _, raw := range args[2:] { 70 arg := raw.(int) 71 switch op { 72 case ast.ArithmeticOpAdd: 73 result += arg 74 case ast.ArithmeticOpSub: 75 result -= arg 76 case ast.ArithmeticOpMul: 77 result *= arg 78 case ast.ArithmeticOpDiv: 79 result /= arg 80 case ast.ArithmeticOpMod: 81 result = result % arg 82 } 83 } 84 85 return result, nil 86 }, 87 } 88 } 89 90 func builtinFloatToInt() ast.Function { 91 return ast.Function{ 92 ArgTypes: []ast.Type{ast.TypeFloat}, 93 ReturnType: ast.TypeInt, 94 Callback: func(args []interface{}) (interface{}, error) { 95 return int(args[0].(float64)), nil 96 }, 97 } 98 } 99 100 func builtinFloatToString() ast.Function { 101 return ast.Function{ 102 ArgTypes: []ast.Type{ast.TypeFloat}, 103 ReturnType: ast.TypeString, 104 Callback: func(args []interface{}) (interface{}, error) { 105 return strconv.FormatFloat( 106 args[0].(float64), 'g', -1, 64), nil 107 }, 108 } 109 } 110 111 func builtinIntToFloat() ast.Function { 112 return ast.Function{ 113 ArgTypes: []ast.Type{ast.TypeInt}, 114 ReturnType: ast.TypeFloat, 115 Callback: func(args []interface{}) (interface{}, error) { 116 return float64(args[0].(int)), nil 117 }, 118 } 119 } 120 121 func builtinIntToString() ast.Function { 122 return ast.Function{ 123 ArgTypes: []ast.Type{ast.TypeInt}, 124 ReturnType: ast.TypeString, 125 Callback: func(args []interface{}) (interface{}, error) { 126 return strconv.FormatInt(int64(args[0].(int)), 10), nil 127 }, 128 } 129 } 130 131 func builtinStringToInt() ast.Function { 132 return ast.Function{ 133 ArgTypes: []ast.Type{ast.TypeInt}, 134 ReturnType: ast.TypeString, 135 Callback: func(args []interface{}) (interface{}, error) { 136 v, err := strconv.ParseInt(args[0].(string), 0, 0) 137 if err != nil { 138 return nil, err 139 } 140 141 return int(v), nil 142 }, 143 } 144 }