diff --git a/builtin/builtin.go b/builtin/builtin.go index fc48e111..f7a20f18 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "math" "reflect" "sort" "strings" @@ -209,6 +210,64 @@ var Builtins = []*Function{ return anyType, fmt.Errorf("invalid argument for float (type %s)", args[0]) }, }, + { + // switch(bool(expr1), 1, bool(expr2), 2, ...) + Name: "switch", + Func: func(args ...any) (any, error) { + for i := 0; i < len(args); i += 2 { + if args[i].(bool) { + return args[i+1], nil + } + } + return nil, nil + }, + Validate: func(args []reflect.Type) (reflect.Type, error) { + if len(args)%2 != 0 { + return anyType, fmt.Errorf("not enough arguments to call switch(expected a multiple of 2, got %d)", len(args)) + } + + for i := 0; i < len(args); i += 2 { + arg := args[i] + switch kind(arg) { + case reflect.Bool: + default: + return anyType, fmt.Errorf("invalid argument for bool (type %s)", arg) + } + } + return anyType, nil + }, + }, + { + Name: "pow", + Func: func(args ...any) (any, error) { + x := Float(args[0]) + y := Float(args[1]) + res := math.Pow(x.(float64), y.(float64)) + return any(res), nil + }, + //Types: types(math.Pow), + Validate: func(args []reflect.Type) (reflect.Type, error) { + if len(args) != 2 { + return anyType, fmt.Errorf("invalid number of arguments (expected 2, got %d)", len(args)) + } + var ret reflect.Type + var err error + for _, arg := range args[0:1] { + switch kind(arg) { + case reflect.Interface: + ret = floatType + case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + ret = floatType + case reflect.String: + ret = floatType + default: + return anyType, fmt.Errorf("invalid argument for float (type %s)", arg) + } + } + + return ret, err + }, + }, { Name: "string", Fast: String, diff --git a/builtin/builtin_test.go b/builtin/builtin_test.go index bc1a2e14..e783fd14 100644 --- a/builtin/builtin_test.go +++ b/builtin/builtin_test.go @@ -51,6 +51,8 @@ func TestBuiltin(t *testing.T) { {`float(5)`, 5.0}, {`float(5.5)`, 5.5}, {`float("5.5")`, 5.5}, + {`pow(2,2)`, 4.0}, + {`switch(ArrayOfInt?.[0]==1,2, ArrayOfInt?.[2]==33, 3, true, 0)`, 2}, {`string(5)`, "5"}, {`string(5.5)`, "5.5"}, {`string("5.5")`, "5.5"},