mangle_analysis/
simple_program.rs1use crate::{ast, PredicateSet, Program, StratifiedProgram};
16use bumpalo::Bump;
17use std::collections::HashMap;
18
19pub struct SimpleProgram<'p> {
21 pub bump: &'p Bump,
22 pub ext_preds: Vec<ast::PredicateSym<'p>>,
23 pub rules: HashMap<ast::PredicateSym<'p>, Vec<&'p ast::Clause<'p>>>,
24}
25
26pub struct SimpleStratifiedProgram<'p> {
29 program: SimpleProgram<'p>,
30 strata: &'p [&'p PredicateSet<'p>],
31}
32
33impl<'p> Program<'p> for SimpleProgram<'p> {
34 fn extensional_preds(&'p self) -> impl Iterator<Item = &'p ast::PredicateSym<'p>> {
35 self.ext_preds.iter()
36 }
37
38 fn intensional_preds(&'p self) -> impl Iterator<Item = &'p ast::PredicateSym<'p>> {
39 self.rules.keys()
40 }
41
42 fn rules(
43 &'p self,
44 sym: &'p ast::PredicateSym<'p>,
45 ) -> impl Iterator<Item = &'p ast::Clause<'p>> {
46 self.rules.get(sym).unwrap().iter().copied()
47 }
48}
49
50impl<'p> SimpleProgram<'p> {
51 pub fn add_clause(&mut self, clause: &ast::Clause) {
52 let clause = ast::copy_clause(self.bump, clause);
53 let sym = clause.head.sym;
54 use std::collections::hash_map::Entry;
55 match self.rules.entry(sym) {
56 Entry::Occupied(mut v) => v.get_mut().push(clause),
57 Entry::Vacant(v) => {
58 v.insert(vec![clause]);
59 }
60 }
61 }
62
63 pub fn stratify(
66 self,
67 strata: impl Iterator<Item = &'p PredicateSet<'p>>,
68 ) -> SimpleStratifiedProgram<'p> {
69 let mut layers = vec![];
70 for layer in strata {
71 layers.push(*self.bump.alloc(layer))
72 }
73 let strata = &*self.bump.alloc_slice_copy(&layers);
74 SimpleStratifiedProgram {
75 program: self,
76 strata,
77 }
78 }
79}
80
81impl<'p> Program<'p> for SimpleStratifiedProgram<'p> {
82 fn extensional_preds(&'p self) -> impl Iterator<Item = &'p ast::PredicateSym<'p>> {
83 self.program.extensional_preds()
84 }
85
86 fn intensional_preds(&'p self) -> impl Iterator<Item = &'p ast::PredicateSym<'p>> {
87 self.program.intensional_preds()
88 }
89
90 fn rules(
91 &'p self,
92 sym: &'p ast::PredicateSym<'p>,
93 ) -> impl Iterator<Item = &'p ast::Clause<'p>> {
94 self.program.rules(sym)
95 }
96}
97
98impl<'p> StratifiedProgram<'p> for SimpleStratifiedProgram<'p> {
99 fn strata(&'p self) -> impl Iterator<Item = &'p PredicateSet<'p>> {
100 self.strata.iter().copied()
101 }
102
103 fn pred_to_index(&'p self, sym: &ast::PredicateSym) -> Option<usize> {
104 self.strata.iter().position(|x| x.contains(sym))
105 }
106}
107
108#[cfg(test)]
109mod test {
110 use super::*;
111 use std::collections::HashSet;
112
113 static FOO: ast::PredicateSym = ast::PredicateSym {
114 name: "foo",
115 arity: Some(2),
116 };
117 static BAR: ast::PredicateSym = ast::PredicateSym {
118 name: "bar",
119 arity: Some(1),
120 };
121
122 #[test]
123 fn try_eval() {
124 let bump = Bump::new();
125 let mut simple = SimpleProgram {
126 bump: &bump,
127 ext_preds: vec![FOO],
128 rules: HashMap::new(),
129 };
130
131 let atom = ast::Atom {
133 sym: FOO,
134 args: &[&ast::BaseTerm::Variable("X"), &ast::BaseTerm::Variable("_")],
135 };
136 let clause = &ast::Clause {
137 head: &ast::Atom {
138 sym: BAR,
139 args: &[&ast::BaseTerm::Variable("X")],
140 },
141 premises: &[&ast::Term::Atom(&atom)],
142 transform: &[],
143 };
144 simple.add_clause(clause);
145
146 assert_eq!(simple.extensional_preds().collect::<Vec<_>>(), vec![&FOO]);
147 assert_eq!(simple.intensional_preds().collect::<Vec<_>>(), vec![&BAR]);
148
149 let mut single_layer = HashSet::new();
150 single_layer.insert(&BAR);
151 let strata = vec![single_layer.clone()];
152 let stratified = simple.stratify(strata.iter());
153
154 assert_eq!(stratified.pred_to_index(&BAR), Some(0));
155 assert_eq!(stratified.strata().collect::<Vec<_>>(), vec![&single_layer])
156 }
157}