Skip to content

Commit

Permalink
Add AsKind and AsInt func
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv committed Nov 10, 2022
1 parent 9c67ada commit 226bdb0
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 45 deletions.
2 changes: 1 addition & 1 deletion checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
6 changes: 4 additions & 2 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
26 changes: 0 additions & 26 deletions compiler/compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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())
}
20 changes: 17 additions & 3 deletions expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
60 changes: 48 additions & 12 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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() {
Expand All @@ -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 &&
Expand Down
4 changes: 3 additions & 1 deletion vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
}

Expand Down

0 comments on commit 226bdb0

Please sign in to comment.