Skip to main content

datalog_structural_model/
requirements.rs

1//! Exhaustive nested feature discovery, independent of evaluation.
2use crate::ir::walk::Visitor;
3use crate::{BindExpr, BuiltinFilter, DatalogCapabilities, DatalogFeature, Literal, Program, Term};
4#[derive(Default)]
5struct Requirements(DatalogCapabilities);
6impl Visitor for Requirements {
7    fn term(&mut self, term: &Term) {
8        match term {
9            Term::Variable(_) | Term::Constant(_) => {}
10            Term::TripleTerm(_) => self.0.insert(DatalogFeature::TripleTerms),
11            Term::Skolem { .. } => self.0.insert(DatalogFeature::SkolemGeneration),
12        }
13    }
14    fn binding(&mut self, expr: &BindExpr) {
15        self.0.insert(DatalogFeature::Binding(expr.kind()));
16    }
17    fn filter(&mut self, expr: &BuiltinFilter) {
18        self.0.insert(DatalogFeature::Filter(expr.kind()));
19    }
20    fn literal(&mut self, literal: &Literal) {
21        match literal {
22            Literal::Negative(_) => self.0.insert(DatalogFeature::StratifiedNegation),
23            Literal::Aggregate(aggregate) => self
24                .0
25                .insert(DatalogFeature::Aggregate(aggregate.aggregator)),
26            Literal::Positive(_) | Literal::Filter(_) | Literal::Bind { .. } => {}
27        }
28    }
29}
30impl Program {
31    /// Discover every required language feature, including inside aggregate scopes.
32    /// This inspects authored structure and does not validate or execute it.
33    #[must_use]
34    pub fn required_capabilities(&self) -> DatalogCapabilities {
35        let mut requirements = Requirements::default();
36        for rule in &self.rules {
37            rule.walk(&mut requirements);
38        }
39        requirements.0
40    }
41}