1use crate::prelude::*;
2use std::collections::hash_map::Entry;
3use std::collections::HashMap;
4
5pub(crate) fn obj_eligible_for_known_objs_in_fn_sets(obj: &Obj) -> bool {
7 matches!(
8 obj,
9 Obj::Atom(AtomObj::Identifier(_))
10 | Obj::Atom(AtomObj::IdentifierWithMod(_))
11 | Obj::Atom(AtomObj::Forall(_))
12 | Obj::Atom(AtomObj::Exist(_))
13 | Obj::Atom(AtomObj::Def(_))
14 | Obj::Atom(AtomObj::SetBuilder(_))
15 | Obj::Atom(AtomObj::FnSet(_))
16 | Obj::Atom(AtomObj::Induc(_))
17 | Obj::Atom(AtomObj::DefAlgo(_))
18 )
19}
20
21fn extra_known_fn_set_keys_for_bare_name_lookup(element: &Obj) -> Vec<String> {
24 match element {
25 Obj::Atom(AtomObj::Forall(p)) => vec![p.name.clone()],
26 Obj::Atom(AtomObj::Exist(p)) => vec![p.name.clone()],
27 Obj::Atom(AtomObj::Def(p)) => vec![p.name.clone()],
28 Obj::Atom(AtomObj::SetBuilder(p)) => vec![p.name.clone()],
29 Obj::Atom(AtomObj::FnSet(p)) => vec![p.name.clone()],
30 Obj::Atom(AtomObj::Induc(p)) => vec![p.name.clone()],
31 Obj::Atom(AtomObj::DefAlgo(p)) => vec![p.name.clone()],
32 _ => vec![],
33 }
34}
35
36impl Runtime {
37 fn upsert_known_fn_info_for_key(
38 map: &mut HashMap<ObjString, KnownFnInfo>,
39 key: ObjString,
40 body: Option<(FnSetBody, LineFile)>,
41 equal_to: Option<(Obj, LineFile)>,
42 ) {
43 match map.entry(key) {
44 Entry::Occupied(mut o) => {
45 let info = o.get_mut();
46 if let Some((b, lf)) = body {
47 info.fn_set = Some((b, lf));
48 }
49 if let Some((eq, lf)) = equal_to {
50 info.equal_to = Some((eq, lf));
51 }
52 }
53 Entry::Vacant(v) => {
54 if body.is_none() && equal_to.is_none() {
55 return;
56 }
57 v.insert(KnownFnInfo::merge_fn_set_equal_to(body, equal_to));
58 }
59 }
60 }
61
62 fn upsert_known_fn_restrict_to_for_key(
63 map: &mut HashMap<ObjString, KnownFnInfo>,
64 key: ObjString,
65 restrict_body: FnSetBody,
66 line_file: LineFile,
67 ) {
68 match map.entry(key) {
69 Entry::Occupied(mut o) => {
70 o.get_mut()
71 .update_restrict_to(restrict_body, line_file.clone());
72 }
73 Entry::Vacant(v) => {
74 let mut info = KnownFnInfo::default();
75 info.update_restrict_to(restrict_body, line_file);
76 v.insert(info);
77 }
78 }
79 }
80
81 pub(crate) fn register_known_fn_restrict_to_for_element(
83 &mut self,
84 element: &Obj,
85 restrict_body: FnSetBody,
86 line_file: LineFile,
87 ) {
88 if !obj_eligible_for_known_objs_in_fn_sets(element) {
89 return;
90 }
91 let key = element.to_string();
92 let env = self.top_level_env();
93 Self::upsert_known_fn_restrict_to_for_key(
94 &mut env.known_objs_in_fn_sets,
95 key.clone(),
96 restrict_body.clone(),
97 line_file.clone(),
98 );
99 for alias in extra_known_fn_set_keys_for_bare_name_lookup(element) {
100 if alias != key {
101 Self::upsert_known_fn_restrict_to_for_key(
102 &mut env.known_objs_in_fn_sets,
103 alias,
104 restrict_body.clone(),
105 line_file.clone(),
106 );
107 }
108 }
109 }
110
111 pub fn infer_restrict_fact(&mut self, rf: &RestrictFact) -> Result<InferResult, RuntimeError> {
113 let restrict_body = match &rf.obj_can_restrict_to_fn_set {
114 Obj::FnSet(fs) => fs.body.clone(),
115 _ => return Ok(InferResult::new()),
116 };
117 self.register_known_fn_restrict_to_for_element(
118 &rf.obj,
119 restrict_body,
120 rf.line_file.clone(),
121 );
122 Ok(InferResult::new())
123 }
124
125 pub(crate) fn register_known_objs_in_fn_sets_for_element_body(
128 &mut self,
129 element: &Obj,
130 body: FnSetBody,
131 equal_to: Option<Obj>,
132 fn_signature_line_file: LineFile,
133 defining_expr_line_file: LineFile,
134 ) {
135 if !obj_eligible_for_known_objs_in_fn_sets(element) {
136 return;
137 }
138 let key = element.to_string();
139 let env = self.top_level_env();
140 let body_opt = Some((body.clone(), fn_signature_line_file.clone()));
141 let equal_opt = equal_to
142 .clone()
143 .map(|eq| (eq, defining_expr_line_file.clone()));
144 Self::upsert_known_fn_info_for_key(
145 &mut env.known_objs_in_fn_sets,
146 key.clone(),
147 body_opt,
148 equal_opt.clone(),
149 );
150 for alias in extra_known_fn_set_keys_for_bare_name_lookup(element) {
151 if alias != key {
152 Self::upsert_known_fn_info_for_key(
153 &mut env.known_objs_in_fn_sets,
154 alias,
155 Some((body.clone(), fn_signature_line_file.clone())),
156 equal_opt.clone(),
157 );
158 }
159 }
160 }
161
162 pub fn instantiate_family_member_set(
164 &mut self,
165 family_ty: &FamilyObj,
166 ) -> Result<Obj, RuntimeError> {
167 let family_name = family_ty.name.to_string();
168 let def =
169 match self.get_cloned_family_definition_by_name(&family_name) {
170 Some(d) => d,
171 None => {
172 return Err(UnknownRuntimeError(RuntimeErrorStruct::new_with_just_msg(
173 format!("family `{}` is not defined", family_name),
174 ))
175 .into());
176 }
177 };
178 let expected_count = def.params_def_with_type.number_of_params();
179 if family_ty.params.len() != expected_count {
180 return Err(
181 UnknownRuntimeError(RuntimeErrorStruct::new_with_just_msg(format!(
182 "family `{}` expects {} type argument(s), got {}",
183 family_name,
184 expected_count,
185 family_ty.params.len()
186 )))
187 .into(),
188 );
189 }
190 let param_to_arg_map = def
191 .params_def_with_type
192 .param_defs_and_args_to_param_to_arg_map(family_ty.params.as_slice());
193 self.inst_obj(&def.equal_to, ¶m_to_arg_map, ParamObjType::DefHeader)
194 }
195
196 pub fn infer_membership_in_family_for_param_binding(
198 &mut self,
199 name: &str,
200 family_ty: &FamilyObj,
201 binding_kind: ParamObjType,
202 ) -> Result<InferResult, RuntimeError> {
203 let member_set = self.instantiate_family_member_set(family_ty)?;
204 let type_fact = InFact::new(
205 param_binding_element_obj_for_store(name.to_string(), binding_kind),
206 member_set,
207 default_line_file(),
208 )
209 .into();
210 self.verify_well_defined_and_store_and_infer_with_default_verify_state(type_fact)
211 }
212
213 pub fn infer_membership_in_family_from_in_fact(
215 &mut self,
216 in_fact: &InFact,
217 family_obj: &FamilyObj,
218 ) -> Result<InferResult, RuntimeError> {
219 let member_set = self.instantiate_family_member_set(family_obj)?;
220 let expanded = InFact::new(
221 in_fact.element.clone(),
222 member_set,
223 in_fact.line_file.clone(),
224 );
225 self.infer_in_fact(&expanded)
226 }
227
228 pub fn infer_membership_in_fn_set_from_in_fact(
230 &mut self,
231 in_fact: &InFact,
232 fn_set_with_dom: &FnSet,
233 ) -> Result<InferResult, RuntimeError> {
234 if !obj_eligible_for_known_objs_in_fn_sets(&in_fact.element) {
235 return Ok(InferResult::new());
236 }
237
238 let lf = in_fact.line_file.clone();
239 self.register_known_objs_in_fn_sets_for_element_body(
240 &in_fact.element,
241 fn_set_with_dom.body.clone(),
242 None,
243 lf.clone(),
244 lf,
245 );
246
247 let mut infer_result = InferResult::new();
248 infer_result.new_fact(&in_fact.clone().into());
249 Ok(infer_result)
250 }
251
252 pub fn infer_membership_in_set_builder_from_in_fact(
254 &mut self,
255 in_fact: &InFact,
256 set_builder: &SetBuilder,
257 ) -> Result<InferResult, RuntimeError> {
258 let mut param_to_arg_map: HashMap<String, Obj> = HashMap::new();
259 param_to_arg_map.insert(set_builder.param.clone(), in_fact.element.clone());
260
261 let element_in_param_set_fact = InFact::new(
262 in_fact.element.clone(),
263 *set_builder.param_set.clone(),
264 in_fact.line_file.clone(),
265 )
266 .into();
267
268 let mut infer_result = InferResult::new();
269 infer_result.new_fact(&element_in_param_set_fact);
270 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
271 element_in_param_set_fact,
272 )?;
273
274 for fact_in_set_builder in set_builder.facts.iter() {
275 let instantiated_fact_in_set_builder: OrAndChainAtomicFact = self
276 .inst_or_and_chain_atomic_fact(
277 fact_in_set_builder,
278 ¶m_to_arg_map,
279 ParamObjType::SetBuilder,
280 Some(&in_fact.line_file),
281 )
282 .map_err(|e| {
283 RuntimeError::from(InferRuntimeError(RuntimeErrorStruct::new(
284 None,
285 format!(
286 "failed to instantiate set builder fact while inferring `{}`",
287 in_fact
288 ),
289 in_fact.line_file.clone(),
290 Some(e),
291 vec![],
292 )))
293 })?;
294 let instantiated_fact_as_fact = instantiated_fact_in_set_builder.to_fact();
295 let fact_to_store = instantiated_fact_as_fact;
296
297 infer_result.new_fact(&fact_to_store);
298 self.verify_well_defined_and_store_and_infer_with_default_verify_state(fact_to_store)?;
299 }
300
301 Ok(infer_result)
302 }
303
304 pub(in crate::infer) fn infer_in_fact(
306 &mut self,
307 in_fact: &InFact,
308 ) -> Result<InferResult, RuntimeError> {
309 match &in_fact.set {
310 Obj::FnSet(fn_set_with_dom) => {
312 self.infer_membership_in_fn_set_from_in_fact(in_fact, fn_set_with_dom)
313 }
314 Obj::ListSet(list_set) => {
316 if list_set.list.is_empty() {
317 return Ok(InferResult::new());
318 }
319
320 let mut or_case_facts: Vec<AndChainAtomicFact> =
321 Vec::with_capacity(list_set.list.len());
322 for obj_in_list_set in list_set.list.iter() {
323 let equal_fact = EqualFact::new(
324 in_fact.element.clone(),
325 *obj_in_list_set.clone(),
326 in_fact.line_file.clone(),
327 )
328 .into();
329 or_case_facts.push(AndChainAtomicFact::AtomicFact(equal_fact));
330 }
331
332 let or_fact = OrFact::new(or_case_facts, in_fact.line_file.clone()).into();
333 let mut infer_result = InferResult::new();
334 infer_result.new_fact(&or_fact);
335 self.verify_well_defined_and_store_and_infer_with_default_verify_state(or_fact)?;
336 Ok(infer_result)
337 }
338 Obj::SetBuilder(set_builder) => {
340 self.infer_membership_in_set_builder_from_in_fact(in_fact, set_builder)
341 }
342 Obj::Cart(cart) => {
344 if cart.args.len() < 2 {
345 return Ok(InferResult::new());
346 }
347 let mut infer_result = InferResult::new();
348
349 let is_cart_fact =
350 IsTupleFact::new(in_fact.element.clone(), in_fact.line_file.clone()).into();
351
352 infer_result.new_fact(&is_cart_fact);
353 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
354 is_cart_fact,
355 )?;
356
357 let cart_args_count = cart.args.len();
358 let tuple_dim_obj = TupleDim::new(in_fact.element.clone()).into();
359 let cart_args_count_obj = Number::new(cart_args_count.to_string()).into();
360 let tuple_dim_fact = EqualFact::new(
361 tuple_dim_obj,
362 cart_args_count_obj,
363 in_fact.line_file.clone(),
364 )
365 .into();
366
367 infer_result.new_fact(&tuple_dim_fact);
368 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
369 tuple_dim_fact,
370 )?;
371
372 self.store_tuple_obj_and_cart(
373 &in_fact.element.to_string(),
374 None,
375 Some(cart.clone()),
376 in_fact.line_file.clone(),
377 );
378
379 Ok(infer_result)
380 }
381 Obj::Range(r) => {
383 let start = (*r.start).clone();
384 let end = (*r.end).clone();
385 self.infer_in_fact_element_in_integer_interval(in_fact, start, end, false)
386 }
387 Obj::ClosedRange(c) => {
389 let start = (*c.start).clone();
390 let end = (*c.end).clone();
391 self.infer_in_fact_element_in_integer_interval(in_fact, start, end, true)
392 }
393 Obj::StandardSet(StandardSet::QPos)
395 | Obj::StandardSet(StandardSet::RPos)
396 | Obj::StandardSet(StandardSet::NPos) => {
397 let zero_obj: Obj = Number::new("0".to_string()).into();
398 let inferred_atomic_fact =
399 LessFact::new(zero_obj, in_fact.element.clone(), in_fact.line_file.clone())
400 .into();
401 let mut infer_result = InferResult::new();
402 infer_result.push_atomic_fact(&inferred_atomic_fact);
403 self.store_atomic_fact_without_well_defined_verified_and_infer(
404 inferred_atomic_fact.clone(),
405 )?;
406 Ok(infer_result)
407 }
408 Obj::StandardSet(StandardSet::QNeg)
410 | Obj::StandardSet(StandardSet::ZNeg)
411 | Obj::StandardSet(StandardSet::RNeg) => {
412 let zero_obj: Obj = Number::new("0".to_string()).into();
413 let inferred_atomic_fact =
414 LessFact::new(in_fact.element.clone(), zero_obj, in_fact.line_file.clone())
415 .into();
416 let mut infer_result = InferResult::new();
417 infer_result.push_atomic_fact(&inferred_atomic_fact);
418 self.store_atomic_fact_without_well_defined_verified_and_infer(
419 inferred_atomic_fact.clone(),
420 )?;
421 Ok(infer_result)
422 }
423 Obj::StandardSet(StandardSet::QNz)
425 | Obj::StandardSet(StandardSet::ZNz)
426 | Obj::StandardSet(StandardSet::RNz) => {
427 let zero_obj: Obj = Number::new("0".to_string()).into();
428 let inferred_atomic_fact =
429 NotEqualFact::new(in_fact.element.clone(), zero_obj, in_fact.line_file.clone())
430 .into();
431 let mut infer_result = InferResult::new();
432 infer_result.push_atomic_fact(&inferred_atomic_fact);
433 self.store_atomic_fact_without_well_defined_verified_and_infer(
434 inferred_atomic_fact.clone(),
435 )?;
436 Ok(infer_result)
437 }
438 Obj::StandardSet(StandardSet::N) => {
441 let zero_obj: Obj = Number::new("0".to_string()).into();
442 let inferred_atomic_fact = GreaterEqualFact::new(
443 in_fact.element.clone(),
444 zero_obj,
445 in_fact.line_file.clone(),
446 )
447 .into();
448 let mut infer_result = InferResult::new();
449 infer_result.push_atomic_fact(&inferred_atomic_fact);
450 self.store_atomic_fact_without_well_defined_verified_and_infer(
451 inferred_atomic_fact.clone(),
452 )?;
453 Ok(infer_result)
454 }
455 Obj::StandardSet(StandardSet::Q)
457 | Obj::StandardSet(StandardSet::Z)
458 | Obj::StandardSet(StandardSet::R) => Ok(InferResult::new()),
459 Obj::StructObj(struct_obj) => {
464 let (def, header_map) =
465 self.struct_header_param_to_arg_map(struct_obj, &VerifyState::new(0, false))?;
466 let field_types =
467 self.instantiated_struct_field_types(struct_obj, &VerifyState::new(0, false))?;
468
469 let mut infer_result = InferResult::new();
470 let cart_membership: Fact = InFact::new(
471 in_fact.element.clone(),
472 Cart::new(field_types.clone()).into(),
473 in_fact.line_file.clone(),
474 )
475 .into();
476 infer_result.new_fact(&cart_membership);
477 infer_result.new_infer_result_inside(
478 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
479 cart_membership,
480 )?,
481 );
482
483 let mut field_map: HashMap<String, Obj> = HashMap::new();
484 let mut projection_field_map: HashMap<String, Obj> = HashMap::new();
485 for (index, (field_name, _)) in def.fields.iter().enumerate() {
486 let field_access: Obj = ObjAsStructInstanceWithFieldAccess::new(
487 struct_obj.clone(),
488 in_fact.element.clone(),
489 field_name.clone(),
490 )
491 .into();
492 field_map.insert(field_name.clone(), field_access.clone());
493
494 let field_in_type: Fact = InFact::new(
495 field_access,
496 field_types[index].clone(),
497 in_fact.line_file.clone(),
498 )
499 .into();
500 infer_result.new_fact(&field_in_type);
501 infer_result.new_infer_result_inside(
502 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
503 field_in_type,
504 )?,
505 );
506
507 let projected_field: Obj = match &in_fact.element {
508 Obj::Tuple(tuple) => (*tuple.args[index]).clone(),
509 _ => ObjAtIndex::new(
510 in_fact.element.clone(),
511 Number::new((index + 1).to_string()).into(),
512 )
513 .into(),
514 };
515 projection_field_map.insert(field_name.clone(), projected_field.clone());
516 let projected_field_in_type: Fact = InFact::new(
517 projected_field,
518 field_types[index].clone(),
519 in_fact.line_file.clone(),
520 )
521 .into();
522 infer_result.new_fact(&projected_field_in_type);
523 infer_result.new_infer_result_inside(
524 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
525 projected_field_in_type,
526 )?,
527 );
528 }
529
530 for fact in def.equivalent_facts.iter() {
531 let after_header = self.inst_fact(
532 fact,
533 &header_map,
534 ParamObjType::DefHeader,
535 Some(in_fact.line_file.clone()),
536 )?;
537 let instantiated_fact = self.inst_fact(
538 &after_header,
539 &field_map,
540 ParamObjType::DefStructField,
541 Some(in_fact.line_file.clone()),
542 )?;
543 infer_result.new_fact(&instantiated_fact);
544 let instantiated_fact_line_file = instantiated_fact.line_file();
545 let instantiated_fact_string = instantiated_fact.to_string();
546 self.top_level_env().store_fact(instantiated_fact)?;
547 self.top_level_env().store_fact_to_cache_known_fact(
548 instantiated_fact_string,
549 instantiated_fact_line_file,
550 )?;
551
552 let projected_fact = self.inst_fact(
553 &after_header,
554 &projection_field_map,
555 ParamObjType::DefStructField,
556 Some(in_fact.line_file.clone()),
557 )?;
558 infer_result.new_fact(&projected_fact);
559 infer_result.new_infer_result_inside(
560 self.verify_well_defined_and_store_and_infer_with_default_verify_state(
561 projected_fact,
562 )?,
563 );
564 }
565
566 Ok(infer_result)
567 }
568 Obj::FamilyObj(family_obj) => {
569 self.infer_membership_in_family_from_in_fact(in_fact, family_obj)
570 }
571 Obj::FiniteSeqSet(fs) => {
573 let fn_set = self.finite_seq_set_to_fn_set(fs, in_fact.line_file.clone());
574 let mut infer_result =
575 self.infer_membership_in_fn_set_from_in_fact(in_fact, &fn_set)?;
576 let expanded_atomic: AtomicFact = InFact::new(
577 in_fact.element.clone(),
578 fn_set.into(),
579 in_fact.line_file.clone(),
580 )
581 .into();
582 infer_result.new_infer_result_inside(
583 self.store_atomic_fact_without_well_defined_verified_and_infer(
584 expanded_atomic,
585 )?,
586 );
587 Ok(infer_result)
588 }
589 Obj::SeqSet(ss) => {
591 let fn_set = self.seq_set_to_fn_set(ss, in_fact.line_file.clone());
592 let mut infer_result =
593 self.infer_membership_in_fn_set_from_in_fact(in_fact, &fn_set)?;
594 let expanded_atomic: AtomicFact = InFact::new(
595 in_fact.element.clone(),
596 fn_set.into(),
597 in_fact.line_file.clone(),
598 )
599 .into();
600 infer_result.new_infer_result_inside(
601 self.store_atomic_fact_without_well_defined_verified_and_infer(
602 expanded_atomic,
603 )?,
604 );
605 Ok(infer_result)
606 }
607 Obj::MatrixSet(ms) => {
609 let fn_set = self.matrix_set_to_fn_set(ms, in_fact.line_file.clone());
610 let mut infer_result =
611 self.infer_membership_in_fn_set_from_in_fact(in_fact, &fn_set)?;
612 let expanded_atomic: AtomicFact = InFact::new(
613 in_fact.element.clone(),
614 fn_set.into(),
615 in_fact.line_file.clone(),
616 )
617 .into();
618 infer_result.new_infer_result_inside(
619 self.store_atomic_fact_without_well_defined_verified_and_infer(
620 expanded_atomic,
621 )?,
622 );
623 Ok(infer_result)
624 }
625 _ => Ok(InferResult::new()),
627 }
628 }
629
630 fn infer_in_fact_element_in_integer_interval(
632 &mut self,
633 in_fact: &InFact,
634 start: Obj,
635 end: Obj,
636 end_inclusive: bool,
637 ) -> Result<InferResult, RuntimeError> {
638 let element = in_fact.element.clone();
639 let lf = in_fact.line_file.clone();
640
641 let inferred_in_z_fact =
642 InFact::new(element.clone(), StandardSet::Z.into(), lf.clone()).into();
643 let mut infer_result = InferResult::new();
644 infer_result.push_atomic_fact(&inferred_in_z_fact);
645 self.store_atomic_fact_without_well_defined_verified_and_infer(inferred_in_z_fact.clone())?;
646
647 let lower_bound = LessEqualFact::new(start, element.clone(), lf.clone()).into();
648 infer_result.push_atomic_fact(&lower_bound);
649 self.store_atomic_fact_without_well_defined_verified_and_infer(lower_bound.clone())?;
650
651 let upper_bound = if end_inclusive {
652 LessEqualFact::new(element, end, lf.clone()).into()
653 } else {
654 LessFact::new(element, end, lf.clone()).into()
655 };
656 infer_result.push_atomic_fact(&upper_bound);
657 self.store_atomic_fact_without_well_defined_verified_and_infer(upper_bound.clone())?;
658
659 Ok(infer_result)
660 }
661}