Cycle-aware display: `seen` tracks containers on the current path, so self-referential structures emit "..." instead of recursing forever (and its length bounds raw nesting depth). */
(&self, v: Val, seen: &mut Vec<u32>)
| 266 | |
| 267 | /* Cycle-aware display: `seen` tracks containers on the current path, so self-referential structures emit "..." instead of recursing forever (and its length bounds raw nesting depth). */ |
| 268 | fn display_d(&self, v: Val, seen: &mut Vec<u32>) -> String { |
| 269 | if seen.len() > RENDER_DEPTH_MAX { return "...".into(); } |
| 270 | if v.is_int() { let mut b = itoa::Buffer::new(); return b.format(v.as_int()).into(); } |
| 271 | if v.is_float() { |
| 272 | // Single source of truth for float text (CPython repr rules, scientific + .0). |
| 273 | return crate::util::fstr::format_f64(v.as_float()); |
| 274 | } |
| 275 | if v.is_true() { return "True".into(); } |
| 276 | if v.is_false() { return "False".into(); } |
| 277 | if v.is_none() { return "None".into(); } |
| 278 | match self.heap.get(v) { |
| 279 | HeapObj::Str(s) => s.clone(), |
| 280 | HeapObj::Bytes(b) => format_bytes(b), |
| 281 | HeapObj::LongInt(i) => i128_to_dec(*i), |
| 282 | HeapObj::Type(name) => s!("<class '", str name, "'>"), |
| 283 | HeapObj::Func(i,_,_) => s!("<function ", int *i), |
| 284 | HeapObj::Slice(s,e,st) => s!("slice(", str &self.display_d(*s, seen), ", ", str &self.display_d(*e, seen), ", ", str &self.display_d(*st, seen), ")"), |
| 285 | HeapObj::Range(s,e,st) => if *st == 1 { s!("range(", int *s, ", ", int *e, ")") } else { s!("range(", int *s, ", ", int *e, ", ", int *st, ")") }, |
| 286 | HeapObj::List(l) => { let id = v.as_heap(); if seen.contains(&id) { return "[...]".into(); } seen.push(id); let mut o = s!(cap: 32; "["); self.append_reprs(&mut o, l.borrow().iter(), seen); o.push(']'); seen.pop(); o }, |
| 287 | HeapObj::Tuple(t) => { let id = v.as_heap(); if seen.contains(&id) { return "(...)".into(); } seen.push(id); let o = if t.len() == 1 { s!("(", str &self.repr_d(t[0], seen), ",)") } else { let mut o = s!(cap: 32; "("); self.append_reprs(&mut o, t.iter(), seen); o.push(')'); o }; seen.pop(); o }, |
| 288 | HeapObj::Dict(d) => { let id = v.as_heap(); if seen.contains(&id) { return "{...}".into(); } seen.push(id); let mut o = s!(cap: 32; "{"); for (i,(k,val)) in d.borrow().iter().enumerate() { if i>0 { if o.len() > MAX_REPR_LEN { o.push_str(", ..."); break; } o.push_str(", "); } o.push_str(&self.repr_d(k, seen)); o.push_str(": "); o.push_str(&self.repr_d(val, seen)); } o.push('}'); seen.pop(); o }, |
| 289 | HeapObj::BoundMethod(_, id) => s!("<built-in method ", str id.name(), ">"), |
| 290 | HeapObj::NativeFn(id) => s!("<built-in function ", str id.name(), ">"), |
| 291 | // User classes live in `__main__`; CPython qualifies the repr with the module. |
| 292 | HeapObj::Class(name, _, _) => crate::s!("<class '__main__.", str name, "'>"), |
| 293 | HeapObj::Instance(cls, _) => { |
| 294 | if cls.is_heap() && let HeapObj::Class(name, _, _) = self.heap.get(*cls) { return crate::s!("<", str name, " instance>"); } |
| 295 | "<instance>".into() |
| 296 | } |
| 297 | HeapObj::BoundUserMethod(..) => "<bound method>".into(), |
| 298 | HeapObj::Super(..) => "<super object>".into(), |
| 299 | HeapObj::Property(..) => "<property object>".into(), |
| 300 | HeapObj::PropertySetter(..) => "<property.setter>".into(), |
| 301 | HeapObj::StaticMethod(..) => "<staticmethod object>".into(), |
| 302 | HeapObj::Coroutine(..) => "<coroutine>".into(), |
| 303 | HeapObj::Module(name, _) => s!("<module '", str name, "'>"), |
| 304 | HeapObj::Extern(f) => s!("<extern function ", str &f.name, ">"), |
| 305 | HeapObj::ExcInstance(name, args) => { |
| 306 | // `str(E("x"))` -> "x"; KeyError is special, stringifying as the key's repr. |
| 307 | if args.len() == 1 { |
| 308 | if name == "KeyError" { self.repr_d(args[0], seen) } else { self.display_d(args[0], seen) } |
| 309 | } else if args.is_empty() { |
| 310 | name.clone() |
| 311 | } else { |
| 312 | let mut o = s!(cap: 32; str name, "("); |
| 313 | self.append_reprs(&mut o, args.iter(), seen); |
| 314 | o.push(')'); |
| 315 | o |
| 316 | } |
| 317 | } |
| 318 | HeapObj::Set(s) => { |
| 319 | let items: Vec<Val> = s.borrow().iter().cloned().collect(); |
| 320 | if items.is_empty() { return "set()".into(); } |
| 321 | let id = v.as_heap(); if seen.contains(&id) { return "{...}".into(); } seen.push(id); |
| 322 | let mut out = String::new(); |
| 323 | out.push('{'); |
| 324 | self.append_reprs(&mut out, items.iter(), seen); |
| 325 | out.push('}'); |
no test coverage detected