Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix as result not working with int32,int16,int8 #693

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion checker/checker.go
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ func Check(tree *parser.Tree, config *conf.Config) (reflect.Type, error) {
}

switch v.config.Expect {
case reflect.Int, reflect.Int64, reflect.Float64:
case reflect.Int, reflect.Int64, reflect.Float64, reflect.Int32, reflect.Int16, reflect.Int8:
if !isNumber(nt) {
return nil, fmt.Errorf("expected %v, but got %v", v.config.Expect, nt)
}
14 changes: 10 additions & 4 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
@@ -40,12 +40,18 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro

if c.config != nil {
switch c.config.Expect {
case reflect.Int:
c.emit(OpCast, 0)
case reflect.Int8:
c.emit(OpCast, runtime.ResultAsTypInt8)
case reflect.Int16:
c.emit(OpCast, runtime.ResultAsTypInt16)
case reflect.Int32:
c.emit(OpCast, runtime.ResultAsTypInt32)
case reflect.Int64:
c.emit(OpCast, 1)
c.emit(OpCast, runtime.ResultAsTypInt64)
case reflect.Int:
c.emit(OpCast, runtime.ResultAsTypInt)
case reflect.Float64:
c.emit(OpCast, 2)
c.emit(OpCast, runtime.ResultAsTypFloat64)
}
if c.config.Optimize {
c.optimize()
91 changes: 91 additions & 0 deletions expr_test.go
Original file line number Diff line number Diff line change
@@ -210,6 +210,97 @@ func ExampleAsInt() {
// Output: int(42)
}

func ExampleAsInt32() {
program, err := expr.Compile("42", expr.AsKind(reflect.Int32))
if err != nil {
fmt.Printf("%v", err)
return
}

output, err := expr.Run(program, nil)
if err != nil {
fmt.Printf("%v", err)
return
}

fmt.Printf("%T(%v)", output, output)

// Output: int32(42)
}

func TestAsResult(t *testing.T) {
type Case struct {
Name string
Want any
Code string
Opts []expr.Option
}
var cases = []Case{
{
Name: "StrAsInt32",
Want: int32(42),
Code: "42",
Opts: []expr.Option{
expr.AsKind(reflect.Int32),
},
},
{
Name: "FloatAsInt32",
Want: int32(42),
Code: "42.111",
Opts: []expr.Option{
expr.AsKind(reflect.Int32),
},
},
{
Name: "StrAsInt16",
Want: int16(42),
Code: "42",
Opts: []expr.Option{
expr.AsKind(reflect.Int16),
},
},
{
Name: "FloatAsInt16",
Want: int16(42),
Code: "42.111",
Opts: []expr.Option{
expr.AsKind(reflect.Int16),
},
},
{
Name: "StrAsInt8",
Want: int8(42),
Code: "42",
Opts: []expr.Option{
expr.AsKind(reflect.Int8),
},
},
{
Name: "FloatAsInt8",
Want: int8(42),
Code: "42.111",
Opts: []expr.Option{
expr.AsKind(reflect.Int8),
},
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
program, err := expr.Compile(c.Code, c.Opts...)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

output, err := expr.Run(program, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assert.Equal(t, c.Want, output)
})
}
}

func ExampleAsInt64() {
env := map[string]any{
"rating": 5.5,
103 changes: 103 additions & 0 deletions vm/runtime/runtime.go
Original file line number Diff line number Diff line change
@@ -318,6 +318,99 @@ func ToInt(a any) int {
}
}

func ToInt8(a any) int8 {
switch x := a.(type) {
case float32:
return int8(x)
case float64:
return int8(x)
case int:
return int8(x)
case int8:
return int8(x)
case int16:
return int8(x)
case int32:
return int8(x)
case int64:
return int8(x)
case uint:
return int8(x)
case uint8:
return int8(x)
case uint16:
return int8(x)
case uint32:
return int8(x)
case uint64:
return int8(x)
default:
panic(fmt.Sprintf("invalid operation: int8(%T)", x))
}
}

func ToInt16(a any) int16 {
switch x := a.(type) {
case float32:
return int16(x)
case float64:
return int16(x)
case int:
return int16(x)
case int8:
return int16(x)
case int16:
return int16(x)
case int32:
return int16(x)
case int64:
return int16(x)
case uint:
return int16(x)
case uint8:
return int16(x)
case uint16:
return int16(x)
case uint32:
return int16(x)
case uint64:
return int16(x)
default:
panic(fmt.Sprintf("invalid operation: int16(%T)", x))
}
}

func ToInt32(a any) int32 {
switch x := a.(type) {
case float32:
return int32(x)
case float64:
return int32(x)
case int:
return int32(x)
case int8:
return int32(x)
case int16:
return int32(x)
case int32:
return x
case int64:
return int32(x)
case uint:
return int32(x)
case uint8:
return int32(x)
case uint16:
return int32(x)
case uint32:
return int32(x)
case uint64:
return int32(x)
default:
panic(fmt.Sprintf("invalid operation: int32(%T)", x))
}
}

func ToInt64(a any) int64 {
switch x := a.(type) {
case float32:
@@ -392,3 +485,13 @@ func IsNil(v any) bool {
return false
}
}

const (
ResultAsTypUnknown int = iota
ResultAsTypInt8
ResultAsTypInt16
ResultAsTypInt32
ResultAsTypInt64
ResultAsTypInt
ResultAsTypFloat64
)
12 changes: 9 additions & 3 deletions vm/vm.go
Original file line number Diff line number Diff line change
@@ -447,11 +447,17 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {

case OpCast:
switch arg {
case 0:
case runtime.ResultAsTypInt8:
vm.push(runtime.ToInt8(vm.pop()))
case runtime.ResultAsTypInt16:
vm.push(runtime.ToInt16(vm.pop()))
case runtime.ResultAsTypInt:
vm.push(runtime.ToInt(vm.pop()))
case 1:
case runtime.ResultAsTypInt32:
vm.push(runtime.ToInt32(vm.pop()))
case runtime.ResultAsTypInt64:
vm.push(runtime.ToInt64(vm.pop()))
case 2:
case runtime.ResultAsTypFloat64:
vm.push(runtime.ToFloat64(vm.pop()))
}