Container-aware repr: dispatches `__repr__` on nested instances; elements always use repr, with `seen` tracking heap ids for cycle detection. */
(&mut self, v: Val, chunk: &SSAChunk, slots: &mut [Val], seen: &mut Vec<u32>)
| 259 | |
| 260 | /* Container-aware repr: dispatches `__repr__` on nested instances; elements always use repr, with `seen` tracking heap ids for cycle detection. */ |
| 261 | pub(crate) fn repr_deep(&mut self, v: Val, chunk: &SSAChunk, slots: &mut [Val], seen: &mut Vec<u32>) -> Result<String, VmErr> { |
| 262 | const DEEP_MAX: usize = 100; |
| 263 | if !v.is_heap() { return Ok(self.repr(v)); } |
| 264 | if !self.is_container_val(v) { |
| 265 | if matches!(self.heap.get(v), HeapObj::Instance(..)) |
| 266 | && let Some(r) = self.try_call_dunder(v, "__repr__", &[], chunk, slots)? { |
| 267 | return self.require_str(r, "__repr__"); |
| 268 | } |
| 269 | return Ok(self.repr(v)); |
| 270 | } |
| 271 | let id = v.as_heap(); |
| 272 | if seen.contains(&id) { |
| 273 | return Ok(match self.heap.get(v) { |
| 274 | HeapObj::Dict(_) | HeapObj::Set(_) => "{...}".into(), |
| 275 | HeapObj::Tuple(_) => "(...)".into(), |
| 276 | HeapObj::FrozenSet(_) => "frozenset({...})".into(), |
| 277 | _ => "[...]".into(), |
| 278 | }); |
| 279 | } |
| 280 | if seen.len() > DEEP_MAX { return Ok("...".into()); } |
| 281 | seen.push(id); |
| 282 | let body = self.repr_container_body(v, chunk, slots, seen); |
| 283 | seen.pop(); |
| 284 | body |
| 285 | } |
| 286 | |
| 287 | /* Builds the bracketed body for a container `v` (caller has pushed `v` to `seen`). */ |
| 288 | fn repr_container_body(&mut self, v: Val, chunk: &SSAChunk, slots: &mut [Val], seen: &mut Vec<u32>) -> Result<String, VmErr> { |
no test coverage detected