totally misunderstood rust's "polymorphism"

main
Ziyang Hu 2 years ago
parent f6b58e460f
commit c0f2618278

@ -0,0 +1,77 @@
use crate::data::expr::StaticExpr;
use crate::data::tuple_set::TupleSet;
use crate::data::value::{StaticValue, Value};
pub(crate) trait Algebra {
fn get_iterator(&self) -> TupleSource;
fn get_filter(&self) -> Filter;
}
type AlgebraItem = Box<dyn Algebra>;
type AlgebraPair = (Box<dyn Algebra>, Box<dyn Algebra>);
#[derive(Clone, Debug)]
pub(crate) struct Filter {
pub(crate) filter: Option<StaticExpr>,
pub(crate) skip: Option<usize>,
pub(crate) take: Option<usize>,
}
impl Default for Filter {
fn default() -> Self {
Self {
filter: None,
skip: None,
take: None,
}
}
}
type TupleSource = Box<dyn Iterator<Item=TupleSet>>;
// pub(crate) struct Source(TupleSource);
pub(crate) struct Edge(Filter);
pub(crate) struct Node(Filter);
pub(crate) struct InnerJoin(Filter, AlgebraPair);
pub(crate) struct LeftJoin(Filter, AlgebraPair);
pub(crate) struct Cartesian(Filter, AlgebraPair);
pub(crate) struct LeftCartesian(Filter, AlgebraPair);
pub(crate) struct Intersection(Filter, AlgebraPair);
pub(crate) struct Difference(Filter, AlgebraPair);
pub(crate) struct Selection(Filter, AlgebraItem);
pub(crate) struct Sort(Filter, AlgebraItem);
// Group
// Window
// Materialize
// Walk
// WalkRepeat
// Values
pub(crate) struct Select {
algebra: AlgebraItem,
}
pub(crate) struct Update {
algebra: AlgebraItem,
}
pub(crate) struct Insert {
algebra: AlgebraItem,
upsert: bool,
}
pub(crate) struct Delete {
algebra: AlgebraItem,
}

@ -169,30 +169,29 @@ impl<'a> Expr<'a> {
n if n == OpCoalesce.name() => partial_eval_coalesce(ctx, args)?,
_ => {
let mut has_unevaluated = false;
let mut has_null = false;
let args = args
.into_iter()
.map(|v| {
let v = v.partial_eval(ctx);
if !matches!(v, Ok(Expr::Const(_))) {
has_unevaluated = true;
} else if matches!(v, Ok(Expr::Const(Value::Null))) {
has_null = true;
}
v
})
.collect::<Result<Vec<_>>>()?;
let non_null_args_fn = op.non_null_args();
let mut eval_args = Vec::with_capacity(args.len());
for v in args {
let v = v.partial_eval(ctx)?;
if !matches!(v, Expr::Const(_)) {
has_unevaluated = true;
} else if non_null_args_fn && matches!(v, Expr::Const(Value::Null)) {
return Ok(Expr::Const(Value::Null));
} else {
eval_args.push(v);
}
}
if has_unevaluated {
Expr::Apply(op, args)
Expr::Apply(op, eval_args)
} else {
let args = args
let args = eval_args
.into_iter()
.map(|v| match v {
Expr::Const(v) => v,
_ => unreachable!(),
})
.collect();
op.eval(has_null, args).map(Expr::Const)?
op.eval(args).map(Expr::Const)?
}
}
}
@ -213,10 +212,7 @@ impl<'a> Expr<'a> {
partial_eval_if_expr(ctx, cond, if_part, else_part)?
}
Expr::SwitchExpr(args) => partial_eval_switch_expr(ctx, args)?,
Expr::ApplyZero(_)
| Expr::ApplyOne(_, _)
| Expr::ApplyTwo(_, _)
| Expr::Add(_)
Expr::Add(_)
| Expr::Sub(_)
| Expr::Mul(_)
| Expr::Div(_)
@ -296,17 +292,10 @@ impl<'a> Expr<'a> {
}
arg
}
_ => match op.arity() {
Some(0) => Expr::ApplyZero(op),
Some(1) => Expr::ApplyOne(op, args.into_iter().next().unwrap().into()),
Some(2) => {
let mut args = args.into_iter();
let left = args.next().unwrap();
let right = args.next().unwrap();
Expr::ApplyTwo(op, (left, right).into())
}
_ => Expr::Apply(op, args.into_iter().map(|v| v.optimize_ops()).collect()),
},
_ => Expr::Apply(
op,
args.into_iter().map(|v| v.optimize_ops()).collect(),
),
},
Expr::ApplyAgg(op, a_args, args) => Expr::ApplyAgg(
op,
@ -335,9 +324,6 @@ impl<'a> Expr<'a> {
| Expr::Variable(_)
| Expr::TableCol(_, _)
| Expr::TupleSetIdx(_)
| Expr::ApplyZero(_)
| Expr::ApplyOne(_, _)
| Expr::ApplyTwo(_, _)
| Expr::Add(_)
| Expr::Sub(_)
| Expr::Mul(_)
@ -379,53 +365,18 @@ impl<'a> Expr<'a> {
Expr::Variable(v) => return Err(EvalError::UnresolvedVariable(v.clone())),
Expr::TableCol(tid, cid) => return Err(EvalError::UnresolveTableCol(*tid, *cid)),
Expr::TupleSetIdx(idx) => ctx.resolve(idx)?.clone(),
Expr::Apply(op, vals) => {
let (has_null, args) = vals.iter().try_fold(
(false, Vec::with_capacity(vals.len())),
|(has_null, mut acc), v| {
v.row_eval(ctx).map(|v| match v {
Value::Null => {
acc.push(Value::Null);
(true, acc)
}
v => {
acc.push(v);
(has_null, acc)
}
})
},
)?;
op.eval(has_null, args)?
}
Expr::ApplyZero(op) => op.eval_zero()?,
Expr::ApplyOne(op, arg) => {
let arg = arg.row_eval(ctx)?;
if op.non_null_args() {
if arg == Value::Null {
Value::Null
Expr::Apply(op, args) => {
let mut eval_args = Vec::with_capacity(args.len());
let op_non_null_args = op.non_null_args();
for v in args {
let v = v.row_eval(ctx)?;
if op_non_null_args && v == Value::Null {
return Ok(Value::Null)
} else {
op.eval_one_non_null(arg)?
}
} else {
op.eval_one(arg)?
}
}
Expr::ApplyTwo(op, args) => {
if op.non_null_args() {
let left = args.as_ref().0.row_eval(ctx)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = args.as_ref().0.row_eval(ctx)?;
if right == Value::Null {
return Ok(Value::Null);
eval_args.push(v);
}
op.eval_two_non_null(left, right)?
} else {
let left = args.as_ref().0.row_eval(ctx)?;
let right = args.as_ref().0.row_eval(ctx)?;
op.eval_two(left, right)?
}
op.eval(eval_args)?
}
Expr::ApplyAgg(_, _, _) => {
todo!()
@ -646,6 +597,8 @@ mod tests {
dbg!(str2expr("switch 1 {2 => '2', 0 => '3', .. => 'x'}")?.partial_eval(&())?);
dbg!(str2expr("switch 3 {2 => '2', 1+2 => '3', .. => 'x'}")?.row_eval(&())?);
dbg!(str2expr("switch 3 {2 => '2', 1+2 => '3', .. => 'x'}")?.partial_eval(&())?);
dbg!(str2expr("null.is_null()")?.row_eval(&())?);
dbg!(str2expr("null.is_null()")?.partial_eval(&())?);
Ok(())
}

@ -38,9 +38,6 @@ pub(crate) enum Expr<'a> {
IfExpr(Box<(Expr<'a>, Expr<'a>, Expr<'a>)>),
SwitchExpr(Vec<(Expr<'a>, Expr<'a>)>),
// optimized
ApplyZero(Arc<dyn Op + Send + Sync>),
ApplyOne(Arc<dyn Op + Send + Sync>, Box<Expr<'a>>),
ApplyTwo(Arc<dyn Op + Send + Sync>, Box<(Expr<'a>, Expr<'a>)>),
Add(Box<(Expr<'a>, Expr<'a>)>),
Sub(Box<(Expr<'a>, Expr<'a>)>),
Mul(Box<(Expr<'a>, Expr<'a>)>),
@ -103,15 +100,6 @@ impl<'a> Debug for Expr<'a> {
.collect::<Vec<_>>()
.join(" ")
),
Expr::ApplyZero(op) => write!(f, "({})", op.name()),
Expr::ApplyOne(op, arg) => write!(f, "({} {:?})", op.name(), arg),
Expr::ApplyTwo(op, args) => write!(
f,
"({} {:?} {:?})",
op.name(),
args.as_ref().0,
args.as_ref().1
),
Expr::Add(args) => write!(f, "(`+ {:?} {:?})", args.as_ref().0, args.as_ref().1),
Expr::Sub(args) => write!(f, "(`- {:?} {:?})", args.as_ref().0, args.as_ref().1),
Expr::Mul(args) => write!(f, "(`* {:?} {:?})", args.as_ref().0, args.as_ref().1),
@ -379,12 +367,6 @@ impl<'a> From<Expr<'a>> for Value<'a> {
]
.into(),
),
Expr::ApplyZero(op) => build_tagged_value(
"Apply",
vec![Value::from(op.name().to_string()), Value::List(vec![])].into(),
),
Expr::ApplyOne(op, arg) => build_value_from_uop(op.name(), *arg),
Expr::ApplyTwo(op, args) => build_value_from_binop(op.name(), *args),
Expr::Add(arg) => build_value_from_binop(OpAdd.name(), *arg),
Expr::Sub(arg) => build_value_from_binop(OpSub.name(), *arg),
Expr::Mul(arg) => build_value_from_binop(OpMul.name(), *arg),

@ -1,8 +1,5 @@
use crate::data::expr::Expr;
use crate::data::op::{
Op, OpAdd, OpAnd, OpCoalesce, OpConcat, OpDiv, OpEq, OpGe, OpGt, OpLe, OpLt, OpMerge, OpMinus,
OpMod, OpMul, OpNe, OpNot, OpOr, OpPow, OpStrCat, OpSub, UnresolvedOp,
};
use crate::data::op::{Op, OpAdd, OpAnd, OpCoalesce, OpConcat, OpDiv, OpEq, OpGe, OpGt, OpIsNull, OpLe, OpLt, OpMerge, OpMinus, OpMod, OpMul, OpNe, OpNot, OpNotNull, OpOr, OpPow, OpStrCat, OpSub, UnresolvedOp};
use crate::data::value::Value;
use crate::parser::number::parse_int;
use crate::parser::text_identifier::parse_string;
@ -146,7 +143,11 @@ fn build_expr_primary(pair: Pair) -> Result<Expr> {
Rule::call => {
let mut pairs = p.into_inner();
let method_name = pairs.next().unwrap().as_str();
let op = Arc::new(UnresolvedOp(method_name.to_string()));
let op: Arc<dyn Op + Send + Sync> = match method_name {
n if n == OpIsNull.name() => Arc::new(OpIsNull),
n if n == OpNotNull.name() => Arc::new(OpNotNull),
method_name => Arc::new(UnresolvedOp(method_name.to_string()))
};
let mut args = vec![head];
args.extend(pairs.map(Expr::try_from).collect::<Result<Vec<_>>>()?);
head = Expr::Apply(op, args);
@ -319,7 +320,7 @@ pub(crate) mod tests {
use pest::Parser;
pub(crate) fn str2expr(s: &str) -> Result<Expr> {
let pair = CozoParser::parse(Rule::expr, s.as_ref())
let pair = CozoParser::parse(Rule::expr, s)
.unwrap()
.next()
.unwrap();

@ -20,113 +20,54 @@ pub(crate) use text::*;
type Result<T> = result::Result<T, EvalError>;
pub(crate) trait Op: Send + Sync {
fn is_resolved(&self) -> bool {
true
}
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
false
}
fn arity(&self) -> Option<usize>;
fn has_side_effect(&self) -> bool;
fn name(&self) -> &str;
fn non_null_args(&self) -> bool {
true
}
fn typing_eval(&self, args: &[Typing]) -> Typing {
let representatives = args.iter().map(|v| v.representative_value()).collect();
match self.eval_non_null(representatives) {
Ok(t) => t.deduce_typing(),
Err(_) => Typing::Any,
}
}
fn eval<'a>(&self, has_null: bool, args: Vec<Value<'a>>) -> Result<Value<'a>> {
if self.non_null_args() {
if has_null {
Ok(Value::Null)
} else {
match self.arity() {
Some(0) => self.eval_zero(),
Some(1) => self.eval_one_non_null(args.into_iter().next().unwrap()),
Some(2) => {
let mut args = args.into_iter();
self.eval_two_non_null(args.next().unwrap(), args.next().unwrap())
}
_ => self.eval_non_null(args),
}
}
} else {
panic!(
"Required method `eval` not implemented for `{}`",
self.name()
)
}
}
fn eval_non_null<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
panic!(
"Required method `eval_non_null` not implemented for `{}`",
self.name()
)
}
fn eval_zero(&self) -> Result<StaticValue> {
panic!(
"Required method `eval_zero` not implemented for `{}`",
self.name()
)
}
fn eval_one_non_null<'a>(&self, _arg: Value<'a>) -> Result<Value<'a>> {
panic!(
"Required method `eval_one` not implemented for `{}`",
self.name()
)
}
fn eval_two_non_null<'a>(&self, _left: Value<'a>, _right: Value<'a>) -> Result<Value<'a>> {
panic!(
"Required method `eval_two` not implemented for `{}`",
self.name()
)
}
fn eval_one<'a>(&self, _arg: Value<'a>) -> Result<Value<'a>> {
panic!(
"Required method `eval_one` not implemented for `{}`",
self.name()
)
}
fn eval_two<'a>(&self, _left: Value<'a>, _right: Value<'a>) -> Result<Value<'a>> {
panic!(
"Required method `eval_two` not implemented for `{}`",
self.name()
)
}
fn non_null_args(&self) -> bool;
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>>;
}
pub(crate) trait AggOp: Send + Sync {
fn is_resolved(&self) -> bool {
true
}
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
false
}
fn arity(&self) -> Option<usize>;
fn has_side_effect(&self) -> bool;
fn name(&self) -> &str;
}
pub(crate) struct UnresolvedOp(pub String);
impl Op for UnresolvedOp {
fn is_resolved(&self) -> bool {
fn non_null_args(&self) -> bool {
false
}
fn has_side_effect(&self) -> bool {
true
}
fn arity(&self) -> Option<usize> {
None
}
fn name(&self) -> &str {
&self.0
}
fn eval<'a>(&self, _args: Vec<Value<'a>>) -> Result<Value<'a>> {
unimplemented!()
}
}
impl AggOp for UnresolvedOp {
fn arity(&self) -> Option<usize> {
None
}
fn has_side_effect(&self) -> bool {
true
}
fn name(&self) -> &str {
&self.0
}
}
pub(crate) fn extract_two_args<'a>(args: Vec<Value<'a>>) -> (Value<'a>, Value<'a>) {
let mut args = args.into_iter();
(args.next().unwrap(), args.next().unwrap())
}

@ -1,20 +1,14 @@
use crate::data::eval::EvalError;
use crate::data::op::Op;
use crate::data::value::Value;
use crate::data::op::{extract_two_args, Op};
use crate::data::value::{StaticValue, Value};
use std::result;
type Result<T> = result::Result<T, EvalError>;
pub(crate) struct OpAdd;
impl Op for OpAdd {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn name(&self) -> &str {
"+"
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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(),
@ -31,16 +25,32 @@ impl Op for OpAdd {
}
}
pub(crate) struct OpSub;
impl Op for OpSub {
impl Op for OpAdd {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"-"
"+"
}
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)
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
}
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(),
@ -57,16 +67,32 @@ impl Op for OpSub {
}
}
pub(crate) struct OpMul;
impl Op for OpMul {
impl Op for OpSub {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"*"
"-"
}
fn non_null_args(&self) -> bool {
true
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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 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(),
@ -83,16 +109,33 @@ impl Op for OpMul {
}
}
pub(crate) struct OpDiv;
impl Op for OpDiv {
impl Op for OpMul {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"/"
"*"
}
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)
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
}
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(),
@ -109,16 +152,33 @@ impl Op for OpDiv {
}
}
pub(crate) struct OpMod;
impl Op for OpMod {
impl Op for OpDiv {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"%"
"/"
}
fn non_null_args(&self) -> bool {
true
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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 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) => {
@ -132,16 +192,33 @@ impl Op for OpMod {
}
}
pub(crate) struct OpPow;
impl Op for OpPow {
impl Op for OpMod {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"**"
"%"
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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 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(),
@ -158,13 +235,32 @@ impl Op for OpPow {
}
}
pub(crate) struct OpMinus;
impl Op for OpPow {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
impl Op for OpMinus {
fn name(&self) -> &str {
"--"
"**"
}
fn eval_one_non_null<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
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()),
@ -175,3 +271,21 @@ impl Op for OpMinus {
}
}
}
impl Op for OpMinus {
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
false
}
fn non_null_args(&self) -> bool {
true
}
fn name(&self) -> &str {
"--"
}
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
self.eval_one_non_null(args.into_iter().next().unwrap())
}
}

@ -10,36 +10,55 @@ type Result<T> = result::Result<T, EvalError>;
pub(crate) struct OpIsNull;
impl OpIsNull {
pub(crate) fn eval_one<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
Ok((arg == Value::Null).into())
}
}
impl Op for OpIsNull {
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"is_null"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, has_null: bool, _args: Vec<Value<'a>>) -> Result<Value<'a>> {
Ok(has_null.into())
}
fn eval_one<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
Ok((arg == Value::Null).into())
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
self.eval_one(args.into_iter().next().unwrap())
}
}
pub(crate) struct OpNotNull;
impl OpNotNull {
pub(crate) fn eval_one<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
Ok((arg != Value::Null).into())
}
}
impl Op for OpNotNull {
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"not_null"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, has_null: bool, _args: Vec<Value<'a>>) -> Result<Value<'a>> {
Ok((!has_null).into())
}
fn eval_one<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
Ok((arg != Value::Null).into())
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
self.eval_one(args.into_iter().next().unwrap())
}
}
pub(crate) struct OpOr;
@ -48,16 +67,22 @@ impl Op for OpOr {
fn arity(&self) -> Option<usize> {
None
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"||"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, has_null: bool, args: Vec<Value<'a>>) -> Result<Value<'a>> {
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
let mut has_null = false;
for arg in args {
match arg {
Value::Null => {}
Value::Null => has_null = true,
Value::Bool(true) => return Ok(Value::Bool(true)),
Value::Bool(false) => {}
v => {
@ -144,16 +169,22 @@ impl Op for OpAnd {
fn arity(&self) -> Option<usize> {
None
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"&&"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, has_null: bool, args: Vec<Value<'a>>) -> Result<Value<'a>> {
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
let mut has_null = false;
for arg in args {
match arg {
Value::Null => {}
Value::Null => has_null = true,
Value::Bool(false) => return Ok(Value::Bool(false)),
Value::Bool(true) => {}
v => {
@ -236,11 +267,8 @@ pub(crate) fn row_eval_and<'a, T: RowEvalContext + 'a>(
pub(crate) struct OpNot;
impl Op for OpNot {
fn name(&self) -> &str {
"!"
}
fn eval_one_non_null<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
impl OpNot {
pub(crate) fn eval_one_non_null<'a>(&self, arg: Value<'a>) -> Result<Value<'a>> {
match arg {
Value::Bool(b) => Ok((!b).into()),
v => Err(EvalError::OpTypeMismatch(
@ -250,3 +278,21 @@ impl Op for OpNot {
}
}
}
impl Op for OpNot {
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
false
}
fn non_null_args(&self) -> bool {
true
}
fn name(&self) -> &str {
"!"
}
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
self.eval_one_non_null(args.into_iter().next().unwrap())
}
}

@ -14,13 +14,18 @@ impl Op for OpConcat {
fn arity(&self) -> Option<usize> {
None
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"concat"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, _has_null: bool, args: Vec<Value<'a>>) -> Result<Value<'a>> {
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
let mut coll = vec![];
for v in args.into_iter() {
match v {
@ -44,13 +49,18 @@ impl Op for OpMerge {
fn arity(&self) -> Option<usize> {
None
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"merge"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, _has_null: bool, args: Vec<Value<'a>>) -> Result<Value<'a>> {
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
let mut coll = BTreeMap::new();
for v in args.into_iter() {
match v {

@ -1,5 +1,5 @@
use crate::data::eval::EvalError;
use crate::data::op::Op;
use crate::data::op::{extract_two_args, Op};
use crate::data::value::Value;
use std::result;
@ -7,42 +7,70 @@ type Result<T> = result::Result<T, EvalError>;
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())
}
}
impl Op for OpEq {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"=="
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
Ok((left == right).into())
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 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())
}
}
impl Op for OpNe {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"!="
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
Ok((left != right).into())
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 OpGt;
impl Op for OpGt {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn name(&self) -> &str {
">"
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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(),
@ -60,16 +88,32 @@ impl Op for OpGt {
}
}
pub(crate) struct OpGe;
impl Op for OpGe {
impl Op for OpGt {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
">="
">"
}
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)
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
}
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(),
@ -87,16 +131,32 @@ impl Op for OpGe {
}
}
pub(crate) struct OpLt;
impl Op for OpLt {
impl Op for OpGe {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"<"
">="
}
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)
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
}
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(),
@ -114,16 +174,32 @@ impl Op for OpLt {
}
}
pub(crate) struct OpLe;
impl Op for OpLe {
impl Op for OpLt {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"<="
"<"
}
fn non_null_args(&self) -> bool {
true
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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 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(),
@ -140,3 +216,25 @@ impl Op for OpLe {
Ok(res)
}
}
impl Op for OpLe {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"<="
}
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)
}
}

@ -15,13 +15,18 @@ impl Op for OpCoalesce {
fn arity(&self) -> Option<usize> {
None
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"~~"
}
fn non_null_args(&self) -> bool {
false
}
fn eval<'a>(&self, _has_null: bool, args: Vec<Value<'a>>) -> Result<Value<'a>> {
fn eval<'a>(&self, args: Vec<Value<'a>>) -> Result<Value<'a>> {
for arg in args {
if arg != Value::Null {
return Ok(arg);

@ -1,5 +1,5 @@
use crate::data::eval::EvalError;
use crate::data::op::Op;
use crate::data::op::{extract_two_args, Op};
use crate::data::value::Value;
use std::result;
@ -7,14 +7,8 @@ type Result<T> = result::Result<T, EvalError>;
pub(crate) struct OpStrCat;
impl Op for OpStrCat {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn name(&self) -> &str {
"++"
}
fn eval_two_non_null<'a>(&self, left: Value<'a>, right: Value<'a>) -> Result<Value<'a>> {
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();
@ -28,3 +22,26 @@ impl Op for OpStrCat {
}
}
}
impl Op for OpStrCat {
fn arity(&self) -> Option<usize> {
Some(2)
}
fn has_side_effect(&self) -> bool {
false
}
fn name(&self) -> &str {
"++"
}
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)
}
}

@ -1,4 +1,4 @@
file = _{SOI ~ (statement | mutation)* ~ EOI}
file = _{SOI ~ (statement)* ~ EOI}
// whitespace
@ -80,7 +80,7 @@ literal = _{ null | boolean | number | string}
// date, time, datetime, duration: no literal, do with functions. User passed in stuff can be coerced from string
// but they do exist at the AST level (and of course at the value level)
// expressions
// Expressions
comma_sep_expr = { expr ~ ("," ~ expr)* }
expr = {unary ~ (operation ~ unary) *}
@ -148,6 +148,7 @@ col_entry = { col_name ~ ":" ~ typing ~ ("=" ~ expr)? }
col_name = { key_marker? ~ name_in_def }
key_marker = { "*" }
// Typing
typing = _{ simple_type | nullable_type | homogeneous_list_type | unnamed_tuple_type | named_tuple_type | function_type }
simple_type = { ident }
@ -160,6 +161,8 @@ function_type = { "<" ~ args_type ~ ">" ~ "->" ~ typing }
args_type = { typing? ~ ("," ~ typing)* }
// Data definition
cols_def = { "{" ~ col_entry ~ ("," ~ col_entry)* ~ ","? ~ "}" }
col_list = {"(" ~ name_in_def ~ ("," ~ name_in_def)* ~ ","? ~ ")"}
@ -177,35 +180,40 @@ global_def = { "create" ~ definition }
local_def = { "local" ~ definition }
statement = _{ global_def | local_def }
mutation = { (upsert|insert) ~ expr ~ ("as" ~ name_in_def)? ~ mutation_filter? ~ ";" }
mutation_filter = { (exclude|include) ~ name_in_def ~ ("," ~ name_in_def)* }
exclude = {"exclude"}
include = {"include"}
upsert = {"upsert"}
insert = {"insert"}
from_pattern = { "from" ~ (from_el ~ ",")* ~ from_el }
from_el = _{ simple_from_pattern | node_edge_pattern }
simple_from_pattern = { ident ~ ":" ~ name_in_def ~ ("+" ~ name_in_def)* }
node_edge_pattern = { node_pattern? ~ (edge_pattern ~ node_pattern)* ~ edge_pattern? }
node_pattern = {"(" ~ ident? ~ ":" ~ name_in_def ~ ("+" ~ name_in_def)* ~ ")"}
edge_pattern = { outer_join_marker? ~ (fwd_edge_pattern | bwd_edge_pattern) ~ outer_join_marker? }
fwd_edge_pattern = { "-" ~ edge_pattern_inner ~ "->" }
bwd_edge_pattern = { "<-" ~ edge_pattern_inner ~ "-" }
edge_pattern_inner = _{"[" ~ ident? ~ ":" ~ name_in_def ~ ("+" ~ name_in_def)* ~ "]"}
outer_join_marker = { "?" }
where_pattern = { "where" ~ (expr ~ ",")* ~ expr }
select_pattern = { "select" ~ (select_dict | scoped_dict) ~ ( (order_pattern ~ offset_pattern?) | (offset_pattern ~ order_pattern?) )? }
order_pattern = { "ordered" ~ "[" ~ order_el ~ ("," ~ order_el)* ~ "]" }
order_el = _{order_dsc | order_asc}
order_dsc = {expr ~ (":" ~ "desc")}
order_asc = {expr ~ (":" ~ "asc")?}
offset_pattern = { limit_clause? ~ offset_clause? }
limit_clause = { "limit" ~ pos_int }
offset_clause = { "offset" ~ pos_int }
relational_query = { from_pattern ~ where_pattern? ~ select_pattern }
// mutation = { (upsert|insert) ~ expr ~ ("as" ~ name_in_def)? ~ mutation_filter? ~ ";" }
// mutation_filter = { (exclude|include) ~ name_in_def ~ ("," ~ name_in_def)* }
// exclude = {"exclude"}
// include = {"include"}
// upsert = {"upsert"}
// insert = {"insert"}
// from_pattern = { "from" ~ (from_el ~ ",")* ~ from_el }
// from_el = _{ simple_from_pattern | node_edge_pattern }
//
// simple_from_pattern = { ident ~ ":" ~ name_in_def ~ ("+" ~ name_in_def)* }
//
// node_edge_pattern = { node_pattern? ~ (edge_pattern ~ node_pattern)* ~ edge_pattern? }
// node_pattern = {"(" ~ ident? ~ ":" ~ name_in_def ~ ("+" ~ name_in_def)* ~ ")"}
// edge_pattern = { outer_join_marker? ~ (fwd_edge_pattern | bwd_edge_pattern) ~ outer_join_marker? }
// fwd_edge_pattern = { "-" ~ edge_pattern_inner ~ "->" }
// bwd_edge_pattern = { "<-" ~ edge_pattern_inner ~ "-" }
// edge_pattern_inner = _{"[" ~ ident? ~ ":" ~ name_in_def ~ ("+" ~ name_in_def)* ~ "]"}
// outer_join_marker = { "?" }
//
// where_pattern = { "where" ~ (expr ~ ",")* ~ expr }
// select_pattern = { "select" ~ (select_dict | scoped_dict) ~ ( (order_pattern ~ offset_pattern?) | (offset_pattern ~ order_pattern?) )? }
//
// order_pattern = { "ordered" ~ "[" ~ order_el ~ ("," ~ order_el)* ~ "]" }
// order_el = _{order_dsc | order_asc}
// order_dsc = {expr ~ (":" ~ "desc")}
// order_asc = {expr ~ (":" ~ "asc")?}
// offset_pattern = { limit_clause? ~ offset_clause? }
// limit_clause = { "limit" ~ pos_int }
// offset_clause = { "offset" ~ pos_int }
//
// relational_query = { from_pattern ~ where_pattern? ~ select_pattern }
// Relational algebra
// ra = { (ra_source | ra_fn_call) ~ ra_method_call* }

@ -2,5 +2,6 @@ pub(crate) mod data;
pub(crate) mod logger;
pub(crate) mod parser;
pub(crate) mod runtime;
pub(crate) mod algebra;
pub use runtime::instance::DbInstance;

Loading…
Cancel
Save