github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/operators/operator.go (about)

     1  package operators
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/MontFerret/ferret/pkg/runtime/core"
     8  	"github.com/MontFerret/ferret/pkg/runtime/values"
     9  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
    10  )
    11  
    12  type (
    13  	OperatorFunc func(left, right core.Value) core.Value
    14  	baseOperator struct {
    15  		src   core.SourceMap
    16  		left  core.Expression
    17  		right core.Expression
    18  	}
    19  )
    20  
    21  func (operator *baseOperator) Exec(_ context.Context, _ *core.Scope) (core.Value, error) {
    22  	return values.None, core.ErrInvalidOperation
    23  }
    24  
    25  func (operator *baseOperator) Eval(_ context.Context, _, _ core.Value) (core.Value, error) {
    26  	return values.None, core.ErrInvalidOperation
    27  }
    28  
    29  // Equality
    30  func Equal(left, right core.Value) core.Value {
    31  	if left.Compare(right) == 0 {
    32  		return values.True
    33  	}
    34  
    35  	return values.False
    36  }
    37  
    38  func NotEqual(left, right core.Value) core.Value {
    39  	if left.Compare(right) != 0 {
    40  		return values.True
    41  	}
    42  
    43  	return values.False
    44  }
    45  
    46  func Less(left, right core.Value) core.Value {
    47  	if left.Compare(right) < 0 {
    48  		return values.True
    49  	}
    50  
    51  	return values.False
    52  }
    53  
    54  func LessOrEqual(left, right core.Value) core.Value {
    55  	out := left.Compare(right)
    56  
    57  	if out < 0 || out == 0 {
    58  		return values.True
    59  	}
    60  
    61  	return values.False
    62  }
    63  
    64  func Greater(left, right core.Value) core.Value {
    65  	if left.Compare(right) > 0 {
    66  		return values.True
    67  	}
    68  
    69  	return values.False
    70  }
    71  
    72  func GreaterOrEqual(left, right core.Value) core.Value {
    73  	out := left.Compare(right)
    74  
    75  	if out > 0 || out == 0 {
    76  		return values.True
    77  	}
    78  
    79  	return values.False
    80  }
    81  
    82  func Not(left, _ core.Value) core.Value {
    83  	b := values.ToBoolean(left)
    84  
    85  	if b == values.True {
    86  		return values.False
    87  	}
    88  
    89  	return values.True
    90  }
    91  
    92  func ToNumberOrString(input core.Value) core.Value {
    93  	switch input.Type() {
    94  	case types.Int, types.Float, types.String:
    95  		return input
    96  	default:
    97  		return values.ToInt(input)
    98  	}
    99  }
   100  
   101  func ToNumberOnly(input core.Value) core.Value {
   102  	switch input.Type() {
   103  	case types.Int, types.Float:
   104  		return input
   105  	case types.String:
   106  		if strings.Contains(input.String(), ".") {
   107  			return values.ToFloat(input)
   108  		}
   109  
   110  		return values.ToInt(input)
   111  	case types.Array:
   112  		arr := input.(*values.Array)
   113  		length := arr.Length()
   114  
   115  		if length == 0 {
   116  			return values.ZeroInt
   117  		}
   118  
   119  		i := values.ZeroInt
   120  		f := values.ZeroFloat
   121  
   122  		for y := values.Int(0); y < length; y++ {
   123  			out := ToNumberOnly(arr.Get(y))
   124  
   125  			if out.Type() == types.Int {
   126  				i += out.(values.Int)
   127  			} else {
   128  				f += out.(values.Float)
   129  			}
   130  		}
   131  
   132  		if f == 0 {
   133  			return i
   134  		}
   135  
   136  		return values.Float(i) + f
   137  	default:
   138  		return values.ToInt(input)
   139  	}
   140  }
   141  
   142  // Adds numbers
   143  // Concatenates strings
   144  func Add(inputL, inputR core.Value) core.Value {
   145  	left := ToNumberOrString(inputL)
   146  	right := ToNumberOrString(inputR)
   147  
   148  	if left.Type() == types.Int {
   149  		if right.Type() == types.Int {
   150  			l := left.(values.Int)
   151  			r := right.(values.Int)
   152  
   153  			return l + r
   154  		}
   155  
   156  		if right.Type() == types.Float {
   157  			l := left.(values.Int)
   158  			r := right.(values.Float)
   159  
   160  			return values.Float(l) + r
   161  		}
   162  	}
   163  
   164  	if left.Type() == types.Float {
   165  		if right.Type() == types.Float {
   166  			l := left.(values.Float)
   167  			r := right.(values.Float)
   168  
   169  			return l + r
   170  		}
   171  
   172  		if right.Type() == types.Int {
   173  			l := left.(values.Float)
   174  			r := right.(values.Int)
   175  
   176  			return l + values.Float(r)
   177  		}
   178  	}
   179  
   180  	return values.NewString(left.String() + right.String())
   181  }
   182  
   183  func Subtract(inputL, inputR core.Value) core.Value {
   184  	left := ToNumberOnly(inputL)
   185  	right := ToNumberOnly(inputR)
   186  
   187  	if left.Type() == types.Int {
   188  		if right.Type() == types.Int {
   189  			l := left.(values.Int)
   190  			r := right.(values.Int)
   191  
   192  			return l - r
   193  		}
   194  
   195  		if right.Type() == types.Float {
   196  			l := left.(values.Int)
   197  			r := right.(values.Float)
   198  
   199  			return values.Float(l) - r
   200  		}
   201  	}
   202  
   203  	if left.Type() == types.Float {
   204  		if right.Type() == types.Float {
   205  			l := left.(values.Float)
   206  			r := right.(values.Float)
   207  
   208  			return l - r
   209  		}
   210  
   211  		if right.Type() == types.Int {
   212  			l := left.(values.Float)
   213  			r := right.(values.Int)
   214  
   215  			return l - values.Float(r)
   216  		}
   217  	}
   218  
   219  	return values.ZeroInt
   220  }
   221  
   222  func Multiply(inputL, inputR core.Value) core.Value {
   223  	left := ToNumberOnly(inputL)
   224  	right := ToNumberOnly(inputR)
   225  
   226  	if left.Type() == types.Int {
   227  		if right.Type() == types.Int {
   228  			l := left.(values.Int)
   229  			r := right.(values.Int)
   230  
   231  			return l * r
   232  		}
   233  
   234  		if right.Type() == types.Float {
   235  			l := left.(values.Int)
   236  			r := right.(values.Float)
   237  
   238  			return values.Float(l) * r
   239  		}
   240  	}
   241  
   242  	if left.Type() == types.Float {
   243  		if right.Type() == types.Float {
   244  			l := left.(values.Float)
   245  			r := right.(values.Float)
   246  
   247  			return l * r
   248  		}
   249  
   250  		if right.Type() == types.Int {
   251  			l := left.(values.Float)
   252  			r := right.(values.Int)
   253  
   254  			return l * values.Float(r)
   255  		}
   256  	}
   257  
   258  	return values.ZeroInt
   259  }
   260  
   261  func Divide(inputL, inputR core.Value) core.Value {
   262  	left := ToNumberOnly(inputL)
   263  	right := ToNumberOnly(inputR)
   264  
   265  	if left.Type() == types.Int {
   266  		if right.Type() == types.Int {
   267  			l := values.Float(left.(values.Int))
   268  			r := values.Float(right.(values.Int))
   269  
   270  			if r == 0.0 {
   271  				panic("divide by zero")
   272  			}
   273  
   274  			return l / r
   275  		}
   276  
   277  		if right.Type() == types.Float {
   278  			l := values.Float(left.(values.Int))
   279  			r := right.(values.Float)
   280  
   281  			if r == 0.0 {
   282  				panic("divide by zero")
   283  			}
   284  
   285  			return l / r
   286  		}
   287  	}
   288  
   289  	if left.Type() == types.Float {
   290  		if right.Type() == types.Float {
   291  			l := left.(values.Float)
   292  			r := right.(values.Float)
   293  
   294  			if r == 0.0 {
   295  				panic("divide by zero")
   296  			}
   297  
   298  			return l / r
   299  		}
   300  
   301  		if right.Type() == types.Int {
   302  			l := left.(values.Float)
   303  			r := values.Float(right.(values.Int))
   304  
   305  			if r == 0.0 {
   306  				panic("divide by zero")
   307  			}
   308  
   309  			return l / r
   310  		}
   311  	}
   312  
   313  	return values.ZeroInt
   314  }
   315  
   316  func Modulus(inputL, inputR core.Value) core.Value {
   317  	left := ToNumberOnly(inputL)
   318  	right := ToNumberOnly(inputR)
   319  
   320  	if left.Type() == types.Int {
   321  		if right.Type() == types.Int {
   322  			l := left.(values.Int)
   323  			r := right.(values.Int)
   324  
   325  			return l % r
   326  		}
   327  
   328  		if right.Type() == types.Float {
   329  			l := left.(values.Int)
   330  			r := right.(values.Float)
   331  
   332  			return l % values.Int(r)
   333  		}
   334  	}
   335  
   336  	if left.Type() == types.Float {
   337  		if right.Type() == types.Float {
   338  			l := left.(values.Float)
   339  			r := right.(values.Float)
   340  
   341  			return values.Int(l) % values.Int(r)
   342  		}
   343  
   344  		if right.Type() == types.Int {
   345  			l := left.(values.Float)
   346  			r := right.(values.Int)
   347  
   348  			return values.Int(l) % r
   349  		}
   350  	}
   351  
   352  	return values.ZeroInt
   353  }
   354  
   355  func Increment(inputL, _ core.Value) core.Value {
   356  	left := ToNumberOnly(inputL)
   357  
   358  	if left.Type() == types.Int {
   359  		l := left.(values.Int)
   360  
   361  		return l + 1
   362  	}
   363  
   364  	if left.Type() == types.Float {
   365  		l := left.(values.Float)
   366  
   367  		return l + 1
   368  	}
   369  
   370  	return values.None
   371  }
   372  
   373  func Decrement(inputL, _ core.Value) core.Value {
   374  	left := ToNumberOnly(inputL)
   375  
   376  	if left.Type() == types.Int {
   377  		l := left.(values.Int)
   378  
   379  		return l - 1
   380  	}
   381  
   382  	if left.Type() == types.Float {
   383  		l := left.(values.Float)
   384  
   385  		return l - 1
   386  	}
   387  
   388  	return values.None
   389  }
   390  
   391  func Negative(value, _ core.Value) core.Value {
   392  	if value.Type() == types.Int {
   393  		return -value.(values.Int)
   394  	}
   395  
   396  	if value.Type() == types.Float {
   397  		return -value.(values.Float)
   398  	}
   399  
   400  	return value
   401  }
   402  
   403  func Positive(value, _ core.Value) core.Value {
   404  	if value.Type() == types.Int {
   405  		return +value.(values.Int)
   406  	}
   407  
   408  	if value.Type() == types.Float {
   409  		return +value.(values.Float)
   410  	}
   411  
   412  	return value
   413  }
   414  
   415  func ToBoolean(value, _ core.Value) core.Value {
   416  	return values.ToBoolean(value)
   417  }