bool_logic/transforms/
dedup_list.rs1use crate::ast::Expr;
2use crate::visit_mut::VisitMut;
3use crate::visit_mut::walk_mut_expr;
4
5pub struct DedupList;
6
7impl<T> VisitMut<T> for DedupList
8where
9 T: Eq,
10{
11 fn visit_mut_expr(&mut self, expr: &mut Expr<T>) {
12 walk_mut_expr(self, expr);
13
14 if let Some(list) = expr.as_mut_expr_list() {
15 let mut i = 0;
16 while i < list.len() {
17 let mut j = i + 1;
18 while j < list.len() {
19 if list[i] == list[j] {
20 list.remove(j);
21 } else {
22 j += 1;
23 }
24 }
25 i += 1;
26 }
27 }
28 }
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34 use crate::ast::{all, any, const_, expr, not, var};
35
36 #[test]
37 fn dedup_any_with_duplicates() {
38 let mut x: Expr<u32> = expr(any((var(1), var(2), var(1), var(3), var(2))));
39 let expected: Expr<u32> = expr(any((var(1), var(2), var(3))));
40
41 DedupList.visit_mut_expr(&mut x);
42
43 assert_eq!(x.to_string(), expected.to_string());
44 }
45
46 #[test]
47 fn dedup_all_with_duplicates() {
48 let mut x: Expr<u32> = expr(all((var(1), var(2), var(1), var(3), var(2))));
49 let expected: Expr<u32> = expr(all((var(1), var(2), var(3))));
50
51 DedupList.visit_mut_expr(&mut x);
52
53 assert_eq!(x.to_string(), expected.to_string());
54 }
55
56 #[test]
57 fn dedup_no_duplicates() {
58 let mut x: Expr<u32> = expr(any((var(1), var(2), var(3))));
59 let expected: Expr<u32> = expr(any((var(1), var(2), var(3))));
60
61 DedupList.visit_mut_expr(&mut x);
62
63 assert_eq!(x.to_string(), expected.to_string());
64 }
65
66 #[test]
67 fn dedup_empty_list() {
68 let mut x: Expr<u32> = expr(any(()));
69 let expected: Expr<u32> = expr(any(()));
70
71 DedupList.visit_mut_expr(&mut x);
72
73 assert_eq!(x.to_string(), expected.to_string());
74 }
75
76 #[test]
77 fn dedup_single_element() {
78 let mut x: Expr<u32> = expr(any((var(1),)));
79 let expected: Expr<u32> = expr(any((var(1),)));
80
81 DedupList.visit_mut_expr(&mut x);
82
83 assert_eq!(x.to_string(), expected.to_string());
84 }
85
86 #[test]
87 fn dedup_all_same_elements() {
88 let mut x: Expr<u32> = expr(any((var(1), var(1), var(1), var(1))));
89 let expected: Expr<u32> = expr(any((var(1),)));
90
91 DedupList.visit_mut_expr(&mut x);
92
93 assert_eq!(x.to_string(), expected.to_string());
94 }
95
96 #[test]
97 fn dedup_nested_expressions() {
98 let mut x: Expr<u32> = expr(any((
99 all((var(1), var(2))),
100 var(3),
101 all((var(1), var(2))),
102 var(3),
103 )));
104 let expected: Expr<u32> = expr(any((all((var(1), var(2))), var(3))));
105
106 DedupList.visit_mut_expr(&mut x);
107
108 assert_eq!(x.to_string(), expected.to_string());
109 }
110
111 #[test]
112 fn dedup_with_constants() {
113 let mut x: Expr<u32> = expr(any((const_(true), var(1), const_(true), const_(false))));
114 let expected: Expr<u32> = expr(any((const_(true), var(1), const_(false))));
115
116 DedupList.visit_mut_expr(&mut x);
117
118 assert_eq!(x.to_string(), expected.to_string());
119 }
120
121 #[test]
122 fn dedup_preserves_order() {
123 let mut x: Expr<u32> = expr(any((var(3), var(1), var(2), var(1), var(3))));
124 let expected: Expr<u32> = expr(any((var(3), var(1), var(2))));
125
126 DedupList.visit_mut_expr(&mut x);
127
128 assert_eq!(x.to_string(), expected.to_string());
129 }
130
131 #[test]
132 fn dedup_non_list_expression() {
133 let mut x: Expr<u32> = expr(not(var(1)));
134 let expected: Expr<u32> = expr(not(var(1)));
135
136 DedupList.visit_mut_expr(&mut x);
137
138 assert_eq!(x.to_string(), expected.to_string());
139 }
140}