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    ) -> Self {
47        FnSet {
48            body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
49        }
50    }
51
52    pub fn get_params(&self) -> Vec<String> {
53        self.body.get_params()
54    }
55}
56
57// Anonymous function value: `FnSetBody` plus braced `equal_to` body.
58#[derive(Clone)]
59pub struct AnonymousFn {
60    pub body: FnSetBody,
61    pub equal_to: Box<Obj>,
62}
63
64impl AnonymousFn {
65    pub fn new(
66        params_and_their_sets: Vec<ParamGroupWithSet>,
67        dom_facts: Vec<OrAndChainAtomicFact>,
68        ret_set: Obj,
69        equal_to: Obj,
70    ) -> Self {
71        AnonymousFn {
72            body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
73            equal_to: Box::new(equal_to),
74        }
75    }
76}
77
78// FnSet or AnonymousFn as the current callable space for curried FnObj application checks.
79#[derive(Clone)]
80pub enum FnSetSpace {
81    Set(FnSet),
82    Anon(AnonymousFn),
83}
84
85impl FnSetSpace {
86    pub fn params(&self) -> &Vec<ParamGroupWithSet> {
87        match self {
88            FnSetSpace::Set(f) => &f.body.params_def_with_set,
89            FnSetSpace::Anon(a) => &a.body.params_def_with_set,
90        }
91    }
92
93    pub fn dom(&self) -> &Vec<OrAndChainAtomicFact> {
94        match self {
95            FnSetSpace::Set(f) => &f.body.dom_facts,
96            FnSetSpace::Anon(a) => &a.body.dom_facts,
97        }
98    }
99
100    pub fn ret_set_obj(&self) -> Obj {
101        match self {
102            FnSetSpace::Set(f) => (*f.body.ret_set).clone(),
103            FnSetSpace::Anon(a) => (*a.body.ret_set).clone(),
104        }
105    }
106
107    pub fn binding(&self) -> ParamObjType {
108        match self {
109            FnSetSpace::Set(_) => ParamObjType::FnSet,
110            FnSetSpace::Anon(_) => ParamObjType::FnSet,
111        }
112    }
113
114    pub fn from_ret_obj(obj: Obj) -> Result<Self, RuntimeError> {
115        match obj {
116            Obj::FnSet(f) => Ok(FnSetSpace::Set(f)),
117            Obj::AnonymousFn(a) => Ok(FnSetSpace::Anon(a)),
118            _ => Err(RuntimeError::from(WellDefinedRuntimeError(
119                RuntimeErrorStruct::new_with_just_msg(format!(
120                        "expect return set of function space to be `fn` or anonymous fn, got {}",
121                        obj
122                    )),
123            ))),
124        }
125    }
126}
127
128impl fmt::Display for FnSetBody {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        let params_with_sets_display: Vec<String> = self
131            .params_def_with_set
132            .iter()
133            .map(|g| format!("{} {}", vec_to_string_join_by_comma(&g.params), g.set))
134            .collect();
135        write!(
136            f,
137            "{} {} {}",
138            FN_LOWER_CASE,
139            brace_vec_colon_vec_to_string(&params_with_sets_display, &self.dom_facts),
140            self.ret_set
141        )
142    }
143}
144
145impl fmt::Display for FnSet {
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        write!(f, "{}", self.body)
148    }
149}
150
151impl fmt::Display for AnonymousFn {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        let params_with_sets_display: Vec<String> = self
154            .body
155            .params_def_with_set
156            .iter()
157            .map(|g| format!("{} {}", vec_to_string_join_by_comma(&g.params), g.set))
158            .collect();
159        write!(
160            f,
161            "{}{} {} {}{}{}",
162            ANONYMOUS_FN_PREFIX,
163            brace_vec_colon_vec_to_string(&params_with_sets_display, &self.body.dom_facts),
164            self.body.ret_set,
165            LEFT_CURLY_BRACE,
166            self.equal_to,
167            RIGHT_CURLY_BRACE,
168        )
169    }
170}
171
172impl From<FnSet> for Obj {
173    fn from(fs: FnSet) -> Self {
174        Obj::FnSet(fs)
175    }
176}
177
178impl From<AnonymousFn> for Obj {
179    fn from(af: AnonymousFn) -> Self {
180        Obj::AnonymousFn(af)
181    }
182}