66 lines
2.0 KiB
Rust
66 lines
2.0 KiB
Rust
use crate::CompilationError;
|
|
use crate::context::Context;
|
|
use crate::schemas::path;
|
|
use crate::step::BoolCollector;
|
|
use crate::step::Node;
|
|
use crate::step::StepMaker;
|
|
|
|
use preserves::value::IOValue;
|
|
|
|
pub trait Predicate: std::fmt::Debug {
|
|
fn test(&mut self, ctxt: &mut Context, value: &IOValue) -> bool;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum CompiledPredicate {
|
|
Selector(Node),
|
|
Not(Box<CompiledPredicate>),
|
|
Or(Vec<CompiledPredicate>),
|
|
And(Vec<CompiledPredicate>),
|
|
}
|
|
|
|
impl path::Predicate {
|
|
pub fn compile(&self) -> Result<CompiledPredicate, CompilationError> {
|
|
match self {
|
|
path::Predicate::Selector(b) =>
|
|
Ok(CompiledPredicate::Selector((&**b).connect(BoolCollector::new())?)),
|
|
path::Predicate::Not { pred } =>
|
|
Ok(CompiledPredicate::Not(Box::new((&**pred).compile()?))),
|
|
path::Predicate::Or { preds } =>
|
|
Ok(CompiledPredicate::Or(preds.iter().map(Self::compile).collect::<Result<_,_>>()?)),
|
|
path::Predicate::And { preds } =>
|
|
Ok(CompiledPredicate::And(preds.iter().map(Self::compile).collect::<Result<_,_>>()?)),
|
|
}
|
|
}
|
|
|
|
pub fn exec(&self, ctxt: &mut Context, value: &IOValue) -> Result<bool, CompilationError> {
|
|
Ok(self.compile()?.test(ctxt, value))
|
|
}
|
|
}
|
|
|
|
impl Predicate for CompiledPredicate {
|
|
fn test(&mut self, ctxt: &mut Context, value: &IOValue) -> bool {
|
|
match self {
|
|
CompiledPredicate::Selector(n) => n.test(ctxt, value),
|
|
CompiledPredicate::Not(p) => !p.test(ctxt, value),
|
|
CompiledPredicate::Or(ps) => {
|
|
for p in ps.iter_mut() {
|
|
if p.test(ctxt, value) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
CompiledPredicate::And(ps) => {
|
|
for p in ps.iter_mut() {
|
|
if !p.test(ctxt, value) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|