1use crate::prelude::*;
2use std::collections::HashMap;
3
4fn mark_forall_param_name_if_tracked(
8 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
9 name: &IdentifierName,
10) {
11 match coverage_by_forall_param.get_mut(name) {
12 Some(is_mentioned) => {
13 *is_mentioned = true;
14 }
15 None => {}
16 }
17}
18
19fn mark_forall_param_coverage_in_param_type(
20 param_type: &ParamType,
21 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
22) {
23 match param_type {
24 ParamType::Obj(obj) => {
25 mark_forall_param_coverage_in_obj(obj, coverage_by_forall_param);
26 }
27 ParamType::Set(_) | ParamType::NonemptySet(_) | ParamType::FiniteSet(_) => {}
28 ParamType::Struct(struct_ty) => {
29 for param_obj in struct_ty.args.iter() {
30 mark_forall_param_coverage_in_obj(param_obj, coverage_by_forall_param);
31 }
32 }
33 }
34}
35
36fn mark_forall_param_coverage_in_atom(
37 atom: &Atom,
38 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
39) {
40 match atom {
41 Atom::Identifier(identifier) => {
42 mark_forall_param_name_if_tracked(coverage_by_forall_param, &identifier.name);
43 }
44 Atom::IdentifierWithMod(_) => {}
45 Atom::FieldAccess(field_access) => {
46 mark_forall_param_name_if_tracked(coverage_by_forall_param, &field_access.name);
47 }
48 Atom::FieldAccessWithMod(_) => {}
49 }
50}
51
52fn mark_forall_param_coverage_in_obj(
53 obj: &Obj,
54 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
55) {
56 match obj {
57 Obj::Identifier(identifier) => {
58 mark_forall_param_name_if_tracked(coverage_by_forall_param, &identifier.name);
59 }
60 Obj::IdentifierWithMod(_) => {}
61 Obj::FieldAccess(field_access) => {
62 mark_forall_param_name_if_tracked(coverage_by_forall_param, &field_access.name);
63 }
64 Obj::FieldAccessWithMod(_) => {}
65 Obj::FnObj(fn_obj) => {
66 mark_forall_param_coverage_in_atom(fn_obj.head.as_ref(), coverage_by_forall_param);
67 for group in fn_obj.body.iter() {
68 for boxed_obj in group.iter() {
69 mark_forall_param_coverage_in_obj(boxed_obj.as_ref(), coverage_by_forall_param);
70 }
71 }
72 }
73 Obj::Number(_) | Obj::StandardSet(_) => {}
74 Obj::Add(binary) => {
75 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
76 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
77 }
78 Obj::Sub(binary) => {
79 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
80 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
81 }
82 Obj::Mul(binary) => {
83 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
84 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
85 }
86 Obj::Div(binary) => {
87 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
88 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
89 }
90 Obj::Mod(binary) => {
91 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
92 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
93 }
94 Obj::Pow(binary) => {
95 mark_forall_param_coverage_in_obj(binary.base.as_ref(), coverage_by_forall_param);
96 mark_forall_param_coverage_in_obj(binary.exponent.as_ref(), coverage_by_forall_param);
97 }
98 Obj::Union(binary) => {
99 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
100 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
101 }
102 Obj::Intersect(binary) => {
103 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
104 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
105 }
106 Obj::SetMinus(binary) => {
107 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
108 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
109 }
110 Obj::SetDiff(binary) => {
111 mark_forall_param_coverage_in_obj(binary.left.as_ref(), coverage_by_forall_param);
112 mark_forall_param_coverage_in_obj(binary.right.as_ref(), coverage_by_forall_param);
113 }
114 Obj::Cup(unary) => {
115 mark_forall_param_coverage_in_obj(unary.left.as_ref(), coverage_by_forall_param);
116 }
117 Obj::Cap(unary) => {
118 mark_forall_param_coverage_in_obj(unary.left.as_ref(), coverage_by_forall_param);
119 }
120 Obj::PowerSet(unary) => {
121 mark_forall_param_coverage_in_obj(unary.set.as_ref(), coverage_by_forall_param);
122 }
123 Obj::ListSet(list_set) => {
124 for boxed_obj in list_set.list.iter() {
125 mark_forall_param_coverage_in_obj(boxed_obj.as_ref(), coverage_by_forall_param);
126 }
127 }
128 Obj::SetBuilder(set_builder) => {
129 mark_forall_param_coverage_in_obj(
130 set_builder.param_set.as_ref(),
131 coverage_by_forall_param,
132 );
133 for inner_fact in set_builder.facts.iter() {
134 mark_forall_param_coverage_in_or_and_chain_atomic_fact(
135 inner_fact,
136 coverage_by_forall_param,
137 );
138 }
139 }
140 Obj::FnSet(fn_set) => {
141 for param_def_with_set in fn_set.params_def_with_set.iter() {
142 mark_forall_param_coverage_in_obj(
143 ¶m_def_with_set.set,
144 coverage_by_forall_param,
145 );
146 }
147 for dom_fact in fn_set.dom_facts.iter() {
148 mark_forall_param_coverage_in_or_and_chain_atomic_fact(
149 dom_fact,
150 coverage_by_forall_param,
151 );
152 }
153 mark_forall_param_coverage_in_obj(fn_set.ret_set.as_ref(), coverage_by_forall_param);
154 }
155 Obj::Cart(cart) => {
156 for boxed_arg in cart.args.iter() {
157 mark_forall_param_coverage_in_obj(boxed_arg.as_ref(), coverage_by_forall_param);
158 }
159 }
160 Obj::CartDim(cart_dim) => {
161 mark_forall_param_coverage_in_obj(cart_dim.set.as_ref(), coverage_by_forall_param);
162 }
163 Obj::Proj(proj) => {
164 mark_forall_param_coverage_in_obj(proj.set.as_ref(), coverage_by_forall_param);
165 mark_forall_param_coverage_in_obj(proj.dim.as_ref(), coverage_by_forall_param);
166 }
167 Obj::TupleDim(tuple_dim) => {
168 mark_forall_param_coverage_in_obj(tuple_dim.arg.as_ref(), coverage_by_forall_param);
169 }
170 Obj::Tuple(tuple_obj) => {
171 for boxed_arg in tuple_obj.args.iter() {
172 mark_forall_param_coverage_in_obj(boxed_arg.as_ref(), coverage_by_forall_param);
173 }
174 }
175 Obj::Count(count) => {
176 mark_forall_param_coverage_in_obj(count.set.as_ref(), coverage_by_forall_param);
177 }
178 Obj::Range(range) => {
179 mark_forall_param_coverage_in_obj(range.start.as_ref(), coverage_by_forall_param);
180 mark_forall_param_coverage_in_obj(range.end.as_ref(), coverage_by_forall_param);
181 }
182 Obj::ClosedRange(closed_range) => {
183 mark_forall_param_coverage_in_obj(
184 closed_range.start.as_ref(),
185 coverage_by_forall_param,
186 );
187 mark_forall_param_coverage_in_obj(closed_range.end.as_ref(), coverage_by_forall_param);
188 }
189 Obj::Choose(choose) => {
190 mark_forall_param_coverage_in_obj(choose.set.as_ref(), coverage_by_forall_param);
191 }
192 Obj::ObjAtIndex(obj_at_index) => {
193 mark_forall_param_coverage_in_obj(obj_at_index.obj.as_ref(), coverage_by_forall_param);
194 mark_forall_param_coverage_in_obj(
195 obj_at_index.index.as_ref(),
196 coverage_by_forall_param,
197 );
198 }
199 Obj::FamilyObj(family) => {
200 for param_obj in family.params.iter() {
201 mark_forall_param_coverage_in_obj(param_obj, coverage_by_forall_param);
202 }
203 }
204 Obj::StructObj(struct_ty) => {
205 for param_obj in struct_ty.args.iter() {
206 mark_forall_param_coverage_in_obj(param_obj, coverage_by_forall_param);
207 }
208 }
209 }
210}
211
212fn mark_forall_param_coverage_in_atomic_fact(
213 atomic_fact: &AtomicFact,
214 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
215) {
216 match atomic_fact {
217 AtomicFact::NormalAtomicFact(fact) => {
218 for body_obj in fact.body.iter() {
219 mark_forall_param_coverage_in_obj(body_obj, coverage_by_forall_param);
220 }
221 }
222 AtomicFact::NotNormalAtomicFact(fact) => {
223 for body_obj in fact.body.iter() {
224 mark_forall_param_coverage_in_obj(body_obj, coverage_by_forall_param);
225 }
226 }
227 AtomicFact::EqualFact(fact) => {
228 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
229 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
230 }
231 AtomicFact::LessFact(fact) => {
232 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
233 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
234 }
235 AtomicFact::GreaterFact(fact) => {
236 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
237 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
238 }
239 AtomicFact::LessEqualFact(fact) => {
240 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
241 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
242 }
243 AtomicFact::GreaterEqualFact(fact) => {
244 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
245 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
246 }
247 AtomicFact::NotEqualFact(fact) => {
248 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
249 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
250 }
251 AtomicFact::NotLessFact(fact) => {
252 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
253 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
254 }
255 AtomicFact::NotGreaterFact(fact) => {
256 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
257 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
258 }
259 AtomicFact::NotLessEqualFact(fact) => {
260 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
261 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
262 }
263 AtomicFact::NotGreaterEqualFact(fact) => {
264 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
265 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
266 }
267 AtomicFact::IsSetFact(fact) => {
268 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
269 }
270 AtomicFact::NotIsSetFact(fact) => {
271 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
272 }
273 AtomicFact::IsNonemptySetFact(fact) => {
274 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
275 }
276 AtomicFact::NotIsNonemptySetFact(fact) => {
277 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
278 }
279 AtomicFact::IsFiniteSetFact(fact) => {
280 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
281 }
282 AtomicFact::NotIsFiniteSetFact(fact) => {
283 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
284 }
285 AtomicFact::InFact(fact) => {
286 mark_forall_param_coverage_in_obj(&fact.element, coverage_by_forall_param);
287 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
288 }
289 AtomicFact::NotInFact(fact) => {
290 mark_forall_param_coverage_in_obj(&fact.element, coverage_by_forall_param);
291 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
292 }
293 AtomicFact::IsCartFact(fact) => {
294 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
295 }
296 AtomicFact::NotIsCartFact(fact) => {
297 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
298 }
299 AtomicFact::IsTupleFact(fact) => {
300 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
301 }
302 AtomicFact::NotIsTupleFact(fact) => {
303 mark_forall_param_coverage_in_obj(&fact.set, coverage_by_forall_param);
304 }
305 AtomicFact::SubsetFact(fact) => {
306 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
307 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
308 }
309 AtomicFact::SupersetFact(fact) => {
310 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
311 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
312 }
313 AtomicFact::NotSubsetFact(fact) => {
314 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
315 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
316 }
317 AtomicFact::NotSupersetFact(fact) => {
318 mark_forall_param_coverage_in_obj(&fact.left, coverage_by_forall_param);
319 mark_forall_param_coverage_in_obj(&fact.right, coverage_by_forall_param);
320 }
321 AtomicFact::RestrictFact(fact) => {
322 mark_forall_param_coverage_in_obj(&fact.obj, coverage_by_forall_param);
323 mark_forall_param_coverage_in_obj(
324 &fact.obj_can_restrict_to_fn_set,
325 coverage_by_forall_param,
326 );
327 }
328 AtomicFact::NotRestrictFact(fact) => {
329 mark_forall_param_coverage_in_obj(&fact.obj, coverage_by_forall_param);
330 mark_forall_param_coverage_in_obj(
331 &fact.obj_cannot_restrict_to_fn_set,
332 coverage_by_forall_param,
333 );
334 }
335 }
336}
337
338fn mark_forall_param_coverage_in_and_chain_atomic_fact(
339 parent_fact: &AndChainAtomicFact,
340 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
341) {
342 match parent_fact {
343 AndChainAtomicFact::AtomicFact(atomic_fact) => {
344 mark_forall_param_coverage_in_atomic_fact(atomic_fact, coverage_by_forall_param);
345 }
346 AndChainAtomicFact::AndFact(and_fact) => {
347 for inner_atomic in and_fact.facts.iter() {
348 mark_forall_param_coverage_in_atomic_fact(inner_atomic, coverage_by_forall_param);
349 }
350 }
351 AndChainAtomicFact::ChainFact(chain_fact) => {
352 for chain_obj in chain_fact.objs.iter() {
353 mark_forall_param_coverage_in_obj(chain_obj, coverage_by_forall_param);
354 }
355 }
356 }
357}
358
359fn mark_forall_param_coverage_in_or_and_chain_atomic_fact(
360 parent_fact: &OrAndChainAtomicFact,
361 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
362) {
363 match parent_fact {
364 OrAndChainAtomicFact::AtomicFact(atomic_fact) => {
365 mark_forall_param_coverage_in_atomic_fact(atomic_fact, coverage_by_forall_param);
366 }
367 OrAndChainAtomicFact::AndFact(and_fact) => {
368 for inner_atomic in and_fact.facts.iter() {
369 mark_forall_param_coverage_in_atomic_fact(inner_atomic, coverage_by_forall_param);
370 }
371 }
372 OrAndChainAtomicFact::ChainFact(chain_fact) => {
373 for chain_obj in chain_fact.objs.iter() {
374 mark_forall_param_coverage_in_obj(chain_obj, coverage_by_forall_param);
375 }
376 }
377 OrAndChainAtomicFact::OrFact(or_fact) => {
378 for branch in or_fact.facts.iter() {
379 mark_forall_param_coverage_in_and_chain_atomic_fact(
380 branch,
381 coverage_by_forall_param,
382 );
383 }
384 }
385 }
386}
387
388fn mark_forall_param_coverage_in_exist_fact(
389 exist_fact: &ExistFact,
390 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
391) {
392 for param_def_with_type in exist_fact.params_def_with_type.iter() {
393 mark_forall_param_coverage_in_param_type(
394 ¶m_def_with_type.param_type,
395 coverage_by_forall_param,
396 );
397 }
398 for inner_fact in exist_fact.facts.iter() {
399 mark_forall_param_coverage_in_or_and_chain_atomic_fact(
400 inner_fact,
401 coverage_by_forall_param,
402 );
403 }
404}
405
406fn mark_forall_param_coverage_in_exist_or_and_chain_atomic_fact(
407 parent_fact: &ExistOrAndChainAtomicFact,
408 coverage_by_forall_param: &mut HashMap<IdentifierName, bool>,
409) {
410 match parent_fact {
411 ExistOrAndChainAtomicFact::AtomicFact(atomic_fact) => {
412 mark_forall_param_coverage_in_atomic_fact(atomic_fact, coverage_by_forall_param);
413 }
414 ExistOrAndChainAtomicFact::AndFact(and_fact) => {
415 for inner_atomic in and_fact.facts.iter() {
416 mark_forall_param_coverage_in_atomic_fact(inner_atomic, coverage_by_forall_param);
417 }
418 }
419 ExistOrAndChainAtomicFact::ChainFact(chain_fact) => {
420 for chain_obj in chain_fact.objs.iter() {
421 mark_forall_param_coverage_in_obj(chain_obj, coverage_by_forall_param);
422 }
423 }
424 ExistOrAndChainAtomicFact::OrFact(or_fact) => {
425 for branch in or_fact.facts.iter() {
426 mark_forall_param_coverage_in_and_chain_atomic_fact(
427 branch,
428 coverage_by_forall_param,
429 );
430 }
431 }
432 ExistOrAndChainAtomicFact::ExistFact(exist_fact) => {
433 mark_forall_param_coverage_in_exist_fact(exist_fact, coverage_by_forall_param);
434 }
435 }
436}
437
438impl ForallFact {
439 pub fn error_messages_if_forall_param_missing_in_some_then_clause(&self) -> Vec<(usize, String)> {
440 let forall_param_names =
441 ParamGroupWithParamType::collect_param_names(&self.params_def_with_type);
442 if forall_param_names.is_empty() {
443 return Vec::new();
444 }
445 let mut error_messages = Vec::new();
446 let mut then_index: usize = 0;
447 while then_index < self.then_facts.len() {
448 let then_fact = &self.then_facts[then_index];
449 let mut coverage_by_forall_param: HashMap<IdentifierName, bool> = HashMap::new();
450 for param_name in forall_param_names.iter() {
451 coverage_by_forall_param.insert(param_name.clone(), false);
452 }
453 mark_forall_param_coverage_in_exist_or_and_chain_atomic_fact(
454 then_fact,
455 &mut coverage_by_forall_param,
456 );
457 let mut missing_param_names = Vec::new();
458 for param_name in forall_param_names.iter() {
459 let is_mentioned_in_then_clause = match coverage_by_forall_param.get(param_name) {
460 Some(flag) => *flag,
461 None => false,
462 };
463 if !is_mentioned_in_then_clause {
464 missing_param_names.push(param_name.clone());
465 }
466 }
467 if !missing_param_names.is_empty() {
468 let missing_list = missing_param_names.join(", ");
469 error_messages.push((
470 then_index,
471 format!(
472 "then-clause `{}` does not mention forall parameter(s) {{{}}}",
473 then_fact, missing_list,
474 ),
475 ));
476 }
477 then_index += 1;
478 }
479 error_messages
480 }
481}
482
483impl ForallFactWithIff {
484 pub fn error_messages_if_forall_param_missing_in_forall_then_clause(&self) -> Vec<(usize, String)> {
486 self.forall_fact
487 .error_messages_if_forall_param_missing_in_some_then_clause()
488 }
489}