From 731f4a88a736f92d49d55f3fed176ec207425681 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Wed, 27 Apr 2022 18:40:27 +0800 Subject: [PATCH] complete first batch of operators --- src/db/eval.rs | 125 +++++++++++++++++++++++++++++++++++++++++-------- src/eval.rs | 90 ----------------------------------- 2 files changed, 105 insertions(+), 110 deletions(-) delete mode 100644 src/eval.rs diff --git a/src/db/eval.rs b/src/db/eval.rs index bac2d64e..9a6444b0 100644 --- a/src/db/eval.rs +++ b/src/db/eval.rs @@ -15,7 +15,6 @@ use crate::relation::data::DataKind; use crate::parser::Rule; use crate::parser::text_identifier::build_name_in_def; use crate::relation::value; -use crate::relation::value::Value::Apply; pub trait Environment> where Self: Sized { fn get_next_storage_id(&mut self, in_root: bool) -> Result; @@ -255,16 +254,47 @@ pub trait Environment> where Self: Sized { value::OP_GE => self.ge_values(args)?, value::OP_LT => self.lt_values(args)?, value::OP_LE => self.le_values(args)?, - value::OP_POW => { todo!() } - value::OP_COALESCE => { todo!() } - value::OP_NEGATE => { todo!() } - value::OP_MINUS => { todo!() } + value::OP_POW => self.pow_values(args)?, + value::OP_COALESCE => self.coalesce_values(args)?, + value::OP_NEGATE => self.negate_values(args)?, + value::OP_MINUS => self.minus_values(args)?, _ => { todo!() } }) } } } + fn coalesce_values<'a>(&self, args: Vec>) -> Result<(bool, Value<'a>)> { + let res = args.into_iter().try_fold(vec![], |mut accum, cur| { + match self.partial_eval(cur) { + Ok((ev, cur)) => { + if ev { + if cur == Value::Null { + Ok(accum) + } else { + Err(Ok(cur)) + } + } else { + accum.push(cur); + Ok(accum) + } + } + Err(e) => Err(Err(e)) + } + }); + match res { + Ok(accum) => { + match accum.len() { + 0 => Ok((true, Value::Null)), + 1 => Ok((false, accum.into_iter().next().unwrap())), + _ => Ok((false, Value::Apply(value::OP_COALESCE.into(), accum))) + } + } + Err(Ok(v)) => Ok((true, v)), + Err(Err(e)) => Err(e) + } + } + fn add_values<'a>(&self, args: Vec>) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap())?; @@ -273,12 +303,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_ADD.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_ADD.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l + r).into()), (Value::Float(l), Value::Int(r)) => (true, (l + (r as f64)).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) + r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l.into_inner() + r.into_inner()).into()), (Value::Text(l), Value::Text(r)) => (true, (l.to_string() + r.as_ref()).into()), (_, _) => return Err(CozoError::InvalidArgument) }) @@ -291,12 +322,60 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_SUB.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_SUB.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l - r).into()), (Value::Float(l), Value::Int(r)) => (true, (l - (r as f64)).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) - r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l.into_inner() - r.into_inner()).into()), + (_, _) => return Err(CozoError::InvalidArgument) + }) + } + fn minus_values<'a>(&self, args: Vec>) -> Result<(bool, Value<'a>)> { + let mut args = args.into_iter(); + let (le, left) = self.partial_eval(args.next().unwrap())?; + if left == Value::Null { + return Ok((true, Value::Null)); + } + if !le { + return Ok((false, Value::Apply(value::OP_MINUS.into(), vec![left]))); + } + Ok(match left { + Value::Int(l) => (true, (-l).into()), + Value::Float(l) => (true, (-l).into()), + _ => return Err(CozoError::InvalidArgument) + }) + } + fn negate_values<'a>(&self, args: Vec>) -> Result<(bool, Value<'a>)> { + let mut args = args.into_iter(); + let (le, left) = self.partial_eval(args.next().unwrap())?; + if left == Value::Null { + return Ok((true, Value::Null)); + } + if !le { + return Ok((false, Value::Apply(value::OP_NEGATE.into(), vec![left]))); + } + Ok(match left { + Value::Bool(l) => (true, (!l).into()), + _ => return Err(CozoError::InvalidArgument) + }) + } + fn pow_values<'a>(&self, args: Vec>) -> Result<(bool, Value<'a>)> { + let mut args = args.into_iter(); + let (le, left) = self.partial_eval(args.next().unwrap())?; + let (re, right) = self.partial_eval(args.next().unwrap())?; + if left == Value::Null || right == Value::Null { + return Ok((true, Value::Null)); + } + if !le || !re { + return Ok((false, Value::Apply(value::OP_POW.into(), vec![left, right]))); + } + Ok(match (left, right) { + (Value::Int(l), Value::Int(r)) => (true, ((l as f64).powf(r as f64)).into()), + (Value::Float(l), Value::Int(r)) => (true, ((l.into_inner()).powf(r as f64)).into()), + (Value::Int(l), Value::Float(r)) => (true, ((l as f64).powf(r.into_inner())).into()), + (Value::Float(l), Value::Float(r)) => (true, ((l.into_inner()).powf(r.into_inner())).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -308,12 +387,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_GT.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_GT.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l > r).into()), (Value::Float(l), Value::Int(r)) => (true, (l > (r as f64).into()).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) > r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l > r).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -325,12 +405,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_LT.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_LT.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l < r).into()), (Value::Float(l), Value::Int(r)) => (true, (l < (r as f64).into()).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) < r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l < r).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -342,12 +423,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_GE.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_GE.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l >= r).into()), (Value::Float(l), Value::Int(r)) => (true, (l >= (r as f64).into()).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) >= r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l >= r).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -359,12 +441,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_GE.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_GE.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l <= r).into()), (Value::Float(l), Value::Int(r)) => (true, (l <= (r as f64).into()).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) <= r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l <= r).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -376,7 +459,7 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_MOD.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_MOD.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l % r).into()), @@ -391,12 +474,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_MUL.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_MUL.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l * r).into()), (Value::Float(l), Value::Int(r)) => (true, (l * (r as f64)).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) * r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l.into_inner() * r.into_inner()).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -408,12 +492,13 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_DIV.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_DIV.into(), vec![left, right]))); } Ok(match (left, right) { (Value::Int(l), Value::Int(r)) => (true, (l as f64 / r as f64).into()), (Value::Float(l), Value::Int(r)) => (true, (l / (r as f64)).into()), (Value::Int(l), Value::Float(r)) => (true, ((l as f64) / r.into_inner()).into()), + (Value::Float(l), Value::Float(r)) => (true, (l.into_inner() / r.into_inner()).into()), (_, _) => return Err(CozoError::InvalidArgument) }) } @@ -425,7 +510,7 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_EQ.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_EQ.into(), vec![left, right]))); } Ok((true, (left == right).into())) } @@ -437,7 +522,7 @@ pub trait Environment> where Self: Sized { return Ok((true, Value::Null)); } if !le || !re { - return Ok((false, Apply(value::OP_NE.into(), vec![left, right]))); + return Ok((false, Value::Apply(value::OP_NE.into(), vec![left, right]))); } Ok((true, (left != right).into())) } @@ -473,7 +558,7 @@ pub trait Environment> where Self: Sized { Value::List(_) | Value::Dict(_) => Err(Err(CozoError::InvalidArgument)), cur_val @ (Value::Variable(_) | - Apply(_, _)) => { + Value::Apply(_, _)) => { collected.push(cur_val); Ok((false, has_null, collected)) } @@ -534,7 +619,7 @@ pub trait Environment> where Self: Sized { Value::List(_) | Value::Dict(_) => Err(Err(CozoError::InvalidArgument)), cur_val @ (Value::Variable(_) | - Apply(_, _)) => { + Value::Apply(_, _)) => { collected.push(cur_val); Ok((false, has_null, collected)) } @@ -807,7 +892,7 @@ mod tests { // match self.visit_expr(a)? { // Const(Null) => Const(Bool(true)), // Const(_) => Const(Bool(false)), -// v => Apply(Op::IsNull, vec![v]) +// v => Value::Apply(Op::IsNull, vec![v]) // } // } // _ => unreachable!() @@ -820,7 +905,7 @@ mod tests { // match self.visit_expr(a)? { // Const(Null) => Const(Bool(false)), // Const(_) => Const(Bool(true)), -// v => Apply(Op::IsNull, vec![v]) +// v => Value::Apply(Op::IsNull, vec![v]) // } // } // _ => unreachable!() diff --git a/src/eval.rs b/src/eval.rs deleted file mode 100644 index 016322d0..00000000 --- a/src/eval.rs +++ /dev/null @@ -1,90 +0,0 @@ -// impl Evaluator -// where Evaluator: Env { -// -// fn pow_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { -// match exprs { -// [a, b] => { -// let a = self.visit_expr(a)?; -// let b = self.visit_expr(b)?; -// if a == Const(Null) || b == Const(Null) { -// return Ok(Const(Null)); -// } -// match (a, b) { -// (Const(a), Const(b)) => { -// match (a, b) { -// (Int(a), Int(b)) => Ok(Const(Float((a as f64).powf(b as f64)))), -// (Float(a), Int(b)) => Ok(Const(Float(a.powi(b as i32)))), -// (Int(a), Float(b)) => Ok(Const(Float((a as f64).powf(b)))), -// (Float(a), Float(b)) => Ok(Const(Float(a.powf(b)))), -// (_, _) => Err(CozoError::TypeError) -// } -// } -// (a, b) => Ok(Apply(Op::Pow, vec![a, b])) -// } -// } -// _ => unreachable!() -// } -// } -// -// fn coalesce_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { -// match exprs { -// [a, b] => { -// let a = self.visit_expr(a)?; -// let b = self.visit_expr(b)?; -// if a == Const(Null) { -// return Ok(b); -// } -// if b == Const(Null) { -// return Ok(a); -// } -// if let a @ Const(_) = a { -// return Ok(a); -// } -// return Ok(Apply(Op::Coalesce, vec![a, b])); -// } -// _ => unreachable!() -// } -// } -// -// fn negate_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { -// Ok(match exprs { -// [a] => { -// match self.visit_expr(a)? { -// Const(Null) => Const(Null), -// Const(Bool(b)) => Const(Bool(!b)), -// Const(_) => return Err(TypeError), -// Apply(Op::Neg, v) => v.into_iter().next().unwrap(), -// Apply(Op::IsNull, v) => Apply(Op::NotNull, v), -// Apply(Op::NotNull, v) => Apply(Op::IsNull, v), -// Apply(Op::Eq, v) => Apply(Op::Neq, v), -// Apply(Op::Neq, v) => Apply(Op::Eq, v), -// Apply(Op::Gt, v) => Apply(Op::Le, v), -// Apply(Op::Ge, v) => Apply(Op::Lt, v), -// Apply(Op::Le, v) => Apply(Op::Gt, v), -// Apply(Op::Lt, v) => Apply(Op::Ge, v), -// v => Apply(Op::Neg, vec![v]) -// } -// } -// _ => unreachable!() -// }) -// } -// -// fn minus_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { -// Ok(match exprs { -// [a] => { -// match self.visit_expr(a)? { -// Const(Null) => Const(Null), -// Const(Int(i)) => Const(Int(-i)), -// Const(Float(f)) => Const(Float(-f)), -// Const(_) => return Err(TypeError), -// Apply(Op::Minus, v) => v.into_iter().next().unwrap(), -// v => Apply(Op::Minus, vec![v]) -// } -// } -// _ => unreachable!() -// }) -// } -// -// -// } -//