evaluate expressions

main
Ziyang Hu 2 years ago
parent 4707d13bfb
commit ea72a01f5a

@ -4,21 +4,48 @@ use anyhow::Result;
use itertools::Itertools;
use crate::data::expr::ExprError::UnexpectedArgs;
use crate::data::keyword::Keyword;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue;
use crate::query::compile::Term;
#[derive(Debug, thiserror::Error)]
pub enum ExprError {
#[error("unexpected args for {0}: {1:?}")]
UnexpectedArgs(&'static str, Vec<DataValue>),
#[error("unexpected return type: expected {0}, got {1:?}")]
UnexpectedReturnType(String, DataValue),
}
#[derive(Debug, Clone)]
pub enum Expr {
Const(Term<DataValue>),
Binding(Keyword),
BoundIdx(usize),
Const(DataValue),
Apply(&'static Op, Box<[Expr]>),
}
impl Expr {
pub(crate) fn eval(&self, bindings: &Tuple) -> Result<DataValue> {
match self {
Expr::Binding(_) => {
unreachable!()
}
Expr::BoundIdx(i) => Ok(bindings.0[*i].clone()),
Expr::Const(d) => Ok(d.clone()),
Expr::Apply(op, args) => {
let args: Box<[DataValue]> = args.iter().map(|v| v.eval(bindings)).try_collect()?;
(op.inner)(&args)
}
}
}
pub(crate) fn eval_pred(&self, bindings: &Tuple) -> Result<bool> {
match self.eval(bindings)? {
DataValue::Bool(b) => Ok(b),
v => Err(ExprError::UnexpectedReturnType("bool".to_string(), v).into()),
}
}
}
#[derive(Clone)]
pub struct Op {
pub(crate) name: &'static str,

@ -7,7 +7,8 @@ use serde_json::Map;
use crate::data::attr::Attribute;
use crate::data::expr::{
Expr, OP_ADD, OP_DIV, OP_EQ, OP_GE, OP_GT, OP_LE, OP_LT, OP_MUL, OP_NEQ, OP_SUB,
Expr, OP_ADD, OP_AND, OP_DIV, OP_EQ, OP_GE, OP_GT, OP_LE, OP_LT, OP_MUL, OP_NEQ, OP_NOT, OP_OR,
OP_SUB,
};
use crate::data::json::JsonValue;
use crate::data::keyword::{Keyword, PROG_ENTRY};
@ -112,6 +113,9 @@ impl SessionTx {
"Ge" => &OP_GE,
"Lt" => &OP_LT,
"Le" => &OP_LE,
"Or" => &OP_OR,
"And" => &OP_AND,
"Not" => &OP_NOT,
s => return Err(QueryCompilationError::UnknownOperator(s.to_string()).into()),
};
@ -159,14 +163,14 @@ impl SessionTx {
JsonValue::String(s) => {
let kw = Keyword::from(s as &str);
if kw.is_reserved() {
Ok(Expr::Const(Term::Var(kw)))
Ok(Expr::Binding(kw))
} else {
Ok(Expr::Const(Term::Const(DataValue::String(s.into()))))
Ok(Expr::Const(DataValue::String(s.into())))
}
}
JsonValue::Object(map) => {
if let Some(v) = map.get("const") {
Ok(Expr::Const(Term::Const(v.into())))
Ok(Expr::Const(v.into()))
} else if map.contains_key("pred") {
Self::parse_expr(map)
} else {
@ -177,7 +181,7 @@ impl SessionTx {
.into())
}
}
v => Ok(Expr::Const(Term::Const(v.into()))),
v => Ok(Expr::Const(v.into())),
}
}
fn parse_rule_atom(&mut self, payload: &Map<String, JsonValue>, vld: Validity) -> Result<Atom> {

Loading…
Cancel
Save