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