1use crate::prelude::*;
2
3impl Runtime {
4 pub fn verify_non_equational_atomic_fact(
5 &mut self,
6 atomic_fact: &AtomicFact,
7 verify_state: &VerifyState,
8 post_process: bool,
9 ) -> Result<StmtResult, RuntimeError> {
10 let mut result =
11 self.verify_non_equational_atomic_fact_with_builtin_rules(atomic_fact, verify_state)?;
12 if result.is_true() {
13 return Ok(result);
14 }
15
16 result = self.verify_non_equational_atomic_fact_with_known_atomic_facts(atomic_fact)?;
17 if result.is_true() {
18 return Ok(result);
19 }
20
21 if verify_state.is_round_0() {
22 let verify_state_add_one_round = verify_state.new_state_with_round_increased();
23
24 if let Some(verified_by_definition) =
25 self.verify_atomic_fact_using_builtin_or_prop_definition(atomic_fact, verify_state)?
26 {
27 return Ok(verified_by_definition);
28 }
29
30 result = self
31 .verify_atomic_fact_with_known_forall(atomic_fact, &verify_state_add_one_round)?;
32 if result.is_true() {
33 return Ok(result);
34 }
35 }
36
37 if post_process {
38 result =
39 self.post_process_non_equational_atomic_fact(atomic_fact, verify_state, result)?;
40 if result.is_true() {
41 return Ok(result);
42 }
43 }
44
45 Ok((StmtUnknown::new()).into())
46 }
47
48 pub fn verify_non_equational_atomic_fact_with_known_atomic_facts(
49 &mut self,
50 atomic_fact: &AtomicFact,
51 ) -> Result<StmtResult, RuntimeError> {
52 let result = if atomic_fact.number_of_args() == 1 {
53 self.verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param(atomic_fact)?
54 } else if atomic_fact.number_of_args() == 2 {
55 self.verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params(atomic_fact)?
56 } else {
57 self.verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params(
58 atomic_fact,
59 )?
60 };
61
62 if result.is_true() {
63 return Ok(result);
64 }
65
66 Ok(result)
67 }
68
69 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param(
70 &mut self,
71 atomic_fact: &AtomicFact,
72 ) -> Result<StmtResult, RuntimeError> {
73 let mut all_objs_equal_to_arg =
74 self.get_all_objs_equal_to_given(&atomic_fact.args()[0].to_string());
75
76 if let Some(calculated_obj) = self.resolve_obj_to_number(&atomic_fact.args()[0]) {
77 if calculated_obj.to_string() != atomic_fact.args()[0].to_string() {
78 let equal_tos = self.get_all_objs_equal_to_given(&calculated_obj.to_string());
79 all_objs_equal_to_arg.extend(equal_tos);
80 }
81 }
82
83 if all_objs_equal_to_arg.is_empty() {
84 all_objs_equal_to_arg.push(atomic_fact.args()[0].to_string());
85 }
86
87 for environment in self.iter_environments_from_top() {
88 let result = Self::verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param_with_facts_in_environment(environment, atomic_fact, &all_objs_equal_to_arg)?;
89 if result.is_true() {
90 return Ok(result);
91 }
92 }
93
94 let arg = atomic_fact.args()[0].clone();
95 let arg_resolved = self.resolve_obj(&arg);
96 if arg_resolved.to_string() != arg.to_string() {
97 let rewritten =
98 Self::atomic_fact_with_resolved_unary_operand(atomic_fact, arg_resolved);
99 return self
100 .verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param(&rewritten);
101 }
102
103 Ok((StmtUnknown::new()).into())
104 }
105
106 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params(
107 &mut self,
108 atomic_fact: &AtomicFact,
109 ) -> Result<StmtResult, RuntimeError> {
110 let mut all_objs_equal_to_arg0 =
111 self.get_all_objs_equal_to_given(&atomic_fact.args()[0].to_string());
112 if let Some(calculated_obj) = self.resolve_obj_to_number(&atomic_fact.args()[0]) {
113 if calculated_obj.to_string() != atomic_fact.args()[0].to_string() {
114 let equal_tos = self.get_all_objs_equal_to_given(&calculated_obj.to_string());
115 all_objs_equal_to_arg0.extend(equal_tos);
116 }
117 }
118 if all_objs_equal_to_arg0.is_empty() {
119 all_objs_equal_to_arg0.push(atomic_fact.args()[0].to_string());
120 }
121 let mut all_objs_equal_to_arg1 =
122 self.get_all_objs_equal_to_given(&atomic_fact.args()[1].to_string());
123 if let Some(calculated_obj) = self.resolve_obj_to_number(&atomic_fact.args()[1]) {
124 if calculated_obj.to_string() != atomic_fact.args()[1].to_string() {
125 let equal_tos = self.get_all_objs_equal_to_given(&calculated_obj.to_string());
126 all_objs_equal_to_arg1.extend(equal_tos);
127 }
128 }
129 if all_objs_equal_to_arg1.is_empty() {
130 all_objs_equal_to_arg1.push(atomic_fact.args()[1].to_string());
131 }
132
133 for environment in self.iter_environments_from_top() {
134 let result = Self::verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params_with_facts_in_environment(environment, atomic_fact, &all_objs_equal_to_arg0, &all_objs_equal_to_arg1)?;
135 if result.is_true() {
136 return Ok(result);
137 }
138 }
139
140 let left = atomic_fact.args()[0].clone();
141 let right = atomic_fact.args()[1].clone();
142 let left_resolved = self.resolve_obj(&left);
143 let right_resolved = self.resolve_obj(&right);
144 if left_resolved.to_string() != left.to_string()
145 || right_resolved.to_string() != right.to_string()
146 {
147 let rewritten = Self::atomic_fact_with_resolved_binary_operands(
148 atomic_fact,
149 left_resolved,
150 right_resolved,
151 );
152 return self
153 .verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params(&rewritten);
154 }
155
156 Ok((StmtUnknown::new()).into())
157 }
158
159 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params(
160 &mut self,
161 atomic_fact: &AtomicFact,
162 ) -> Result<StmtResult, RuntimeError> {
163 let mut all_objs_equal_to_each_arg: Vec<Vec<String>> = Vec::new();
164 for arg in atomic_fact.args().iter() {
165 let mut all_objs_equal_to_current_arg =
166 self.get_all_objs_equal_to_given(&arg.to_string());
167 if all_objs_equal_to_current_arg.is_empty() {
168 all_objs_equal_to_current_arg.push(arg.to_string());
169 }
170 all_objs_equal_to_each_arg.push(all_objs_equal_to_current_arg);
171 }
172
173 for environment in self.iter_environments_from_top() {
174 let result = Self::verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params_with_facts_in_environment(
175 environment,
176 atomic_fact,
177 &all_objs_equal_to_each_arg,
178 )?;
179 if result.is_true() {
180 return Ok(result);
181 }
182 }
183
184 let old_args = atomic_fact.args();
185 let mut new_args: Vec<Obj> = Vec::with_capacity(old_args.len());
186 let mut any_changed = false;
187 for a in old_args.iter() {
188 let r = self.resolve_obj(a);
189 if r.to_string() != a.to_string() {
190 any_changed = true;
191 }
192 new_args.push(r);
193 }
194 if any_changed {
195 let rewritten = Self::atomic_fact_with_resolved_predicate_args(atomic_fact, new_args);
196 return self
197 .verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params(
198 &rewritten,
199 );
200 }
201
202 Ok((StmtUnknown::new()).into())
203 }
204
205 fn atomic_fact_with_resolved_unary_operand(fact: &AtomicFact, x: Obj) -> AtomicFact {
206 let line_file = fact.line_file();
207 match fact {
208 AtomicFact::IsSetFact(_) => IsSetFact::new(x, line_file).into(),
209 AtomicFact::IsNonemptySetFact(_) => IsNonemptySetFact::new(x, line_file).into(),
210 AtomicFact::IsFiniteSetFact(_) => IsFiniteSetFact::new(x, line_file).into(),
211 AtomicFact::IsCartFact(_) => IsCartFact::new(x, line_file).into(),
212 AtomicFact::IsTupleFact(_) => IsTupleFact::new(x, line_file).into(),
213 AtomicFact::NotIsSetFact(_) => NotIsSetFact::new(x, line_file).into(),
214 AtomicFact::NotIsNonemptySetFact(_) => NotIsNonemptySetFact::new(x, line_file).into(),
215 AtomicFact::NotIsFiniteSetFact(_) => NotIsFiniteSetFact::new(x, line_file).into(),
216 AtomicFact::NotIsCartFact(_) => NotIsCartFact::new(x, line_file).into(),
217 AtomicFact::NotIsTupleFact(_) => NotIsTupleFact::new(x, line_file).into(),
218 AtomicFact::NormalAtomicFact(n) => {
219 NormalAtomicFact::new(n.predicate.clone(), vec![x], line_file).into()
220 }
221 AtomicFact::NotNormalAtomicFact(n) => {
222 NotNormalAtomicFact::new(n.predicate.clone(), vec![x], line_file).into()
223 }
224 _ => unreachable!(
225 "atomic_fact_with_resolved_unary_operand: expected a one-argument atomic fact"
226 ),
227 }
228 }
229
230 fn atomic_fact_with_resolved_binary_operands(
231 fact: &AtomicFact,
232 left: Obj,
233 right: Obj,
234 ) -> AtomicFact {
235 let line_file = fact.line_file();
236 match fact {
237 AtomicFact::EqualFact(_) => EqualFact::new(left, right, line_file).into(),
238 AtomicFact::LessFact(_) => LessFact::new(left, right, line_file).into(),
239 AtomicFact::GreaterFact(_) => GreaterFact::new(left, right, line_file).into(),
240 AtomicFact::LessEqualFact(_) => LessEqualFact::new(left, right, line_file).into(),
241 AtomicFact::GreaterEqualFact(_) => GreaterEqualFact::new(left, right, line_file).into(),
242 AtomicFact::InFact(_) => InFact::new(left, right, line_file).into(),
243 AtomicFact::SubsetFact(_) => SubsetFact::new(left, right, line_file).into(),
244 AtomicFact::SupersetFact(_) => SupersetFact::new(left, right, line_file).into(),
245 AtomicFact::NotEqualFact(_) => NotEqualFact::new(left, right, line_file).into(),
246 AtomicFact::NotLessFact(_) => NotLessFact::new(left, right, line_file).into(),
247 AtomicFact::NotGreaterFact(_) => NotGreaterFact::new(left, right, line_file).into(),
248 AtomicFact::NotLessEqualFact(_) => NotLessEqualFact::new(left, right, line_file).into(),
249 AtomicFact::NotGreaterEqualFact(_) => {
250 NotGreaterEqualFact::new(left, right, line_file).into()
251 }
252 AtomicFact::NotInFact(_) => NotInFact::new(left, right, line_file).into(),
253 AtomicFact::NotSubsetFact(_) => NotSubsetFact::new(left, right, line_file).into(),
254 AtomicFact::NotSupersetFact(_) => NotSupersetFact::new(left, right, line_file).into(),
255 AtomicFact::RestrictFact(_) => RestrictFact::new(left, right, line_file).into(),
256 AtomicFact::NotRestrictFact(_) => NotRestrictFact::new(left, right, line_file).into(),
257 AtomicFact::NormalAtomicFact(x) => {
258 NormalAtomicFact::new(x.predicate.clone(), vec![left, right], line_file).into()
259 }
260 AtomicFact::NotNormalAtomicFact(x) => {
261 NotNormalAtomicFact::new(x.predicate.clone(), vec![left, right], line_file).into()
262 }
263 _ => unreachable!(
264 "atomic_fact_with_resolved_binary_operands: expected a two-argument atomic fact"
265 ),
266 }
267 }
268
269 fn atomic_fact_with_resolved_predicate_args(fact: &AtomicFact, args: Vec<Obj>) -> AtomicFact {
270 let line_file = fact.line_file();
271 match fact {
272 AtomicFact::NormalAtomicFact(x) => {
273 NormalAtomicFact::new(x.predicate.clone(), args, line_file).into()
274 }
275 AtomicFact::NotNormalAtomicFact(x) => {
276 NotNormalAtomicFact::new(x.predicate.clone(), args, line_file).into()
277 }
278 _ => unreachable!(
279 "atomic_fact_with_resolved_predicate_args: expected NormalAtomicFact or NotNormalAtomicFact"
280 ),
281 }
282 }
283
284 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param_with_facts_in_environment(
285 environment: &Environment,
286 atomic_fact: &AtomicFact,
287 all_objs_equal_to_arg: &Vec<String>,
288 ) -> Result<StmtResult, RuntimeError> {
289 if let Some(known_facts_map) = environment
290 .known_atomic_facts_with_1_arg
291 .get(&(atomic_fact.key(), atomic_fact.is_true()))
292 {
293 for obj in all_objs_equal_to_arg.iter() {
294 if let Some(known_atomic_fact) = known_facts_map.get(obj) {
295 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
296 atomic_fact.clone().into(),
297 VerifiedByResult::Fact(
298 known_atomic_fact.clone().into(),
299 known_atomic_fact.to_string(),
300 ),
301 Vec::new(),
302 ))
303 .into());
304 }
305 }
306 }
307
308 Ok((StmtUnknown::new()).into())
309 }
310
311 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params_with_facts_in_environment(
312 environment: &Environment,
313 atomic_fact: &AtomicFact,
314 all_objs_equal_to_arg0: &Vec<String>,
315 all_objs_equal_to_arg1: &Vec<String>,
316 ) -> Result<StmtResult, RuntimeError> {
317 if let Some(known_facts_map) = environment
318 .known_atomic_facts_with_2_args
319 .get(&(atomic_fact.key(), atomic_fact.is_true()))
320 {
321 for obj0 in all_objs_equal_to_arg0.iter() {
322 for obj1 in all_objs_equal_to_arg1.iter() {
323 if let Some(known_atomic_fact) =
324 known_facts_map.get(&(obj0.clone(), obj1.clone()))
325 {
326 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
327 atomic_fact.clone().into(),
328 VerifiedByResult::Fact(
329 known_atomic_fact.clone().into(),
330 known_atomic_fact.to_string(),
331 ),
332 Vec::new(),
333 ))
334 .into());
335 }
336 }
337 }
338 }
339
340 if let Some(alt) = atomic_fact.transposed_binary_order_equivalent() {
342 if let Some(known_facts_map) = environment
343 .known_atomic_facts_with_2_args
344 .get(&(alt.key(), alt.is_true()))
345 {
346 for obj0 in all_objs_equal_to_arg1.iter() {
347 for obj1 in all_objs_equal_to_arg0.iter() {
348 if let Some(known_atomic_fact) =
349 known_facts_map.get(&(obj0.clone(), obj1.clone()))
350 {
351 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
352 atomic_fact.clone().into(),
353 VerifiedByResult::Fact(
354 known_atomic_fact.clone().into(),
355 known_atomic_fact.to_string(),
356 ),
357 Vec::new(),
358 ))
359 .into());
360 }
361 }
362 }
363 }
364 }
365
366 Ok((StmtUnknown::new()).into())
367 }
368
369 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params_with_facts_in_environment(
370 environment: &Environment,
371 atomic_fact: &AtomicFact,
372 all_objs_equal_to_each_arg: &Vec<Vec<String>>,
373 ) -> Result<StmtResult, RuntimeError> {
374 if let Some(known_facts) = environment
375 .known_atomic_facts_with_0_or_more_than_2_args
376 .get(&(atomic_fact.key(), atomic_fact.is_true()))
377 {
378 for known_fact in known_facts.iter() {
379 if known_fact.args().len() != atomic_fact.args().len() {
380 let message = format!(
381 "known atomic fact {} has different number of args than the given fact {}",
382 known_fact.to_string(),
383 atomic_fact.to_string()
384 );
385 return Err({
386 VerifyRuntimeError(RuntimeErrorStruct::new(
387 Some(Fact::from(atomic_fact.clone()).into_stmt()),
388 message.clone(),
389 atomic_fact.line_file(),
390 Some(
391 UnknownRuntimeError(RuntimeErrorStruct::new(
392 Some(Fact::from(atomic_fact.clone()).into_stmt()),
393 message,
394 atomic_fact.line_file(),
395 None,
396 vec![],
397 ))
398 .into(),
399 ),
400 vec![],
401 ))
402 .into()
403 });
404 }
405 let mut all_args_match = true;
406 for (index, known_arg) in known_fact.args().iter().enumerate() {
407 let known_arg_string = known_arg.to_string();
408 if !all_objs_equal_to_each_arg[index].contains(&known_arg_string) {
409 all_args_match = false;
410 break;
411 }
412 }
413 if all_args_match {
414 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
415 atomic_fact.clone().into(),
416 VerifiedByResult::Fact(known_fact.clone().into(), known_fact.to_string()),
417 Vec::new(),
418 ))
419 .into());
420 }
421 }
422 }
423
424 Ok((StmtUnknown::new()).into())
425 }
426
427 pub fn verify_fact(
428 &mut self,
429 fact: &Fact,
430 verify_state: &VerifyState,
431 ) -> Result<StmtResult, RuntimeError> {
432 match fact {
433 Fact::AtomicFact(atomic_fact) => self.verify_atomic_fact(atomic_fact, verify_state),
434 Fact::AndFact(and_fact) => self.verify_and_fact(and_fact, verify_state),
435 Fact::ChainFact(chain_fact) => self.verify_chain_fact(chain_fact, verify_state),
436 Fact::ForallFact(forall_fact) => self.verify_forall_fact(forall_fact, verify_state),
437 Fact::ForallFactWithIff(forall_iff) => {
438 self.verify_forall_fact_with_iff(forall_iff, verify_state)
439 }
440 Fact::NotForall(not_forall) => self.verify_not_forall_fact(not_forall, verify_state),
441 Fact::ExistFact(exist_fact) => self.verify_exist_fact(exist_fact, verify_state),
442 Fact::OrFact(or_fact) => self.verify_or_fact(or_fact, verify_state),
443 }
444 }
445
446 fn verify_subset_fact_by_membership_forall_definition(
447 &mut self,
448 subset_fact: &SubsetFact,
449 verify_state: &VerifyState,
450 ) -> Result<Option<StmtResult>, RuntimeError> {
451 let bound_param_name = self.generate_random_unused_name();
452 let membership_forall_fact = ForallFact::new(
453 ParamDefWithType::new(vec![ParamGroupWithParamType::new(
454 vec![bound_param_name.clone()],
455 ParamType::Obj(subset_fact.left.clone()),
456 )]),
457 vec![],
458 vec![InFact::new(
459 obj_for_bound_param_in_scope(bound_param_name.clone(), ParamObjType::Forall),
460 subset_fact.right.clone(),
461 subset_fact.line_file.clone(),
462 )
463 .into()],
464 subset_fact.line_file.clone(),
465 )?
466 .into();
467 let verify_forall_result = self.verify_fact(&membership_forall_fact, verify_state)?;
468 if !verify_forall_result.is_true() {
469 return Ok(None);
470 }
471 Ok(Some(
472 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
473 subset_fact.clone().into(),
474 "subset by definition (forall x in left: x in right)".to_string(),
475 Vec::new(),
476 ))
477 .into(),
478 ))
479 }
480
481 fn verify_superset_fact_by_membership_forall_definition(
482 &mut self,
483 superset_fact: &SupersetFact,
484 verify_state: &VerifyState,
485 ) -> Result<Option<StmtResult>, RuntimeError> {
486 let bound_param_name = self.generate_random_unused_name();
487 let membership_forall_fact = ForallFact::new(
488 ParamDefWithType::new(vec![ParamGroupWithParamType::new(
489 vec![bound_param_name.clone()],
490 ParamType::Obj(superset_fact.right.clone()),
491 )]),
492 vec![],
493 vec![InFact::new(
494 obj_for_bound_param_in_scope(bound_param_name.clone(), ParamObjType::Forall),
495 superset_fact.left.clone(),
496 superset_fact.line_file.clone(),
497 )
498 .into()],
499 superset_fact.line_file.clone(),
500 )?
501 .into();
502 let verify_forall_result = self.verify_fact(&membership_forall_fact, verify_state)?;
503 if !verify_forall_result.is_true() {
504 return Ok(None);
505 }
506 Ok(Some(
507 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
508 superset_fact.clone().into(),
509 "superset by definition (forall x in right: x in left)".to_string(),
510 Vec::new(),
511 ))
512 .into(),
513 ))
514 }
515
516 fn verify_atomic_fact_using_builtin_or_prop_definition(
518 &mut self,
519 atomic_fact: &AtomicFact,
520 verify_state: &VerifyState,
521 ) -> Result<Option<StmtResult>, RuntimeError> {
522 if let Some(result) =
523 self.verify_builtin_fact_with_their_definition(atomic_fact, verify_state)?
524 {
525 return Ok(Some(result));
526 }
527 if let AtomicFact::NormalAtomicFact(n) = atomic_fact {
528 return self.verify_normal_atomic_fact_using_its_definition(n, verify_state);
529 }
530 Ok(None)
531 }
532
533 fn verify_normal_atomic_fact_using_its_definition(
534 &mut self,
535 normal_atomic_fact: &NormalAtomicFact,
536 verify_state: &VerifyState,
537 ) -> Result<Option<StmtResult>, RuntimeError> {
538 if let Some(_) =
539 self.get_abstract_prop_definition_by_name(&normal_atomic_fact.predicate.to_string())
540 {
541 return Ok(None);
542 }
543
544 let predicate_name = normal_atomic_fact.predicate.to_string();
545
546 let definition = match self.get_prop_definition_by_name(&predicate_name) {
547 Some(definition_reference) => definition_reference.clone(),
548 None => {
549 return Err({
550 VerifyRuntimeError(RuntimeErrorStruct::new(
551 Some(Fact::from(normal_atomic_fact.clone()).into_stmt()),
552 format!("prop definition not found for {}", predicate_name),
553 normal_atomic_fact.line_file.clone(),
554 None,
555 vec![],
556 ))
557 .into()
558 })
559 }
560 };
561
562 let verify_state_for_definition_clauses = verify_state;
563
564 let args_param_types = match self.verify_args_satisfy_param_def_flat_types(
565 &definition.params_def_with_type,
566 &normal_atomic_fact.body,
567 verify_state_for_definition_clauses,
568 ParamObjType::DefHeader,
569 ) {
570 Ok(x) => x,
571 Err(_) => {
572 return Err({
573 VerifyRuntimeError(RuntimeErrorStruct::new(
574 Some(Fact::from(normal_atomic_fact.clone()).into_stmt()),
575 format!("failed to verify parameter types for {}", predicate_name),
576 normal_atomic_fact.line_file.clone(),
577 None,
578 vec![],
579 ))
580 .into()
581 })
582 }
583 };
584 if args_param_types.is_unknown() {
585 return Ok(None);
586 }
587
588 if definition.iff_facts.is_empty() {
589 return Ok(None);
590 }
591
592 let param_to_arg_map = definition
593 .params_def_with_type
594 .param_defs_and_args_to_param_to_arg_map(normal_atomic_fact.body.as_slice());
595
596 let mut infer_result = InferResult::new();
597 let mut definition_clause_descriptions: Vec<String> = Vec::new();
598
599 for iff_fact in definition.iff_facts.iter() {
600 let instantiated_iff_fact = self
601 .inst_fact(iff_fact, ¶m_to_arg_map, ParamObjType::DefHeader, None)
602 .map_err(|e| {
603 {
604 RuntimeError::from(VerifyRuntimeError(RuntimeErrorStruct::new(
605 Some(Fact::from(normal_atomic_fact.clone()).into_stmt()),
606 String::new(),
607 normal_atomic_fact.line_file.clone(),
608 Some(e),
609 vec![],
610 )))
611 }
612 })?;
613 let iff_clause_verify_result =
614 self.verify_fact(&instantiated_iff_fact, &verify_state_for_definition_clauses)?;
615 if iff_clause_verify_result.is_unknown() {
616 return Ok(None);
617 }
618 match &iff_clause_verify_result {
619 StmtResult::FactualStmtSuccess(factual_success) => {
620 infer_result.new_infer_result_inside(factual_success.infers.clone());
621 definition_clause_descriptions
622 .push(factual_success.verification_display_line());
623 }
624 StmtResult::NonFactualStmtSuccess(non_factual_success) => {
625 infer_result.new_infer_result_inside(non_factual_success.infers.clone());
626 }
627 StmtResult::StmtUnknown(_) => return Ok(None),
628 }
629 }
630
631 let verified_by_text = format!(
632 "prop with meaning `{}` (param constraints and definition clauses): {}",
633 predicate_name,
634 definition_clause_descriptions.join("; ")
635 );
636 infer_result.new_fact(&normal_atomic_fact.clone().into());
637 Ok(Some(
638 (FactualStmtSuccess::new_with_verified_by_known_fact_and_infer(
639 normal_atomic_fact.clone().into(),
640 infer_result,
641 VerifiedByResult::Fact(normal_atomic_fact.clone().into(), verified_by_text),
642 Vec::new(),
643 ))
644 .into(),
645 ))
646 }
647
648 fn verify_builtin_fact_with_their_definition(
649 &mut self,
650 fact: &AtomicFact,
651 verify_state: &VerifyState,
652 ) -> Result<Option<StmtResult>, RuntimeError> {
653 match fact {
654 AtomicFact::SubsetFact(subset_fact) => {
655 if let Some(verified_by_subset_definition) = self
656 .verify_subset_fact_by_membership_forall_definition(subset_fact, verify_state)?
657 {
658 return Ok(Some(verified_by_subset_definition));
659 }
660 return Ok(None);
661 }
662 AtomicFact::SupersetFact(superset_fact) => {
663 if let Some(verified_by_superset_definition) = self
664 .verify_superset_fact_by_membership_forall_definition(
665 superset_fact,
666 verify_state,
667 )?
668 {
669 return Ok(Some(verified_by_superset_definition));
670 }
671 return Ok(None);
672 }
673 AtomicFact::RestrictFact(restrict_fact) => {
674 if let Some(verified_by_restrict_definition) =
675 self.verify_restrict_fact_using_its_definition(restrict_fact, verify_state)?
676 {
677 return Ok(Some(verified_by_restrict_definition));
678 }
679 return Ok(None);
680 }
681 _ => {}
682 }
683 Ok(None)
684 }
685
686 fn post_process_non_equational_atomic_fact(
688 &mut self,
689 atomic_fact: &AtomicFact,
690 verify_state: &VerifyState,
691 result: StmtResult,
692 ) -> Result<StmtResult, RuntimeError> {
693 let Some(transposed_fact) = atomic_fact.transposed_binary_order_equivalent() else {
694 return Ok(result);
695 };
696 let transposed_result =
697 self.verify_non_equational_atomic_fact(&transposed_fact, verify_state, false)?;
698 match transposed_result {
699 StmtResult::FactualStmtSuccess(inner_success) => {
700 let FactualStmtSuccess {
701 verified_by,
702 infers: _,
703 stmt: _,
704 } = inner_success;
705 Ok(FactualStmtSuccess::new_with_verified_by_known_fact(
706 atomic_fact.clone().into(),
707 verified_by,
708 Vec::new(),
709 )
710 .into())
711 }
712 other if other.is_true() => Ok(other),
713 _ => Ok(result),
714 }
715 }
716}