1#[macro_use]
2extern crate terms;
3#[macro_use]
4extern crate tree_automata as ta;
5extern crate automatic_relations as automatic;
6
7use std::cell::Cell;
8use std::cmp::Ord;
9use std::fmt;
10use std::collections::HashSet;
11use terms::{
12 Term,
13 Pattern,
14 Var,
15 variable::{
16 Spawnable,
17 Family,
18 Parented
19 }
20};
21use ta::{
22 Symbol,
23 State,
24 Sorted,
25 NoLabel,
26 Rank,
27 Ranked,
28 bottom_up::{
29 Automaton,
30 Configuration,
31 width_search::TermFragment
33 }
34};
35
36use automatic::{
37 Relation,
38 Convolution,
39 Convoluted,
40 MaybeBottom,
41 convolution::aligned
42};
43
44struct PList<'a, T: fmt::Display>(&'a [T]);
45
46impl<'a, T: fmt::Display> fmt::Display for PList<'a, T> {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 match self.0.split_first() {
49 Some((head, tail)) => {
50 head.fmt(f)?;
51 for e in tail.iter() {
52 write!(f, ",")?;
53 e.fmt(f)?;
54 }
55 Ok(())
56 },
57 None => Ok(())
58 }
59 }
60}
61
62fn assert_multi_search<F: Ranked + Symbol + Ord, Q: State, X: Family + Ord>(automata: &[&Automaton<Rank<Convoluted<F>>, Q, NoLabel>], mut patterns: Vec<Vec<Pattern<F, X>>>, mut expected_output: Vec<Vec<Term<Rank<Convoluted<F>>>>>) {
63 let convoluted_patterns = patterns.drain(..).map(|patterns| {
65 Convoluted(patterns.into_iter().map(|p| MaybeBottom::Some(p)).collect())
66 }).collect();
67
68 let it = aligned::multi_search(automata, convoluted_patterns, None);
69
70 let mut output: Vec<Vec<Term<Rank<Convoluted<F>>>>> = Vec::with_capacity(expected_output.len());
71 for terms in it {
72 let terms = terms.unwrap();
73
74 #[cfg(debug_assertions)]
75 {
76 if output.len() >= expected_output.len() {
77 for terms in output.iter() {
78 println!("FOUND {}", PList(terms));
79 }
80 println!("FOUND {}", PList(&terms));
81 }
82 }
83 assert!(output.len() < expected_output.len());
84 output.push(terms)
85 }
86
87 let mut expected_output_set = HashSet::new();
88 for e in expected_output.drain(..) {
89 expected_output_set.insert(e);
90 }
91
92 #[cfg(debug_assertions)]
93 {
94 if output.len() != expected_output_set.len() {
95 println!("EXPECTED OUTPUT:");
96 for terms in expected_output_set.iter() {
97 println!("{}", PList(terms));
98 }
99 println!("\nOUTPUT:");
100 for terms in output.iter() {
101 println!("{}", PList(terms));
102 }
103 }
104 }
105
106 assert!(output.len() == expected_output_set.len());
107
108 for terms in output.iter() {
109 #[cfg(debug_assertions)]
110 {
111 if !expected_output_set.contains(terms) {
112 println!("UNEXPECTED TERM: {}", PList(terms));
113 }
114 }
115
116 assert!(expected_output_set.contains(terms));
117 }
118}
119
120fn main() {
121 let a = Rank("a", 0);
122 let b = Rank("b", 0);
123
124 let nil = Rank("nil", 0);
125 let cons = Rank("cons", 2);
126
127 let a_conv = Rank(Convoluted(vec![MaybeBottom::Some(a)]), 0);
128 let b_conv = Rank(Convoluted(vec![MaybeBottom::Some(b)]), 0);
129 let nil_conv = Rank(Convoluted(vec![MaybeBottom::Some(nil)]), 0);
130 let cons_conv = Rank(Convoluted(vec![MaybeBottom::Some(cons)]), 2);
131
132 let mut prop_all_false = automaton! {
133 b_conv -> "0:Bool",
134 cons_conv("0:List", "0:Bool") -> "0:List",
135 nil_conv -> "0:List",
136
137 finals "0:List"
138 };
139
140 let mut prop_sorted = automaton! {
141 cons_conv("_:List", "_:Bool") -> "_:List",
142 cons_conv("1:List", "_:Bool") -> "_:List",
143 cons_conv("2:List", "0:Bool") -> "_:List",
144 cons_conv("_:List", "1:Bool") -> "_:List",
145 cons_conv("_:List", "0:Bool") -> "_:List",
146 cons_conv("0:List", "_:Bool") -> "_:List",
147 cons_conv("2:List", "1:Bool") -> "_:List",
148 cons_conv("2:List", "_:Bool") -> "_:List",
149 cons_conv("1:List", "0:Bool") -> "2:List",
150 a_conv -> "1:Bool",
151 nil_conv -> "0:List",
152 cons_conv("0:List", "0:Bool") -> "1:List",
153 cons_conv("0:List", "1:Bool") -> "1:List",
154 cons_conv("1:List", "1:Bool") -> "1:List",
155 b_conv -> "0:Bool",
156
157 finals "_:List" "2:List"
158 };
159
160 let namespace = Cell::new(0);
161 let x: Parented<Var<_>> = Parented::spawn(&&namespace);
162
163 assert_multi_search(
164 &[&prop_all_false, &prop_sorted],
165 vec![ vec![ pattern![ ?x ] ], vec! [ pattern![ cons(?x, b) ] ] ],
166 vec![
167 vec![
168 aligned::Convolution::convolute(vec![ Some(term![ cons(nil, b) ]) ]),
169 aligned::Convolution::convolute(vec![ Some(term![ cons(cons(nil, b), b) ]) ])
170 ]
171 ]
172 )
173}