Skip to main content

litex/runtime/
runtime_instantiate_obj.rs

1use crate::prelude::*;
2use std::collections::HashMap;
3
4fn remove_param_names_from_param_to_arg_map(
5    param_to_arg_map: &HashMap<String, Obj>,
6    param_names: &Vec<String>,
7) -> HashMap<String, Obj> {
8    let mut filtered_param_to_arg_map = HashMap::new();
9    for (param_name, arg) in param_to_arg_map.iter() {
10        if !param_names.contains(param_name) {
11            filtered_param_to_arg_map.insert(param_name.clone(), arg.clone());
12        }
13    }
14    filtered_param_to_arg_map
15}
16
17impl Runtime {
18    pub fn inst_obj(
19        &self,
20        obj: &Obj,
21        param_to_arg_map: &HashMap<String, Obj>,
22        param_obj_type: ParamObjType,
23    ) -> Result<Obj, RuntimeError> {
24        match obj {
25            Obj::Atom(AtomObj::Identifier(inner)) => self.inst_identifier(inner, param_to_arg_map),
26            Obj::Atom(AtomObj::IdentifierWithMod(inner)) => {
27                self.inst_identifier_with_mod(inner, param_to_arg_map)
28            }
29            Obj::FnObj(inner) => self.inst_fn_obj(inner, param_to_arg_map, param_obj_type),
30            Obj::Number(inner) => self.inst_number(inner, param_to_arg_map, param_obj_type),
31            Obj::Add(inner) => self.inst_add(inner, param_to_arg_map, param_obj_type),
32            Obj::Sub(inner) => self.inst_sub(inner, param_to_arg_map, param_obj_type),
33            Obj::Mul(inner) => self.inst_mul(inner, param_to_arg_map, param_obj_type),
34            Obj::Div(inner) => self.inst_div(inner, param_to_arg_map, param_obj_type),
35            Obj::Mod(inner) => self.inst_mod(inner, param_to_arg_map, param_obj_type),
36            Obj::Pow(inner) => self.inst_pow(inner, param_to_arg_map, param_obj_type),
37            Obj::MatrixAdd(inner) => self.inst_matrix_add(inner, param_to_arg_map, param_obj_type),
38            Obj::MatrixSub(inner) => self.inst_matrix_sub(inner, param_to_arg_map, param_obj_type),
39            Obj::MatrixMul(inner) => self.inst_matrix_mul(inner, param_to_arg_map, param_obj_type),
40            Obj::MatrixScalarMul(inner) => {
41                self.inst_matrix_scalar_mul(inner, param_to_arg_map, param_obj_type)
42            }
43            Obj::MatrixPow(inner) => self.inst_matrix_pow(inner, param_to_arg_map, param_obj_type),
44            Obj::Abs(inner) => self.inst_abs(inner, param_to_arg_map, param_obj_type),
45            Obj::Log(inner) => self.inst_log(inner, param_to_arg_map, param_obj_type),
46            Obj::Max(inner) => self.inst_max(inner, param_to_arg_map, param_obj_type),
47            Obj::Min(inner) => self.inst_min(inner, param_to_arg_map, param_obj_type),
48            Obj::Union(inner) => self.inst_union(inner, param_to_arg_map, param_obj_type),
49            Obj::Intersect(inner) => self.inst_intersect(inner, param_to_arg_map, param_obj_type),
50            Obj::SetMinus(inner) => self.inst_set_minus(inner, param_to_arg_map, param_obj_type),
51            Obj::SetDiff(inner) => self.inst_set_diff(inner, param_to_arg_map, param_obj_type),
52            Obj::Cup(inner) => self.inst_cup(inner, param_to_arg_map, param_obj_type),
53            Obj::Cap(inner) => self.inst_cap(inner, param_to_arg_map, param_obj_type),
54            Obj::ListSet(inner) => self.inst_list_set(inner, param_to_arg_map, param_obj_type),
55            Obj::SetBuilder(inner) => {
56                self.inst_set_builder(inner, param_to_arg_map, param_obj_type)
57            }
58            Obj::FnSet(inner) => {
59                self.inst_fn_set_with_params(inner, param_to_arg_map, param_obj_type)
60            }
61            Obj::AnonymousFn(inner) => {
62                self.inst_anonymous_fn_with_params(inner, param_to_arg_map, param_obj_type)
63            }
64            Obj::StandardSet(standard_set) => self.inst_standard_set(standard_set),
65            Obj::Cart(inner) => self.inst_cart(inner, param_to_arg_map, param_obj_type),
66            Obj::CartDim(inner) => self.inst_cart_dim(inner, param_to_arg_map, param_obj_type),
67            Obj::Proj(inner) => self.inst_proj(inner, param_to_arg_map, param_obj_type),
68            Obj::TupleDim(inner) => self.inst_tuple_dim(inner, param_to_arg_map, param_obj_type),
69            Obj::Tuple(inner) => self.inst_tuple(inner, param_to_arg_map, param_obj_type),
70            Obj::Count(inner) => self.inst_count(inner, param_to_arg_map, param_obj_type),
71            Obj::Sum(inner) => self.inst_sum(inner, param_to_arg_map, param_obj_type),
72            Obj::Product(inner) => self.inst_product(inner, param_to_arg_map, param_obj_type),
73            Obj::Range(inner) => self.inst_range(inner, param_to_arg_map, param_obj_type),
74            Obj::ClosedRange(inner) => {
75                self.inst_closed_range(inner, param_to_arg_map, param_obj_type)
76            }
77            Obj::FnRange(inner) => Ok(FnRange::new(self.inst_obj(
78                inner.fn_obj.as_ref(),
79                param_to_arg_map,
80                param_obj_type,
81            )?)
82            .into()),
83            Obj::FnDom(inner) => Ok(FnDom::new(self.inst_obj(
84                inner.fn_obj.as_ref(),
85                param_to_arg_map,
86                param_obj_type,
87            )?)
88            .into()),
89            Obj::FiniteSeqSet(inner) => {
90                self.inst_finite_seq_set(inner, param_to_arg_map, param_obj_type)
91            }
92            Obj::SeqSet(inner) => self.inst_seq_set(inner, param_to_arg_map, param_obj_type),
93            Obj::FiniteSeqListObj(inner) => {
94                self.inst_finite_seq_list_obj(inner, param_to_arg_map, param_obj_type)
95            }
96            Obj::MatrixSet(inner) => self.inst_matrix_set(inner, param_to_arg_map, param_obj_type),
97            Obj::MatrixListObj(inner) => {
98                self.inst_matrix_list_obj(inner, param_to_arg_map, param_obj_type)
99            }
100            Obj::PowerSet(inner) => self.inst_power_set(inner, param_to_arg_map, param_obj_type),
101            Obj::Choose(inner) => self.inst_choose(inner, param_to_arg_map, param_obj_type),
102            Obj::ObjAtIndex(inner) => {
103                self.inst_obj_at_index(inner, param_to_arg_map, param_obj_type)
104            }
105            Obj::FamilyObj(family) => {
106                let mut params = Vec::with_capacity(family.params.len());
107                for p in family.params.iter() {
108                    params.push(self.inst_obj(p, param_to_arg_map, param_obj_type)?);
109                }
110                Ok(FamilyObj::new(family.name.clone(), params).into())
111            }
112            Obj::StructObj(struct_obj) => {
113                let mut params = Vec::with_capacity(struct_obj.params.len());
114                for p in struct_obj.params.iter() {
115                    params.push(self.inst_obj(p, param_to_arg_map, param_obj_type)?);
116                }
117                Ok(StructObj::new(struct_obj.name.clone(), params).into())
118            }
119            Obj::ObjAsStructInstanceWithFieldAccess(field_access) => {
120                let mut params = Vec::with_capacity(field_access.struct_obj.params.len());
121                for p in field_access.struct_obj.params.iter() {
122                    params.push(self.inst_obj(p, param_to_arg_map, param_obj_type)?);
123                }
124                let struct_obj = StructObj::new(field_access.struct_obj.name.clone(), params);
125                let obj = self.inst_obj(&field_access.obj, param_to_arg_map, param_obj_type)?;
126                Ok(ObjAsStructInstanceWithFieldAccess::new(
127                    struct_obj,
128                    obj,
129                    field_access.field_name.clone(),
130                )
131                .into())
132            }
133            Obj::Atom(AtomObj::Forall(p)) => {
134                if param_obj_type == ParamObjType::Forall {
135                    if let Some(obj) = param_to_arg_map.get(&p.name) {
136                        return Ok(obj.clone());
137                    }
138                }
139                // See `runtime_instantiate_have_fn_forall.rs`: under FnSet inst, align Forall atoms
140                // with the canonical forall binder map.
141                if param_obj_type == ParamObjType::FnSet {
142                    if let Some(obj) = param_to_arg_map.get(&p.name) {
143                        return Ok(obj.clone());
144                    }
145                }
146                Ok(p.clone().into())
147            }
148            Obj::Atom(AtomObj::Def(p)) => {
149                if param_obj_type == ParamObjType::DefHeader {
150                    if let Some(obj) = param_to_arg_map.get(&p.name) {
151                        return Ok(obj.clone());
152                    }
153                }
154                Ok(p.clone().into())
155            }
156            Obj::Atom(AtomObj::Exist(p)) => {
157                if param_obj_type == ParamObjType::Exist {
158                    if let Some(obj) = param_to_arg_map.get(&p.name) {
159                        return Ok(obj.clone());
160                    }
161                }
162                Ok(p.clone().into())
163            }
164            Obj::Atom(AtomObj::SetBuilder(p)) => {
165                if param_obj_type == ParamObjType::SetBuilder {
166                    if let Some(obj) = param_to_arg_map.get(&p.name) {
167                        return Ok(obj.clone());
168                    }
169                }
170                Ok(p.clone().into())
171            }
172            Obj::Atom(AtomObj::FnSet(p)) => {
173                if param_obj_type == ParamObjType::FnSet {
174                    if let Some(obj) = param_to_arg_map.get(&p.name) {
175                        return Ok(obj.clone());
176                    }
177                }
178                Ok(p.clone().into())
179            }
180            Obj::Atom(AtomObj::Induc(p)) => {
181                if param_obj_type == ParamObjType::Induc || param_obj_type == ParamObjType::Forall {
182                    if let Some(obj) = param_to_arg_map.get(&p.name) {
183                        return Ok(obj.clone());
184                    }
185                }
186                if param_obj_type == ParamObjType::FnSet {
187                    if let Some(obj) = param_to_arg_map.get(&p.name) {
188                        return Ok(obj.clone());
189                    }
190                }
191                Ok(p.clone().into())
192            }
193            Obj::Atom(AtomObj::DefAlgo(p)) => {
194                if param_obj_type == ParamObjType::DefAlgo || param_obj_type == ParamObjType::Forall
195                {
196                    if let Some(obj) = param_to_arg_map.get(&p.name) {
197                        return Ok(obj.clone());
198                    }
199                }
200                Ok(p.clone().into())
201            }
202            Obj::Atom(AtomObj::DefStructField(p)) => {
203                if param_obj_type == ParamObjType::DefStructField {
204                    if let Some(obj) = param_to_arg_map.get(&p.name) {
205                        return Ok(obj.clone());
206                    }
207                }
208                Ok(p.clone().into())
209            }
210        }
211    }
212
213    pub fn inst_identifier(
214        &self,
215        identifier: &Identifier,
216        param_to_arg_map: &HashMap<String, Obj>,
217    ) -> Result<Obj, RuntimeError> {
218        Ok(match param_to_arg_map.get(&identifier.name) {
219            Some(obj) => obj.clone(),
220            None => identifier.clone().into(),
221        })
222    }
223
224    pub fn inst_identifier_with_mod(
225        &self,
226        identifier_with_mod: &IdentifierWithMod,
227        param_to_arg_map: &HashMap<String, Obj>,
228    ) -> Result<Obj, RuntimeError> {
229        _ = param_to_arg_map;
230        Ok(identifier_with_mod.clone().into())
231    }
232
233    pub fn inst_fn_obj(
234        &self,
235        fn_obj: &FnObj,
236        param_to_arg_map: &HashMap<String, Obj>,
237        param_obj_type: ParamObjType,
238    ) -> Result<Obj, RuntimeError> {
239        let mut merged_body = Vec::with_capacity(fn_obj.body.len());
240        for obj_vec in fn_obj.body.iter() {
241            let mut new_obj_vec = Vec::with_capacity(obj_vec.len());
242            for obj in obj_vec.iter() {
243                new_obj_vec.push(Box::new(self.inst_obj(
244                    obj,
245                    param_to_arg_map,
246                    param_obj_type,
247                )?));
248            }
249            merged_body.push(new_obj_vec);
250        }
251
252        let inst_head = self.inst_obj(
253            &(*fn_obj.head.clone()).into(),
254            param_to_arg_map,
255            param_obj_type,
256        )?;
257
258        let final_head: FnObjHead = match inst_head {
259            Obj::Atom(AtomObj::Identifier(x)) => FnObjHead::Identifier(x.clone()),
260            Obj::Atom(AtomObj::IdentifierWithMod(x)) => FnObjHead::IdentifierWithMod(x.clone()),
261            Obj::Atom(AtomObj::Forall(p)) => p.clone().into(),
262            Obj::Atom(AtomObj::Def(p)) => p.clone().into(),
263            Obj::Atom(AtomObj::Exist(p)) => p.clone().into(),
264            Obj::Atom(AtomObj::SetBuilder(p)) => p.clone().into(),
265            Obj::Atom(AtomObj::FnSet(p)) => p.clone().into(),
266            Obj::Atom(AtomObj::Induc(p)) => p.clone().into(),
267            Obj::Atom(AtomObj::DefAlgo(p)) => p.clone().into(),
268            Obj::Atom(AtomObj::DefStructField(_)) => {
269                return Err(RuntimeError::from(ParseRuntimeError(
270                    RuntimeErrorStruct::new_with_just_msg(
271                        "struct field cannot be used as a function head".to_string(),
272                    ),
273                )));
274            }
275            Obj::AnonymousFn(a) => FnObjHead::AnonymousFnLiteral(Box::new(a)),
276            Obj::FnObj(x) => {
277                let merged_body_original = merged_body.clone();
278                merged_body = vec![];
279                merged_body.extend(x.body);
280                merged_body.extend(merged_body_original);
281                *x.head.clone()
282            }
283            _ => return Err(InstantiateRuntimeError(RuntimeErrorStruct::new_with_just_msg(format!("instantiate fn object: after substitution, head must be an atom, curried fn, or free-param binder, got {}", inst_head)))
284            .into()),
285        };
286
287        Ok(FnObj::new(final_head, merged_body).into())
288    }
289
290    pub fn inst_number(
291        &self,
292        number: &Number,
293        param_to_arg_map: &HashMap<String, Obj>,
294        param_obj_type: ParamObjType,
295    ) -> Result<Obj, RuntimeError> {
296        _ = param_to_arg_map;
297        _ = param_obj_type;
298        Ok(number.clone().into())
299    }
300
301    pub fn inst_add(
302        &self,
303        add: &Add,
304        param_to_arg_map: &HashMap<String, Obj>,
305        param_obj_type: ParamObjType,
306    ) -> Result<Obj, RuntimeError> {
307        let instantiated_left_obj = self.inst_obj(&add.left, param_to_arg_map, param_obj_type)?;
308        let instantiated_right_obj = self.inst_obj(&add.right, param_to_arg_map, param_obj_type)?;
309        Ok(Add::new(instantiated_left_obj, instantiated_right_obj).into())
310    }
311
312    pub fn inst_matrix_add(
313        &self,
314        ma: &MatrixAdd,
315        param_to_arg_map: &HashMap<String, Obj>,
316        param_obj_type: ParamObjType,
317    ) -> Result<Obj, RuntimeError> {
318        let instantiated_left_obj = self.inst_obj(&ma.left, param_to_arg_map, param_obj_type)?;
319        let instantiated_right_obj = self.inst_obj(&ma.right, param_to_arg_map, param_obj_type)?;
320        Ok(MatrixAdd::new(instantiated_left_obj, instantiated_right_obj).into())
321    }
322
323    pub fn inst_matrix_sub(
324        &self,
325        ms: &MatrixSub,
326        param_to_arg_map: &HashMap<String, Obj>,
327        param_obj_type: ParamObjType,
328    ) -> Result<Obj, RuntimeError> {
329        let l = self.inst_obj(&ms.left, param_to_arg_map, param_obj_type)?;
330        let r = self.inst_obj(&ms.right, param_to_arg_map, param_obj_type)?;
331        Ok(MatrixSub::new(l, r).into())
332    }
333
334    pub fn inst_matrix_mul(
335        &self,
336        mm: &MatrixMul,
337        param_to_arg_map: &HashMap<String, Obj>,
338        param_obj_type: ParamObjType,
339    ) -> Result<Obj, RuntimeError> {
340        let l = self.inst_obj(&mm.left, param_to_arg_map, param_obj_type)?;
341        let r = self.inst_obj(&mm.right, param_to_arg_map, param_obj_type)?;
342        Ok(MatrixMul::new(l, r).into())
343    }
344
345    pub fn inst_matrix_scalar_mul(
346        &self,
347        m: &MatrixScalarMul,
348        param_to_arg_map: &HashMap<String, Obj>,
349        param_obj_type: ParamObjType,
350    ) -> Result<Obj, RuntimeError> {
351        let s = self.inst_obj(&m.scalar, param_to_arg_map, param_obj_type)?;
352        let mat = self.inst_obj(&m.matrix, param_to_arg_map, param_obj_type)?;
353        Ok(MatrixScalarMul::new(s, mat).into())
354    }
355
356    pub fn inst_matrix_pow(
357        &self,
358        m: &MatrixPow,
359        param_to_arg_map: &HashMap<String, Obj>,
360        param_obj_type: ParamObjType,
361    ) -> Result<Obj, RuntimeError> {
362        let b = self.inst_obj(&m.base, param_to_arg_map, param_obj_type)?;
363        let e = self.inst_obj(&m.exponent, param_to_arg_map, param_obj_type)?;
364        Ok(MatrixPow::new(b, e).into())
365    }
366
367    pub fn inst_sub(
368        &self,
369        sub: &Sub,
370        param_to_arg_map: &HashMap<String, Obj>,
371        param_obj_type: ParamObjType,
372    ) -> Result<Obj, RuntimeError> {
373        let instantiated_left_obj = self.inst_obj(&sub.left, param_to_arg_map, param_obj_type)?;
374        let instantiated_right_obj = self.inst_obj(&sub.right, param_to_arg_map, param_obj_type)?;
375        Ok(Sub::new(instantiated_left_obj, instantiated_right_obj).into())
376    }
377
378    pub fn inst_mul(
379        &self,
380        mul: &Mul,
381        param_to_arg_map: &HashMap<String, Obj>,
382        param_obj_type: ParamObjType,
383    ) -> Result<Obj, RuntimeError> {
384        let instantiated_left_obj = self.inst_obj(&mul.left, param_to_arg_map, param_obj_type)?;
385        let instantiated_right_obj = self.inst_obj(&mul.right, param_to_arg_map, param_obj_type)?;
386        Ok(Mul::new(instantiated_left_obj, instantiated_right_obj).into())
387    }
388
389    pub fn inst_div(
390        &self,
391        div: &Div,
392        param_to_arg_map: &HashMap<String, Obj>,
393        param_obj_type: ParamObjType,
394    ) -> Result<Obj, RuntimeError> {
395        Ok(Div::new(
396            self.inst_obj(&div.left, param_to_arg_map, param_obj_type)?,
397            self.inst_obj(&div.right, param_to_arg_map, param_obj_type)?,
398        )
399        .into())
400    }
401
402    pub fn inst_mod(
403        &self,
404        mod_obj: &Mod,
405        param_to_arg_map: &HashMap<String, Obj>,
406        param_obj_type: ParamObjType,
407    ) -> Result<Obj, RuntimeError> {
408        let instantiated_left_obj =
409            self.inst_obj(&mod_obj.left, param_to_arg_map, param_obj_type)?;
410        let instantiated_right_obj =
411            self.inst_obj(&mod_obj.right, param_to_arg_map, param_obj_type)?;
412        Ok(Mod::new(instantiated_left_obj, instantiated_right_obj).into())
413    }
414
415    pub fn inst_pow(
416        &self,
417        pow: &Pow,
418        param_to_arg_map: &HashMap<String, Obj>,
419        param_obj_type: ParamObjType,
420    ) -> Result<Obj, RuntimeError> {
421        let instantiated_base_obj = self.inst_obj(&pow.base, param_to_arg_map, param_obj_type)?;
422        let instantiated_exponent_obj =
423            self.inst_obj(&pow.exponent, param_to_arg_map, param_obj_type)?;
424        Ok(Pow::new(instantiated_base_obj, instantiated_exponent_obj).into())
425    }
426
427    pub fn inst_abs(
428        &self,
429        abs: &Abs,
430        param_to_arg_map: &HashMap<String, Obj>,
431        param_obj_type: ParamObjType,
432    ) -> Result<Obj, RuntimeError> {
433        Ok(Abs::new(self.inst_obj(&abs.arg, param_to_arg_map, param_obj_type)?).into())
434    }
435
436    pub fn inst_log(
437        &self,
438        log: &Log,
439        param_to_arg_map: &HashMap<String, Obj>,
440        param_obj_type: ParamObjType,
441    ) -> Result<Obj, RuntimeError> {
442        Ok(Log::new(
443            self.inst_obj(&log.base, param_to_arg_map, param_obj_type)?,
444            self.inst_obj(&log.arg, param_to_arg_map, param_obj_type)?,
445        )
446        .into())
447    }
448
449    pub fn inst_max(
450        &self,
451        max: &Max,
452        param_to_arg_map: &HashMap<String, Obj>,
453        param_obj_type: ParamObjType,
454    ) -> Result<Obj, RuntimeError> {
455        Ok(Max::new(
456            self.inst_obj(&max.left, param_to_arg_map, param_obj_type)?,
457            self.inst_obj(&max.right, param_to_arg_map, param_obj_type)?,
458        )
459        .into())
460    }
461
462    pub fn inst_min(
463        &self,
464        min: &Min,
465        param_to_arg_map: &HashMap<String, Obj>,
466        param_obj_type: ParamObjType,
467    ) -> Result<Obj, RuntimeError> {
468        Ok(Min::new(
469            self.inst_obj(&min.left, param_to_arg_map, param_obj_type)?,
470            self.inst_obj(&min.right, param_to_arg_map, param_obj_type)?,
471        )
472        .into())
473    }
474
475    pub fn inst_union(
476        &self,
477        union: &Union,
478        param_to_arg_map: &HashMap<String, Obj>,
479        param_obj_type: ParamObjType,
480    ) -> Result<Obj, RuntimeError> {
481        Ok(Union::new(
482            self.inst_obj(&union.left, param_to_arg_map, param_obj_type)?,
483            self.inst_obj(&union.right, param_to_arg_map, param_obj_type)?,
484        )
485        .into())
486    }
487
488    pub fn inst_intersect(
489        &self,
490        intersect: &Intersect,
491        param_to_arg_map: &HashMap<String, Obj>,
492        param_obj_type: ParamObjType,
493    ) -> Result<Obj, RuntimeError> {
494        Ok(Intersect::new(
495            self.inst_obj(&intersect.left, param_to_arg_map, param_obj_type)?,
496            self.inst_obj(&intersect.right, param_to_arg_map, param_obj_type)?,
497        )
498        .into())
499    }
500
501    pub fn inst_set_minus(
502        &self,
503        set_minus: &SetMinus,
504        param_to_arg_map: &HashMap<String, Obj>,
505        param_obj_type: ParamObjType,
506    ) -> Result<Obj, RuntimeError> {
507        Ok(SetMinus::new(
508            self.inst_obj(&set_minus.left, param_to_arg_map, param_obj_type)?,
509            self.inst_obj(&set_minus.right, param_to_arg_map, param_obj_type)?,
510        )
511        .into())
512    }
513
514    pub fn inst_set_diff(
515        &self,
516        set_diff: &SetDiff,
517        param_to_arg_map: &HashMap<String, Obj>,
518        param_obj_type: ParamObjType,
519    ) -> Result<Obj, RuntimeError> {
520        Ok(SetDiff::new(
521            self.inst_obj(&set_diff.left, param_to_arg_map, param_obj_type)?,
522            self.inst_obj(&set_diff.right, param_to_arg_map, param_obj_type)?,
523        )
524        .into())
525    }
526
527    pub fn inst_cup(
528        &self,
529        cup: &Cup,
530        param_to_arg_map: &HashMap<String, Obj>,
531        param_obj_type: ParamObjType,
532    ) -> Result<Obj, RuntimeError> {
533        Ok(Cup::new(self.inst_obj(&cup.left, param_to_arg_map, param_obj_type)?).into())
534    }
535
536    pub fn inst_cap(
537        &self,
538        cap: &Cap,
539        param_to_arg_map: &HashMap<String, Obj>,
540        param_obj_type: ParamObjType,
541    ) -> Result<Obj, RuntimeError> {
542        Ok(Cap::new(self.inst_obj(&cap.left, param_to_arg_map, param_obj_type)?).into())
543    }
544
545    pub fn inst_power_set(
546        &self,
547        power_set: &PowerSet,
548        param_to_arg_map: &HashMap<String, Obj>,
549        param_obj_type: ParamObjType,
550    ) -> Result<Obj, RuntimeError> {
551        Ok(PowerSet::new(self.inst_obj(&power_set.set, param_to_arg_map, param_obj_type)?).into())
552    }
553
554    pub fn inst_list_set(
555        &self,
556        list_set: &ListSet,
557        param_to_arg_map: &HashMap<String, Obj>,
558        param_obj_type: ParamObjType,
559    ) -> Result<Obj, RuntimeError> {
560        let mut list = Vec::with_capacity(list_set.list.len());
561        for obj in list_set.list.iter() {
562            list.push(self.inst_obj(obj, param_to_arg_map, param_obj_type)?);
563        }
564        Ok(ListSet::new(list).into())
565    }
566
567    pub fn inst_set_builder(
568        &self,
569        set_builder: &SetBuilder,
570        param_to_arg_map: &HashMap<String, Obj>,
571        param_obj_type: ParamObjType,
572    ) -> Result<Obj, RuntimeError> {
573        let param_names = vec![set_builder.param.clone()];
574        let filtered_param_to_arg_map =
575            remove_param_names_from_param_to_arg_map(param_to_arg_map, &param_names);
576        let mut facts = Vec::with_capacity(set_builder.facts.len());
577        for fact in set_builder.facts.iter() {
578            facts.push(self.inst_or_and_chain_atomic_fact(
579                fact,
580                &filtered_param_to_arg_map,
581                param_obj_type,
582                None,
583            )?);
584        }
585        Ok(SetBuilder::new(
586            set_builder.param.clone(),
587            self.inst_obj(
588                &set_builder.param_set,
589                &filtered_param_to_arg_map,
590                param_obj_type,
591            )?,
592            facts,
593        )?
594        .into())
595    }
596
597    pub fn inst_fn_set_with_params(
598        &self,
599        fn_set_with_params: &FnSet,
600        param_to_arg_map: &HashMap<String, Obj>,
601        param_obj_type: ParamObjType,
602    ) -> Result<Obj, RuntimeError> {
603        let param_names =
604            ParamGroupWithSet::collect_param_names(&fn_set_with_params.body.params_def_with_set);
605        let filtered_param_to_arg_map =
606            remove_param_names_from_param_to_arg_map(param_to_arg_map, &param_names);
607        let mut params_def_with_set =
608            Vec::with_capacity(fn_set_with_params.body.params_def_with_set.len());
609        for param_def_with_set in fn_set_with_params.body.params_def_with_set.iter() {
610            params_def_with_set.push(ParamGroupWithSet::new(
611                param_def_with_set.params.clone(),
612                self.inst_obj(
613                    param_def_with_set.set_obj(),
614                    &filtered_param_to_arg_map,
615                    param_obj_type,
616                )?,
617            ));
618        }
619        let mut dom_facts = Vec::with_capacity(fn_set_with_params.body.dom_facts.len());
620        for dom_fact in fn_set_with_params.body.dom_facts.iter() {
621            dom_facts.push(self.inst_or_and_chain_atomic_fact(
622                dom_fact,
623                &filtered_param_to_arg_map,
624                param_obj_type,
625                None,
626            )?);
627        }
628        Ok(FnSet::new(
629            params_def_with_set,
630            dom_facts,
631            self.inst_obj(
632                &fn_set_with_params.body.ret_set,
633                &filtered_param_to_arg_map,
634                param_obj_type,
635            )?,
636        )?
637        .into())
638    }
639
640    pub fn inst_anonymous_fn_with_params(
641        &self,
642        af: &AnonymousFn,
643        param_to_arg_map: &HashMap<String, Obj>,
644        param_obj_type: ParamObjType,
645    ) -> Result<Obj, RuntimeError> {
646        let param_names = ParamGroupWithSet::collect_param_names(&af.body.params_def_with_set);
647        let filtered_param_to_arg_map =
648            remove_param_names_from_param_to_arg_map(param_to_arg_map, &param_names);
649        let mut params_def_with_set = Vec::with_capacity(af.body.params_def_with_set.len());
650        for param_def_with_set in af.body.params_def_with_set.iter() {
651            params_def_with_set.push(ParamGroupWithSet::new(
652                param_def_with_set.params.clone(),
653                self.inst_obj(
654                    param_def_with_set.set_obj(),
655                    &filtered_param_to_arg_map,
656                    param_obj_type,
657                )?,
658            ));
659        }
660        let mut dom_facts = Vec::with_capacity(af.body.dom_facts.len());
661        for dom_fact in af.body.dom_facts.iter() {
662            dom_facts.push(self.inst_or_and_chain_atomic_fact(
663                dom_fact,
664                &filtered_param_to_arg_map,
665                param_obj_type,
666                None,
667            )?);
668        }
669        Ok(AnonymousFn::new(
670            params_def_with_set,
671            dom_facts,
672            self.inst_obj(
673                af.body.ret_set.as_ref(),
674                &filtered_param_to_arg_map,
675                param_obj_type,
676            )?,
677            self.inst_obj(
678                af.equal_to.as_ref(),
679                &filtered_param_to_arg_map,
680                param_obj_type,
681            )?,
682        )?
683        .into())
684    }
685
686    pub fn inst_cart(
687        &self,
688        cart: &Cart,
689        param_to_arg_map: &HashMap<String, Obj>,
690        param_obj_type: ParamObjType,
691    ) -> Result<Obj, RuntimeError> {
692        let mut args = Vec::with_capacity(cart.args.len());
693        for arg in cart.args.iter() {
694            args.push(self.inst_obj(arg, param_to_arg_map, param_obj_type)?);
695        }
696        Ok(Cart::new(args).into())
697    }
698
699    pub fn inst_cart_dim(
700        &self,
701        cart_dim: &CartDim,
702        param_to_arg_map: &HashMap<String, Obj>,
703        param_obj_type: ParamObjType,
704    ) -> Result<Obj, RuntimeError> {
705        Ok(CartDim::new(self.inst_obj(&cart_dim.set, param_to_arg_map, param_obj_type)?).into())
706    }
707
708    pub fn inst_proj(
709        &self,
710        proj: &Proj,
711        param_to_arg_map: &HashMap<String, Obj>,
712        param_obj_type: ParamObjType,
713    ) -> Result<Obj, RuntimeError> {
714        Ok(Proj::new(
715            self.inst_obj(&proj.set, param_to_arg_map, param_obj_type)?,
716            self.inst_obj(&proj.dim, param_to_arg_map, param_obj_type)?,
717        )
718        .into())
719    }
720
721    pub fn inst_tuple_dim(
722        &self,
723        tuple_dim: &TupleDim,
724        param_to_arg_map: &HashMap<String, Obj>,
725        param_obj_type: ParamObjType,
726    ) -> Result<Obj, RuntimeError> {
727        Ok(TupleDim::new(self.inst_obj(&tuple_dim.arg, param_to_arg_map, param_obj_type)?).into())
728    }
729
730    pub fn inst_tuple(
731        &self,
732        tuple: &Tuple,
733        param_to_arg_map: &HashMap<String, Obj>,
734        param_obj_type: ParamObjType,
735    ) -> Result<Obj, RuntimeError> {
736        let mut elements = Vec::with_capacity(tuple.args.len());
737        for element in tuple.args.iter() {
738            elements.push(self.inst_obj(element, param_to_arg_map, param_obj_type)?);
739        }
740        Ok(Tuple::new(elements).into())
741    }
742
743    pub fn inst_count(
744        &self,
745        count: &Count,
746        param_to_arg_map: &HashMap<String, Obj>,
747        param_obj_type: ParamObjType,
748    ) -> Result<Obj, RuntimeError> {
749        Ok(Count::new(self.inst_obj(&count.set, param_to_arg_map, param_obj_type)?).into())
750    }
751
752    pub fn inst_sum(
753        &self,
754        sum: &Sum,
755        param_to_arg_map: &HashMap<String, Obj>,
756        param_obj_type: ParamObjType,
757    ) -> Result<Obj, RuntimeError> {
758        Ok(Sum::new(
759            self.inst_obj(&sum.start, param_to_arg_map, param_obj_type)?,
760            self.inst_obj(&sum.end, param_to_arg_map, param_obj_type)?,
761            self.inst_obj(&sum.func, param_to_arg_map, param_obj_type)?,
762        )
763        .into())
764    }
765
766    pub fn inst_product(
767        &self,
768        product: &Product,
769        param_to_arg_map: &HashMap<String, Obj>,
770        param_obj_type: ParamObjType,
771    ) -> Result<Obj, RuntimeError> {
772        Ok(Product::new(
773            self.inst_obj(&product.start, param_to_arg_map, param_obj_type)?,
774            self.inst_obj(&product.end, param_to_arg_map, param_obj_type)?,
775            self.inst_obj(&product.func, param_to_arg_map, param_obj_type)?,
776        )
777        .into())
778    }
779
780    pub fn inst_range(
781        &self,
782        range: &Range,
783        param_to_arg_map: &HashMap<String, Obj>,
784        param_obj_type: ParamObjType,
785    ) -> Result<Obj, RuntimeError> {
786        Ok(Range::new(
787            self.inst_obj(&range.start, param_to_arg_map, param_obj_type)?,
788            self.inst_obj(&range.end, param_to_arg_map, param_obj_type)?,
789        )
790        .into())
791    }
792
793    pub fn inst_closed_range(
794        &self,
795        closed_range: &ClosedRange,
796        param_to_arg_map: &HashMap<String, Obj>,
797        param_obj_type: ParamObjType,
798    ) -> Result<Obj, RuntimeError> {
799        Ok(ClosedRange::new(
800            self.inst_obj(&closed_range.start, param_to_arg_map, param_obj_type)?,
801            self.inst_obj(&closed_range.end, param_to_arg_map, param_obj_type)?,
802        )
803        .into())
804    }
805
806    pub fn inst_finite_seq_set(
807        &self,
808        fs: &FiniteSeqSet,
809        param_to_arg_map: &HashMap<String, Obj>,
810        param_obj_type: ParamObjType,
811    ) -> Result<Obj, RuntimeError> {
812        Ok(FiniteSeqSet::new(
813            self.inst_obj(&fs.set, param_to_arg_map, param_obj_type)?,
814            self.inst_obj(&fs.n, param_to_arg_map, param_obj_type)?,
815        )
816        .into())
817    }
818
819    pub fn inst_seq_set(
820        &self,
821        ss: &SeqSet,
822        param_to_arg_map: &HashMap<String, Obj>,
823        param_obj_type: ParamObjType,
824    ) -> Result<Obj, RuntimeError> {
825        Ok(SeqSet::new(self.inst_obj(&ss.set, param_to_arg_map, param_obj_type)?).into())
826    }
827
828    pub fn inst_finite_seq_list_obj(
829        &self,
830        v: &FiniteSeqListObj,
831        param_to_arg_map: &HashMap<String, Obj>,
832        param_obj_type: ParamObjType,
833    ) -> Result<Obj, RuntimeError> {
834        let mut objs = Vec::with_capacity(v.objs.len());
835        for o in v.objs.iter() {
836            objs.push(self.inst_obj(o, param_to_arg_map, param_obj_type)?);
837        }
838        Ok(FiniteSeqListObj::new(objs).into())
839    }
840
841    pub fn inst_matrix_set(
842        &self,
843        ms: &MatrixSet,
844        param_to_arg_map: &HashMap<String, Obj>,
845        param_obj_type: ParamObjType,
846    ) -> Result<Obj, RuntimeError> {
847        Ok(MatrixSet::new(
848            self.inst_obj(&ms.set, param_to_arg_map, param_obj_type)?,
849            self.inst_obj(&ms.row_len, param_to_arg_map, param_obj_type)?,
850            self.inst_obj(&ms.col_len, param_to_arg_map, param_obj_type)?,
851        )
852        .into())
853    }
854
855    pub fn inst_matrix_list_obj(
856        &self,
857        m: &MatrixListObj,
858        param_to_arg_map: &HashMap<String, Obj>,
859        param_obj_type: ParamObjType,
860    ) -> Result<Obj, RuntimeError> {
861        let mut rows: Vec<Vec<Obj>> = Vec::with_capacity(m.rows.len());
862        for row in m.rows.iter() {
863            let mut inst_row = Vec::with_capacity(row.len());
864            for o in row.iter() {
865                inst_row.push(self.inst_obj(o, param_to_arg_map, param_obj_type)?);
866            }
867            rows.push(inst_row);
868        }
869        Ok(MatrixListObj::new(rows).into())
870    }
871
872    pub fn inst_choose(
873        &self,
874        choose: &Choose,
875        param_to_arg_map: &HashMap<String, Obj>,
876        param_obj_type: ParamObjType,
877    ) -> Result<Obj, RuntimeError> {
878        Ok(Choose::new(self.inst_obj(&choose.set, param_to_arg_map, param_obj_type)?).into())
879    }
880
881    pub fn inst_obj_at_index(
882        &self,
883        obj_at_index: &ObjAtIndex,
884        param_to_arg_map: &HashMap<String, Obj>,
885        param_obj_type: ParamObjType,
886    ) -> Result<Obj, RuntimeError> {
887        Ok(ObjAtIndex::new(
888            self.inst_obj(&obj_at_index.obj, param_to_arg_map, param_obj_type)?,
889            self.inst_obj(&obj_at_index.index, param_to_arg_map, param_obj_type)?,
890        )
891        .into())
892    }
893
894    pub fn inst_standard_set(&self, standard_set: &StandardSet) -> Result<Obj, RuntimeError> {
895        Ok(standard_set.clone().into())
896    }
897
898    pub fn inst_param_type(
899        &self,
900        param_type: &ParamType,
901        param_to_arg_map: &HashMap<String, Obj>,
902        param_obj_type: ParamObjType,
903    ) -> Result<ParamType, RuntimeError> {
904        match param_type {
905            ParamType::Set(_) => Ok(param_type.clone()),
906            ParamType::FiniteSet(_) => Ok(param_type.clone()),
907            ParamType::NonemptySet(_) => Ok(param_type.clone()),
908            ParamType::Obj(obj) => Ok(ParamType::Obj(self.inst_obj(
909                obj,
910                param_to_arg_map,
911                param_obj_type,
912            )?)),
913        }
914    }
915
916    pub fn inst_param_def_with_set_one_by_one(
917        &self,
918        param_defs: &Vec<ParamGroupWithSet>,
919        args: &Vec<Obj>,
920        param_obj_type: ParamObjType,
921    ) -> Result<Vec<Obj>, RuntimeError> {
922        let total_param_count = ParamGroupWithSet::number_of_params(param_defs);
923        if total_param_count != args.len() {
924            return Err(
925                InstantiateRuntimeError(RuntimeErrorStruct::new_with_just_msg(format!(
926                    "argument count mismatch: expected {} parameter(s), got {} argument(s)",
927                    total_param_count,
928                    args.len()
929                )))
930                .into(),
931            );
932        }
933
934        let mut param_to_arg_map: HashMap<String, Obj> = HashMap::with_capacity(total_param_count);
935        let mut arg_index: usize = 0;
936        let mut instantiated_param_sets: Vec<Obj> = Vec::with_capacity(param_defs.len());
937        for param_def in param_defs.iter() {
938            let instantiated_param_set = if arg_index != 0 {
939                self.inst_obj(param_def.set_obj(), &param_to_arg_map, param_obj_type)?
940            } else {
941                param_def.set_obj().clone()
942            };
943            instantiated_param_sets.push(instantiated_param_set);
944
945            for param_name in param_def.params.iter() {
946                param_to_arg_map.insert(param_name.clone(), args[arg_index].clone());
947                arg_index += 1;
948            }
949        }
950
951        Ok(instantiated_param_sets)
952    }
953
954    pub fn inst_param_def_with_type_one_by_one(
955        &self,
956        param_defs: &ParamDefWithType,
957        args: &Vec<Obj>,
958        param_obj_type: ParamObjType,
959    ) -> Result<Vec<ParamType>, RuntimeError> {
960        let total_param_count = param_defs.number_of_params();
961        if total_param_count != args.len() {
962            return Err(
963                InstantiateRuntimeError(RuntimeErrorStruct::new_with_just_msg(format!(
964                    "argument count mismatch: expected {} parameter(s), got {} argument(s)",
965                    total_param_count,
966                    args.len()
967                )))
968                .into(),
969            );
970        }
971
972        let mut param_arg_map: HashMap<String, Obj> = HashMap::with_capacity(total_param_count);
973        let mut arg_index: usize = 0;
974        let mut new_types: Vec<ParamType> = Vec::with_capacity(param_defs.groups.len());
975        for param_def in param_defs.groups.iter() {
976            let new_type = if arg_index != 0 {
977                self.inst_param_type(&param_def.param_type, &param_arg_map, param_obj_type)?
978            } else {
979                param_def.param_type.clone()
980            };
981            new_types.push(new_type);
982
983            for param_name in param_def.params.iter() {
984                param_arg_map.insert(param_name.clone(), args[arg_index].clone());
985                arg_index += 1;
986            }
987        }
988
989        Ok(new_types)
990    }
991}