1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Datalog [`Atom`] — predicate applied to an ordered term list.
use std::collections::BTreeSet;
use std::fmt;
use super::symbols::{PredicateSymbol, VariableSymbol};
use super::term::Term;
/// Datalog atom: `predicate(term_1, ..., term_n)`.
#[derive(Clone, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Atom {
/// Predicate identifier.
pub predicate: PredicateSymbol,
/// Ordered list of terms.
pub terms: Vec<Term>,
}
impl Atom {
/// Arity of the atom.
#[must_use]
pub fn arity(&self) -> usize {
self.terms.len()
}
/// All variables that appear anywhere in this atom, including
/// variables nested inside [`Term::TripleTerm`] arguments
/// (recursively).
#[must_use]
pub(super) fn variables(&self) -> BTreeSet<VariableSymbol> {
let mut acc = BTreeSet::new();
self.collect_variables(&mut acc);
acc
}
fn collect_variables(&self, acc: &mut BTreeSet<VariableSymbol>) {
for term in &self.terms {
term.collect_variables(acc);
}
}
/// Maximum [`Term::TripleTerm`] nesting depth observed
/// anywhere in this atom's argument tree. `0` for a
/// plain-term atom; otherwise the depth of the deepest
/// nested triple-term.
#[must_use]
pub(super) fn nesting_depth(&self) -> usize {
self.terms
.iter()
.map(Term::nesting_depth)
.max()
.unwrap_or(0)
}
}
/// Display an [`Atom`] as `predicate(term_1, term_2, …)`. Used
/// directly by [`Term`]'s [`std::fmt::Display`] impl for non-2-arity
/// triple terms and available to error messages / debugging.
impl fmt::Display for Atom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}(", self.predicate.as_str())?;
for (idx, term) in self.terms.iter().enumerate() {
if idx > 0 {
write!(f, ", ")?;
}
write!(f, "{term}")?;
}
write!(f, ")")
}
}