Skip to main content

litex/execute/by_stmt/
family_by_stmt.rs

1use crate::prelude::*;
2
3impl Runtime {
4    /// `by family: \p(R)` — stores the instantiated `\p(R) =` body (`equal_to` with `R` for the type param).
5    pub fn exec_by_family_stmt(&mut self, stmt: &ByFamilyStmt) -> Result<StmtResult, RuntimeError> {
6        let stmt_exec: Stmt = stmt.clone().into();
7        let family_ty = match &stmt.family_obj {
8            Obj::FamilyObj(f) => f,
9            _ => {
10                return Err(short_exec_error(
11                    stmt_exec,
12                    "by family: expected `\\name(...)` family object".to_string(),
13                    None,
14                    vec![],
15                ));
16            }
17        };
18
19        let family_name = family_ty.name.to_string();
20        let def = match self.get_cloned_family_definition_by_name(&family_name) {
21            Some(d) => d,
22            None => {
23                return Err(short_exec_error(
24                    stmt_exec.clone(),
25                    format!("by family: family `{}` is not defined", family_name),
26                    None,
27                    vec![],
28                ));
29            }
30        };
31
32        let expected_count = def.params_def_with_type.number_of_params();
33        if family_ty.params.len() != expected_count {
34            return Err(short_exec_error(
35                stmt_exec,
36                format!(
37                    "by family: family `{}` expects {} type argument(s), got {}",
38                    family_name,
39                    expected_count,
40                    family_ty.params.len()
41                ),
42                None,
43                vec![],
44            ));
45        }
46
47        let param_to_arg_map = def
48            .params_def_with_type
49            .param_defs_and_args_to_param_to_arg_map(family_ty.params.as_slice());
50
51        let right = self
52            .inst_obj(&def.equal_to, &param_to_arg_map, ParamObjType::DefHeader)
53            .map_err(|e| {
54                short_exec_error(
55                    stmt_exec.clone(),
56                    "by family: failed to instantiate family body `equal_to`".to_string(),
57                    Some(e),
58                    vec![],
59                )
60            })?;
61
62        let verify_state = VerifyState::new(0, false);
63        self.verify_obj_well_defined_and_store_cache(&stmt.family_obj, &verify_state)
64            .map_err(|e| {
65                short_exec_error(
66                    stmt_exec.clone(),
67                    format!(
68                        "by family: left-hand side `{}` is not well-defined",
69                        stmt.family_obj
70                    ),
71                    Some(e),
72                    vec![],
73                )
74            })?;
75        self.verify_obj_well_defined_and_store_cache(&right, &verify_state)
76            .map_err(|e| {
77                short_exec_error(
78                    stmt_exec.clone(),
79                    format!(
80                        "by family: instantiated body `{}` is not well-defined",
81                        right
82                    ),
83                    Some(e),
84                    vec![],
85                )
86            })?;
87
88        let equal_fact =
89            EqualFact::new(stmt.family_obj.clone(), right, stmt.line_file.clone()).into();
90
91        // 与 `by_enumerate` 一致:先把本语句直接生成的事实写进 `infer_facts`,再追加 store+infer 链上的结果。
92        let mut infer_result = InferResult::new();
93        infer_result.push_atomic_fact(&equal_fact);
94        infer_result.new_infer_result_inside(
95            self.store_atomic_fact_without_well_defined_verified_and_infer(equal_fact)?,
96        );
97
98        Ok((NonFactualStmtSuccess::new(stmt_exec, infer_result, vec![])).into())
99    }
100}