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