1use std::fmt;
2use terms::Term;
3use crate::{
4 Symbol,
5 State,
6 NoLabel,
7 bottom_up::{
8 Automaton,
9 Configuration,
10 }
12};
13
14#[derive(Debug, Clone, Copy)]
15pub struct Killed;
16
17pub trait LanguageState<F: Symbol, E: ?Sized>: State + Sized {
18 fn configurations<'a>(&self, env: &'a E) -> Box<dyn Iterator<Item = Configuration<F, Self>> + 'a>;
19}
20
21impl<F: Symbol, Q: State> LanguageState<F, Automaton<F, Q, NoLabel>> for Q {
22 fn configurations<'a>(&self, aut: &'a Automaton<F, Q, NoLabel>) -> Box<dyn Iterator<Item = Configuration<F, Self>> + 'a> {
23 Box::new(aut.configurations_for_state(self).map(|(conf, _)| conf.clone()))
24 }
25}
26
27impl<'e, F: Symbol, Q: State> LanguageState<F, [&'e Automaton<F, Q, NoLabel>]> for Indexed<Q> {
28 fn configurations<'a>(&self, automata: &'a [&'e Automaton<F, Q, NoLabel>]) -> Box<dyn Iterator<Item = Configuration<F, Self>> + 'a> {
29 let index = self.1;
30 let aut = automata[index];
31 Box::new(aut.configurations_for_state(&self.0).map(move |(conf, _)| {
32 let states = conf.states().iter().map(|q| Indexed((*q).clone(), index)).collect();
33 Configuration(conf.symbol().clone(), states)
34 }))
35 }
36}
37
38fn add_language_state<'a, F: Symbol, E, Q: LanguageState<F, E>>(q: Q, env: &'a E, aut: &mut Automaton<F, Q, NoLabel>) {
39 if !aut.includes(&q) {
40 for conf in q.configurations(env) {
41 aut.add(conf.clone(), NoLabel, q.clone());
42 for sub in conf.1.into_iter() {
43 add_language_state(sub, env, aut);
44 }
45 }
46 }
47}
48
49impl<'a, F: Symbol, E, Q: LanguageState<F, E>> From<(Q, &'a E)> for Automaton<F, Q, NoLabel> {
50 fn from((q, env): (Q, &'a E)) -> Automaton<F, Q, NoLabel> {
51 let mut aut = Automaton::new();
52 add_language_state(q.clone(), env, &mut aut);
53 aut.set_final(q);
54 aut
55 }
56}
57
58impl<'a, F: Symbol, Q: LanguageState<F, ()>> From<Q> for Automaton<F, Q, NoLabel> {
59 fn from(q: Q) -> Automaton<F, Q, NoLabel> {
60 let mut aut = Automaton::new();
61 add_language_state(q.clone(), &(), &mut aut);
62 aut.set_final(q);
63 aut
64 }
65}
66
67#[derive(Clone, Debug, Hash, PartialEq, Eq)]
68pub struct Indexed<Q: State>(pub Q, pub usize);
69
70impl<T: State + fmt::Display> fmt::Display for Indexed<T> {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 write!(f, "{}.{}", self.0, self.1)
73 }
74}
75
76#[cfg(not(debug_assertions))]
77pub trait SearchPattern<F: Symbol, Q: State, C: SearchContext>: Clone {
78 fn matches(&self, depth: usize, context: &C, q: &Q, configuration: &Configuration<F, Q>) -> Option<(C, Vec<Self>)>;
79}
80
81#[cfg(debug_assertions)]
82pub trait SearchPattern<F: Symbol, Q: State, C: SearchContext>: Clone + fmt::Display + fmt::Debug {
83 fn matches(&self, depth: usize, context: &C, q: &Q, configuration: &Configuration<F, Q>) -> Option<(C, Vec<Self>)>;
84}
85
86#[cfg(not(debug_assertions))]
87pub trait SearchContext: Clone {
88 fn looping(&self) -> bool;
89}
90
91#[cfg(debug_assertions)]
92pub trait SearchContext: Clone + fmt::Display + fmt::Debug {
93 fn looping(&self) -> bool;
94}
95
96#[derive(Hash, PartialEq, Eq)]
97struct Item<F: Symbol, Q: State, C, P>(Configuration<F, Q>, C, Vec<P>);
98
99impl<F: Symbol + fmt::Display, Q: State + fmt::Display, C: fmt::Display, P: fmt::Display> fmt::Debug for Item<F, Q, C, P> {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 write!(f, "({}/{}/{})", self.0, self.1, PList(&self.2))
102 }
103}
104
105pub struct TermFragment<'a, E: ?Sized, F: Symbol, Q: LanguageState<F, E>, C: SearchContext, P: SearchPattern<F, Q, C>> {
108 env: &'a E,
109
110 context: C,
112
113 patterns: Vec<P>,
115
116 leaves: Vec<Q>,
118
119 leaves_configurations: Vec<Box<dyn Iterator<Item = Configuration<F, Q>> + 'a>>,
121
122 current: Vec<Item<F, Q, C, P>>,
124
125 next_fragment: Option<Box<TermFragment<'a, E, F, Q, C, P>>>,
127
128 visited: bool,
132
133 depth: usize,
135
136 kill_signal: Option<crossbeam_channel::Receiver<()>>
137}
138
139impl<'a, E: ?Sized, F: Symbol, Q: LanguageState<F, E>, C: SearchContext, P: SearchPattern<F, Q, C>> TermFragment<'a, E, F, Q, C, P> {
140 pub fn new(env: &'a E, depth: usize, context: C, leaves: Vec<Q>, patterns: Vec<P>, kill_signal: Option<crossbeam_channel::Receiver<()>>) -> TermFragment<'a, E, F, Q, C, P> {
141 let leaves_configurations = if leaves.is_empty() {
142 Vec::new()
143 } else {
144 vec![leaves[0].configurations(env)]
145 };
146 TermFragment {
147 env,
148 context,
149 patterns,
150 leaves,
151 leaves_configurations,
152 current: Vec::new(),
153 next_fragment: None,
154 visited: false,
155 depth,
156 kill_signal
157 }
158 }
159}
160
161impl<'a, E: ?Sized, F: Symbol, Q: LanguageState<F, E>, C: SearchContext, P: SearchPattern<F, Q, C>> Iterator for TermFragment<'a, E, F, Q, C, P> {
162 type Item = Result<Vec<Term<F>>, Killed>;
163
164 fn next(&mut self) -> Option<Result<Vec<Term<F>>, Killed>> {
165 loop {
169 if let Some(kill_signal) = self.kill_signal.as_ref() {
171 if let Ok(()) = kill_signal.try_recv() {
172 return Some(Err(Killed))
173 }
174 }
175
176 if self.leaves.is_empty() {
177 if self.visited {
178 return None
179 } else {
180 self.visited = true;
181 return Some(Ok(Vec::new()))
182 }
183 } else {
184 let current_context = match self.current.last() {
185 Some(Item(_, context, _)) => context,
186 None => &self.context
187 };
188
189 if self.current.len() < self.leaves.len() {
190 let i = self.current.len();
191 let j = i + 1;
192
193 match self.leaves_configurations.last_mut().unwrap().next() {
194 Some(conf) => {
195 if let Some((next_context, sub_patterns)) = self.patterns[i].matches(self.depth, ¤t_context, &self.leaves[i], &conf) {
196 assert!(conf.states().len() == sub_patterns.len());
197 self.current.push(Item(conf, next_context, sub_patterns));
198
199 if j < self.leaves.len() {
202 let confs = self.leaves[j].configurations(self.env);
203 self.leaves_configurations.push(confs);
204 }
205 } else {
206 }
208 },
209 None => {
210 if i > 0 {
211 self.current.pop();
212 self.leaves_configurations.pop();
213 } else {
214 return None
215 }
216 }
217 }
218 } else {
219 match self.next_fragment {
220 Some(ref mut frag) => {
221 match frag.next() {
222 Some(Err(Killed)) => return Some(Err(Killed)),
223 Some(Ok(mut sub_terms)) => {
224 sub_terms.reverse();
225 let mut terms = Vec::with_capacity(self.current.len());
226
227 for Item(Configuration(f, sub_states), _, _) in self.current.iter() {
228 let mut subs = Vec::with_capacity(sub_states.len());
229 for _ in sub_states.iter() {
230 subs.push(sub_terms.pop().unwrap());
231 }
232
233 terms.push(Term::new(f.clone(), subs))
234 }
235
236 return Some(Ok(terms))
237 },
238 None => {
239 self.next_fragment = None;
241 self.current.pop();
242 }
243 }
244 },
245 None if !current_context.looping() => {
246 let mut leaves = Vec::new();
247 let mut patterns = Vec::new();
248 for Item(Configuration(_, sub_states), _, sub_patterns) in self.current.iter() {
249 for q in sub_states.iter() {
250 leaves.push(q.clone())
251 }
252
253 for p in sub_patterns.iter() {
254 patterns.push(p.clone())
255 }
256 }
257
258 let next_fragment = TermFragment::new(self.env, self.depth + 1, current_context.clone(), leaves, patterns, self.kill_signal.clone());
259 self.next_fragment = Some(Box::new(next_fragment))
260 },
261 None => { self.current.pop();
263 }
264 }
265 }
266 }
267 }
268 }
269}
270
271struct PList<'a, T: fmt::Display>(&'a [T]);
272
273impl<'a, T: fmt::Display> fmt::Display for PList<'a, T> {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 match self.0.split_first() {
276 Some((head, tail)) => {
277 head.fmt(f)?;
278 for e in tail.iter() {
279 write!(f, ",")?;
280 e.fmt(f)?;
281 }
282 Ok(())
283 },
284 None => Ok(())
285 }
286 }
287}
288
289#[cfg(debug_assertions)]
290impl<'a, E: ?Sized, F: Symbol, Q: LanguageState<F, E>, C: SearchContext, P: SearchPattern<F, Q, C>> fmt::Display for TermFragment<'a, E, F, Q, C, P> {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 write!(f, "({}) {} with context {}", PList(&self.patterns), PList(&self.leaves), self.context)
293 }
294}