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::FamilyObj(family_obj) => {
460 self.infer_membership_in_family_from_in_fact(in_fact, family_obj)
461 }
462 Obj::FiniteSeqSet(fs) => {
464 let fn_set = self.finite_seq_set_to_fn_set(fs, in_fact.line_file.clone());
465 let mut infer_result =
466 self.infer_membership_in_fn_set_from_in_fact(in_fact, &fn_set)?;
467 let expanded_atomic: AtomicFact = InFact::new(
468 in_fact.element.clone(),
469 fn_set.into(),
470 in_fact.line_file.clone(),
471 )
472 .into();
473 infer_result.new_infer_result_inside(
474 self.store_atomic_fact_without_well_defined_verified_and_infer(
475 expanded_atomic,
476 )?,
477 );
478 Ok(infer_result)
479 }
480 Obj::SeqSet(ss) => {
482 let fn_set = self.seq_set_to_fn_set(ss, in_fact.line_file.clone());
483 let mut infer_result =
484 self.infer_membership_in_fn_set_from_in_fact(in_fact, &fn_set)?;
485 let expanded_atomic: AtomicFact = InFact::new(
486 in_fact.element.clone(),
487 fn_set.into(),
488 in_fact.line_file.clone(),
489 )
490 .into();
491 infer_result.new_infer_result_inside(
492 self.store_atomic_fact_without_well_defined_verified_and_infer(
493 expanded_atomic,
494 )?,
495 );
496 Ok(infer_result)
497 }
498 Obj::MatrixSet(ms) => {
500 let fn_set = self.matrix_set_to_fn_set(ms, in_fact.line_file.clone());
501 let mut infer_result =
502 self.infer_membership_in_fn_set_from_in_fact(in_fact, &fn_set)?;
503 let expanded_atomic: AtomicFact = InFact::new(
504 in_fact.element.clone(),
505 fn_set.into(),
506 in_fact.line_file.clone(),
507 )
508 .into();
509 infer_result.new_infer_result_inside(
510 self.store_atomic_fact_without_well_defined_verified_and_infer(
511 expanded_atomic,
512 )?,
513 );
514 Ok(infer_result)
515 }
516 _ => Ok(InferResult::new()),
518 }
519 }
520
521 fn infer_in_fact_element_in_integer_interval(
523 &mut self,
524 in_fact: &InFact,
525 start: Obj,
526 end: Obj,
527 end_inclusive: bool,
528 ) -> Result<InferResult, RuntimeError> {
529 let element = in_fact.element.clone();
530 let lf = in_fact.line_file.clone();
531
532 let inferred_in_z_fact =
533 InFact::new(element.clone(), StandardSet::Z.into(), lf.clone()).into();
534 let mut infer_result = InferResult::new();
535 infer_result.push_atomic_fact(&inferred_in_z_fact);
536 self.store_atomic_fact_without_well_defined_verified_and_infer(inferred_in_z_fact.clone())?;
537
538 let lower_bound = LessEqualFact::new(start, element.clone(), lf.clone()).into();
539 infer_result.push_atomic_fact(&lower_bound);
540 self.store_atomic_fact_without_well_defined_verified_and_infer(lower_bound.clone())?;
541
542 let upper_bound = if end_inclusive {
543 LessEqualFact::new(element, end, lf.clone()).into()
544 } else {
545 LessFact::new(element, end, lf.clone()).into()
546 };
547 infer_result.push_atomic_fact(&upper_bound);
548 self.store_atomic_fact_without_well_defined_verified_and_infer(upper_bound.clone())?;
549
550 Ok(infer_result)
551 }
552}