pattern_compiler/
matrix.rs1use ::std::collections::HashSet;
2
3use ::prettytable::Table;
4
5use ::petgraph::graph::NodeIndex;
6
7use ::either::Either;
8
9use super::pattern::PatternProvider;
10
11#[derive(Debug, Derivative)]
12#[derivative(Clone(bound=""))]
13pub struct MatchMatrix<P> where P: PatternProvider {
14 pub data: Vec<MatchMatrixElement<P>>,
15
16 pub variables: Vec<P::CfgVariable>,
17 pub clause_leaves: Vec<super::cfg::CfgNodeIndex>,
18}
19
20#[derive(Debug, Derivative)]
21#[derivative(Clone(bound=""))]
22pub struct MatchMatrixElement<P> where P: PatternProvider {
23 pub node: P::PatternNodeKey,
24 pub variable_num: usize,
25 pub clause_num: usize,
26}
27
28fn chunks_len<'a, T>(entities: &'a [T], chunk_len: usize, num_chunks: usize)
29 -> Box<Iterator<Item = &'a [T]> + 'a> {
30
31 assert!(entities.len() == (chunk_len * num_chunks));
32 let ret = if chunk_len == 0 {
33 Either::Left((0..num_chunks).map(|_| [].as_ref()))
34 } else {
35 Either::Right(entities.chunks(chunk_len))
36 };
37 Box::new(ret)
38}
39
40impl<P> MatchMatrix<P> where P: PatternProvider {
41
42 pub fn new(nodes: &[P::PatternNodeKey],
43 leaves: Vec<super::cfg::CfgNodeIndex>,
44 vars: Vec<P::CfgVariable>) -> Self {
45 assert!(vars.len() * leaves.len() == nodes.len());
46
47 let data = if vars.len() == 0 {
48 vec![]
49 } else {
50 nodes.chunks(vars.len()).enumerate()
51 .flat_map(|(clause_idx, clause)| {
52 clause.iter().enumerate().map(move |(variable_idx, pat)| {
53 MatchMatrixElement {
54 variable_num: variable_idx,
55 clause_num: clause_idx,
56 node: *pat,
57 }
58 })
59 }).collect()
60 };
61
62 MatchMatrix {
63 data: data,
64 variables: vars,
65 clause_leaves: leaves,
66 }
67 }
68
69 pub fn select_specialize_variable(&self, pattern: &P) -> usize
74 {
75 let mut sums = vec![(0, true); self.variables.len()];
76
77 let clauses = self.data.chunks(self.variables.len());
78 for clause in clauses {
79 for variable_pattern in clause.iter() {
80 if pattern.is_wildcard(pattern.get_kind(variable_pattern.node)) {
81 sums[variable_pattern.variable_num].1 = false;
82 } else {
83 if sums[variable_pattern.variable_num].1 {
84 sums[variable_pattern.variable_num].0 += 1;
85 }
86 }
87 }
88 }
89
90 sums.iter().enumerate()
91 .max_by_key(|&(_, s)| s.0)
92 .map(|(i, _)| i).unwrap()
93 }
94
95 pub fn get_var(&self, var: usize) -> P::CfgVariable {
96 self.variables[var]
97 }
98
99 pub fn collect_specialization_types<'a>(&self, pattern: &'a P,
101 variable: usize)
102 -> HashSet<P::PatternNodeKind>
103 {
104 let mut types = HashSet::new();
105
106 let clauses = self.data.chunks(self.variables.len());
107 for clause in clauses {
108 let variable_pattern = &clause[variable];
109 types.insert(pattern.get_kind(variable_pattern.node));
110 }
111
112 types.remove(&pattern.get_wildcard());
113
114 types
115 }
116
117 pub fn specialize(&self, ctx: &mut super::MatchCompileContext<P>,
118 variable: usize,
119 on: P::PatternNodeKind)
120 -> (Vec<P::CfgVariable>, MatchMatrix<P>)
121 {
122
123 let to_specialize_rows: Vec<(usize, &[MatchMatrixElement<_>])> = self.data
125 .chunks(self.variables.len())
126 .enumerate()
127 .filter(|&(_, node)| ctx.pattern.kind_includes(on, node[variable].node))
128 .collect();
129
130 let specialize_nodes: Vec<&MatchMatrixElement<_>> = to_specialize_rows.iter()
132 .map(|&(_, nodes)| &nodes[variable])
133 .collect();
134 let rest_nodes: Vec<Vec<&MatchMatrixElement<_>>> = to_specialize_rows.iter()
135 .map(|&(_, nodes)| {
136 nodes.iter()
137 .filter(|node| node.variable_num != variable)
138 .collect::<Vec<_>>()
139 })
140 .collect();
141
142 let specialized = {
144 let nodes: Vec<_> = specialize_nodes.iter()
145 .map(|node| node.node)
146 .collect();
147 ctx.pattern.expand_clause_nodes(nodes)
148 };
149
150 let specialized_chunked = chunks_len(&specialized.nodes, specialized.variables.len(),
154 specialized.clauses);
155
156 let new_nodes: Vec<_> = specialized_chunked
157 .zip(rest_nodes.iter())
158 .flat_map(|(specialized, rest)| {
159 let specialized_m = specialized.iter().map(|node| *node);
160 let rest_m = rest.iter().map(|node| node.node);
161
162 specialized_m.chain(rest_m)
163 })
164 .collect();
165
166 let new_clause_leaves: Vec<_> = to_specialize_rows.iter()
167 .map(|&(clause_num, _)| self.clause_leaves[clause_num])
168 .collect();
169
170 let new_variables: Vec<_> = {
171 let rest_variables = self.variables.iter()
172 .enumerate()
173 .filter(|&(var_num, _)| var_num != variable)
174 .map(|(_, var)| *var);
175
176 specialized.variables.iter()
177 .map(|var| *var)
178 .chain(rest_variables)
179 .collect()
180 };
181
182 let new_mat = Self::new(new_nodes.as_slice(),
183 new_clause_leaves, new_variables);
184 (specialized.variables, new_mat)
185 }
186
187 pub fn iterate_clauses<'a>(&'a self) -> Box<Iterator<Item = (NodeIndex, &'a [MatchMatrixElement<P>])> + 'a> {
188 let iter = self.clause_leaves.iter().map(|l| *l)
189 .zip(chunks_len(&self.data, self.variables.len(), self.clause_leaves.len()));
190
191 Box::new(iter)
192 }
193
194 pub fn default(&self, ctx: &mut super::MatchCompileContext<P>,
195 variable: usize)
196 -> (Vec<P::CfgVariable>, MatchMatrix<P>)
197 {
198 let wildcard = ctx.pattern.get_wildcard();
199 self.specialize(ctx, variable, wildcard)
200 }
201
202 pub fn is_empty(&self) -> bool {
203 self.clause_leaves.len() == 0
204 }
205
206 pub fn has_wildcard_head(&self, pattern: &P)
207 -> Option<super::cfg::CfgNodeIndex>
208 {
209
210 assert!(self.clause_leaves.len() > 0);
211 if self.variables.len() == 0 {
212 Some(self.clause_leaves[0])
213 } else {
214 let has_wildcard_head = self.data
215 .chunks(self.variables.len())
216 .next().unwrap()
217 .iter().all(|p| {
218 pattern.is_wildcard(pattern.get_kind(p.node))
219 });
220 if has_wildcard_head {
221 Some(self.clause_leaves[0])
222 } else {
223 None
224 }
225 }
226 }
227
228 pub fn to_table(&self, pat: &P) -> Table {
229 use ::prettytable::Cell;
230
231 let mut table = Table::new();
232
233 {
234 let head_row = table.add_empty_row();
235 head_row.add_cell(Cell::new(&format!(
236 "{}*{}=={}",
237 self.variables.len(),
238 self.clause_leaves.len(),
239 self.data.len())));
240 for variable in self.variables.iter() {
241 let var_str = format!("{:?}", variable);
242 head_row.add_cell(Cell::new(&var_str));
243 }
244 }
245
246 for row_idx in 0..self.clause_leaves.len() {
247 let t_row = table.add_empty_row();
248 let leaf_id = format!("{:?}", self.clause_leaves[row_idx]);
249 t_row.add_cell(Cell::new(&leaf_id));
250
251 let row_start = row_idx * self.variables.len();
252 for col in &self.data[row_start..(row_start+self.variables.len())] {
253 let node = pat.get_kind(col.node);
254 let cell_fmt = format!("{:?}", node);
255 let cell = Cell::new(&cell_fmt);
256 t_row.add_cell(cell);
257 }
258 }
259
260 table
261 }
262
263}