1use crate::{Located, MatchArm, Pattern, Span, SurfaceExpr};
8use std::collections::HashSet;
9
10use super::types::{CaseBranch, CaseTree, MatchClause, PatternRow, TypeConstructors};
11
12use super::patterncompiler_type::PatternCompiler;
13
14impl PatternCompiler {
15 pub fn new() -> Self {
17 Self { next_var: 0 }
18 }
19 pub fn compile_match(
25 &mut self,
26 scrutinee: &SurfaceExpr,
27 clauses: &[MatchClause],
28 ) -> Result<SurfaceExpr, String> {
29 if clauses.is_empty() {
30 return Err("Match with no clauses".to_string());
31 }
32 let dummy = Span::new(0, 0, 0, 0);
33 let arms: Vec<MatchArm> = clauses
34 .iter()
35 .map(|clause| MatchArm {
36 pattern: Located::new(clause.pattern.clone(), dummy.clone()),
37 guard: None,
38 rhs: Located::new(clause.body.clone(), dummy.clone()),
39 })
40 .collect();
41 Ok(SurfaceExpr::Match(
42 Box::new(Located::new(scrutinee.clone(), dummy)),
43 arms,
44 ))
45 }
46 pub fn check_redundant(&self, patterns: &[Pattern]) -> Vec<usize> {
52 let mut redundant = Vec::new();
53 let mut has_irrefutable = false;
54 for (i, pattern) in patterns.iter().enumerate() {
55 if has_irrefutable {
56 redundant.push(i);
57 }
58 if matches!(pattern, Pattern::Wild | Pattern::Var(_)) {
59 has_irrefutable = true;
60 }
61 }
62 redundant
63 }
64 #[allow(dead_code)]
70 pub fn compile_matrix(&mut self, rows: &[PatternRow], num_cols: usize) -> CaseTree {
71 if rows.is_empty() {
72 return CaseTree::Failure;
73 }
74 if num_cols == 0 {
75 return CaseTree::Leaf { body_idx: 0 };
76 }
77 let first_row = &rows[0];
78 let all_wild = first_row.patterns.iter().all(|p| self.is_irrefutable(p));
79 if all_wild && first_row.guard.is_none() {
80 return CaseTree::Leaf { body_idx: 0 };
81 }
82 let col = self.select_column(rows, num_cols);
83 let ctors = self.collect_constructors(rows, col);
84 if ctors.is_empty() {
85 let defaults = self.default_rows(rows, col);
86 let new_cols = num_cols.saturating_sub(1);
87 return self.compile_matrix(&defaults, new_cols);
88 }
89 let mut branches = Vec::new();
90 for (ctor_name, arity) in &ctors {
91 let specialized = self.specialize(rows, col, ctor_name, *arity);
92 let new_cols = num_cols - 1 + arity;
93 let subtree = self.compile_matrix(&specialized, new_cols);
94 branches.push(CaseBranch {
95 ctor: ctor_name.clone(),
96 num_fields: *arity,
97 subtree,
98 });
99 }
100 let defaults = self.default_rows(rows, col);
101 let default = if defaults.is_empty() {
102 None
103 } else {
104 let new_cols = num_cols.saturating_sub(1);
105 Some(Box::new(self.compile_matrix(&defaults, new_cols)))
106 };
107 CaseTree::Switch {
108 scrutinee: col,
109 branches,
110 default,
111 }
112 }
113 #[allow(dead_code)]
121 pub fn specialize(
122 &self,
123 rows: &[PatternRow],
124 col: usize,
125 ctor: &str,
126 arity: usize,
127 ) -> Vec<PatternRow> {
128 let mut result = Vec::new();
129 for row in rows {
130 if col >= row.patterns.len() {
131 continue;
132 }
133 match &row.patterns[col] {
134 Pattern::Ctor(name, args) => {
135 if name == ctor {
136 let mut new_patterns = Vec::new();
137 for (i, p) in row.patterns.iter().enumerate() {
138 if i == col {
139 for arg in args {
140 new_patterns.push(arg.value.clone());
141 }
142 } else {
143 new_patterns.push(p.clone());
144 }
145 }
146 result.push(PatternRow {
147 patterns: new_patterns,
148 body: row.body.clone(),
149 guard: row.guard.clone(),
150 });
151 }
152 }
153 Pattern::Wild | Pattern::Var(_) => {
154 let mut new_patterns = Vec::new();
155 for (i, p) in row.patterns.iter().enumerate() {
156 if i == col {
157 for _ in 0..arity {
158 new_patterns.push(Pattern::Wild);
159 }
160 } else {
161 new_patterns.push(p.clone());
162 }
163 }
164 result.push(PatternRow {
165 patterns: new_patterns,
166 body: row.body.clone(),
167 guard: row.guard.clone(),
168 });
169 }
170 Pattern::Lit(_) => {}
171 Pattern::Or(left, right) => {
172 let mut left_row = row.clone();
173 left_row.patterns[col] = left.value.clone();
174 let mut right_row = row.clone();
175 right_row.patterns[col] = right.value.clone();
176 let left_spec = self.specialize(&[left_row], col, ctor, arity);
177 let right_spec = self.specialize(&[right_row], col, ctor, arity);
178 result.extend(left_spec);
179 result.extend(right_spec);
180 }
181 }
182 }
183 result
184 }
185 #[allow(dead_code)]
190 pub fn default_rows(&self, rows: &[PatternRow], col: usize) -> Vec<PatternRow> {
191 let mut result = Vec::new();
192 for row in rows {
193 if col >= row.patterns.len() {
194 continue;
195 }
196 match &row.patterns[col] {
197 Pattern::Wild | Pattern::Var(_) => {
198 let new_patterns: Vec<Pattern> = row
199 .patterns
200 .iter()
201 .enumerate()
202 .filter(|(i, _)| *i != col)
203 .map(|(_, p)| p.clone())
204 .collect();
205 result.push(PatternRow {
206 patterns: new_patterns,
207 body: row.body.clone(),
208 guard: row.guard.clone(),
209 });
210 }
211 Pattern::Or(left, right) => {
212 if self.is_irrefutable(&left.value) || self.is_irrefutable(&right.value) {
213 let new_patterns: Vec<Pattern> = row
214 .patterns
215 .iter()
216 .enumerate()
217 .filter(|(i, _)| *i != col)
218 .map(|(_, p)| p.clone())
219 .collect();
220 result.push(PatternRow {
221 patterns: new_patterns,
222 body: row.body.clone(),
223 guard: row.guard.clone(),
224 });
225 }
226 }
227 _ => {}
228 }
229 }
230 result
231 }
232 #[allow(dead_code)]
236 pub fn collect_constructors(&self, rows: &[PatternRow], col: usize) -> Vec<(String, usize)> {
237 let mut seen = Vec::new();
238 for row in rows {
239 if col >= row.patterns.len() {
240 continue;
241 }
242 self.collect_ctors_from_pattern(&row.patterns[col], &mut seen);
243 }
244 seen
245 }
246 #[allow(dead_code)]
251 pub fn check_exhaustive_with_ctors(
252 &self,
253 patterns: &[Pattern],
254 ctors: &TypeConstructors,
255 ) -> Result<(), Vec<String>> {
256 for pat in patterns {
257 if self.is_irrefutable(pat) {
258 return Ok(());
259 }
260 }
261 let mut covered = Vec::new();
262 for pat in patterns {
263 self.collect_pattern_ctors(pat, &mut covered);
264 }
265 let mut missing = Vec::new();
266 for ctor_info in &ctors.constructors {
267 if !covered.contains(&ctor_info.name) {
268 missing.push(ctor_info.name.clone());
269 }
270 }
271 if missing.is_empty() {
272 Ok(())
273 } else {
274 Err(missing)
275 }
276 }
277 #[allow(dead_code)]
284 pub fn check_nested_exhaustive(
285 &self,
286 patterns: &[Vec<Pattern>],
287 ctors: &[TypeConstructors],
288 ) -> Result<(), Vec<Vec<String>>> {
289 if patterns.is_empty() {
290 if ctors.is_empty() {
291 return Ok(());
292 }
293 let missing: Vec<Vec<String>> = ctors[0]
294 .constructors
295 .iter()
296 .map(|c| vec![c.name.clone()])
297 .collect();
298 return if missing.is_empty() {
299 Ok(())
300 } else {
301 Err(missing)
302 };
303 }
304 if ctors.is_empty() {
305 return Ok(());
306 }
307 let mut all_missing: Vec<Vec<String>> = Vec::new();
308 for (col_idx, type_ctors) in ctors.iter().enumerate() {
309 let col_patterns: Vec<Pattern> = patterns
310 .iter()
311 .filter_map(|row| row.get(col_idx).cloned())
312 .collect();
313 if let Err(missing) = self.check_exhaustive_with_ctors(&col_patterns, type_ctors) {
314 for m in &missing {
315 let mut combo = vec!["_".to_string(); ctors.len()];
316 combo[col_idx] = m.clone();
317 all_missing.push(combo);
318 }
319 }
320 }
321 if all_missing.is_empty() {
322 Ok(())
323 } else {
324 Err(all_missing)
325 }
326 }
327 #[allow(dead_code)]
332 pub fn simplify_pattern(&self, pattern: &Pattern) -> Pattern {
333 match pattern {
334 Pattern::Or(left, right) => {
335 let sl = self.simplify_pattern(&left.value);
336 let sr = self.simplify_pattern(&right.value);
337 if self.is_irrefutable(&sl) || self.is_irrefutable(&sr) {
338 return Pattern::Wild;
339 }
340 Pattern::Or(
341 Box::new(crate::Located::new(sl, left.span.clone())),
342 Box::new(crate::Located::new(sr, right.span.clone())),
343 )
344 }
345 Pattern::Ctor(name, args) => {
346 let simplified_args: Vec<crate::Located<Pattern>> = args
347 .iter()
348 .map(|a| crate::Located::new(self.simplify_pattern(&a.value), a.span.clone()))
349 .collect();
350 Pattern::Ctor(name.clone(), simplified_args)
351 }
352 Pattern::Wild => Pattern::Wild,
353 Pattern::Var(v) => Pattern::Var(v.clone()),
354 Pattern::Lit(l) => Pattern::Lit(l.clone()),
355 }
356 }
357 pub fn extract_literal_range(&self, patterns: &[Pattern]) -> Option<(i64, i64)> {
359 let mut values = Vec::new();
360 for pat in patterns {
361 self.collect_literals(pat, &mut values);
362 }
363 if values.is_empty() {
364 return None;
365 }
366 values.sort();
367 Some((values[0], values[values.len() - 1]))
368 }
369 pub fn check_range_coverage(&self, patterns: &[Pattern], min: i64, max: i64) -> bool {
371 let mut covered = HashSet::new();
372 for pat in patterns {
373 self.collect_literal_set(pat, &mut covered);
374 }
375 for pat in patterns {
376 if self.is_irrefutable(pat) {
377 return true;
378 }
379 }
380 for i in min..=max {
381 if !covered.contains(&(i as u64)) {
382 return false;
383 }
384 }
385 true
386 }
387 pub fn find_dead_patterns(&self, rows: &[PatternRow]) -> Vec<usize> {
389 let mut dead = Vec::new();
390 for (i, _row) in rows.iter().enumerate() {
391 if i > 0 && self.all_irrefutable(&rows[..i]) {
392 dead.push(i);
393 }
394 }
395 dead
396 }
397 #[allow(dead_code)]
399 pub fn extract_bound_names(&self, pattern: &Pattern) -> Vec<String> {
400 let mut names = Vec::new();
401 self.collect_bound_names(pattern, &mut names);
402 names
403 }
404}