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