litex/runtime/
runtime_resolve_obj.rs1use crate::common::count_range_integer::{
2 count_closed_range_integer_endpoints, count_half_open_range_integer_endpoints,
3};
4use crate::prelude::*;
5use crate::verify::{compare_normalized_number_str_to_zero, NumberCompareResult};
6
7impl Runtime {
8 pub fn resolve_obj_to_number(&self, obj: &Obj) -> Option<Number> {
9 if let Some(number) = obj.evaluate_to_normalized_decimal_number() {
10 return Some(number);
11 }
12 self.get_object_equal_to_normalized_decimal_number(&obj.to_string())
13 }
14
15 pub fn resolve_obj_to_number_resolved(&self, obj: &Obj) -> Option<Number> {
16 self.resolve_obj_to_number(&self.resolve_obj(obj))
17 }
18
19 fn resolve_obj_try_fold_arithmetic(&self, result: Obj) -> Obj {
23 if let Some(calculated) = result.evaluate_to_normalized_decimal_number() {
24 return calculated.into();
25 }
26 if let Some(n) = self.resolve_obj_to_number(&result) {
27 return n.into();
28 }
29 result
30 }
31
32 pub fn resolve_obj(&self, obj: &Obj) -> Obj {
33 match obj {
34 Obj::Number(number) => number.clone().into(),
35 Obj::Add(add) => {
36 let result: Obj =
37 Add::new(self.resolve_obj(&add.left), self.resolve_obj(&add.right)).into();
38 self.resolve_obj_try_fold_arithmetic(result)
39 }
40 Obj::Sub(sub) => {
41 let result: Obj =
42 Sub::new(self.resolve_obj(&sub.left), self.resolve_obj(&sub.right)).into();
43 self.resolve_obj_try_fold_arithmetic(result)
44 }
45 Obj::Mul(mul) => {
46 let result: Obj =
47 Mul::new(self.resolve_obj(&mul.left), self.resolve_obj(&mul.right)).into();
48 self.resolve_obj_try_fold_arithmetic(result)
49 }
50 Obj::Mod(mod_obj) => {
51 let result: Obj = Mod::new(
52 self.resolve_obj(&mod_obj.left),
53 self.resolve_obj(&mod_obj.right),
54 )
55 .into();
56 self.resolve_obj_try_fold_arithmetic(result)
57 }
58 Obj::Pow(pow) => {
59 let result: Obj =
60 Pow::new(self.resolve_obj(&pow.base), self.resolve_obj(&pow.exponent)).into();
61 self.resolve_obj_try_fold_arithmetic(result)
62 }
63 Obj::Div(div) => {
64 let result: Obj =
65 Div::new(self.resolve_obj(&div.left), self.resolve_obj(&div.right)).into();
66 self.resolve_obj_try_fold_arithmetic(result)
67 }
68 Obj::Abs(a) => {
69 let result: Obj = Abs::new(self.resolve_obj(&a.arg)).into();
70 self.resolve_obj_try_fold_arithmetic(result)
71 }
72 Obj::Max(m) => {
73 let result: Obj =
74 Max::new(self.resolve_obj(&m.left), self.resolve_obj(&m.right)).into();
75 self.resolve_obj_try_fold_arithmetic(result)
76 }
77 Obj::Min(m) => {
78 let result: Obj =
79 Min::new(self.resolve_obj(&m.left), self.resolve_obj(&m.right)).into();
80 self.resolve_obj_try_fold_arithmetic(result)
81 }
82 Obj::Log(l) => {
83 let result: Obj =
84 Log::new(self.resolve_obj(&l.base), self.resolve_obj(&l.arg)).into();
85 self.resolve_obj_try_fold_arithmetic(result)
86 }
87 Obj::FiniteSeqSet(fs) => {
88 FiniteSeqSet::new(self.resolve_obj(&fs.set), self.resolve_obj(&fs.n)).into()
89 }
90 Obj::SeqSet(ss) => SeqSet::new(self.resolve_obj(&ss.set)).into(),
91 Obj::MatrixSet(ms) => MatrixSet::new(
92 self.resolve_obj(&ms.set),
93 self.resolve_obj(&ms.row_len),
94 self.resolve_obj(&ms.col_len),
95 )
96 .into(),
97 Obj::FiniteSeqListObj(list) => {
98 let objs: Vec<Obj> = list.objs.iter().map(|o| self.resolve_obj(o)).collect();
99 FiniteSeqListObj::new(objs).into()
100 }
101 Obj::MatrixListObj(matrix) => {
102 let rows: Vec<Vec<Obj>> = matrix
103 .rows
104 .iter()
105 .map(|row| row.iter().map(|o| self.resolve_obj(o)).collect())
106 .collect();
107 MatrixListObj::new(rows).into()
108 }
109 Obj::FnObj(fn_obj) => {
110 if fn_obj.body.len() == 1 && fn_obj.body[0].len() == 1 {
111 let head_key = fn_obj.head.to_string();
112 if let Some(list) = self.get_obj_equal_to_finite_seq_list(&head_key) {
113 let arg = self.resolve_obj(fn_obj.body[0][0].as_ref());
114 if let Some(ix) = self.resolve_obj_to_number(&arg) {
115 if let Ok(one_based) = ix.normalized_value.parse::<usize>() {
116 if one_based >= 1 && one_based <= list.objs.len() {
117 return (*list.objs[one_based - 1]).clone();
118 }
119 }
120 }
121 }
122 }
123 if fn_obj.body.len() == 2 && fn_obj.body[0].len() == 1 && fn_obj.body[1].len() == 1
124 {
125 let head_key = fn_obj.head.to_string();
126 if let Some(mat) = self.get_obj_equal_to_matrix_list(&head_key) {
127 let r_arg = self.resolve_obj(fn_obj.body[0][0].as_ref());
128 let c_arg = self.resolve_obj(fn_obj.body[1][0].as_ref());
129 if let (Some(rn), Some(cn)) = (
130 self.resolve_obj_to_number(&r_arg),
131 self.resolve_obj_to_number(&c_arg),
132 ) {
133 if let (Ok(r1), Ok(c1)) = (
134 rn.normalized_value.parse::<usize>(),
135 cn.normalized_value.parse::<usize>(),
136 ) {
137 if r1 >= 1
138 && r1 <= mat.rows.len()
139 && c1 >= 1
140 && c1 <= mat.rows[r1 - 1].len()
141 {
142 return (*mat.rows[r1 - 1][c1 - 1]).clone();
143 }
144 }
145 }
146 }
147 }
148 if fn_obj.body.len() == 1 && fn_obj.body[0].len() == 2 {
149 let head_key = fn_obj.head.to_string();
150 if let Some(mat) = self.get_obj_equal_to_matrix_list(&head_key) {
151 let r_arg = self.resolve_obj(fn_obj.body[0][0].as_ref());
152 let c_arg = self.resolve_obj(fn_obj.body[0][1].as_ref());
153 if let (Some(rn), Some(cn)) = (
154 self.resolve_obj_to_number(&r_arg),
155 self.resolve_obj_to_number(&c_arg),
156 ) {
157 if let (Ok(r1), Ok(c1)) = (
158 rn.normalized_value.parse::<usize>(),
159 cn.normalized_value.parse::<usize>(),
160 ) {
161 if r1 >= 1
162 && r1 <= mat.rows.len()
163 && c1 >= 1
164 && c1 <= mat.rows[r1 - 1].len()
165 {
166 return (*mat.rows[r1 - 1][c1 - 1]).clone();
167 }
168 }
169 }
170 }
171 }
172 if let Some(number) = self.resolve_obj_to_number(obj) {
173 number.into()
174 } else {
175 obj.clone()
176 }
177 }
178 Obj::Atom(AtomObj::Identifier(_)) | Obj::Atom(AtomObj::IdentifierWithMod(_)) => {
179 if let Some(number) = self.resolve_obj_to_number(obj) {
180 number.into()
181 } else {
182 obj.clone()
183 }
184 }
185 Obj::Count(count) => match &*count.set {
186 Obj::ListSet(list_set) => Number::new(list_set.list.len().to_string()).into(),
187 Obj::ClosedRange(cr) => {
188 if let (Some(a_num), Some(b_num)) = (
189 self.resolve_obj_to_number_resolved(cr.start.as_ref()),
190 self.resolve_obj_to_number_resolved(cr.end.as_ref()),
191 ) {
192 if let Some(n) = count_closed_range_integer_endpoints(&a_num, &b_num) {
193 return n.into();
194 }
195 }
196 obj.clone()
197 }
198 Obj::Range(r) => {
199 if let (Some(a_num), Some(b_num)) = (
200 self.resolve_obj_to_number_resolved(r.start.as_ref()),
201 self.resolve_obj_to_number_resolved(r.end.as_ref()),
202 ) {
203 if let Some(n) = count_half_open_range_integer_endpoints(&a_num, &b_num) {
204 return n.into();
205 }
206 }
207 obj.clone()
208 }
209 _ => obj.clone(),
210 },
211 Obj::TupleDim(dim) => match &*dim.arg {
212 Obj::Tuple(tuple) => Number::new(tuple.args.len().to_string()).into(),
213 _ => obj.clone(),
214 },
215 Obj::CartDim(cart_dim) => match &*cart_dim.set {
216 Obj::Cart(cart) => Number::new(cart.args.len().to_string()).into(),
217 _ => obj.clone(),
218 },
219 Obj::Proj(proj) => match &*proj.set {
220 Obj::Cart(cart) => {
221 let projection_index_number = self.resolve_obj_to_number(&proj.dim);
222 if let Some(projection_index_number) = projection_index_number {
223 let projection_index_parsed_result =
224 projection_index_number.normalized_value.parse::<usize>();
225 if let Ok(projection_index_one_based) = projection_index_parsed_result {
226 if projection_index_one_based >= 1
227 && projection_index_one_based <= cart.args.len()
228 {
229 return (*cart.args[projection_index_one_based - 1]).clone();
230 }
231 }
232 }
233 obj.clone()
234 }
235 _ => {
236 let known_cart_obj = self.get_object_equal_to_cart(&proj.set.to_string());
237 if let Some(known_cart_obj) = known_cart_obj {
238 let projection_index_number = self.resolve_obj_to_number(&proj.dim);
239 if let Some(projection_index_number) = projection_index_number {
240 let projection_index_parsed_result =
241 projection_index_number.normalized_value.parse::<usize>();
242 if let Ok(projection_index_one_based) = projection_index_parsed_result {
243 if projection_index_one_based >= 1
244 && projection_index_one_based <= known_cart_obj.args.len()
245 {
246 return (*known_cart_obj.args[projection_index_one_based - 1])
247 .clone();
248 }
249 }
250 }
251 }
252 obj.clone()
253 }
254 },
255 Obj::ObjAtIndex(obj_at_index) => match &*obj_at_index.obj {
256 Obj::Tuple(tuple) => {
257 let tuple_index_number = self.resolve_obj_to_number(&obj_at_index.index);
258 if let Some(tuple_index_number) = tuple_index_number {
259 let tuple_index_parsed_result =
260 tuple_index_number.normalized_value.parse::<usize>();
261 if let Ok(tuple_index_one_based) = tuple_index_parsed_result {
262 if tuple_index_one_based >= 1
263 && tuple_index_one_based <= tuple.args.len()
264 {
265 return (*tuple.args[tuple_index_one_based - 1]).clone();
266 }
267 }
268 }
269 obj.clone()
270 }
271 Obj::FiniteSeqListObj(list) => {
272 let ix = self.resolve_obj_to_number(&obj_at_index.index);
273 if let Some(ix) = ix {
274 if let Ok(one_based) = ix.normalized_value.parse::<usize>() {
275 if one_based >= 1 && one_based <= list.objs.len() {
276 return (*list.objs[one_based - 1]).clone();
277 }
278 }
279 }
280 obj.clone()
281 }
282 _ => {
283 let known_tuple_obj =
284 self.get_obj_equal_to_tuple(&obj_at_index.obj.to_string());
285 if let Some(known_tuple_obj) = known_tuple_obj {
286 let tuple_index_number = self.resolve_obj_to_number(&obj_at_index.index);
287 if let Some(tuple_index_number) = tuple_index_number {
288 let tuple_index_parsed_result =
289 tuple_index_number.normalized_value.parse::<usize>();
290 if let Ok(tuple_index_one_based) = tuple_index_parsed_result {
291 if tuple_index_one_based >= 1
292 && tuple_index_one_based <= known_tuple_obj.args.len()
293 {
294 return (*known_tuple_obj.args[tuple_index_one_based - 1])
295 .clone();
296 }
297 }
298 }
299 }
300 if let Some(known_list) =
301 self.get_obj_equal_to_finite_seq_list(&obj_at_index.obj.to_string())
302 {
303 let ix = self.resolve_obj_to_number(&obj_at_index.index);
304 if let Some(ix) = ix {
305 if let Ok(one_based) = ix.normalized_value.parse::<usize>() {
306 if one_based >= 1 && one_based <= known_list.objs.len() {
307 return (*known_list.objs[one_based - 1]).clone();
308 }
309 }
310 }
311 }
312 obj.clone()
313 }
314 },
315 Obj::FamilyObj(f) => {
316 let params: Vec<Obj> = f.params.iter().map(|p| self.resolve_obj(p)).collect();
317 FamilyObj::new(f.name.clone(), params).into()
318 }
319 _ => obj.clone(),
320 }
321 }
322
323 pub(crate) fn obj_is_resolved_zero(&self, obj: &Obj) -> bool {
324 self.resolve_obj_to_number(obj)
325 .map(|n| {
326 matches!(
327 compare_normalized_number_str_to_zero(&n.normalized_value),
328 NumberCompareResult::Equal
329 )
330 })
331 .unwrap_or(false)
332 }
333
334 pub(crate) fn peel_mul_by_literal_neg_one(&self, obj: &Obj) -> Option<Obj> {
336 let Obj::Mul(m) = obj else {
337 return None;
338 };
339 if let Some(ln) = self.resolve_obj_to_number(m.left.as_ref()) {
340 if ln.normalized_value == "-1" {
341 return Some(m.right.as_ref().clone());
342 }
343 }
344 if let Some(rn) = self.resolve_obj_to_number(m.right.as_ref()) {
345 if rn.normalized_value == "-1" {
346 return Some(m.left.as_ref().clone());
347 }
348 }
349 None
350 }
351}