Backend support for custom statements and deductions (#105)

* Custom statements on backend

* Add support for custom statements and deductions on backend

* typo checker smh

* clean up match statement

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* clean up more match statement

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* delete done todo

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

---------

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>
This commit is contained in:
tideofwords 2025-03-03 15:55:30 -08:00 committed by GitHub
parent 5092149f9f
commit 7eeb595dc2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 76 additions and 47 deletions

View file

@ -1,14 +1,16 @@
use anyhow::{anyhow, Result};
use std::fmt;
use crate::middleware::{self, NativePredicate, Params, StatementArg, ToFields};
use crate::middleware::{
self, AnchoredKey, NativePredicate, Params, Predicate, StatementArg, ToFields,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Statement(pub NativePredicate, pub Vec<StatementArg>);
pub struct Statement(pub Predicate, pub Vec<StatementArg>);
impl Statement {
pub fn is_none(&self) -> bool {
self.0 == NativePredicate::None
self.0 == Predicate::Native(NativePredicate::None)
}
/// Argument method. Trailing Nones are filtered out.
pub fn args(&self) -> Vec<StatementArg> {
@ -52,31 +54,53 @@ impl TryFrom<Statement> for middleware::Statement {
proper_args.get(1).cloned(),
proper_args.get(2).cloned(),
);
Ok(match (s.0, args, proper_args.len()) {
(NP::None, _, 0) => S::None,
(NP::ValueOf, (Some(SA::Key(ak)), Some(SA::Literal(v)), None), 2) => S::ValueOf(ak, v),
(NP::Equal, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Equal(ak1, ak2),
(NP::NotEqual, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::NotEqual(ak1, ak2)
Ok(match s.0 {
Predicate::Native(np) => match (np, args, proper_args.len()) {
(NP::None, _, 0) => S::None,
(NP::ValueOf, (Some(SA::Key(ak)), Some(SA::Literal(v)), None), 2) => {
S::ValueOf(ak, v)
}
(NP::Equal, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::Equal(ak1, ak2)
}
(NP::NotEqual, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::NotEqual(ak1, ak2)
}
(NP::Gt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Gt(ak1, ak2),
(NP::Lt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Lt(ak1, ak2),
(NP::Contains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::Contains(ak1, ak2)
}
(NP::NotContains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::NotContains(ak1, ak2)
}
(NP::SumOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
S::SumOf(ak1, ak2, ak3)
}
(
NP::ProductOf,
(Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))),
3,
) => S::ProductOf(ak1, ak2, ak3),
(NP::MaxOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
S::MaxOf(ak1, ak2, ak3)
}
_ => Err(anyhow!("Ill-formed statement expression {:?}", s))?,
},
Predicate::Custom(cpr) => {
let aks: Vec<AnchoredKey> = proper_args
.into_iter()
.filter_map(|arg| match arg {
SA::None => None,
SA::Key(ak) => Some(ak),
SA::Literal(_) => unreachable!(),
})
.collect();
S::Custom(cpr, aks)
}
(NP::Gt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Gt(ak1, ak2),
(NP::Lt, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => S::Lt(ak1, ak2),
(NP::Contains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::Contains(ak1, ak2)
Predicate::BatchSelf(_) => {
unreachable!()
}
(NP::NotContains, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), None), 2) => {
S::NotContains(ak1, ak2)
}
(NP::SumOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
S::SumOf(ak1, ak2, ak3)
}
(NP::ProductOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
S::ProductOf(ak1, ak2, ak3)
}
(NP::MaxOf, (Some(SA::Key(ak1)), Some(SA::Key(ak2)), Some(SA::Key(ak3))), 3) => {
S::MaxOf(ak1, ak2, ak3)
}
_ => Err(anyhow!("Ill-formed statement expression {:?}", s))?,
})
}
}
@ -84,11 +108,15 @@ impl TryFrom<Statement> for middleware::Statement {
impl From<middleware::Statement> for Statement {
fn from(s: middleware::Statement) -> Self {
match s.code() {
middleware::Predicate::Native(c) => {
Statement(c, s.args().into_iter().map(|arg| arg).collect())
}
// TODO: Custom statements
_ => todo!(),
middleware::Predicate::Native(c) => Statement(
middleware::Predicate::Native(c),
s.args().into_iter().map(|arg| arg).collect(),
),
middleware::Predicate::Custom(cpr) => Statement(
middleware::Predicate::Custom(cpr),
s.args().into_iter().map(|arg| arg).collect(),
),
middleware::Predicate::BatchSelf(_) => unreachable!(),
}
}
}