Skip to main content

litex/fact/
matchable_fact_with_atomic_fact_inside.rs

1use crate::prelude::*;
2use std::fmt;
3
4#[derive(Clone)]
5pub struct AndFact {
6    pub facts: Vec<AtomicFact>,
7    pub line_file: LineFile,
8}
9
10impl AndFact {
11    pub fn new(facts: Vec<AtomicFact>, line_file: LineFile) -> Self {
12        AndFact { facts, line_file }
13    }
14    pub fn line_file(&self) -> LineFile {
15        self.line_file.clone()
16    }
17}
18
19#[derive(Clone)]
20pub struct ChainFact {
21    pub objs: Vec<Obj>,
22    pub prop_names: Vec<IdentifierOrIdentifierWithMod>,
23    pub line_file: LineFile,
24}
25
26impl ChainFact {
27    pub fn new(
28        objs: Vec<Obj>,
29        prop_names: Vec<IdentifierOrIdentifierWithMod>,
30        line_file: LineFile,
31    ) -> Self {
32        ChainFact {
33            objs,
34            prop_names,
35            line_file,
36        }
37    }
38    pub fn line_file(&self) -> LineFile {
39        self.line_file.clone()
40    }
41
42    pub fn facts(&self) -> Result<Vec<AtomicFact>, RuntimeErrorStruct> {
43        if self.objs.len() != self.prop_names.len() + 1 {
44            return Err(RuntimeErrorStruct::new_with_msg_previous_error(
45                format!(
46                    "the number of objects ({}) is not equal to the number of property names ({}) + 1",
47                    self.objs.len(),
48                    self.prop_names.len(),
49                ),
50                None,
51            ));
52        }
53
54        let mut facts = Vec::with_capacity(self.prop_names.len());
55        for (i, _) in self.prop_names.iter().enumerate() {
56            let prop_name = self.prop_names[i].clone();
57            let left_obj = self.objs[i].clone();
58            let right_obj = self.objs[i + 1].clone();
59            let atomic_fact =             AtomicFact::to_atomic_fact(
60                prop_name,
61                true,
62                vec![left_obj, right_obj],
63                self.line_file.clone(),
64            );
65            facts.push(atomic_fact?);
66        }
67        Ok(facts)
68    }
69}
70
71#[derive(Clone)]
72pub enum ChainAtomicFact {
73    AtomicFact(AtomicFact),
74    ChainFact(ChainFact),
75}
76
77impl fmt::Display for ChainAtomicFact {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            ChainAtomicFact::AtomicFact(a) => write!(f, "{}", a),
81            ChainAtomicFact::ChainFact(c) => write!(f, "{}", c),
82        }
83    }
84}
85
86#[derive(Clone)]
87pub enum AndChainAtomicFact {
88    AtomicFact(AtomicFact),
89    AndFact(AndFact),
90    ChainFact(ChainFact),
91}
92
93impl AndChainAtomicFact {
94    pub fn line_file(&self) -> LineFile {
95        match self {
96            AndChainAtomicFact::AtomicFact(a) => a.line_file(),
97            AndChainAtomicFact::AndFact(a) => a.line_file(),
98            AndChainAtomicFact::ChainFact(c) => c.line_file(),
99        }
100    }
101
102    pub fn replace_bound_identifier(self, from: &str, to: &str) -> Self {
103        if from == to {
104            return self;
105        }
106        match self {
107            AndChainAtomicFact::AtomicFact(a) => {
108                AndChainAtomicFact::AtomicFact(a.replace_bound_identifier(from, to))
109            }
110            AndChainAtomicFact::AndFact(af) => AndChainAtomicFact::AndFact(AndFact {
111                facts: af
112                    .facts
113                    .into_iter()
114                    .map(|x| x.replace_bound_identifier(from, to))
115                    .collect(),
116                line_file: af.line_file,
117            }),
118            AndChainAtomicFact::ChainFact(cf) => AndChainAtomicFact::ChainFact(ChainFact {
119                objs: cf
120                    .objs
121                    .into_iter()
122                    .map(|o| Obj::replace_bound_identifier(o, from, to))
123                    .collect(),
124                prop_names: cf.prop_names,
125                line_file: cf.line_file,
126            }),
127        }
128    }
129}
130
131impl fmt::Display for AndFact {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        write!(
134            f,
135            "{}",
136            vec_to_string_with_sep(&self.facts, format!(" {} ", AND))
137        )
138    }
139}
140
141impl AndFact {
142    pub fn key(&self) -> String {
143        vec_to_string_with_sep(
144            &self.facts.iter().map(|a| a.key()).collect::<Vec<_>>(),
145            format!(" {} ", AND),
146        )
147    }
148
149    pub fn get_args_from_fact(&self) -> Vec<Obj> {
150        let mut result: Vec<Obj> = Vec::new();
151        for atomic_fact in self.facts.iter() {
152            let args_from_atomic_fact = atomic_fact.get_args_from_fact();
153            for arg in args_from_atomic_fact {
154                result.push(arg);
155            }
156        }
157        result
158    }
159}
160
161impl fmt::Display for ChainFact {
162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163        let mut s = self.objs[0].to_string();
164        for (i, obj) in self.objs[1..].iter().enumerate() {
165            if is_comparison_str(&self.prop_names[i].to_string()) {
166                s.push_str(&format!(" {} {}", self.prop_names[i], obj));
167            } else {
168                s.push_str(&format!(" {}{} {}", FACT_PREFIX, self.prop_names[i], obj));
169            }
170        }
171        write!(f, "{}", s)
172    }
173}
174
175impl ChainFact {
176    pub fn key(&self) -> String {
177        vec_to_string_with_sep(
178            &self
179                .prop_names
180                .iter()
181                .map(|p| p.to_string())
182                .collect::<Vec<_>>(),
183            format!(" {} ", AND),
184        )
185    }
186
187    pub fn get_args_from_fact(&self) -> Vec<Obj> {
188        let mut result: Vec<Obj> = Vec::new();
189        for obj in self.objs.iter() {
190            result.push(obj.clone());
191        }
192        result
193    }
194}
195
196impl fmt::Display for AndChainAtomicFact {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        match self {
199            AndChainAtomicFact::AtomicFact(a) => write!(f, "{}", a),
200            AndChainAtomicFact::AndFact(a) => write!(f, "{}", a),
201            AndChainAtomicFact::ChainFact(c) => write!(f, "{}", c),
202        }
203    }
204}
205
206impl AndChainAtomicFact {
207    pub fn key(&self) -> String {
208        match self {
209            AndChainAtomicFact::AtomicFact(a) => a.key(),
210            AndChainAtomicFact::AndFact(a) => a.key(),
211            AndChainAtomicFact::ChainFact(c) => c.key(),
212        }
213    }
214
215    pub fn to_fact(&self) -> Fact {
216        match self {
217            AndChainAtomicFact::AtomicFact(atomic_fact) => Fact::AtomicFact(atomic_fact.clone()),
218            AndChainAtomicFact::AndFact(and_fact) => Fact::AndFact(and_fact.clone()),
219            AndChainAtomicFact::ChainFact(chain_fact) => Fact::ChainFact(chain_fact.clone()),
220        }
221    }
222
223    pub fn to_exist_or_and_chain_atomic_fact(&self) -> crate::fact::ExistOrAndChainAtomicFact {
224        match self {
225            AndChainAtomicFact::AtomicFact(atomic_fact) => {
226                crate::fact::ExistOrAndChainAtomicFact::AtomicFact(atomic_fact.clone())
227            }
228            AndChainAtomicFact::AndFact(and_fact) => {
229                crate::fact::ExistOrAndChainAtomicFact::AndFact(and_fact.clone())
230            }
231            AndChainAtomicFact::ChainFact(chain_fact) => {
232                crate::fact::ExistOrAndChainAtomicFact::ChainFact(chain_fact.clone())
233            }
234        }
235    }
236}
237
238impl AndChainAtomicFact {
239    pub fn get_args_from_fact(&self) -> Vec<Obj> {
240        match self {
241            AndChainAtomicFact::AtomicFact(atomic_fact) => atomic_fact.get_args_from_fact(),
242            AndChainAtomicFact::AndFact(and_fact) => and_fact.get_args_from_fact(),
243            AndChainAtomicFact::ChainFact(chain_fact) => chain_fact.get_args_from_fact(),
244        }
245    }
246}