1use crate::prelude::*;
2
3impl Runtime {
4 pub fn verify_non_equational_atomic_fact_with_known_atomic_facts(
5 &mut self,
6 atomic_fact: &AtomicFact,
7 ) -> Result<StmtResult, RuntimeError> {
8 let result = if atomic_fact.number_of_args() == 1 {
9 self.verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param(atomic_fact)?
10 } else if atomic_fact.number_of_args() == 2 {
11 self.verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params(atomic_fact)?
12 } else {
13 self.verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params(
14 atomic_fact,
15 )?
16 };
17
18 if result.is_true() {
19 return Ok(result);
20 }
21
22 Ok(result)
23 }
24
25 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param(
26 &mut self,
27 atomic_fact: &AtomicFact,
28 ) -> Result<StmtResult, RuntimeError> {
29 let mut all_objs_equal_to_arg =
30 self.get_all_objs_equal_to_given(&atomic_fact.args()[0].to_string());
31
32 if let Some(calculated_obj) = self.resolve_obj_to_number(&atomic_fact.args()[0]) {
33 if calculated_obj.to_string() != atomic_fact.args()[0].to_string() {
34 let equal_tos = self.get_all_objs_equal_to_given(&calculated_obj.to_string());
35 all_objs_equal_to_arg.extend(equal_tos);
36 }
37 }
38
39 if all_objs_equal_to_arg.is_empty() {
40 all_objs_equal_to_arg.push(atomic_fact.args()[0].to_string());
41 }
42
43 for environment in self.iter_environments_from_top() {
44 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)?;
45 if result.is_true() {
46 return Ok(result);
47 }
48 }
49
50 let arg = atomic_fact.args()[0].clone();
51 let arg_resolved = self.resolve_obj(&arg);
52 if arg_resolved.to_string() != arg.to_string() {
53 let rewritten =
54 Self::atomic_fact_with_resolved_unary_operand(atomic_fact, arg_resolved);
55 return self
56 .verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param(&rewritten);
57 }
58
59 Ok((StmtUnknown::new()).into())
60 }
61
62 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params(
63 &mut self,
64 atomic_fact: &AtomicFact,
65 ) -> Result<StmtResult, RuntimeError> {
66 let mut all_objs_equal_to_arg0 =
67 self.get_all_objs_equal_to_given(&atomic_fact.args()[0].to_string());
68 if let Some(calculated_obj) = self.resolve_obj_to_number(&atomic_fact.args()[0]) {
69 if calculated_obj.to_string() != atomic_fact.args()[0].to_string() {
70 let equal_tos = self.get_all_objs_equal_to_given(&calculated_obj.to_string());
71 all_objs_equal_to_arg0.extend(equal_tos);
72 }
73 }
74 if all_objs_equal_to_arg0.is_empty() {
75 all_objs_equal_to_arg0.push(atomic_fact.args()[0].to_string());
76 }
77 let mut all_objs_equal_to_arg1 =
78 self.get_all_objs_equal_to_given(&atomic_fact.args()[1].to_string());
79 if let Some(calculated_obj) = self.resolve_obj_to_number(&atomic_fact.args()[1]) {
80 if calculated_obj.to_string() != atomic_fact.args()[1].to_string() {
81 let equal_tos = self.get_all_objs_equal_to_given(&calculated_obj.to_string());
82 all_objs_equal_to_arg1.extend(equal_tos);
83 }
84 }
85 if all_objs_equal_to_arg1.is_empty() {
86 all_objs_equal_to_arg1.push(atomic_fact.args()[1].to_string());
87 }
88
89 for environment in self.iter_environments_from_top() {
90 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)?;
91 if result.is_true() {
92 return Ok(result);
93 }
94 }
95
96 let left = atomic_fact.args()[0].clone();
97 let right = atomic_fact.args()[1].clone();
98 let left_resolved = self.resolve_obj(&left);
99 let right_resolved = self.resolve_obj(&right);
100 if left_resolved.to_string() != left.to_string()
101 || right_resolved.to_string() != right.to_string()
102 {
103 let rewritten = Self::atomic_fact_with_resolved_binary_operands(
104 atomic_fact,
105 left_resolved,
106 right_resolved,
107 );
108 return self
109 .verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params(&rewritten);
110 }
111
112 Ok((StmtUnknown::new()).into())
113 }
114
115 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params(
116 &mut self,
117 atomic_fact: &AtomicFact,
118 ) -> Result<StmtResult, RuntimeError> {
119 let mut all_objs_equal_to_each_arg: Vec<Vec<String>> = Vec::new();
120 for arg in atomic_fact.args().iter() {
121 let mut all_objs_equal_to_current_arg =
122 self.get_all_objs_equal_to_given(&arg.to_string());
123 if all_objs_equal_to_current_arg.is_empty() {
124 all_objs_equal_to_current_arg.push(arg.to_string());
125 }
126 all_objs_equal_to_each_arg.push(all_objs_equal_to_current_arg);
127 }
128
129 for environment in self.iter_environments_from_top() {
130 let result = Self::verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params_with_facts_in_environment(
131 environment,
132 atomic_fact,
133 &all_objs_equal_to_each_arg,
134 )?;
135 if result.is_true() {
136 return Ok(result);
137 }
138 }
139
140 let old_args = atomic_fact.args();
141 let mut new_args: Vec<Obj> = Vec::with_capacity(old_args.len());
142 let mut any_changed = false;
143 for a in old_args.iter() {
144 let r = self.resolve_obj(a);
145 if r.to_string() != a.to_string() {
146 any_changed = true;
147 }
148 new_args.push(r);
149 }
150 if any_changed {
151 let rewritten = Self::atomic_fact_with_resolved_predicate_args(atomic_fact, new_args);
152 return self
153 .verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params(
154 &rewritten,
155 );
156 }
157
158 Ok((StmtUnknown::new()).into())
159 }
160
161 fn atomic_fact_with_resolved_unary_operand(fact: &AtomicFact, x: Obj) -> AtomicFact {
162 let line_file = fact.line_file();
163 match fact {
164 AtomicFact::IsSetFact(_) => IsSetFact::new(x, line_file).into(),
165 AtomicFact::IsNonemptySetFact(_) => IsNonemptySetFact::new(x, line_file).into(),
166 AtomicFact::IsFiniteSetFact(_) => IsFiniteSetFact::new(x, line_file).into(),
167 AtomicFact::IsCartFact(_) => IsCartFact::new(x, line_file).into(),
168 AtomicFact::IsTupleFact(_) => IsTupleFact::new(x, line_file).into(),
169 AtomicFact::NotIsSetFact(_) => NotIsSetFact::new(x, line_file).into(),
170 AtomicFact::NotIsNonemptySetFact(_) => NotIsNonemptySetFact::new(x, line_file).into(),
171 AtomicFact::NotIsFiniteSetFact(_) => NotIsFiniteSetFact::new(x, line_file).into(),
172 AtomicFact::NotIsCartFact(_) => NotIsCartFact::new(x, line_file).into(),
173 AtomicFact::NotIsTupleFact(_) => NotIsTupleFact::new(x, line_file).into(),
174 AtomicFact::NormalAtomicFact(n) => {
175 NormalAtomicFact::new(n.predicate.clone(), vec![x], line_file).into()
176 }
177 AtomicFact::NotNormalAtomicFact(n) => {
178 NotNormalAtomicFact::new(n.predicate.clone(), vec![x], line_file).into()
179 }
180 _ => unreachable!(
181 "atomic_fact_with_resolved_unary_operand: expected a one-argument atomic fact"
182 ),
183 }
184 }
185
186 fn atomic_fact_with_resolved_binary_operands(
187 fact: &AtomicFact,
188 left: Obj,
189 right: Obj,
190 ) -> AtomicFact {
191 let line_file = fact.line_file();
192 match fact {
193 AtomicFact::EqualFact(_) => EqualFact::new(left, right, line_file).into(),
194 AtomicFact::LessFact(_) => LessFact::new(left, right, line_file).into(),
195 AtomicFact::GreaterFact(_) => GreaterFact::new(left, right, line_file).into(),
196 AtomicFact::LessEqualFact(_) => LessEqualFact::new(left, right, line_file).into(),
197 AtomicFact::GreaterEqualFact(_) => GreaterEqualFact::new(left, right, line_file).into(),
198 AtomicFact::InFact(_) => InFact::new(left, right, line_file).into(),
199 AtomicFact::SubsetFact(_) => SubsetFact::new(left, right, line_file).into(),
200 AtomicFact::SupersetFact(_) => SupersetFact::new(left, right, line_file).into(),
201 AtomicFact::NotEqualFact(_) => NotEqualFact::new(left, right, line_file).into(),
202 AtomicFact::NotLessFact(_) => NotLessFact::new(left, right, line_file).into(),
203 AtomicFact::NotGreaterFact(_) => NotGreaterFact::new(left, right, line_file).into(),
204 AtomicFact::NotLessEqualFact(_) => NotLessEqualFact::new(left, right, line_file).into(),
205 AtomicFact::NotGreaterEqualFact(_) => {
206 NotGreaterEqualFact::new(left, right, line_file).into()
207 }
208 AtomicFact::NotInFact(_) => NotInFact::new(left, right, line_file).into(),
209 AtomicFact::NotSubsetFact(_) => NotSubsetFact::new(left, right, line_file).into(),
210 AtomicFact::NotSupersetFact(_) => NotSupersetFact::new(left, right, line_file).into(),
211 AtomicFact::RestrictFact(_) => RestrictFact::new(left, right, line_file).into(),
212 AtomicFact::NotRestrictFact(_) => NotRestrictFact::new(left, right, line_file).into(),
213 AtomicFact::NormalAtomicFact(x) => {
214 NormalAtomicFact::new(x.predicate.clone(), vec![left, right], line_file).into()
215 }
216 AtomicFact::NotNormalAtomicFact(x) => {
217 NotNormalAtomicFact::new(x.predicate.clone(), vec![left, right], line_file).into()
218 }
219 _ => unreachable!(
220 "atomic_fact_with_resolved_binary_operands: expected a two-argument atomic fact"
221 ),
222 }
223 }
224
225 fn atomic_fact_with_resolved_predicate_args(fact: &AtomicFact, args: Vec<Obj>) -> AtomicFact {
226 let line_file = fact.line_file();
227 match fact {
228 AtomicFact::NormalAtomicFact(x) => {
229 NormalAtomicFact::new(x.predicate.clone(), args, line_file).into()
230 }
231 AtomicFact::NotNormalAtomicFact(x) => {
232 NotNormalAtomicFact::new(x.predicate.clone(), args, line_file).into()
233 }
234 _ => unreachable!(
235 "atomic_fact_with_resolved_predicate_args: expected NormalAtomicFact or NotNormalAtomicFact"
236 ),
237 }
238 }
239
240 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_1_param_with_facts_in_environment(
241 environment: &Environment,
242 atomic_fact: &AtomicFact,
243 all_objs_equal_to_arg: &Vec<String>,
244 ) -> Result<StmtResult, RuntimeError> {
245 if let Some(known_facts_map) = environment
246 .known_atomic_facts_with_1_arg
247 .get(&(atomic_fact.key(), atomic_fact.is_true()))
248 {
249 for obj in all_objs_equal_to_arg.iter() {
250 if let Some(known_atomic_fact) = known_facts_map.get(obj) {
251 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
252 atomic_fact.clone().into(),
253 VerifiedByResult::cited_fact(
254 atomic_fact.clone().into(),
255 known_atomic_fact.clone().into(),
256 None,
257 ),
258 Vec::new(),
259 ))
260 .into());
261 }
262 }
263 }
264
265 Ok((StmtUnknown::new()).into())
266 }
267
268 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_2_params_with_facts_in_environment(
269 environment: &Environment,
270 atomic_fact: &AtomicFact,
271 all_objs_equal_to_arg0: &Vec<String>,
272 all_objs_equal_to_arg1: &Vec<String>,
273 ) -> Result<StmtResult, RuntimeError> {
274 if let Some(known_facts_map) = environment
275 .known_atomic_facts_with_2_args
276 .get(&(atomic_fact.key(), atomic_fact.is_true()))
277 {
278 for obj0 in all_objs_equal_to_arg0.iter() {
279 for obj1 in all_objs_equal_to_arg1.iter() {
280 if let Some(known_atomic_fact) =
281 known_facts_map.get(&(obj0.clone(), obj1.clone()))
282 {
283 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
284 atomic_fact.clone().into(),
285 VerifiedByResult::cited_fact(
286 atomic_fact.clone().into(),
287 known_atomic_fact.clone().into(),
288 None,
289 ),
290 Vec::new(),
291 ))
292 .into());
293 }
294 }
295 }
296 }
297
298 if let Some(alt) = atomic_fact.transposed_binary_order_equivalent() {
300 if let Some(known_facts_map) = environment
301 .known_atomic_facts_with_2_args
302 .get(&(alt.key(), alt.is_true()))
303 {
304 for obj0 in all_objs_equal_to_arg1.iter() {
305 for obj1 in all_objs_equal_to_arg0.iter() {
306 if let Some(known_atomic_fact) =
307 known_facts_map.get(&(obj0.clone(), obj1.clone()))
308 {
309 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
310 atomic_fact.clone().into(),
311 VerifiedByResult::cited_fact(
312 atomic_fact.clone().into(),
313 known_atomic_fact.clone().into(),
314 None,
315 ),
316 Vec::new(),
317 ))
318 .into());
319 }
320 }
321 }
322 }
323 }
324
325 Ok((StmtUnknown::new()).into())
326 }
327
328 fn verify_atomic_fact_not_equality_with_known_atomic_fact_with_0_or_more_than_2_params_with_facts_in_environment(
329 environment: &Environment,
330 atomic_fact: &AtomicFact,
331 all_objs_equal_to_each_arg: &Vec<Vec<String>>,
332 ) -> Result<StmtResult, RuntimeError> {
333 if let Some(known_facts) = environment
334 .known_atomic_facts_with_0_or_more_than_2_args
335 .get(&(atomic_fact.key(), atomic_fact.is_true()))
336 {
337 for known_fact in known_facts.iter() {
338 if known_fact.args().len() != atomic_fact.args().len() {
339 let message = format!(
340 "known atomic fact {} has different number of args than the given fact {}",
341 known_fact.to_string(),
342 atomic_fact.to_string()
343 );
344 return Err({
345 VerifyRuntimeError(RuntimeErrorStruct::new(
346 Some(Fact::from(atomic_fact.clone()).into_stmt()),
347 message.clone(),
348 atomic_fact.line_file(),
349 Some(
350 UnknownRuntimeError(RuntimeErrorStruct::new(
351 Some(Fact::from(atomic_fact.clone()).into_stmt()),
352 message,
353 atomic_fact.line_file(),
354 None,
355 vec![],
356 ))
357 .into(),
358 ),
359 vec![],
360 ))
361 .into()
362 });
363 }
364 let mut all_args_match = true;
365 for (index, known_arg) in known_fact.args().iter().enumerate() {
366 let known_arg_string = known_arg.to_string();
367 if !all_objs_equal_to_each_arg[index].contains(&known_arg_string) {
368 all_args_match = false;
369 break;
370 }
371 }
372 if all_args_match {
373 return Ok((FactualStmtSuccess::new_with_verified_by_known_fact(
374 atomic_fact.clone().into(),
375 VerifiedByResult::cited_fact(
376 atomic_fact.clone().into(),
377 known_fact.clone().into(),
378 None,
379 ),
380 Vec::new(),
381 ))
382 .into());
383 }
384 }
385 }
386
387 Ok((StmtUnknown::new()).into())
388 }
389}