1use crate::prelude::*;
2use std::collections::HashMap;
3
4impl Runtime {
5 fn build_fn_characterization_facts(
6 &mut self,
7 function: &Obj,
8 fn_body: &FnSetBody,
9 line_file: &LineFile,
10 stmt_exec: &Stmt,
11 context: &str,
12 ) -> Result<(Fact, Fact, Fact, Fact), RuntimeError> {
13 let param_names = ParamGroupWithSet::collect_param_names(&fn_body.params_def_with_set);
14 if param_names.is_empty() {
15 return Err(short_exec_error(
16 stmt_exec.clone(),
17 format!("{}: fn set has no parameters", context),
18 None,
19 vec![],
20 ));
21 }
22
23 let mut generated_forall_names = self
24 .generate_random_unused_names(param_names.len() + 2)
25 .into_iter();
26 let forall_element_name = generated_forall_names.next().unwrap();
27 let forall_z_name = generated_forall_names.next().unwrap();
28 let generated_forall_param_names: Vec<String> = generated_forall_names.collect();
29 let mut original_param_to_forall_obj: HashMap<String, Obj> =
30 HashMap::with_capacity(param_names.len());
31 let mut forall_param_defs_with_type: Vec<ParamGroupWithParamType> =
32 Vec::with_capacity(fn_body.params_def_with_set.len());
33 let mut flat_index: usize = 0;
34 for param_def_with_set in fn_body.params_def_with_set.iter() {
35 let next_flat_index = flat_index + param_def_with_set.params.len();
36 let generated_names_for_current_group =
37 generated_forall_param_names[flat_index..next_flat_index].to_vec();
38 let instantiated_set = self
39 .inst_obj(
40 ¶m_def_with_set.set,
41 &original_param_to_forall_obj,
42 ParamObjType::FnSet,
43 )
44 .map_err(|inst_error| {
45 short_exec_error(
46 stmt_exec.clone(),
47 format!("{}: failed to instantiate generated parameter set", context),
48 Some(inst_error),
49 vec![],
50 )
51 })?;
52 forall_param_defs_with_type.push(ParamGroupWithParamType::new(
53 generated_names_for_current_group.clone(),
54 ParamType::Obj(instantiated_set),
55 ));
56 for (original_name, generated_name) in param_def_with_set
57 .params
58 .iter()
59 .zip(generated_names_for_current_group.iter())
60 {
61 original_param_to_forall_obj.insert(
62 original_name.clone(),
63 obj_for_bound_param_in_scope(generated_name.clone(), ParamObjType::FnSet),
64 );
65 }
66 flat_index = next_flat_index;
67 }
68 let original_param_to_exist_inner: HashMap<String, Obj> = original_param_to_forall_obj
70 .iter()
71 .filter_map(|(orig, obj)| {
72 if let Obj::Atom(AtomObj::FnSet(p)) = obj {
73 Some((
74 orig.clone(),
75 obj_for_bound_param_in_scope(p.name.clone(), ParamObjType::Exist),
76 ))
77 } else {
78 None
79 }
80 })
81 .collect();
82 let forall_ret_set = self
83 .inst_obj(
84 fn_body.ret_set.as_ref(),
85 &original_param_to_forall_obj,
86 ParamObjType::FnSet,
87 )
88 .map_err(|inst_error| {
89 short_exec_error(
90 stmt_exec.clone(),
91 format!("{}: failed to instantiate generated return set", context),
92 Some(inst_error),
93 vec![],
94 )
95 })?;
96 let forall_args_exist: Vec<Obj> = param_names
97 .iter()
98 .map(|param_name| {
99 original_param_to_exist_inner
100 .get(param_name)
101 .unwrap()
102 .clone()
103 })
104 .collect();
105 let forall_element_obj: Obj =
106 obj_for_bound_param_in_scope(forall_element_name.clone(), ParamObjType::Forall);
107 let mut forall_element_cart_factors: Vec<Obj> = Vec::with_capacity(param_names.len() + 1);
108 for param_def_with_type in forall_param_defs_with_type.iter() {
109 match ¶m_def_with_type.param_type {
110 ParamType::Obj(obj) => {
111 for _ in param_def_with_type.params.iter() {
112 forall_element_cart_factors.push(obj.clone());
113 }
114 }
115 _ => unreachable!(),
116 }
117 }
118 forall_element_cart_factors.push(forall_ret_set.clone());
119 let forall_element_cart_set = Cart::new(forall_element_cart_factors).into();
120 let forall_shape = ForallFact::new(
121 ParamDefWithType::new(vec![ParamGroupWithParamType::new(
122 vec![forall_element_name.clone()],
123 ParamType::Obj(function.clone()),
124 )]),
125 vec![],
126 vec![
127 InFact::new(
128 forall_element_obj.clone(),
129 forall_element_cart_set,
130 line_file.clone(),
131 )
132 .into(),
133 EqualFact::new(
134 TupleDim::new(forall_element_obj.clone()).into(),
135 Number::new((param_names.len() + 1).to_string()).into(),
136 line_file.clone(),
137 )
138 .into(),
139 ],
140 line_file.clone(),
141 )?
142 .into();
143 let forall_z_obj = obj_for_bound_param_in_scope(forall_z_name.clone(), ParamObjType::Exist);
144 let mut tuple_in_fn = forall_args_exist;
145 tuple_in_fn.push(forall_z_obj);
146 let tuple_in_fn = Tuple::new(tuple_in_fn).into();
147 let forall_in = ForallFact::new(
148 ParamDefWithType::new(vec![ParamGroupWithParamType::new(
149 vec![forall_element_name],
150 ParamType::Obj(function.clone()),
151 )]),
152 vec![],
153 vec![ExistFactEnum::ExistFact(ExistFactBody::new(
154 ParamDefWithType::new({
155 let mut exist_param_defs = forall_param_defs_with_type;
156 exist_param_defs.push(ParamGroupWithParamType::new(
157 vec![forall_z_name],
158 ParamType::Obj(forall_ret_set),
159 ));
160 exist_param_defs
161 }),
162 {
163 let mut facts: Vec<ExistBodyFact> =
164 Vec::with_capacity(fn_body.dom_facts.len() + 1);
165 for dom_fact in fn_body.dom_facts.iter() {
166 facts.push(
167 self.inst_or_and_chain_atomic_fact(
168 dom_fact,
169 &original_param_to_exist_inner,
170 ParamObjType::FnSet,
171 None,
172 )
173 .map_err(|inst_error| {
174 short_exec_error(
175 stmt_exec.clone(),
176 format!(
177 "{}: failed to instantiate generated domain fact",
178 context
179 ),
180 Some(inst_error),
181 vec![],
182 )
183 })?
184 .into(),
185 );
186 }
187 facts.push(
188 EqualFact::new(forall_element_obj, tuple_in_fn, line_file.clone()).into(),
189 );
190 facts
191 },
192 line_file.clone(),
193 )?)
194 .into()],
195 line_file.clone(),
196 )?
197 .into();
198
199 let mut generated_exist_names = self
200 .generate_random_unused_names(param_names.len() + 2)
201 .into_iter();
202 let exist_element_name = generated_exist_names.next().unwrap();
203 let exist_z_name = generated_exist_names.next().unwrap();
204 let generated_exist_param_names: Vec<String> = generated_exist_names.collect();
205 let mut original_param_to_exist_obj: HashMap<String, Obj> =
206 HashMap::with_capacity(param_names.len());
207 let mut exist_param_defs_with_type: Vec<ParamGroupWithParamType> =
208 Vec::with_capacity(fn_body.params_def_with_set.len());
209 let mut exist_flat_index: usize = 0;
210 for param_def_with_set in fn_body.params_def_with_set.iter() {
211 let next_flat_index = exist_flat_index + param_def_with_set.params.len();
212 let generated_names_for_current_group =
213 generated_exist_param_names[exist_flat_index..next_flat_index].to_vec();
214 let instantiated_set = self
215 .inst_obj(
216 ¶m_def_with_set.set,
217 &original_param_to_exist_obj,
218 ParamObjType::FnSet,
219 )
220 .map_err(|inst_error| {
221 short_exec_error(
222 stmt_exec.clone(),
223 format!("{}: failed to instantiate witness parameter set", context),
224 Some(inst_error),
225 vec![],
226 )
227 })?;
228 exist_param_defs_with_type.push(ParamGroupWithParamType::new(
229 generated_names_for_current_group.clone(),
230 ParamType::Obj(instantiated_set),
231 ));
232 for (original_name, generated_name) in param_def_with_set
233 .params
234 .iter()
235 .zip(generated_names_for_current_group.iter())
236 {
237 original_param_to_exist_obj.insert(
238 original_name.clone(),
239 obj_for_bound_param_in_scope(generated_name.clone(), ParamObjType::FnSet),
240 );
241 }
242 exist_flat_index = next_flat_index;
243 }
244 let original_param_to_forall_witness: HashMap<String, Obj> = original_param_to_exist_obj
246 .iter()
247 .filter_map(|(orig, obj)| {
248 if let Obj::Atom(AtomObj::FnSet(p)) = obj {
249 Some((
250 orig.clone(),
251 obj_for_bound_param_in_scope(p.name.clone(), ParamObjType::Forall),
252 ))
253 } else {
254 None
255 }
256 })
257 .collect();
258 let exist_ret_set = self
259 .inst_obj(
260 fn_body.ret_set.as_ref(),
261 &original_param_to_exist_obj,
262 ParamObjType::FnSet,
263 )
264 .map_err(|inst_error| {
265 short_exec_error(
266 stmt_exec.clone(),
267 format!("{}: failed to instantiate witness return set", context),
268 Some(inst_error),
269 vec![],
270 )
271 })?;
272 let exist_args_for_pair: Vec<Obj> = param_names
273 .iter()
274 .map(|param_name| {
275 original_param_to_forall_witness
276 .get(param_name)
277 .unwrap()
278 .clone()
279 })
280 .collect();
281 let exist_element_obj =
282 obj_for_bound_param_in_scope(exist_element_name.clone(), ParamObjType::Exist);
283 let exist_z_obj = obj_for_bound_param_in_scope(exist_z_name.clone(), ParamObjType::Exist);
284 let mut exist_tuple = exist_args_for_pair;
285 exist_tuple.push(exist_z_obj);
286 let exist_tuple = Tuple::new(exist_tuple).into();
287 let exist_fact = ExistFactEnum::ExistFact(ExistFactBody::new(
288 ParamDefWithType::new(vec![
289 ParamGroupWithParamType::new(
290 vec![exist_element_name],
291 ParamType::Obj(function.clone()),
292 ),
293 ParamGroupWithParamType::new(vec![exist_z_name], ParamType::Obj(exist_ret_set)),
294 ]),
295 vec![EqualFact::new(exist_element_obj, exist_tuple, line_file.clone()).into()],
296 line_file.clone(),
297 )?);
298 let forall_exist = ForallFact::new(
299 ParamDefWithType::new(exist_param_defs_with_type),
300 {
301 let mut dom_facts: Vec<Fact> = Vec::with_capacity(fn_body.dom_facts.len());
302 for dom_fact in fn_body.dom_facts.iter() {
303 dom_facts.push(
304 self.inst_or_and_chain_atomic_fact(
305 dom_fact,
306 &original_param_to_forall_witness,
307 ParamObjType::FnSet,
308 None,
309 )
310 .map_err(|inst_error| {
311 short_exec_error(
312 stmt_exec.clone(),
313 format!("{}: failed to instantiate witness domain fact", context),
314 Some(inst_error),
315 vec![],
316 )
317 })?
318 .into(),
319 );
320 }
321 dom_facts
322 },
323 vec![exist_fact.into()],
324 line_file.clone(),
325 )?
326 .into();
327
328 let unique_names = self.generate_random_unused_names(2);
329 let unique_x1_name = unique_names[0].clone();
330 let unique_x2_name = unique_names[1].clone();
331 let unique_x1_obj: Obj =
332 obj_for_bound_param_in_scope(unique_x1_name.clone(), ParamObjType::Forall);
333 let unique_x2_obj: Obj =
334 obj_for_bound_param_in_scope(unique_x2_name.clone(), ParamObjType::Forall);
335 let mut unique_element_cart_factors: Vec<Obj> = Vec::with_capacity(param_names.len() + 1);
336 for param_def_with_set in fn_body.params_def_with_set.iter() {
337 for _ in param_def_with_set.params.iter() {
338 unique_element_cart_factors.push(param_def_with_set.set.clone());
339 }
340 }
341 unique_element_cart_factors.push(fn_body.ret_set.as_ref().clone());
342 let unique_element_cart_set: Obj = Cart::new(unique_element_cart_factors).into();
343 let mut unique_dom_facts: Vec<Fact> = Vec::with_capacity(param_names.len() + 2);
344 unique_dom_facts.push(
345 InFact::new(
346 unique_x1_obj.clone(),
347 unique_element_cart_set.clone(),
348 line_file.clone(),
349 )
350 .into(),
351 );
352 unique_dom_facts.push(
353 InFact::new(
354 unique_x2_obj.clone(),
355 unique_element_cart_set.clone(),
356 line_file.clone(),
357 )
358 .into(),
359 );
360 for index in 1..=param_names.len() {
361 unique_dom_facts.push(
362 EqualFact::new(
363 ObjAtIndex::new(unique_x1_obj.clone(), Number::new(index.to_string()).into())
364 .into(),
365 ObjAtIndex::new(unique_x2_obj.clone(), Number::new(index.to_string()).into())
366 .into(),
367 line_file.clone(),
368 )
369 .into(),
370 );
371 }
372 let forall_unique = ForallFact::new(
373 ParamDefWithType::new(vec![ParamGroupWithParamType::new(
374 vec![unique_x1_name, unique_x2_name],
375 ParamType::Obj(function.clone()),
376 )]),
377 unique_dom_facts,
378 vec![EqualFact::new(unique_x1_obj, unique_x2_obj, line_file.clone()).into()],
379 line_file.clone(),
380 )?
381 .into();
382
383 Ok((forall_shape, forall_in, forall_exist, forall_unique))
384 }
385
386 fn exec_by_fn_stmt_verify_process(&mut self) -> Result<(), RuntimeError> {
388 Ok(())
389 }
390
391 fn exec_by_fn_stmt_store_process(
392 &mut self,
393 stmt_exec: &Stmt,
394 forall_shape: Fact,
395 forall_in: Fact,
396 forall_exist: Fact,
397 forall_unique: Fact,
398 ) -> Result<InferResult, RuntimeError> {
399 let mut infer_result = InferResult::new();
402 let infer_shape = self
403 .verify_well_defined_and_store_and_infer_with_default_verify_state(forall_shape)
404 .map_err(|store_fact_error| {
405 short_exec_error(
406 stmt_exec.clone(),
407 "by fn: failed to store cart/tuple shape characterization fact".to_string(),
408 Some(store_fact_error),
409 vec![],
410 )
411 })?;
412 infer_result.new_infer_result_inside(infer_shape);
413 let infer_in = self
414 .verify_well_defined_and_store_and_infer_with_default_verify_state(forall_in)
415 .map_err(|store_fact_error| {
416 short_exec_error(
417 stmt_exec.clone(),
418 "by fn: failed to store graph-element characterization fact".to_string(),
419 Some(store_fact_error),
420 vec![],
421 )
422 })?;
423 infer_result.new_infer_result_inside(infer_in);
424
425 let infer_exist = self
426 .verify_well_defined_and_store_and_infer_with_default_verify_state(forall_exist)
427 .map_err(|store_fact_error| {
428 short_exec_error(
429 stmt_exec.clone(),
430 "by fn: failed to store element characterization fact".to_string(),
431 Some(store_fact_error),
432 vec![],
433 )
434 })?;
435 infer_result.new_infer_result_inside(infer_exist);
436
437 let infer_unique = self
438 .store_fact_without_forall_coverage_check_and_infer(forall_unique)
439 .map_err(|store_fact_error| {
440 short_exec_error(
441 stmt_exec.clone(),
442 "by fn: failed to store uniqueness characterization fact".to_string(),
443 Some(store_fact_error),
444 vec![],
445 )
446 })?;
447 infer_result.new_infer_result_inside(infer_unique);
448
449 Ok(infer_result)
450 }
451
452 pub fn exec_by_fn_stmt(&mut self, stmt: &ByFnStmt) -> Result<StmtResult, RuntimeError> {
453 let stmt_exec: Stmt = stmt.clone().into();
454
455 let fn_set = match self.get_cloned_object_in_fn_set(&stmt.function) {
456 Some(fs) => fs,
457 None => {
458 return Err(short_exec_error(
459 stmt_exec,
460 format!(
461 "by fn: `{}` is not known to belong to a fn set",
462 stmt.function
463 ),
464 None,
465 vec![],
466 ));
467 }
468 };
469
470 let (forall_shape, forall_in, forall_exist, forall_unique) = self
471 .build_fn_characterization_facts(
472 &stmt.function,
473 &fn_set,
474 &stmt.line_file,
475 &stmt_exec,
476 "by fn",
477 )?;
478
479 self.run_in_local_env(|rt| rt.exec_by_fn_stmt_verify_process())?;
480
481 let infer_result = self.exec_by_fn_stmt_store_process(
482 &stmt_exec,
483 forall_shape,
484 forall_in,
485 forall_exist,
486 forall_unique,
487 )?;
488
489 Ok((NonFactualStmtSuccess::new(stmt_exec, infer_result, vec![])).into())
490 }
491
492 fn exec_by_fn_set_stmt_verify_process(
493 &mut self,
494 stmt_exec: &Stmt,
495 forall_shape: &Fact,
496 forall_in: &Fact,
497 forall_exist: &Fact,
498 forall_unique: &Fact,
499 ) -> Result<Vec<StmtResult>, RuntimeError> {
500 let verify_state = VerifyState::new(0, false);
501 let verify_shape_fact = self
502 .verify_fact_return_err_if_not_true(forall_shape, &verify_state)
503 .map_err(|verify_error| {
504 short_exec_error(
505 stmt_exec.clone(),
506 format!(
507 "by fn set: failed to prove cart/tuple shape characterization `{}`",
508 forall_shape
509 ),
510 Some(verify_error),
511 vec![],
512 )
513 })?;
514 let verify_random_param_fact = self
515 .verify_fact_return_err_if_not_true(forall_in, &verify_state)
516 .map_err(|verify_error| {
517 short_exec_error(
518 stmt_exec.clone(),
519 format!(
520 "by fn set: failed to prove graph-element characterization `{}`",
521 forall_in
522 ),
523 Some(verify_error),
524 vec![],
525 )
526 })?;
527 let verify_param_to_element_fact = self
528 .verify_fact_return_err_if_not_true(forall_exist, &verify_state)
529 .map_err(|verify_error| {
530 short_exec_error(
531 stmt_exec.clone(),
532 format!(
533 "by fn set: failed to prove graph-coverage characterization `{}`",
534 forall_exist
535 ),
536 Some(verify_error),
537 vec![],
538 )
539 })?;
540 let verify_uniqueness_fact = self
541 .verify_fact_return_err_if_not_true(forall_unique, &verify_state)
542 .map_err(|verify_error| {
543 short_exec_error(
544 stmt_exec.clone(),
545 format!(
546 "by fn set: failed to prove graph-uniqueness characterization `{}`",
547 forall_unique
548 ),
549 Some(verify_error),
550 vec![],
551 )
552 })?;
553
554 Ok(vec![
555 verify_shape_fact,
556 verify_random_param_fact,
557 verify_param_to_element_fact,
558 verify_uniqueness_fact,
559 ])
560 }
561
562 fn exec_by_fn_set_stmt_store_process(
563 &mut self,
564 stmt: &ByFnSetStmt,
565 stmt_exec: &Stmt,
566 ) -> Result<InferResult, RuntimeError> {
567 let membership_fact = InFact::new(
568 stmt.func.clone(),
569 stmt.fn_set.clone().into(),
570 stmt.line_file.clone(),
571 )
572 .into();
573 self.store_atomic_fact_without_well_defined_verified_and_infer(membership_fact)
574 .map_err(|store_fact_error| {
575 short_exec_error(
576 stmt_exec.clone(),
577 "by fn set: failed to store membership fact".to_string(),
578 Some(store_fact_error),
579 vec![],
580 )
581 })
582 }
583
584 pub fn exec_by_fn_set_stmt(&mut self, stmt: &ByFnSetStmt) -> Result<StmtResult, RuntimeError> {
585 let stmt_exec: Stmt = stmt.clone().into();
586 let (forall_shape, forall_in, forall_exist, forall_unique) = self
587 .build_fn_characterization_facts(
588 &stmt.func,
589 &stmt.fn_set.body,
590 &stmt.line_file,
591 &stmt_exec,
592 "by fn set",
593 )?;
594
595 let verify_inside_results = self.run_in_local_env(|rt| {
596 rt.exec_by_fn_set_stmt_verify_process(
597 &stmt_exec,
598 &forall_shape,
599 &forall_in,
600 &forall_exist,
601 &forall_unique,
602 )
603 })?;
604
605 let infer_result = self.exec_by_fn_set_stmt_store_process(stmt, &stmt_exec)?;
606
607 Ok((NonFactualStmtSuccess::new(stmt_exec, infer_result, verify_inside_results)).into())
608 }
609}