mirror of
https://github.com/MontFerret/ferret.git
synced 2025-02-21 19:50:09 +02:00
Bugfix/#295 arithmetic operators (#298)
* Some work * Updated Add operator * Updated Subtract operator * Updated Subtract operator tests * Added tests for multiplication * Added division * Updated the rest of operators
This commit is contained in:
parent
ab0a617031
commit
6933798419
@ -2,6 +2,7 @@ package operators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
@ -88,9 +89,62 @@ func Not(left, _ core.Value) core.Value {
|
||||
return values.True
|
||||
}
|
||||
|
||||
func ToNumberOrString(input core.Value) core.Value {
|
||||
switch input.Type() {
|
||||
case types.Int, types.Float, types.String:
|
||||
return input
|
||||
default:
|
||||
return values.ToInt(input)
|
||||
}
|
||||
}
|
||||
|
||||
func ToNumberOnly(input core.Value) core.Value {
|
||||
switch input.Type() {
|
||||
case types.Int, types.Float:
|
||||
return input
|
||||
case types.String:
|
||||
if strings.Contains(input.String(), ".") {
|
||||
return values.ToFloat(input)
|
||||
}
|
||||
|
||||
return values.ToInt(input)
|
||||
case types.Array:
|
||||
arr := input.(*values.Array)
|
||||
length := arr.Length()
|
||||
|
||||
if length == 0 {
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
i := values.ZeroInt
|
||||
f := values.ZeroFloat
|
||||
|
||||
for y := values.Int(0); y < length; y++ {
|
||||
out := ToNumberOnly(arr.Get(y))
|
||||
|
||||
if out.Type() == types.Int {
|
||||
i += out.(values.Int)
|
||||
} else {
|
||||
f += out.(values.Float)
|
||||
}
|
||||
}
|
||||
|
||||
if f == 0 {
|
||||
return i
|
||||
}
|
||||
|
||||
return values.Float(i) + f
|
||||
default:
|
||||
return values.ToInt(input)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds numbers
|
||||
// Concats strings
|
||||
func Add(left, right core.Value) core.Value {
|
||||
// Concatenates strings
|
||||
func Add(inputL, inputR core.Value) core.Value {
|
||||
left := ToNumberOrString(inputL)
|
||||
right := ToNumberOrString(inputR)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
if right.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
@ -126,7 +180,10 @@ func Add(left, right core.Value) core.Value {
|
||||
return values.NewString(left.String() + right.String())
|
||||
}
|
||||
|
||||
func Subtract(left, right core.Value) core.Value {
|
||||
func Subtract(inputL, inputR core.Value) core.Value {
|
||||
left := ToNumberOnly(inputL)
|
||||
right := ToNumberOnly(inputR)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
if right.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
@ -162,7 +219,10 @@ func Subtract(left, right core.Value) core.Value {
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
func Multiply(left, right core.Value) core.Value {
|
||||
func Multiply(inputL, inputR core.Value) core.Value {
|
||||
left := ToNumberOnly(inputL)
|
||||
right := ToNumberOnly(inputR)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
if right.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
@ -198,20 +258,31 @@ func Multiply(left, right core.Value) core.Value {
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
func Divide(left, right core.Value) core.Value {
|
||||
func Divide(inputL, inputR core.Value) core.Value {
|
||||
left := ToNumberOnly(inputL)
|
||||
right := ToNumberOnly(inputR)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
if right.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
r := right.(values.Int)
|
||||
l := values.Float(left.(values.Int))
|
||||
r := values.Float(right.(values.Int))
|
||||
|
||||
if r == 0.0 {
|
||||
panic("divide by zero")
|
||||
}
|
||||
|
||||
return l / r
|
||||
}
|
||||
|
||||
if right.Type() == types.Float {
|
||||
l := left.(values.Int)
|
||||
l := values.Float(left.(values.Int))
|
||||
r := right.(values.Float)
|
||||
|
||||
return values.Float(l) / r
|
||||
if r == 0.0 {
|
||||
panic("divide by zero")
|
||||
}
|
||||
|
||||
return l / r
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,21 +291,32 @@ func Divide(left, right core.Value) core.Value {
|
||||
l := left.(values.Float)
|
||||
r := right.(values.Float)
|
||||
|
||||
if r == 0.0 {
|
||||
panic("divide by zero")
|
||||
}
|
||||
|
||||
return l / r
|
||||
}
|
||||
|
||||
if right.Type() == types.Int {
|
||||
l := left.(values.Float)
|
||||
r := right.(values.Int)
|
||||
r := values.Float(right.(values.Int))
|
||||
|
||||
return l / values.Float(r)
|
||||
if r == 0.0 {
|
||||
panic("divide by zero")
|
||||
}
|
||||
|
||||
return l / r
|
||||
}
|
||||
}
|
||||
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
func Modulus(left, right core.Value) core.Value {
|
||||
func Modulus(inputL, inputR core.Value) core.Value {
|
||||
left := ToNumberOnly(inputL)
|
||||
right := ToNumberOnly(inputR)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
if right.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
@ -270,7 +352,9 @@ func Modulus(left, right core.Value) core.Value {
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
func Increment(left, _ core.Value) core.Value {
|
||||
func Increment(inputL, _ core.Value) core.Value {
|
||||
left := ToNumberOnly(inputL)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
|
||||
@ -286,7 +370,9 @@ func Increment(left, _ core.Value) core.Value {
|
||||
return values.None
|
||||
}
|
||||
|
||||
func Decrement(left, _ core.Value) core.Value {
|
||||
func Decrement(inputL, _ core.Value) core.Value {
|
||||
left := ToNumberOnly(inputL)
|
||||
|
||||
if left.Type() == types.Int {
|
||||
l := left.(values.Int)
|
||||
|
||||
@ -303,31 +389,27 @@ func Decrement(left, _ core.Value) core.Value {
|
||||
}
|
||||
|
||||
func Negative(value, _ core.Value) core.Value {
|
||||
err := core.ValidateType(value, types.Int, types.Float)
|
||||
|
||||
if err != nil {
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
if value.Type() == types.Int {
|
||||
return -value.(values.Int)
|
||||
}
|
||||
|
||||
return -value.(values.Float)
|
||||
if value.Type() == types.Float {
|
||||
return -value.(values.Float)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func Positive(value, _ core.Value) core.Value {
|
||||
err := core.ValidateType(value, types.Int, types.Float)
|
||||
|
||||
if err != nil {
|
||||
return values.ZeroInt
|
||||
}
|
||||
|
||||
if value.Type() == types.Int {
|
||||
return +value.(values.Int)
|
||||
}
|
||||
|
||||
return +value.(values.Float)
|
||||
if value.Type() == types.Float {
|
||||
return +value.(values.Float)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func ToBoolean(value, _ core.Value) core.Value {
|
||||
|
1022
pkg/runtime/expressions/operators/operator_test.go
Normal file
1022
pkg/runtime/expressions/operators/operator_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,8 @@ import (
|
||||
|
||||
type Float float64
|
||||
|
||||
var NaN = Float(math.NaN())
|
||||
|
||||
const ZeroFloat = Float(0.0)
|
||||
|
||||
func NewFloat(input float64) Float {
|
||||
@ -80,7 +82,7 @@ func (t Float) Type() core.Type {
|
||||
}
|
||||
|
||||
func (t Float) String() string {
|
||||
return fmt.Sprintf("%f", t)
|
||||
return fmt.Sprintf("%v", float64(t))
|
||||
}
|
||||
|
||||
func (t Float) Compare(other core.Value) int64 {
|
||||
|
@ -235,58 +235,116 @@ func ToBoolean(input core.Value) core.Value {
|
||||
switch input.Type() {
|
||||
case types.Boolean:
|
||||
return input
|
||||
case types.None:
|
||||
return False
|
||||
case types.String:
|
||||
return NewBoolean(input.String() != "")
|
||||
return NewBoolean(input.(String) != "")
|
||||
case types.Int:
|
||||
return NewBoolean(input.(Int) != 0)
|
||||
case types.Float:
|
||||
return NewBoolean(input.(Float) != 0)
|
||||
case types.DateTime:
|
||||
return NewBoolean(!input.(DateTime).IsZero())
|
||||
case types.None:
|
||||
return False
|
||||
default:
|
||||
return True
|
||||
}
|
||||
}
|
||||
|
||||
func ToFloat(input core.Value) (Float, error) {
|
||||
func ToFloat(input core.Value) Float {
|
||||
switch val := input.(type) {
|
||||
case Float:
|
||||
return val, nil
|
||||
return val
|
||||
case Int:
|
||||
return Float(val), nil
|
||||
return Float(val)
|
||||
case String:
|
||||
i, err := strconv.ParseFloat(string(val), 64)
|
||||
|
||||
if err != nil {
|
||||
return ZeroFloat, err
|
||||
return ZeroFloat
|
||||
}
|
||||
|
||||
return Float(i), nil
|
||||
return Float(i)
|
||||
case Boolean:
|
||||
if val {
|
||||
return Float(1)
|
||||
}
|
||||
|
||||
return Float(0)
|
||||
case DateTime:
|
||||
dt := input.(DateTime)
|
||||
|
||||
if dt.IsZero() {
|
||||
return ZeroFloat
|
||||
}
|
||||
|
||||
return NewFloat(float64(dt.Unix()))
|
||||
case *Array:
|
||||
length := val.Length()
|
||||
|
||||
if length == 0 {
|
||||
return ZeroFloat
|
||||
}
|
||||
|
||||
res := ZeroFloat
|
||||
|
||||
for i := Int(0); i < length; i++ {
|
||||
res += ToFloat(val.Get(i))
|
||||
}
|
||||
|
||||
return res
|
||||
default:
|
||||
return ZeroFloat, core.TypeError(input.Type(), types.Int, types.Float, types.String)
|
||||
return ZeroFloat
|
||||
}
|
||||
}
|
||||
|
||||
func ToInt(input core.Value) (Int, error) {
|
||||
func ToInt(input core.Value) Int {
|
||||
switch val := input.(type) {
|
||||
case Int:
|
||||
return val, nil
|
||||
return val
|
||||
case Float:
|
||||
return Int(val), nil
|
||||
return Int(val)
|
||||
case String:
|
||||
i, err := strconv.ParseInt(string(val), 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return ZeroInt, err
|
||||
return ZeroInt
|
||||
}
|
||||
|
||||
return Int(i), nil
|
||||
return Int(i)
|
||||
case Boolean:
|
||||
if val {
|
||||
return Int(1)
|
||||
}
|
||||
|
||||
return Int(0)
|
||||
case DateTime:
|
||||
dt := input.(DateTime)
|
||||
|
||||
if dt.IsZero() {
|
||||
return ZeroInt
|
||||
}
|
||||
|
||||
return NewInt(int(dt.Unix()))
|
||||
case *Array:
|
||||
length := val.Length()
|
||||
|
||||
if length == 0 {
|
||||
return ZeroInt
|
||||
}
|
||||
|
||||
res := ZeroInt
|
||||
|
||||
for i := Int(0); i < length; i++ {
|
||||
res += ToInt(val.Get(i))
|
||||
}
|
||||
|
||||
return res
|
||||
default:
|
||||
return ZeroInt, core.TypeError(input.Type(), types.Int, types.Float, types.String)
|
||||
return ZeroInt
|
||||
}
|
||||
}
|
||||
|
||||
func ToArray(ctx context.Context, input core.Value) (core.Value, error) {
|
||||
func ToArray(ctx context.Context, input core.Value) core.Value {
|
||||
switch value := input.(type) {
|
||||
case Boolean,
|
||||
Int,
|
||||
@ -294,9 +352,9 @@ func ToArray(ctx context.Context, input core.Value) (core.Value, error) {
|
||||
String,
|
||||
DateTime:
|
||||
|
||||
return NewArrayWith(value), nil
|
||||
return NewArrayWith(value)
|
||||
case *Array:
|
||||
return value.Copy(), nil
|
||||
return value.Copy()
|
||||
case *Object:
|
||||
arr := NewArray(int(value.Length()))
|
||||
|
||||
@ -306,12 +364,12 @@ func ToArray(ctx context.Context, input core.Value) (core.Value, error) {
|
||||
return true
|
||||
})
|
||||
|
||||
return arr, nil
|
||||
return arr
|
||||
case core.Iterable:
|
||||
iterator, err := value.Iterate(ctx)
|
||||
|
||||
if err != nil {
|
||||
return None, err
|
||||
return None
|
||||
}
|
||||
|
||||
arr := NewArray(10)
|
||||
@ -320,7 +378,7 @@ func ToArray(ctx context.Context, input core.Value) (core.Value, error) {
|
||||
val, _, err := iterator.Next(ctx)
|
||||
|
||||
if err != nil {
|
||||
return None, err
|
||||
return None
|
||||
}
|
||||
|
||||
if val == None {
|
||||
@ -330,9 +388,9 @@ func ToArray(ctx context.Context, input core.Value) (core.Value, error) {
|
||||
arr.Push(val)
|
||||
}
|
||||
|
||||
return arr, nil
|
||||
return arr
|
||||
default:
|
||||
return NewArray(0), nil
|
||||
return NewArray(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,3 +430,9 @@ func MapHash(input map[string]core.Value) uint64 {
|
||||
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
func IsNumber(input core.Value) Boolean {
|
||||
t := input.Type()
|
||||
|
||||
return t == types.Int || t == types.Float
|
||||
}
|
||||
|
@ -225,41 +225,58 @@ func TestHelpers(t *testing.T) {
|
||||
Convey("ToFloat", func() {
|
||||
Convey("Should convert Int", func() {
|
||||
input := values.NewInt(100)
|
||||
output, err := values.ToFloat(input)
|
||||
output := values.ToFloat(input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, values.NewFloat(100))
|
||||
})
|
||||
|
||||
Convey("Should convert Float", func() {
|
||||
input := values.NewFloat(100)
|
||||
output, err := values.ToFloat(input)
|
||||
output := values.ToFloat(input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, values.NewFloat(100))
|
||||
})
|
||||
|
||||
Convey("Should convert String", func() {
|
||||
input := values.NewString("100.1")
|
||||
output, err := values.ToFloat(input)
|
||||
output := values.ToFloat(input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, values.NewFloat(100.1))
|
||||
|
||||
output2 := values.ToFloat(values.NewString("foobar"))
|
||||
So(output2, ShouldEqual, values.ZeroFloat)
|
||||
})
|
||||
|
||||
Convey("Should convert Boolean", func() {
|
||||
So(values.ToFloat(values.True), ShouldEqual, values.NewFloat(1))
|
||||
So(values.ToFloat(values.False), ShouldEqual, values.NewFloat(0))
|
||||
})
|
||||
|
||||
Convey("Should convert Array with single item", func() {
|
||||
So(values.ToFloat(values.NewArrayWith(values.NewFloat(1))), ShouldEqual, values.NewFloat(1))
|
||||
})
|
||||
|
||||
Convey("Should convert Array with multiple items", func() {
|
||||
arg := values.NewArrayWith(values.NewFloat(1), values.NewFloat(1))
|
||||
|
||||
So(values.ToFloat(arg), ShouldEqual, values.NewFloat(2))
|
||||
})
|
||||
|
||||
Convey("Should convert DateTime", func() {
|
||||
dt := values.NewCurrentDateTime()
|
||||
ts := dt.Time.Unix()
|
||||
|
||||
So(values.ToFloat(dt), ShouldEqual, values.NewFloat(float64(ts)))
|
||||
})
|
||||
|
||||
Convey("Should NOT convert other types", func() {
|
||||
inputs := []core.Value{
|
||||
values.NewBoolean(true),
|
||||
values.NewCurrentDateTime(),
|
||||
values.NewArray(1),
|
||||
values.NewObject(),
|
||||
values.NewBinary([]byte("")),
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
_, err := values.ToFloat(input)
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
So(values.ToFloat(input), ShouldEqual, values.ZeroFloat)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -267,41 +284,58 @@ func TestHelpers(t *testing.T) {
|
||||
Convey("ToInt", func() {
|
||||
Convey("Should convert Int", func() {
|
||||
input := values.NewInt(100)
|
||||
output, err := values.ToInt(input)
|
||||
output := values.ToInt(input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, values.NewInt(100))
|
||||
})
|
||||
|
||||
Convey("Should convert Float", func() {
|
||||
input := values.NewFloat(100.1)
|
||||
output, err := values.ToInt(input)
|
||||
output := values.ToInt(input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, values.NewInt(100))
|
||||
})
|
||||
|
||||
Convey("Should convert String", func() {
|
||||
input := values.NewString("100")
|
||||
output, err := values.ToInt(input)
|
||||
output := values.ToInt(input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(output, ShouldEqual, values.NewInt(100))
|
||||
|
||||
output2 := values.ToInt(values.NewString("foobar"))
|
||||
So(output2, ShouldEqual, values.ZeroInt)
|
||||
})
|
||||
|
||||
Convey("Should convert Boolean", func() {
|
||||
So(values.ToInt(values.True), ShouldEqual, values.NewInt(1))
|
||||
So(values.ToInt(values.False), ShouldEqual, values.NewInt(0))
|
||||
})
|
||||
|
||||
Convey("Should convert Array with single item", func() {
|
||||
So(values.ToInt(values.NewArrayWith(values.NewFloat(1))), ShouldEqual, values.NewInt(1))
|
||||
})
|
||||
|
||||
Convey("Should convert Array with multiple items", func() {
|
||||
arg := values.NewArrayWith(values.NewFloat(1), values.NewFloat(1))
|
||||
|
||||
So(values.ToInt(arg), ShouldEqual, values.NewFloat(2))
|
||||
})
|
||||
|
||||
Convey("Should convert DateTime", func() {
|
||||
dt := values.NewCurrentDateTime()
|
||||
ts := dt.Time.Unix()
|
||||
|
||||
So(values.ToInt(dt), ShouldEqual, values.NewInt(int(ts)))
|
||||
})
|
||||
|
||||
Convey("Should NOT convert other types", func() {
|
||||
inputs := []core.Value{
|
||||
values.NewBoolean(true),
|
||||
values.NewCurrentDateTime(),
|
||||
values.NewArray(1),
|
||||
values.NewObject(),
|
||||
values.NewBinary([]byte("")),
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
_, err := values.ToInt(input)
|
||||
|
||||
So(err, ShouldNotBeNil)
|
||||
So(values.ToInt(input), ShouldEqual, values.ZeroInt)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -338,10 +372,9 @@ func TestHelpers(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, pairs := range inputs {
|
||||
actual, err := values.ToArray(context.Background(), pairs[0])
|
||||
actual := values.ToArray(context.Background(), pairs[0])
|
||||
expected := pairs[1]
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(actual.Compare(expected), ShouldEqual, 0)
|
||||
}
|
||||
})
|
||||
@ -357,9 +390,7 @@ func TestHelpers(t *testing.T) {
|
||||
}
|
||||
|
||||
input := values.NewArrayWith(vals...)
|
||||
output, err := values.ToArray(context.Background(), input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
output := values.ToArray(context.Background(), input)
|
||||
|
||||
arr := output.(*values.Array)
|
||||
|
||||
@ -383,9 +414,7 @@ func TestHelpers(t *testing.T) {
|
||||
values.NewObjectProperty("qaz", values.NewObject()),
|
||||
)
|
||||
|
||||
output, err := values.ToArray(context.Background(), input)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
output := values.ToArray(context.Background(), input)
|
||||
|
||||
arr := output.(*values.Array).Sort()
|
||||
|
||||
|
@ -38,17 +38,8 @@ func MouseMoveXY(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
x, err := values.ToFloat(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
y, err := values.ToFloat(args[1])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
x := values.ToFloat(args[0])
|
||||
y := values.ToFloat(args[1])
|
||||
|
||||
doc := args[0].(drivers.HTMLDocument)
|
||||
|
||||
|
@ -38,17 +38,8 @@ func ScrollXY(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
x, err := values.ToFloat(args[1])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
y, err := values.ToFloat(args[2])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
x := values.ToFloat(args[1])
|
||||
y := values.ToFloat(args[2])
|
||||
|
||||
doc := args[0].(drivers.HTMLDocument)
|
||||
|
||||
|
@ -26,22 +26,10 @@ func Rand(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var max float64
|
||||
var min float64
|
||||
|
||||
arg1, err := values.ToFloat(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
max = float64(arg1)
|
||||
max = float64(values.ToFloat(args[0]))
|
||||
|
||||
if len(args) > 1 {
|
||||
arg2, err := values.ToFloat(args[1])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
min = float64(arg2)
|
||||
min = float64(values.ToFloat(args[1]))
|
||||
} else {
|
||||
max, min = core.NumberBoundaries(max)
|
||||
}
|
||||
|
@ -20,5 +20,5 @@ func ToArray(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.ToArray(ctx, args[0])
|
||||
return values.ToArray(ctx, args[0]), nil
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
)
|
||||
|
||||
// ToBool takes an input value of any type and converts it into the appropriate boolean value.
|
||||
@ -24,44 +23,5 @@ func ToBool(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
switch arg.Type() {
|
||||
case types.Boolean:
|
||||
return arg, nil
|
||||
case types.Int:
|
||||
val := arg.(values.Int)
|
||||
|
||||
if val != 0 {
|
||||
return values.True, nil
|
||||
}
|
||||
|
||||
return values.False, nil
|
||||
case types.Float:
|
||||
val := arg.(values.Float)
|
||||
|
||||
if val != 0 {
|
||||
return values.True, nil
|
||||
}
|
||||
|
||||
return values.False, nil
|
||||
case types.String:
|
||||
if arg.String() != "" {
|
||||
return values.True, nil
|
||||
}
|
||||
|
||||
return values.False, nil
|
||||
case types.DateTime:
|
||||
val := arg.(values.DateTime)
|
||||
|
||||
if !val.IsZero() {
|
||||
return values.True, nil
|
||||
}
|
||||
|
||||
return values.False, nil
|
||||
case types.None:
|
||||
return values.False, nil
|
||||
default:
|
||||
return values.True, nil
|
||||
}
|
||||
return values.ToBoolean(args[0]), nil
|
||||
}
|
||||
|
@ -2,11 +2,9 @@ package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
)
|
||||
|
||||
// ToFloat takes an input value of any type and convert it into a float value.
|
||||
@ -20,67 +18,12 @@ import (
|
||||
// An empty array is converted to 0, an array with one member is converted into the result of TO_NUMBER() for its sole member.
|
||||
// An array with two or more members is converted to the number 0.
|
||||
// An object / HTML node is converted to the number 0.
|
||||
func ToFloat(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
func ToFloat(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
switch arg.Type() {
|
||||
case types.Boolean:
|
||||
val := arg.(values.Boolean)
|
||||
|
||||
if val {
|
||||
return values.NewFloat(1), nil
|
||||
}
|
||||
|
||||
return values.ZeroFloat, nil
|
||||
case types.Int:
|
||||
val := arg.(values.Int)
|
||||
|
||||
return values.Float(val), nil
|
||||
case types.Float:
|
||||
return arg, nil
|
||||
case types.String:
|
||||
str := arg.String()
|
||||
|
||||
if str == "" {
|
||||
return values.ZeroFloat, nil
|
||||
}
|
||||
|
||||
num, err := strconv.ParseFloat(str, 64)
|
||||
|
||||
if err != nil {
|
||||
return values.ZeroFloat, nil
|
||||
}
|
||||
|
||||
return values.NewFloat(num), nil
|
||||
case types.DateTime:
|
||||
val := arg.(values.DateTime)
|
||||
|
||||
if val.IsZero() {
|
||||
return values.ZeroFloat, nil
|
||||
}
|
||||
|
||||
return values.NewFloat(float64(val.Unix())), nil
|
||||
case types.None:
|
||||
return values.ZeroFloat, nil
|
||||
case types.Array:
|
||||
val := arg.(*values.Array)
|
||||
|
||||
if val.Length() == 0 {
|
||||
return values.ZeroFloat, nil
|
||||
}
|
||||
|
||||
if val.Length() == 1 {
|
||||
return ToFloat(ctx, val.Get(0))
|
||||
}
|
||||
|
||||
return values.ZeroFloat, nil
|
||||
default:
|
||||
return values.ZeroFloat, nil
|
||||
}
|
||||
return values.ToFloat(args[0]), nil
|
||||
}
|
||||
|
@ -2,11 +2,9 @@ package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
)
|
||||
|
||||
// ToInt takes an input value of any type and convert it into an integer value.
|
||||
@ -20,67 +18,12 @@ import (
|
||||
// An empty array is converted to 0, an array with one member is converted into the result of TO_NUMBER() for its sole member.
|
||||
// An array with two or more members is converted to the number 0.
|
||||
// An object / HTML node is converted to the number 0.
|
||||
func ToInt(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
func ToInt(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
switch arg.Type() {
|
||||
case types.Boolean:
|
||||
val := arg.(values.Boolean)
|
||||
|
||||
if val {
|
||||
return values.NewInt(1), nil
|
||||
}
|
||||
|
||||
return values.ZeroInt, nil
|
||||
case types.Int:
|
||||
return arg, nil
|
||||
case types.Float:
|
||||
val := arg.(values.Float)
|
||||
|
||||
return values.Int(val), nil
|
||||
case types.String:
|
||||
str := arg.String()
|
||||
|
||||
if str == "" {
|
||||
return values.ZeroInt, nil
|
||||
}
|
||||
|
||||
num, err := strconv.Atoi(str)
|
||||
|
||||
if err != nil {
|
||||
return values.ZeroInt, nil
|
||||
}
|
||||
|
||||
return values.NewInt(num), nil
|
||||
case types.DateTime:
|
||||
val := arg.(values.DateTime)
|
||||
|
||||
if val.IsZero() {
|
||||
return values.ZeroInt, nil
|
||||
}
|
||||
|
||||
return values.NewInt(int(val.Unix())), nil
|
||||
case types.None:
|
||||
return values.ZeroInt, nil
|
||||
case types.Array:
|
||||
val := arg.(*values.Array)
|
||||
|
||||
if val.Length() == 0 {
|
||||
return values.ZeroInt, nil
|
||||
}
|
||||
|
||||
if val.Length() == 1 {
|
||||
return ToInt(ctx, val.Get(0))
|
||||
}
|
||||
|
||||
return values.ZeroInt, nil
|
||||
default:
|
||||
return values.ZeroInt, nil
|
||||
}
|
||||
return values.ToInt(args[0]), nil
|
||||
}
|
||||
|
@ -17,11 +17,7 @@ func Wait(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
arg, err := values.ToInt(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
arg := values.ToInt(args[0])
|
||||
|
||||
time.Sleep(time.Millisecond * time.Duration(arg))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user