refactor expr
parent
3e5ca6c790
commit
64c1ba3263
@ -1,332 +1,199 @@
|
||||
use crate::data::eval::EvalError;
|
||||
use crate::data::op::{extract_two_args, Op};
|
||||
use crate::data::value::Value;
|
||||
use anyhow::Result;
|
||||
use crate::data::expr::BuiltinFn;
|
||||
|
||||
pub(crate) struct OpAdd;
|
||||
|
||||
impl OpAdd {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l + r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l + (r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) + r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() + r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_ADD: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_ADD,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_add
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_ADD: &str = "+";
|
||||
|
||||
impl Op for OpAdd {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_ADD
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_add<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l + r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l + (*r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) + r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() + r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_ADD.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpSub;
|
||||
|
||||
impl OpSub {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l - r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l - (r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) - r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() - r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_SUB: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_SUB,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_sub
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_SUB: &str = "-";
|
||||
|
||||
impl Op for OpSub {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_SUB
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_sub<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l - r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l - (*r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) - r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() - r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_SUB.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpMul;
|
||||
|
||||
impl OpMul {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l * r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l * (r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) * r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() * r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_MUL: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_MUL,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_mul
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_MUL: &str = "*";
|
||||
|
||||
impl Op for OpMul {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_MUL
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_mul<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l * r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l * (*r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) * r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() * r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_MUL.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpDiv;
|
||||
|
||||
impl OpDiv {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l as f64 / r as f64).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l / (r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) / r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() / r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_DIV: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_DIV,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_div
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_DIV: &str = "/";
|
||||
|
||||
impl Op for OpDiv {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_DIV
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_div<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (*l as f64 / *r as f64).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l / (*r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) / r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l.into_inner() / r.into_inner()).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_DIV.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpMod;
|
||||
|
||||
impl OpMod {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l % r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_MOD: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_MOD,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_mod
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_MOD: &str = "%";
|
||||
|
||||
impl Op for OpMod {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_MOD
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_mod<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l % r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_MOD.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpPow;
|
||||
|
||||
impl OpPow {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => ((l as f64).powf(r as f64)).into(),
|
||||
(Value::Float(l), Value::Int(r)) => ((l.into_inner()).powf(r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64).powf(r.into_inner())).into(),
|
||||
(Value::Float(l), Value::Float(r)) => ((l.into_inner()).powf(r.into_inner())).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_POW: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_POW,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_pow
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_POW: &str = "**";
|
||||
|
||||
impl Op for OpPow {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_POW
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct OpMinus;
|
||||
|
||||
impl OpMinus {
|
||||
pub(crate) fn eval_one_non_null<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
|
||||
match arg {
|
||||
Value::Int(i) => Ok((-i).into()),
|
||||
Value::Float(i) => Ok((-i).into()),
|
||||
v => Err(
|
||||
EvalError::OpTypeMismatch(self.name().to_string(), vec![v.into_static()]).into(),
|
||||
),
|
||||
pub(crate) fn op_pow<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => ((*l as f64).powf(*r as f64)).into(),
|
||||
(Value::Float(l), Value::Int(r)) => ((l.into_inner()).powf(*r as f64)).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64).powf(r.into_inner())).into(),
|
||||
(Value::Float(l), Value::Float(r)) => ((l.into_inner()).powf(r.into_inner())).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_POW.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) const OP_MINUS: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_MINUS,
|
||||
arity: Some(1),
|
||||
non_null_args: true,
|
||||
func: op_mul
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_MINUS: &str = "--";
|
||||
|
||||
impl Op for OpMinus {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(1)
|
||||
}
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_MINUS
|
||||
}
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
self.eval_one_non_null(args.into_iter().next().unwrap())
|
||||
pub(crate) fn op_minus<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let arg = args.into_iter().next().unwrap();
|
||||
match arg {
|
||||
Value::Int(i) => Ok((-i).into()),
|
||||
Value::Float(i) => Ok((-i).into()),
|
||||
v => {
|
||||
Err(EvalError::OpTypeMismatch(NAME_OP_MINUS.to_string(), vec![v.clone().into_static()]).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,278 +1,162 @@
|
||||
use crate::data::eval::EvalError;
|
||||
use crate::data::op::{extract_two_args, Op};
|
||||
use crate::data::expr::BuiltinFn;
|
||||
use crate::data::value::Value;
|
||||
use anyhow::Result;
|
||||
|
||||
pub(crate) struct OpEq;
|
||||
|
||||
impl OpEq {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
Ok((left == right).into())
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_EQ: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_EQ,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_eq,
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_EQ: &str = "==";
|
||||
|
||||
impl Op for OpEq {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_EQ
|
||||
}
|
||||
pub(crate) fn op_eq<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
Ok((left == right).into())
|
||||
}
|
||||
|
||||
pub(crate) struct OpNe;
|
||||
|
||||
impl OpNe {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
Ok((left != right).into())
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_NE: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_NE,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_ne,
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_NE: &str = "!=";
|
||||
|
||||
impl Op for OpNe {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
pub(crate) fn op_ne<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_NE
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
Ok((left != right).into())
|
||||
}
|
||||
|
||||
pub(crate) struct OpGt;
|
||||
|
||||
impl OpGt {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l > r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l > (r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) > r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l > r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l > r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_GT: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_GT,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_gt,
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_GT: &str = ">";
|
||||
|
||||
impl Op for OpGt {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_GT
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_gt<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l > r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (*l > (*r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) > r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l > r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l > r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_GT.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpGe;
|
||||
|
||||
impl OpGe {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l >= r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l >= (r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) >= r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l >= r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l >= r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_GE: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_GE,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_ge,
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_GE: &str = ">=";
|
||||
|
||||
impl Op for OpGe {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_GE
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_ge<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l >= r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (*l >= (*r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) >= r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l >= r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l >= r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_GE.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpLt;
|
||||
|
||||
impl OpLt {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l < r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l < (r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) < r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l < r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l < r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_LT: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_LT,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_lt,
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_LT: &str = "<";
|
||||
|
||||
impl Op for OpLt {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_LT
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_lt<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l < r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (*l < (*r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) < r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l < r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l < r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_LT.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) struct OpLe;
|
||||
|
||||
impl OpLe {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l <= r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (l <= (r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((l as f64) <= r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l <= r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l <= r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
pub(crate) const OP_LE: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_LE,
|
||||
arity: Some(2),
|
||||
non_null_args: true,
|
||||
func: op_le,
|
||||
};
|
||||
|
||||
pub(crate) const NAME_OP_LE: &str = "<=";
|
||||
|
||||
impl Op for OpLe {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_LE
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
pub(crate) fn op_le<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut args = args.into_iter();
|
||||
let left = args.next().unwrap();
|
||||
let right = args.next().unwrap();
|
||||
|
||||
let res: Value = match (left, right) {
|
||||
(Value::Int(l), Value::Int(r)) => (l <= r).into(),
|
||||
(Value::Float(l), Value::Int(r)) => (*l <= (*r as f64).into()).into(),
|
||||
(Value::Int(l), Value::Float(r)) => ((*l as f64) <= r.into_inner()).into(),
|
||||
(Value::Float(l), Value::Float(r)) => (l <= r).into(),
|
||||
(Value::Text(l), Value::Text(r)) => (l <= r).into(),
|
||||
(l, r) => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_LE.to_string(),
|
||||
vec![l.clone().into_static(), r.clone().into_static()],
|
||||
)
|
||||
.into());
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
use crate::data::op::Op;
|
||||
use crate::data::value::Value;
|
||||
|
||||
pub(crate) struct SeqNext;
|
||||
|
||||
const NAME_OP_SEQ_NEXT: &str = "seq_next";
|
||||
|
||||
impl Op for SeqNext {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(1)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_SEQ_NEXT
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, _args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -1,52 +1,31 @@
|
||||
use crate::data::eval::EvalError;
|
||||
use crate::data::op::{extract_two_args, Op};
|
||||
use crate::data::value::Value;
|
||||
use anyhow::Result;
|
||||
use crate::data::expr::BuiltinFn;
|
||||
|
||||
pub(crate) struct OpStrCat;
|
||||
pub(crate) const OP_STR_CAT: BuiltinFn = BuiltinFn {
|
||||
name: NAME_OP_STR_CAT,
|
||||
arity: None,
|
||||
non_null_args: true,
|
||||
func: op_str_cat
|
||||
};
|
||||
|
||||
impl OpStrCat {
|
||||
pub(crate) fn eval_two_non_null<'a>(
|
||||
&self,
|
||||
left: Value<'a>,
|
||||
right: Value<'a>,
|
||||
) -> Result<Value<'a>> {
|
||||
match (left, right) {
|
||||
(Value::Text(l), Value::Text(r)) => {
|
||||
let mut l = l.into_owned();
|
||||
l += r.as_ref();
|
||||
Ok(l.into())
|
||||
pub(crate) const NAME_OP_STR_CAT: &str = "++";
|
||||
pub(crate) fn op_str_cat<'a>(args: &[Value<'a>]) -> Result<Value<'a>> {
|
||||
let mut ret = String::new();
|
||||
for arg in args {
|
||||
match arg {
|
||||
Value::Text(t) => {
|
||||
ret += t.as_ref();
|
||||
}
|
||||
_ => {
|
||||
return Err(EvalError::OpTypeMismatch(
|
||||
NAME_OP_STR_CAT.to_string(),
|
||||
args.iter().cloned().map(|v| v.into_static()).collect(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
(l, r) => Err(EvalError::OpTypeMismatch(
|
||||
self.name().to_string(),
|
||||
vec![l.into_static(), r.into_static()],
|
||||
)
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const NAME_OP_STR_CAT: &str = "++";
|
||||
|
||||
impl Op for OpStrCat {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(2)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_STR_CAT
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
let (left, right) = extract_two_args(args);
|
||||
self.eval_two_non_null(left, right)
|
||||
}
|
||||
Ok(ret.into())
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
use crate::data::op::Op;
|
||||
use crate::data::value::Value;
|
||||
|
||||
pub(crate) struct OpGenUuidV1;
|
||||
|
||||
const NAME_OP_GEN_UUID_V1: &str = "gen_uuid_v1";
|
||||
|
||||
impl Op for OpGenUuidV1 {
|
||||
fn arity(&self) -> Option<usize> {
|
||||
Some(0)
|
||||
}
|
||||
|
||||
fn has_side_effect(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
NAME_OP_GEN_UUID_V1
|
||||
}
|
||||
|
||||
fn non_null_args(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn eval<'a>(&self, _args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue