diff --git a/checker/checker.go b/checker/checker.go index 5ed6a391f..c77751eb5 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -31,7 +31,7 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) { if v.config.Expect != reflect.Invalid { switch v.config.Expect { - case reflect.Int64, reflect.Float64: + case reflect.Int, reflect.Int64, reflect.Float64: if !isNumber(t) { return nil, fmt.Errorf("expected %v, but got %v", v.config.Expect, t) } diff --git a/compiler/compiler.go b/compiler/compiler.go index 6c16af032..9f7bcb1bb 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -37,10 +37,12 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro c.compile(tree.Node) switch c.cast { - case reflect.Int64: + case reflect.Int: c.emit(OpCast, 0) - case reflect.Float64: + case reflect.Int64: c.emit(OpCast, 1) + case reflect.Float64: + c.emit(OpCast, 2) } program = &Program{ diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go index c7863db5e..6f472b3da 100644 --- a/compiler/compiler_test.go +++ b/compiler/compiler_test.go @@ -2,13 +2,9 @@ package compiler_test import ( "math" - "reflect" "testing" "github.com/antonmedv/expr" - "github.com/antonmedv/expr/compiler" - "github.com/antonmedv/expr/conf" - "github.com/antonmedv/expr/parser" "github.com/antonmedv/expr/vm" "github.com/antonmedv/expr/vm/runtime" "github.com/stretchr/testify/assert" @@ -242,25 +238,3 @@ func TestCompile(t *testing.T) { assert.Equal(t, test.program.Disassemble(), program.Disassemble(), test.input) } } - -func TestCompile_cast(t *testing.T) { - input := `1` - expected := &vm.Program{ - Constants: []interface{}{ - 1, - }, - Bytecode: []vm.Opcode{ - vm.OpPush, - vm.OpCast, - }, - Arguments: []int{0, 1}, - } - - tree, err := parser.Parse(input) - require.NoError(t, err) - - program, err := compiler.Compile(tree, &conf.Config{Expect: reflect.Float64}) - require.NoError(t, err) - - assert.Equal(t, expected.Disassemble(), program.Disassemble()) -} diff --git a/expr.go b/expr.go index bbc4b2696..4bf8e11da 100644 --- a/expr.go +++ b/expr.go @@ -75,21 +75,35 @@ func ConstExpr(fn string) Option { } } -// AsBool tells the compiler to expect boolean result. +// AsKind tells the compiler to expect kind of the result. +func AsKind(kind reflect.Kind) Option { + return func(c *conf.Config) { + c.Expect = kind + } +} + +// AsBool tells the compiler to expect a boolean result. func AsBool() Option { return func(c *conf.Config) { c.Expect = reflect.Bool } } -// AsInt64 tells the compiler to expect int64 result. +// AsInt tells the compiler to expect an int result. +func AsInt() Option { + return func(c *conf.Config) { + c.Expect = reflect.Int + } +} + +// AsInt64 tells the compiler to expect an int64 result. func AsInt64() Option { return func(c *conf.Config) { c.Expect = reflect.Int64 } } -// AsFloat64 tells the compiler to expect float64 result. +// AsFloat64 tells the compiler to expect a float64 result. func AsFloat64() Option { return func(c *conf.Config) { c.Expect = reflect.Float64 diff --git a/expr_test.go b/expr_test.go index f41ef478c..8fdcc29bb 100644 --- a/expr_test.go +++ b/expr_test.go @@ -135,6 +135,24 @@ func ExampleEnv_tagged_field_names() { // Output : Hello World } +func ExampleAsKind() { + program, err := expr.Compile("{a: 1, b: 2}", expr.AsKind(reflect.Map)) + if err != nil { + fmt.Printf("%v", err) + return + } + + output, err := expr.Run(program, nil) + if err != nil { + fmt.Printf("%v", err) + return + } + + fmt.Printf("%v", output) + + // Output: map[a:1 b:2] +} + func ExampleAsBool() { env := map[string]int{ "foo": 0, @@ -169,8 +187,8 @@ func ExampleAsBool_error() { // Output: expected bool, but got int } -func ExampleAsFloat64() { - program, err := expr.Compile("42", expr.AsFloat64()) +func ExampleAsInt() { + program, err := expr.Compile("42", expr.AsInt()) if err != nil { fmt.Printf("%v", err) return @@ -182,17 +200,9 @@ func ExampleAsFloat64() { return } - fmt.Printf("%v", output.(float64)) - - // Output: 42 -} + fmt.Printf("%T(%v)", output, output) -func ExampleAsFloat64_error() { - _, err := expr.Compile(`!!true`, expr.AsFloat64()) - - fmt.Printf("%v", err) - - // Output: expected float64, but got bool + // Output: int(42) } func ExampleAsInt64() { @@ -217,6 +227,32 @@ func ExampleAsInt64() { // Output: 5 } +func ExampleAsFloat64() { + program, err := expr.Compile("42", expr.AsFloat64()) + if err != nil { + fmt.Printf("%v", err) + return + } + + output, err := expr.Run(program, nil) + if err != nil { + fmt.Printf("%v", err) + return + } + + fmt.Printf("%v", output.(float64)) + + // Output: 42 +} + +func ExampleAsFloat64_error() { + _, err := expr.Compile(`!!true`, expr.AsFloat64()) + + fmt.Printf("%v", err) + + // Output: expected float64, but got bool +} + func ExampleOperator() { code := ` Now() > CreatedAt && diff --git a/vm/vm.go b/vm/vm.go index 20c835b5a..ffd3561d0 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -354,8 +354,10 @@ func (vm *VM) Run(program *Program, env interface{}) (out interface{}, err error t := arg switch t { case 0: - vm.push(runtime.ToInt64(vm.pop())) + vm.push(runtime.ToInt(vm.pop())) case 1: + vm.push(runtime.ToInt64(vm.pop())) + case 2: vm.push(runtime.ToFloat64(vm.pop())) }