1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-18 23:47:48 +02:00
ferret/pkg/runtime/expressions/operators/operator.go

418 lines
7.1 KiB
Go
Raw Normal View History

2018-09-18 22:42:38 +02:00
package operators
import (
"context"
"strings"
2018-09-18 22:42:38 +02:00
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
2018-09-18 22:42:38 +02:00
)
type (
OperatorFunc func(left, right core.Value) core.Value
baseOperator struct {
src core.SourceMap
left core.Expression
right core.Expression
}
)
2018-09-18 22:42:38 +02:00
func (operator *baseOperator) Exec(_ context.Context, _ *core.Scope) (core.Value, error) {
return values.None, core.ErrInvalidOperation
2018-09-18 22:42:38 +02:00
}
func (operator *baseOperator) Eval(_ context.Context, _, _ core.Value) (core.Value, error) {
2018-09-18 22:42:38 +02:00
return values.None, core.ErrInvalidOperation
}
// Equality
func Equal(left, right core.Value) core.Value {
if left.Compare(right) == 0 {
return values.True
}
return values.False
}
func NotEqual(left, right core.Value) core.Value {
if left.Compare(right) != 0 {
return values.True
}
return values.False
}
func Less(left, right core.Value) core.Value {
if left.Compare(right) < 0 {
return values.True
}
return values.False
}
func LessOrEqual(left, right core.Value) core.Value {
out := left.Compare(right)
if out < 0 || out == 0 {
return values.True
}
return values.False
}
func Greater(left, right core.Value) core.Value {
if left.Compare(right) > 0 {
return values.True
}
return values.False
}
func GreaterOrEqual(left, right core.Value) core.Value {
out := left.Compare(right)
if out > 0 || out == 0 {
return values.True
}
return values.False
}
func Not(left, _ core.Value) core.Value {
2018-09-23 02:28:33 +02:00
b := values.ToBoolean(left)
if b == values.True {
2018-09-18 22:42:38 +02:00
return values.False
}
2018-09-23 02:28:33 +02:00
return values.True
2018-09-18 22:42:38 +02:00
}
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)
}
}
2018-09-18 22:42:38 +02:00
// Adds numbers
// 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 {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l + r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return values.Float(l) + r
2018-09-18 22:42:38 +02:00
}
}
if left.Type() == types.Float {
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l + r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l + values.Float(r)
2018-09-18 22:42:38 +02:00
}
}
return values.NewString(left.String() + right.String())
}
func Subtract(inputL, inputR core.Value) core.Value {
left := ToNumberOnly(inputL)
right := ToNumberOnly(inputR)
if left.Type() == types.Int {
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l - r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return values.Float(l) - r
2018-09-18 22:42:38 +02:00
}
}
if left.Type() == types.Float {
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l - r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l - values.Float(r)
2018-09-18 22:42:38 +02:00
}
}
return values.ZeroInt
}
func Multiply(inputL, inputR core.Value) core.Value {
left := ToNumberOnly(inputL)
right := ToNumberOnly(inputR)
if left.Type() == types.Int {
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l * r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return values.Float(l) * r
2018-09-18 22:42:38 +02:00
}
}
if left.Type() == types.Float {
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l * r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l * values.Float(r)
2018-09-18 22:42:38 +02:00
}
}
return values.ZeroInt
}
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 := values.Float(left.(values.Int))
r := values.Float(right.(values.Int))
if r == 0.0 {
panic("divide by zero")
}
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l / r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Float {
l := values.Float(left.(values.Int))
2018-09-23 02:28:33 +02:00
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
if r == 0.0 {
panic("divide by zero")
}
return l / r
2018-09-18 22:42:38 +02:00
}
}
if left.Type() == types.Float {
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
if r == 0.0 {
panic("divide by zero")
}
2018-09-23 02:28:33 +02:00
return l / r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := values.Float(right.(values.Int))
if r == 0.0 {
panic("divide by zero")
}
2018-09-18 22:42:38 +02:00
return l / r
2018-09-18 22:42:38 +02:00
}
}
return values.ZeroInt
}
func Modulus(inputL, inputR core.Value) core.Value {
left := ToNumberOnly(inputL)
right := ToNumberOnly(inputR)
if left.Type() == types.Int {
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l % r
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l % values.Int(r)
2018-09-18 22:42:38 +02:00
}
}
if left.Type() == types.Float {
if right.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return values.Int(l) % values.Int(r)
2018-09-18 22:42:38 +02:00
}
if right.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
r := right.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return values.Int(l) % r
2018-09-18 22:42:38 +02:00
}
}
return values.ZeroInt
}
func Increment(inputL, _ core.Value) core.Value {
left := ToNumberOnly(inputL)
if left.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l + 1
2018-09-18 22:42:38 +02:00
}
if left.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l + 1
2018-09-18 22:42:38 +02:00
}
return values.None
}
func Decrement(inputL, _ core.Value) core.Value {
left := ToNumberOnly(inputL)
if left.Type() == types.Int {
2018-09-23 02:28:33 +02:00
l := left.(values.Int)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l - 1
2018-09-18 22:42:38 +02:00
}
if left.Type() == types.Float {
2018-09-23 02:28:33 +02:00
l := left.(values.Float)
2018-09-18 22:42:38 +02:00
2018-09-23 02:28:33 +02:00
return l - 1
2018-09-18 22:42:38 +02:00
}
return values.None
}
func Negative(value, _ core.Value) core.Value {
if value.Type() == types.Int {
return -value.(values.Int)
}
if value.Type() == types.Float {
return -value.(values.Float)
}
return value
}
func Positive(value, _ core.Value) core.Value {
if value.Type() == types.Int {
return +value.(values.Int)
}
if value.Type() == types.Float {
return +value.(values.Float)
}
return value
}
func ToBoolean(value, _ core.Value) core.Value {
return values.ToBoolean(value)
}