Skip to main content

litex/obj/
fn_set.rs

1use std::fmt;
2
3use crate::prelude::*;
4
5#[derive(Clone)]
6pub struct FnSetBody {
7    pub params_def_with_set: Vec<ParamGroupWithSet>,
8    pub dom_facts: Vec<OrAndChainAtomicFact>,
9    pub ret_set: Box<Obj>,
10}
11
12impl FnSetBody {
13    pub fn new(
14        params_def_with_set: Vec<ParamGroupWithSet>,
15        dom_facts: Vec<OrAndChainAtomicFact>,
16        ret_set: Obj,
17    ) -> Self {
18        Self {
19            params_def_with_set,
20            dom_facts,
21            ret_set: Box::new(ret_set),
22        }
23    }
24
25    pub fn get_params(&self) -> Vec<String> {
26        let mut ret = Vec::with_capacity(ParamGroupWithSet::number_of_params(
27            &self.params_def_with_set,
28        ));
29        for param_def_with_set in &self.params_def_with_set {
30            ret.extend(param_def_with_set.params.iter().cloned());
31        }
32        ret
33    }
34}
35
36#[derive(Clone)]
37pub struct FnSet {
38    pub body: FnSetBody,
39}
40
41impl FnSet {
42    pub fn new(
43        params_and_their_sets: Vec<ParamGroupWithSet>,
44        dom_facts: Vec<OrAndChainAtomicFact>,
45        ret_set: Obj,
46    ) -> Result<Self, RuntimeError> {
47        let fn_set = FnSet {
48            body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
49        };
50        check_fn_set_has_no_duplicate_fn_set_free_parameter(&fn_set)?;
51        Ok(fn_set)
52    }
53
54    pub fn from_body(body: FnSetBody) -> Result<Self, RuntimeError> {
55        let fn_set = FnSet { body };
56        check_fn_set_has_no_duplicate_fn_set_free_parameter(&fn_set)?;
57        Ok(fn_set)
58    }
59
60    pub fn get_params(&self) -> Vec<String> {
61        self.body.get_params()
62    }
63}
64
65// Anonymous function value: `FnSetBody` plus braced `equal_to` body.
66#[derive(Clone)]
67pub struct AnonymousFn {
68    pub body: FnSetBody,
69    pub equal_to: Box<Obj>,
70}
71
72impl AnonymousFn {
73    pub fn new(
74        params_and_their_sets: Vec<ParamGroupWithSet>,
75        dom_facts: Vec<OrAndChainAtomicFact>,
76        ret_set: Obj,
77        equal_to: Obj,
78    ) -> Result<Self, RuntimeError> {
79        let anonymous_fn = AnonymousFn {
80            body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
81            equal_to: Box::new(equal_to),
82        };
83        check_anonymous_fn_has_no_duplicate_fn_set_free_parameter(&anonymous_fn)?;
84        Ok(anonymous_fn)
85    }
86}
87
88// FnSet or AnonymousFn as the current callable space for curried FnObj application checks.
89#[derive(Clone)]
90pub enum FnSetSpace {
91    Set(FnSet),
92    Anon(AnonymousFn),
93}
94
95impl FnSetSpace {
96    pub fn params(&self) -> &Vec<ParamGroupWithSet> {
97        match self {
98            FnSetSpace::Set(f) => &f.body.params_def_with_set,
99            FnSetSpace::Anon(a) => &a.body.params_def_with_set,
100        }
101    }
102
103    pub fn dom(&self) -> &Vec<OrAndChainAtomicFact> {
104        match self {
105            FnSetSpace::Set(f) => &f.body.dom_facts,
106            FnSetSpace::Anon(a) => &a.body.dom_facts,
107        }
108    }
109
110    pub fn ret_set_obj(&self) -> Obj {
111        match self {
112            FnSetSpace::Set(f) => (*f.body.ret_set).clone(),
113            FnSetSpace::Anon(a) => (*a.body.ret_set).clone(),
114        }
115    }
116
117    pub fn binding(&self) -> ParamObjType {
118        match self {
119            FnSetSpace::Set(_) => ParamObjType::FnSet,
120            FnSetSpace::Anon(_) => ParamObjType::FnSet,
121        }
122    }
123
124    pub fn from_ret_obj(obj: Obj) -> Result<Self, RuntimeError> {
125        match obj {
126            Obj::FnSet(f) => Ok(FnSetSpace::Set(f)),
127            Obj::AnonymousFn(a) => Ok(FnSetSpace::Anon(a)),
128            _ => Err(RuntimeError::from(WellDefinedRuntimeError(
129                RuntimeErrorStruct::new_with_just_msg(format!(
130                    "expect return set of function space to be `fn` or anonymous fn, got {}",
131                    obj
132                )),
133            ))),
134        }
135    }
136}
137
138impl fmt::Display for FnSetBody {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        let params_with_sets_display: Vec<String> = self
141            .params_def_with_set
142            .iter()
143            .map(|g| format!("{} {}", vec_to_string_join_by_comma(&g.params), g.set))
144            .collect();
145        write!(
146            f,
147            "{} {} {}",
148            FN_LOWER_CASE,
149            brace_vec_colon_vec_to_string(&params_with_sets_display, &self.dom_facts),
150            self.ret_set
151        )
152    }
153}
154
155impl fmt::Display for FnSet {
156    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157        write!(f, "{}", self.body)
158    }
159}
160
161impl fmt::Display for AnonymousFn {
162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163        let params_with_sets_display: Vec<String> = self
164            .body
165            .params_def_with_set
166            .iter()
167            .map(|g| format!("{} {}", vec_to_string_join_by_comma(&g.params), g.set))
168            .collect();
169        write!(
170            f,
171            "{}{} {} {}{}{}",
172            ANONYMOUS_FN_PREFIX,
173            brace_vec_colon_vec_to_string(&params_with_sets_display, &self.body.dom_facts),
174            self.body.ret_set,
175            LEFT_CURLY_BRACE,
176            self.equal_to,
177            RIGHT_CURLY_BRACE,
178        )
179    }
180}
181
182impl From<FnSet> for Obj {
183    fn from(fs: FnSet) -> Self {
184        Obj::FnSet(fs)
185    }
186}
187
188impl From<AnonymousFn> for Obj {
189    fn from(af: AnonymousFn) -> Self {
190        Obj::AnonymousFn(af)
191    }
192}