github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/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_UnaryIntMath"] = builtinUnaryIntMath()
    28  	scope.FuncMap["__builtin_UnaryFloatMath"] = builtinUnaryFloatMath()
    29  	scope.FuncMap["__builtin_IntMath"] = builtinIntMath()
    30  	scope.FuncMap["__builtin_FloatMath"] = builtinFloatMath()
    31  	return scope
    32  }
    33  
    34  func builtinUnaryIntMath() ast.Function {
    35  	return ast.Function{
    36  		ArgTypes:   []ast.Type{ast.TypeInt},
    37  		Variadic:   false,
    38  		ReturnType: ast.TypeInt,
    39  		Callback: func(args []interface{}) (interface{}, error) {
    40  			op := args[0].(ast.ArithmeticOp)
    41  			result := args[1].(int)
    42  			switch op {
    43  			case ast.ArithmeticOpAdd:
    44  				result = result
    45  			case ast.ArithmeticOpSub:
    46  				result = -result
    47  			}
    48  
    49  			return result, nil
    50  		},
    51  	}
    52  }
    53  
    54  func builtinUnaryFloatMath() ast.Function {
    55  	return ast.Function{
    56  		ArgTypes:   []ast.Type{ast.TypeFloat},
    57  		Variadic:   false,
    58  		ReturnType: ast.TypeFloat,
    59  		Callback: func(args []interface{}) (interface{}, error) {
    60  			op := args[0].(ast.ArithmeticOp)
    61  			result := args[1].(float64)
    62  			switch op {
    63  			case ast.ArithmeticOpAdd:
    64  				result = result
    65  			case ast.ArithmeticOpSub:
    66  				result = -result
    67  			}
    68  
    69  			return result, nil
    70  		},
    71  	}
    72  }
    73  
    74  func builtinFloatMath() ast.Function {
    75  	return ast.Function{
    76  		ArgTypes:     []ast.Type{ast.TypeInt},
    77  		Variadic:     true,
    78  		VariadicType: ast.TypeFloat,
    79  		ReturnType:   ast.TypeFloat,
    80  		Callback: func(args []interface{}) (interface{}, error) {
    81  			op := args[0].(ast.ArithmeticOp)
    82  			result := args[1].(float64)
    83  			for _, raw := range args[2:] {
    84  				arg := raw.(float64)
    85  				switch op {
    86  				case ast.ArithmeticOpAdd:
    87  					result += arg
    88  				case ast.ArithmeticOpSub:
    89  					result -= arg
    90  				case ast.ArithmeticOpMul:
    91  					result *= arg
    92  				case ast.ArithmeticOpDiv:
    93  					result /= arg
    94  				}
    95  			}
    96  
    97  			return result, nil
    98  		},
    99  	}
   100  }
   101  
   102  func builtinIntMath() ast.Function {
   103  	return ast.Function{
   104  		ArgTypes:     []ast.Type{ast.TypeInt},
   105  		Variadic:     true,
   106  		VariadicType: ast.TypeInt,
   107  		ReturnType:   ast.TypeInt,
   108  		Callback: func(args []interface{}) (interface{}, error) {
   109  			op := args[0].(ast.ArithmeticOp)
   110  			result := args[1].(int)
   111  			for _, raw := range args[2:] {
   112  				arg := raw.(int)
   113  				switch op {
   114  				case ast.ArithmeticOpAdd:
   115  					result += arg
   116  				case ast.ArithmeticOpSub:
   117  					result -= arg
   118  				case ast.ArithmeticOpMul:
   119  					result *= arg
   120  				case ast.ArithmeticOpDiv:
   121  					result /= arg
   122  				case ast.ArithmeticOpMod:
   123  					result = result % arg
   124  				}
   125  			}
   126  
   127  			return result, nil
   128  		},
   129  	}
   130  }
   131  
   132  func builtinFloatToInt() ast.Function {
   133  	return ast.Function{
   134  		ArgTypes:   []ast.Type{ast.TypeFloat},
   135  		ReturnType: ast.TypeInt,
   136  		Callback: func(args []interface{}) (interface{}, error) {
   137  			return int(args[0].(float64)), nil
   138  		},
   139  	}
   140  }
   141  
   142  func builtinFloatToString() ast.Function {
   143  	return ast.Function{
   144  		ArgTypes:   []ast.Type{ast.TypeFloat},
   145  		ReturnType: ast.TypeString,
   146  		Callback: func(args []interface{}) (interface{}, error) {
   147  			return strconv.FormatFloat(
   148  				args[0].(float64), 'g', -1, 64), nil
   149  		},
   150  	}
   151  }
   152  
   153  func builtinIntToFloat() ast.Function {
   154  	return ast.Function{
   155  		ArgTypes:   []ast.Type{ast.TypeInt},
   156  		ReturnType: ast.TypeFloat,
   157  		Callback: func(args []interface{}) (interface{}, error) {
   158  			return float64(args[0].(int)), nil
   159  		},
   160  	}
   161  }
   162  
   163  func builtinIntToString() ast.Function {
   164  	return ast.Function{
   165  		ArgTypes:   []ast.Type{ast.TypeInt},
   166  		ReturnType: ast.TypeString,
   167  		Callback: func(args []interface{}) (interface{}, error) {
   168  			return strconv.FormatInt(int64(args[0].(int)), 10), nil
   169  		},
   170  	}
   171  }
   172  
   173  func builtinStringToInt() ast.Function {
   174  	return ast.Function{
   175  		ArgTypes:   []ast.Type{ast.TypeInt},
   176  		ReturnType: ast.TypeString,
   177  		Callback: func(args []interface{}) (interface{}, error) {
   178  			v, err := strconv.ParseInt(args[0].(string), 0, 0)
   179  			if err != nil {
   180  				return nil, err
   181  			}
   182  
   183  			return int(v), nil
   184  		},
   185  	}
   186  }