main
Ziyang Hu 2 years ago
parent c9c7447bb8
commit a9417bdd8f

@ -246,10 +246,10 @@ pub trait Environment<T: AsRef<[u8]>> where Self: Sized {
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!() }
value::OP_AND => { todo!() }
value::OP_EQ => self.eq_values(args)?,
value::OP_NE => self.ne_values(args)?,
value::OP_OR => self.or_values(args)?,
value::OP_AND => self.and_values(args)?,
value::OP_MOD => { todo!() }
value::OP_GT => { todo!() }
value::OP_GE => { todo!() }
@ -334,6 +334,152 @@ pub trait Environment<T: AsRef<[u8]>> where Self: Sized {
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn eq_values<'a>(&self, args: Vec<Value<'a>>) -> 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_EQ.into(), vec![left, right])));
}
Ok((true, (left == right).into()))
}
fn ne_values<'a>(&self, args: Vec<Value<'a>>) -> 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_NE.into(), vec![left, right])));
}
Ok((true, (left != right).into()))
}
fn or_values<'a>(&self, args: Vec<Value<'a>>) -> Result<(bool, Value<'a>)> {
let res = args.into_iter().map(|v| self.partial_eval(v))
.try_fold(
(true, false, vec![]),
|(is_evaluated, has_null, mut collected), x| {
match x {
Ok((cur_eval, cur_val)) => {
if cur_eval {
match cur_val {
Value::Null => {
Ok((is_evaluated, true, collected))
}
Value::Bool(b) => if b {
Err(Ok((true, Value::Bool(true)))) // Early return on true
} else {
Ok((is_evaluated, has_null, collected))
},
_ => Err(Err(CozoError::InvalidArgument))
}
} else {
match cur_val {
Value::Null |
Value::Bool(_) |
Value::UInt(_) |
Value::Int(_) |
Value::Float(_) |
Value::Uuid(_) |
Value::EndSentinel |
Value::Text(_) => unreachable!(),
Value::List(_) |
Value::Dict(_) => Err(Err(CozoError::InvalidArgument)),
cur_val @ (Value::Variable(_) |
Apply(_, _)) => {
collected.push(cur_val);
Ok((false, has_null, collected))
}
}
}
}
Err(e) => Err(Err(e))
}
});
match res {
Ok((is_evaluated, has_null, mut unevaluated)) => {
if is_evaluated {
if has_null {
Ok((true, Value::Null))
} else {
Ok((true, Value::Bool(false)))
}
} else {
if has_null {
unevaluated.push(Value::Null);
}
Ok((false, Value::Apply(value::OP_OR.into(), unevaluated)))
}
}
Err(Ok(res)) => Ok(res),
Err(Err(e)) => Err(e)
}
}
fn and_values<'a>(&self, args: Vec<Value<'a>>) -> Result<(bool, Value<'a>)> {
let res = args.into_iter().map(|v| self.partial_eval(v))
.try_fold(
(true, false, vec![]),
|(is_evaluated, has_null, mut collected), x| {
match x {
Ok((cur_eval, cur_val)) => {
if cur_eval {
match cur_val {
Value::Null => {
Ok((is_evaluated, true, collected))
}
Value::Bool(b) => if b {
Ok((is_evaluated, has_null, collected))
} else {
Err(Ok((true, Value::Bool(false)))) // Early return on true
},
_ => Err(Err(CozoError::InvalidArgument))
}
} else {
match cur_val {
Value::Null |
Value::Bool(_) |
Value::UInt(_) |
Value::Int(_) |
Value::Float(_) |
Value::Uuid(_) |
Value::EndSentinel |
Value::Text(_) => unreachable!(),
Value::List(_) |
Value::Dict(_) => Err(Err(CozoError::InvalidArgument)),
cur_val @ (Value::Variable(_) |
Apply(_, _)) => {
collected.push(cur_val);
Ok((false, has_null, collected))
}
}
}
}
Err(e) => Err(Err(e))
}
});
match res {
Ok((is_evaluated, has_null, mut unevaluated)) => {
if is_evaluated {
if has_null {
Ok((true, Value::Null))
} else {
Ok((true, Value::Bool(true)))
}
} else {
if has_null {
unevaluated.push(Value::Null);
}
Ok((false, Value::Apply(value::OP_AND.into(), unevaluated)))
}
}
Err(Ok(res)) => Ok(res),
Err(Err(e)) => Err(e)
}
}
}
@ -570,4 +716,46 @@ mod tests {
env.run_definition(t).unwrap();
println!("{:?}", env.resolve("WorkInfo"));
}
}
}
// fn test_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// Ok(match exprs {
// [a] => {
// match self.visit_expr(a)? {
// Const(Null) => Const(Bool(true)),
// Const(_) => Const(Bool(false)),
// v => Apply(Op::IsNull, vec![v])
// }
// }
// _ => unreachable!()
// })
// }
//
// fn not_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// Ok(match exprs {
// [a] => {
// match self.visit_expr(a)? {
// Const(Null) => Const(Bool(false)),
// Const(_) => Const(Bool(true)),
// v => Apply(Op::IsNull, vec![v])
// }
// }
// _ => unreachable!()
// })
// }
// #[cfg(test)]
// mod tests {
// use super::*;
//
// #[test]
// fn operators() {
// let ev = Evaluator::new(DummyStorage {}).unwrap();
//
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("1/10+(-2+3)*4^5").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && false").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || false").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || null").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("null || true").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && null").unwrap()).unwrap());
// }
// }

@ -23,40 +23,6 @@
// }
// }
//
// fn eq_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// 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)) => Ok(Const(Bool(a == b))),
// (a, b) => Ok(Apply(Op::Eq, vec![a, b]))
// }
// }
// _ => unreachable!()
// }
// }
//
// fn ne_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// 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)) => Ok(Const(Bool(a != b))),
// (a, b) => Ok(Apply(Op::Neq, vec![a, b]))
// }
// }
// _ => unreachable!()
// }
// }
//
// fn gt_exprs<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// match exprs {
// [a, b] => {
@ -241,110 +207,6 @@
// })
// }
//
// fn test_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// Ok(match exprs {
// [a] => {
// match self.visit_expr(a)? {
// Const(Null) => Const(Bool(true)),
// Const(_) => Const(Bool(false)),
// v => Apply(Op::IsNull, vec![v])
// }
// }
// _ => unreachable!()
// })
// }
//
// fn not_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// Ok(match exprs {
// [a] => {
// match self.visit_expr(a)? {
// Const(Null) => Const(Bool(false)),
// Const(_) => Const(Bool(true)),
// v => Apply(Op::IsNull, vec![v])
// }
// }
// _ => unreachable!()
// })
// }
//
// fn or_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// let mut unevaluated = vec![];
// let mut has_null = false;
// for expr in exprs {
// match self.visit_expr(expr)? {
// Const(Bool(true)) => return Ok(Const(Bool(true))),
// Const(Bool(false)) => {}
// Const(Null) => { has_null = true }
// Const(_) => return Err(TypeError),
// Apply(Op::Or, vs) => {
// for el in vs {
// match el {
// Const(Null) => has_null = true,
// Const(_) => unreachable!(),
// v => unevaluated.push(v)
// }
// }
// }
// v => unevaluated.push(v)
// }
// }
// match (has_null, unevaluated.len()) {
// (true, 0) => Ok(Const(Null)),
// (false, 0) => Ok(Const(Bool(false))),
// (false, _) => Ok(Apply(Op::Or, unevaluated)),
// (true, _) => {
// unevaluated.push(Const(Null));
// Ok(Apply(Op::Or, unevaluated))
// }
// }
// }
//
// fn and_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result<Expr<'a>> {
// let mut unevaluated = vec![];
// let mut no_null = true;
// for expr in exprs {
// match self.visit_expr(expr)? {
// Const(Bool(false)) => return Ok(Const(Bool(false))),
// Const(Bool(true)) => {}
// Const(Null) => no_null = false,
// Const(_) => return Err(TypeError),
// Apply(Op::Or, vs) => {
// for el in vs {
// match el {
// Const(Null) => no_null = false,
// Const(_) => unreachable!(),
// v => unevaluated.push(v)
// }
// }
// }
// v => unevaluated.push(v)
// }
// }
// match (no_null, unevaluated.len()) {
// (true, 0) => Ok(Const(Bool(true))),
// (false, 0) => Ok(Const(Null)),
// (true, _) => Ok(Apply(Op::Add, unevaluated)),
// (false, _) => {
// unevaluated.push(Const(Null));
// Ok(Apply(Op::And, unevaluated))
// }
// }
// }
// }
//
// #[cfg(test)]
// mod tests {
// use super::*;
//
// #[test]
// fn operators() {
// let ev = Evaluator::new(DummyStorage {}).unwrap();
//
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("1/10+(-2+3)*4^5").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && false").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || false").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || null").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("null || true").unwrap()).unwrap());
// println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && null").unwrap()).unwrap());
// }
// }
Loading…
Cancel
Save