use std::collections::BTreeSet;
use super::symbols::VariableSymbol;
use super::term::Term;
#[derive(Clone, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub enum BindExpr {
Term(Term),
Add(Box<BindExpr>, Box<BindExpr>),
Sub(Box<BindExpr>, Box<BindExpr>),
Mul(Box<BindExpr>, Box<BindExpr>),
Div(Box<BindExpr>, Box<BindExpr>),
Neg(Box<BindExpr>),
Abs(Box<BindExpr>),
Ceil(Box<BindExpr>),
Floor(Box<BindExpr>),
Round(Box<BindExpr>),
Str(Box<BindExpr>),
StrLen(Box<BindExpr>),
UCase(Box<BindExpr>),
LCase(Box<BindExpr>),
Concat(Vec<BindExpr>),
SubStr {
value: Box<BindExpr>,
start: Box<BindExpr>,
len: Option<Box<BindExpr>>,
},
StrBefore(Box<BindExpr>, Box<BindExpr>),
StrAfter(Box<BindExpr>, Box<BindExpr>),
Replace {
value: Box<BindExpr>,
pattern: Box<BindExpr>,
replacement: Box<BindExpr>,
flags: Option<Box<BindExpr>>,
},
EncodeForUri(Box<BindExpr>),
Md5(Box<BindExpr>),
Sha1(Box<BindExpr>),
Sha256(Box<BindExpr>),
Sha384(Box<BindExpr>),
Sha512(Box<BindExpr>),
CastInteger(Box<BindExpr>),
CastDecimal(Box<BindExpr>),
CastDouble(Box<BindExpr>),
CastFloat(Box<BindExpr>),
CastString(Box<BindExpr>),
Year(Box<BindExpr>),
Month(Box<BindExpr>),
Day(Box<BindExpr>),
Hours(Box<BindExpr>),
Minutes(Box<BindExpr>),
Seconds(Box<BindExpr>),
Timezone(Box<BindExpr>),
Tz(Box<BindExpr>),
Now,
Lang(Box<BindExpr>),
Iri(Box<BindExpr>),
BNode(Box<BindExpr>),
}
impl BindExpr {
#[must_use]
pub fn variables(&self) -> BTreeSet<VariableSymbol> {
let mut out = BTreeSet::new();
self.collect_variables(&mut out);
out
}
fn collect_variables(&self, out: &mut BTreeSet<VariableSymbol>) {
match self {
Self::Term(term) => {
term.collect_variables(out);
}
Self::Add(lhs, rhs)
| Self::Sub(lhs, rhs)
| Self::Mul(lhs, rhs)
| Self::Div(lhs, rhs) => {
lhs.collect_variables(out);
rhs.collect_variables(out);
}
Self::Neg(inner)
| Self::Abs(inner)
| Self::Ceil(inner)
| Self::Floor(inner)
| Self::Round(inner)
| Self::Str(inner)
| Self::StrLen(inner)
| Self::UCase(inner)
| Self::LCase(inner)
| Self::EncodeForUri(inner)
| Self::Md5(inner)
| Self::Sha1(inner)
| Self::Sha256(inner)
| Self::Sha384(inner)
| Self::Sha512(inner)
| Self::CastInteger(inner)
| Self::CastDecimal(inner)
| Self::CastDouble(inner)
| Self::CastFloat(inner)
| Self::CastString(inner)
| Self::Year(inner)
| Self::Month(inner)
| Self::Day(inner)
| Self::Hours(inner)
| Self::Minutes(inner)
| Self::Seconds(inner)
| Self::Timezone(inner)
| Self::Tz(inner)
| Self::Lang(inner)
| Self::Iri(inner)
| Self::BNode(inner) => inner.collect_variables(out),
Self::Now => {}
Self::Concat(parts) => {
for part in parts {
part.collect_variables(out);
}
}
Self::SubStr { value, start, len } => {
value.collect_variables(out);
start.collect_variables(out);
if let Some(len) = len {
len.collect_variables(out);
}
}
Self::StrBefore(value, needle) | Self::StrAfter(value, needle) => {
value.collect_variables(out);
needle.collect_variables(out);
}
Self::Replace {
value,
pattern,
replacement,
flags,
} => {
value.collect_variables(out);
pattern.collect_variables(out);
replacement.collect_variables(out);
if let Some(flags) = flags {
flags.collect_variables(out);
}
}
}
}
}