diff --git a/src/db/eval.rs b/src/db/eval.rs index 0df299fa..11dd7f8d 100644 --- a/src/db/eval.rs +++ b/src/db/eval.rs @@ -14,6 +14,8 @@ use crate::error::CozoError::UnexpectedDataKind; 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; @@ -240,10 +242,10 @@ pub trait Environment> where Self: Sized { Value::Apply(op, args) => { use crate::relation::value; Ok(match op.as_ref() { - value::OP_ADD => add_values(args)?, - value::OP_SUB => sub_values(args)?, - value::OP_MUL => { todo!() } - value::OP_DIV => { todo!() } + value::OP_ADD => self.add_values(args)?, + value::OP_SUB => self.sub_values(args)?, + value::OP_MUL => self.mul_values(args)?, + value::OP_DIV => self.div_values(args)?, value::OP_EQ => { todo!() } value::OP_NE => { todo!() } value::OP_OR => { todo!() } @@ -262,15 +264,79 @@ pub trait Environment> where Self: Sized { } } } -} -fn add_values(args: Vec) -> Result<(bool, Value)> { - todo!() -} -fn sub_values(args: Vec) -> Result<(bool, Value)> { - todo!() + 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())?; + 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, 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::Text(l), Value::Text(r)) => (true, (l.to_string() + r.as_ref()).into()), + (_, _) => return Err(CozoError::InvalidArgument) + }) + } + fn sub_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, 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()), + (_, _) => return Err(CozoError::InvalidArgument) + }) + } + fn mul_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, 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()), + (_, _) => return Err(CozoError::InvalidArgument) + }) + } + fn div_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, Apply(value::OP_ADD.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()), + (_, _) => return Err(CozoError::InvalidArgument) + }) + } } + pub struct MemoryEnv { root: BTreeMap, stack: Vec>, diff --git a/src/error.rs b/src/error.rs index e7d47737..05acb928 100644 --- a/src/error.rs +++ b/src/error.rs @@ -64,6 +64,9 @@ pub enum CozoError { // #[error("Database already closed")] // DatabaseClosed, + #[error("InvalidArgument")] + InvalidArgument, + #[error(transparent)] ParseInt(#[from] std::num::ParseIntError), diff --git a/src/eval.rs b/src/eval.rs index e9c784d6..15bdf9fd 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,275 +1,5 @@ -// use std::borrow::{Borrow, Cow}; -// use std::sync::Arc; -// use crate::ast::Expr; -// use crate::ast::Expr::*; -// use crate::error::Result; -// use crate::error::CozoError; -// use crate::error::CozoError::*; -// use crate::value::Value::*; -// use crate::ast::*; -// use crate::env::{Env, Environment, LayeredEnv}; -// use crate::storage::{DummyStorage, RocksStorage, Storage}; -// use crate::typing::Structured; -// -// pub struct Evaluator { -// pub env_stack: Vec, -// pub storage: S, -// } -// -// impl Env for Evaluator { -// fn define(&mut self, name: String, value: Structured) -> Option { -// None -// } -// -// fn define_new(&mut self, name: String, value: Structured) -> bool { -// false -// } -// -// fn resolve(&self, name: &str) -> Option> { -// None -// } -// -// fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { -// None -// } -// -// fn undef(&mut self, name: &str) -> Option { -// None -// } -// } -// -// impl Env for Evaluator { -// fn define(&mut self, name: String, value: Structured) -> Option { -// self.env_stack.last_mut().unwrap().define(name, value) -// } -// -// fn define_new(&mut self, name: String, value: Structured) -> bool { -// if self.env_stack.is_empty() { -// self.env_stack.push(Environment::default()); -// } -// self.env_stack.last_mut().unwrap().define_new(name, value) -// } -// -// fn resolve(&self, name: &str) -> Option> { -// let mut res = None; -// for item in self.env_stack.iter().rev() { -// res = item.resolve(name); -// if res.is_some() { -// return res; -// } -// } -// // Unwrap here because read() only fails if lock is poisoned -// let env = self.storage.root_env.read().expect("Root environment is poisoned"); -// env.resolve(name).map(|v| Cow::Owned(v.into_owned())) -// } -// -// fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { -// // Cannot obtain root elements this way -// let mut res = None; -// for item in self.env_stack.iter_mut().rev() { -// res = item.resolve_mut(name); -// if res.is_some() { -// return res; -// } -// } -// res -// } -// -// fn undef(&mut self, name: &str) -> Option { -// // Cannot undef root elements this way -// let mut res = None; -// for item in self.env_stack.iter_mut().rev() { -// res = item.undef(name); -// if res.is_some() { -// return res; -// } -// } -// res -// } -// } -// -// impl LayeredEnv for Evaluator { -// fn root_define(&mut self, name: String, value: Structured) -> Option { -// self.storage.root_env.write().expect("Root environment is poisoned") -// .define(name, value) -// } -// -// fn root_define_new(&mut self, name: String, value: Structured) -> bool { -// self.storage.root_env.write().expect("Root environment is poisoned") -// .define_new(name, value) -// } -// -// fn root_resolve(&self, name: &str) -> Option> { -// let env = self.storage.root_env.read().expect("Root environment is poisoned"); -// env.resolve(name).map(|v| Cow::Owned(v.into_owned())) -// } -// -// fn root_undef(&mut self, name: &str) -> Option { -// self.storage.root_env.write().expect("Root environment is poisoned") -// .undef(name) -// } -// } -// -// pub type EvaluatorWithStorage = Evaluator; -// pub type BareEvaluator = Evaluator; -// -// impl Evaluator { -// pub fn new(storage: S) -> Result { -// Ok(Self { -// env_stack: vec![Environment::default()], -// storage, -// }) -// } -// } -// -// -// impl<'a, S: Storage> ExprVisitor<'a, Result>> for Evaluator -// where Evaluator: Env { -// fn visit_expr(&self, ex: &Expr<'a>) -> Result> { -// match ex { -// Apply(op, args) => { -// match op { -// Op::Add => self.add_exprs(args), -// Op::Sub => self.sub_exprs(args), -// Op::Mul => self.mul_exprs(args), -// Op::Div => self.div_exprs(args), -// Op::Eq => self.eq_exprs(args), -// Op::Neq => self.ne_exprs(args), -// Op::Gt => self.gt_exprs(args), -// Op::Lt => self.lt_exprs(args), -// Op::Ge => self.ge_exprs(args), -// Op::Le => self.le_exprs(args), -// Op::Neg => self.negate_expr(args), -// Op::Minus => self.minus_expr(args), -// Op::Mod => self.mod_exprs(args), -// Op::Or => self.or_expr(args), -// Op::And => self.and_expr(args), -// Op::Coalesce => self.coalesce_exprs(args), -// Op::Pow => self.pow_exprs(args), -// Op::IsNull => self.test_null_expr(args), -// Op::NotNull => self.not_null_expr(args), -// Op::Call => unimplemented!(), -// } -// } -// Const(v) => Ok(Const(v.clone())), -// Expr::List(_) => { unimplemented!() } -// Expr::Dict(_, _) => { unimplemented!() } -// Ident(ident) => { -// let resolved = self.resolve(ident).ok_or(UndefinedParam)?; -// match resolved.borrow() { -// Structured::Value(v) => { -// Ok(Const(v.clone())) -// } -// _ => return Err(ValueRequired) -// } -// } -// } -// } -// } -// // impl Evaluator // where Evaluator: Env { -// fn add_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)); -// } -// Ok(Const(match (a, b) { -// (Const(a), Const(b)) => { -// match (a, b) { -// (Int(va), Int(vb)) => Int(va + vb), -// (Float(va), Int(vb)) => Float(va + vb as f64), -// (Int(va), Float(vb)) => Float(va as f64 + vb), -// (Float(va), Float(vb)) => Float(va + vb), -// (Text(va), Text(vb)) => -// Text(Arc::new(Cow::Owned(va.clone().to_string() + &vb))), -// (_, _) => return Err(CozoError::TypeError) -// } -// } -// (a, b) => return Ok(Apply(Op::Add, vec![a, b])) -// })) -// } -// _ => unreachable!() -// } -// } -// -// fn sub_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)); -// } -// Ok(Const(match (a, b) { -// (Const(a), Const(b)) => { -// match (a, b) { -// (Int(va), Int(vb)) => Int(va - vb), -// (Float(va), Int(vb)) => Float(va - vb as f64), -// (Int(va), Float(vb)) => Float(va as f64 - vb), -// (Float(va), Float(vb)) => Float(va - vb), -// (_, _) => return Err(CozoError::TypeError) -// } -// } -// (a, b) => return Ok(Apply(Op::Sub, vec![a, b])) -// })) -// } -// _ => unreachable!() -// } -// } -// -// fn mul_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)); -// } -// Ok(Const(match (a, b) { -// (Const(a), Const(b)) => { -// match (a, b) { -// (Int(va), Int(vb)) => Int(va * vb), -// (Float(va), Int(vb)) => Float(va * vb as f64), -// (Int(va), Float(vb)) => Float(va as f64 * vb), -// (Float(va), Float(vb)) => Float(va * vb), -// (_, _) => return Err(CozoError::TypeError) -// } -// } -// (a, b) => return Ok(Apply(Op::Mul, vec![a, b])) -// })) -// } -// _ => unreachable!() -// } -// } -// -// fn div_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)); -// } -// Ok(Const(match (a, b) { -// (Const(a), Const(b)) => { -// match (a, b) { -// (Int(va), Int(vb)) => Float(va as f64 / vb as f64), -// (Float(va), Int(vb)) => Float(va / vb as f64), -// (Int(va), Float(vb)) => Float(va as f64 / vb), -// (Float(va), Float(vb)) => Float(va / vb), -// (_, _) => return Err(CozoError::TypeError) -// } -// } -// (a, b) => return Ok(Apply(Op::Div, vec![a, b])) -// })) -// } -// _ => unreachable!() -// } -// } // // fn mod_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result> { // match exprs {