1use std::borrow::Cow;
29use std::cell::RefCell;
30use std::rc::Rc;
31
32use crate::dict::{Dict, Set};
33use crate::exception::Exception;
34use crate::float::{DotZero, float_repr};
35use crate::hash::int_eq_float;
36use crate::int::Int;
37use crate::native::Native;
38use crate::slice::Slice;
39use crate::text::{Str, bytes_repr};
40
41#[derive(Debug, Clone)]
43pub enum Object {
44 None,
46 NotImplemented,
49 Ellipsis,
51 Bool(bool),
54 Int(Int),
56 Float(f64),
58 Str(Rc<Str>),
60 Bytes(Rc<[u8]>),
62 Tuple(Rc<[Object]>),
64 List(Rc<RefCell<Vec<Object>>>),
66 Dict(Rc<RefCell<Dict>>),
68 Set(Rc<RefCell<Set>>),
70 Slice(Rc<Slice>),
74 Native(Rc<dyn Native>),
78}
79
80impl Object {
81 #[must_use]
83 pub const fn int(value: i64) -> Self {
84 Object::Int(Int::Small(value))
85 }
86
87 #[must_use]
89 pub fn str(value: impl Into<Str>) -> Self {
90 Object::Str(Rc::new(value.into()))
91 }
92
93 #[must_use]
95 pub fn list(items: Vec<Object>) -> Self {
96 Object::List(Rc::new(RefCell::new(items)))
97 }
98
99 #[must_use]
101 pub fn tuple(items: Vec<Object>) -> Self {
102 Object::Tuple(items.into())
103 }
104
105 #[must_use]
107 pub fn dict(entries: Dict) -> Self {
108 Object::Dict(Rc::new(RefCell::new(entries)))
109 }
110
111 #[must_use]
113 pub fn set(members: Set) -> Self {
114 Object::Set(Rc::new(RefCell::new(members)))
115 }
116
117 #[must_use]
119 pub fn native(value: impl Native + 'static) -> Self {
120 Object::Native(Rc::new(value))
121 }
122
123 #[must_use]
129 pub fn downcast<T: Native + 'static>(&self) -> Option<&T> {
130 match self {
131 Object::Native(value) => value.as_any().downcast_ref::<T>(),
132 _ => None,
133 }
134 }
135
136 #[must_use]
141 pub fn exception(&self) -> Option<&Exception> {
142 self.downcast::<Exception>()
143 }
144
145 #[must_use]
151 pub fn type_name(&self) -> &str {
152 match self {
153 Object::None => "NoneType",
154 Object::NotImplemented => "NotImplementedType",
155 Object::Ellipsis => "ellipsis",
156 Object::Bool(_) => "bool",
157 Object::Int(_) => "int",
158 Object::Float(_) => "float",
159 Object::Str(_) => "str",
160 Object::Bytes(_) => "bytes",
161 Object::Tuple(_) => "tuple",
162 Object::List(_) => "list",
163 Object::Dict(_) => "dict",
164 Object::Set(_) => "set",
165 Object::Slice(_) => "slice",
166 Object::Native(value) => value.type_name(),
167 }
168 }
169
170 #[must_use]
177 pub fn truthy(&self) -> bool {
178 match self {
179 Object::None => false,
180 Object::Bool(value) => *value,
181 Object::Int(value) => !value.is_zero(),
182 Object::Float(value) => *value != 0.0,
183 Object::Str(value) => !value.is_empty(),
184 Object::Bytes(value) => !value.is_empty(),
185 Object::Tuple(items) => !items.is_empty(),
186 Object::List(items) => !items.borrow().is_empty(),
187 Object::Dict(entries) => !entries.borrow().is_empty(),
188 Object::Set(members) => !members.borrow().is_empty(),
189 Object::Native(value) => value.truthy(),
190 Object::NotImplemented | Object::Ellipsis | Object::Slice(_) => true,
193 }
194 }
195
196 #[must_use]
209 pub fn is(&self, other: &Self) -> bool {
210 match (self, other) {
211 (Object::None, Object::None)
212 | (Object::NotImplemented, Object::NotImplemented)
213 | (Object::Ellipsis, Object::Ellipsis) => true,
214 (Object::Bool(a), Object::Bool(b)) => a == b,
215 (Object::Int(a), Object::Int(b)) => a == b,
216 (Object::Float(a), Object::Float(b)) => a.to_bits() == b.to_bits(),
220 (Object::Str(a), Object::Str(b)) => Rc::ptr_eq(a, b),
221 (Object::Bytes(a), Object::Bytes(b)) => Rc::ptr_eq(a, b),
222 (Object::Tuple(a), Object::Tuple(b)) => Rc::ptr_eq(a, b),
223 (Object::List(a), Object::List(b)) => Rc::ptr_eq(a, b),
224 (Object::Dict(a), Object::Dict(b)) => Rc::ptr_eq(a, b),
225 (Object::Set(a), Object::Set(b)) => Rc::ptr_eq(a, b),
226 (Object::Slice(a), Object::Slice(b)) => Rc::ptr_eq(a, b),
227 (Object::Native(a), Object::Native(b)) => {
230 std::ptr::addr_eq(Rc::as_ptr(a), Rc::as_ptr(b))
231 }
232 _ => false,
233 }
234 }
235
236 #[must_use]
248 pub fn equals(&self, other: &Self) -> bool {
249 match (self, other) {
250 (Object::None, Object::None)
251 | (Object::Ellipsis, Object::Ellipsis)
252 | (Object::NotImplemented, Object::NotImplemented) => true,
253 (Object::Str(a), Object::Str(b)) => a == b,
254 (Object::Bytes(a), Object::Bytes(b)) => a == b,
255 (Object::Tuple(a), Object::Tuple(b)) => elementwise(a, b),
256 (Object::List(a), Object::List(b)) => {
257 Rc::ptr_eq(a, b) || elementwise(&a.borrow(), &b.borrow())
260 }
261 (Object::Dict(a), Object::Dict(b)) => {
262 Rc::ptr_eq(a, b) || a.borrow().equals(&b.borrow())
263 }
264 (Object::Set(a), Object::Set(b)) => Rc::ptr_eq(a, b) || a.borrow().equals(&b.borrow()),
265 (Object::Slice(a), Object::Slice(b)) => {
269 Rc::ptr_eq(a, b)
270 || a.parts()
271 .iter()
272 .zip(b.parts())
273 .all(|(a, b)| a.same_value(b))
274 }
275 (Object::Native(a), Object::Native(b)) => self.is(other) || a.equals(&**b),
279 _ => match (self.as_number(), other.as_number()) {
280 (Some(a), Some(b)) => a.equals(&b),
281 _ => false,
282 },
283 }
284 }
285
286 #[must_use]
294 pub fn same_value(&self, other: &Self) -> bool {
295 self.is(other) || self.equals(other)
296 }
297
298 fn as_number(&self) -> Option<Number<'_>> {
301 match self {
302 Object::Bool(value) => Some(Number::Int(Cow::Owned(Int::Small(i64::from(*value))))),
303 Object::Int(value) => Some(Number::Int(Cow::Borrowed(value))),
304 Object::Float(value) => Some(Number::Float(*value)),
305 _ => None,
306 }
307 }
308
309 #[must_use]
311 pub fn repr(&self) -> String {
312 let mut seen = Vec::new();
313 self.write_repr(&mut seen)
314 }
315
316 #[must_use]
321 pub fn display(&self) -> String {
322 match self {
323 Object::Str(value) => value.to_string(),
324 Object::Native(value) => value.display(),
328 other => other.repr(),
329 }
330 }
331
332 fn write_repr(&self, seen: &mut Vec<*const ()>) -> String {
338 match self {
339 Object::None => "None".to_owned(),
340 Object::NotImplemented => "NotImplemented".to_owned(),
341 Object::Ellipsis => "Ellipsis".to_owned(),
342 Object::Bool(true) => "True".to_owned(),
343 Object::Bool(false) => "False".to_owned(),
344 Object::Int(value) => value.to_string(),
345 Object::Float(value) => float_repr(*value, DotZero::Add),
346 Object::Str(value) => value.repr(),
347 Object::Bytes(value) => bytes_repr(value),
348 Object::Slice(value) => value.repr(),
349 Object::Tuple(items) => {
350 let address = Rc::as_ptr(items).cast::<()>();
351 let inner = with_trail(seen, address, |seen| parts(items, seen));
352 match inner {
353 Some(parts) if parts.len() == 1 => format!("({},)", parts[0]),
356 Some(parts) => format!("({})", parts.join(", ")),
357 None => "(...)".to_owned(),
358 }
359 }
360 Object::List(items) => {
361 let address = Rc::as_ptr(items).cast::<()>();
362 let inner = with_trail(seen, address, |seen| parts(&items.borrow(), seen));
363 match inner {
364 Some(parts) => format!("[{}]", parts.join(", ")),
365 None => "[...]".to_owned(),
366 }
367 }
368 Object::Dict(entries) => {
369 let address = Rc::as_ptr(entries).cast::<()>();
370 let inner = with_trail(seen, address, |seen| {
371 entries
372 .borrow()
373 .iter()
374 .map(|(key, value)| {
375 format!("{}: {}", key.object().repr(), value.write_repr(seen))
379 })
380 .collect::<Vec<_>>()
381 });
382 match inner {
383 Some(parts) => format!("{{{}}}", parts.join(", ")),
384 None => "{...}".to_owned(),
385 }
386 }
387 Object::Set(members) => {
388 let members = members.borrow();
389 if members.is_empty() {
390 return "set()".to_owned();
394 }
395 let parts: Vec<_> = members.iter().map(|value| value.object().repr()).collect();
398 format!("{{{}}}", parts.join(", "))
399 }
400 Object::Native(value) => value.repr(),
403 }
404 }
405}
406
407enum Number<'a> {
410 Int(Cow<'a, Int>),
411 Float(f64),
412}
413
414impl Number<'_> {
415 #[expect(
416 clippy::float_cmp,
417 reason = "this is Python's `==` on two floats, so it is IEEE equality \
418 and an epsilon would be a wrong answer rather than a safer one"
419 )]
420 fn equals(&self, other: &Self) -> bool {
421 match (self, other) {
422 (Number::Int(a), Number::Int(b)) => a == b,
423 (Number::Float(a), Number::Float(b)) => a == b,
424 (Number::Int(a), Number::Float(b)) | (Number::Float(b), Number::Int(a)) => {
425 int_eq_float(a, *b)
426 }
427 }
428 }
429}
430
431fn elementwise(left: &[Object], right: &[Object]) -> bool {
434 left.len() == right.len() && left.iter().zip(right).all(|(a, b)| a.same_value(b))
435}
436
437fn parts(items: &[Object], seen: &mut Vec<*const ()>) -> Vec<String> {
439 items.iter().map(|item| item.write_repr(seen)).collect()
440}
441
442fn with_trail<T>(
445 seen: &mut Vec<*const ()>,
446 address: *const (),
447 body: impl FnOnce(&mut Vec<*const ()>) -> T,
448) -> Option<T> {
449 if seen.contains(&address) {
450 return None;
451 }
452 seen.push(address);
453 let value = body(seen);
454 seen.pop();
455 Some(value)
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461 use crate::hash::Key;
462
463 #[test]
464 fn the_singletons_print_as_their_names() {
465 assert_eq!(Object::None.repr(), "None");
466 assert_eq!(Object::Ellipsis.repr(), "Ellipsis");
467 assert_eq!(Object::NotImplemented.repr(), "NotImplemented");
468 assert_eq!(Object::Bool(true).repr(), "True");
469 assert_eq!(Object::Bool(false).repr(), "False");
470 }
471
472 #[test]
473 fn a_type_names_itself_the_way_an_error_message_would() {
474 assert_eq!(Object::None.type_name(), "NoneType");
475 assert_eq!(Object::Bool(true).type_name(), "bool");
476 assert_eq!(Object::int(1).type_name(), "int");
477 assert_eq!(Object::Float(1.0).type_name(), "float");
478 assert_eq!(Object::str("a").type_name(), "str");
479 assert_eq!(Object::Ellipsis.type_name(), "ellipsis");
480 }
481
482 #[test]
483 fn emptiness_is_falseness_for_every_container() {
484 assert!(!Object::list(vec![]).truthy());
485 assert!(Object::list(vec![Object::None]).truthy());
486 assert!(!Object::tuple(vec![]).truthy());
487 assert!(Object::tuple(vec![Object::None]).truthy());
488 assert!(!Object::str("").truthy());
489 assert!(Object::str("a").truthy());
490 assert!(!Object::Bytes(Rc::from(&b""[..])).truthy());
491 assert!(Object::Bytes(Rc::from(&b"a"[..])).truthy());
492 }
493
494 #[test]
497 fn a_container_of_falsey_things_is_true() {
498 assert!(Object::list(vec![Object::int(0)]).truthy());
499 assert!(Object::tuple(vec![Object::None]).truthy());
500 }
501
502 #[test]
503 fn zero_is_false_in_every_numeric_type() {
504 assert!(!Object::int(0).truthy());
505 assert!(Object::int(1).truthy());
506 assert!(Object::int(-1).truthy());
507 assert!(!Object::Float(0.0).truthy());
508 assert!(!Object::Float(-0.0).truthy());
510 assert!(Object::Float(f64::NAN).truthy());
511 assert!(!Object::Bool(false).truthy());
512 }
513
514 #[test]
515 fn a_tuple_of_one_keeps_the_comma_that_makes_it_a_tuple() {
516 assert_eq!(Object::tuple(vec![]).repr(), "()");
517 assert_eq!(Object::tuple(vec![Object::int(1)]).repr(), "(1,)");
518 assert_eq!(
519 Object::tuple(vec![Object::int(1), Object::int(2)]).repr(),
520 "(1, 2)"
521 );
522 }
523
524 #[test]
525 fn a_container_prints_its_elements_with_repr() {
526 let value = Object::list(vec![Object::str("a"), Object::None, Object::Float(1.5)]);
527 assert_eq!(value.repr(), "['a', None, 1.5]");
528 assert_eq!(value.display(), "['a', None, 1.5]");
531 }
532
533 #[test]
534 fn str_of_a_string_is_the_string_and_repr_of_one_is_quoted() {
535 assert_eq!(Object::str("a").display(), "a");
536 assert_eq!(Object::str("a").repr(), "'a'");
537 assert_eq!(Object::str("it's").repr(), "\"it's\"");
538 assert_eq!(Object::int(1).display(), "1");
540 assert_eq!(Object::None.display(), "None");
541 }
542
543 #[test]
546 fn a_container_that_holds_itself_prints_an_ellipsis() {
547 let items = Rc::new(RefCell::new(Vec::new()));
548 let value = Object::List(Rc::clone(&items));
549 items.borrow_mut().push(value.clone());
550 assert_eq!(value.repr(), "[[...]]");
551
552 let outer = Rc::new(RefCell::new(Vec::new()));
554 items.borrow_mut().clear();
555 items.borrow_mut().push(Object::List(Rc::clone(&outer)));
556 outer.borrow_mut().push(value.clone());
557 assert_eq!(value.repr(), "[[[...]]]");
558 }
559
560 #[test]
563 fn the_same_container_twice_side_by_side_is_not_a_cycle() {
564 let shared = Object::list(vec![Object::int(1)]);
565 let value = Object::list(vec![shared.clone(), shared]);
566 assert_eq!(value.repr(), "[[1], [1]]");
567 }
568
569 #[test]
570 fn identity_is_the_pointer_for_a_heap_value() {
571 let list = Object::list(vec![]);
572 assert!(list.is(&list.clone()));
573 assert!(!list.is(&Object::list(vec![])));
574
575 let text = Object::str("a");
576 assert!(text.is(&text.clone()));
577 assert!(!text.is(&Object::str("a")));
578 }
579
580 #[test]
583 fn identity_is_the_value_for_a_singleton_or_a_number() {
584 assert!(Object::None.is(&Object::None));
585 assert!(Object::Ellipsis.is(&Object::Ellipsis));
586 assert!(!Object::None.is(&Object::Ellipsis));
587 assert!(Object::int(1000).is(&Object::int(1000)));
588 assert!(!Object::int(1).is(&Object::Bool(true)));
589 }
590
591 #[test]
594 fn a_nan_is_itself() {
595 let nan = Object::Float(f64::NAN);
596 assert!(nan.is(&nan.clone()));
597 assert!(!nan.is(&Object::Float(1.0)));
598 assert!(!nan.equals(&nan.clone()));
599 assert!(nan.same_value(&nan.clone()));
600 }
601
602 #[test]
605 fn an_empty_set_is_the_one_repr_that_is_not_a_literal() {
606 assert_eq!(Object::dict(Dict::new()).repr(), "{}");
607 assert_eq!(Object::set(Set::new()).repr(), "set()");
608 }
609
610 #[test]
611 fn a_dict_prints_its_pairs_in_the_order_they_went_in() {
612 let key = |object| Key::new(object).expect("expected this to be hashable");
613 let dict: Dict = [
614 (key(Object::str("b")), Object::int(1)),
615 (key(Object::str("a")), Object::int(2)),
616 ]
617 .into_iter()
618 .collect();
619 assert_eq!(Object::dict(dict).repr(), "{'b': 1, 'a': 2}");
620
621 let set: Set = [key(Object::int(1)), key(Object::int(2))]
622 .into_iter()
623 .collect();
624 assert_eq!(Object::set(set).repr(), "{1, 2}");
625 }
626
627 #[test]
631 fn a_dict_that_holds_itself_prints_an_ellipsis() {
632 let entries = Rc::new(RefCell::new(Dict::new()));
633 let value = Object::Dict(Rc::clone(&entries));
634 let key = Key::new(Object::str("x")).expect("expected this to be hashable");
635 entries.borrow_mut().insert(key, value.clone());
636 assert_eq!(value.repr(), "{'x': {...}}");
637 }
638
639 #[test]
640 fn dicts_and_sets_compare_by_what_is_in_them() {
641 let dict = |pairs: Vec<(i64, i64)>| {
642 let entries: Dict = pairs
643 .into_iter()
644 .map(|(k, v)| (Key::new(Object::int(k)).expect("hashable"), Object::int(v)))
645 .collect();
646 Object::dict(entries)
647 };
648 assert!(dict(vec![(1, 2), (3, 4)]).equals(&dict(vec![(3, 4), (1, 2)])));
649 assert!(!dict(vec![(1, 2)]).equals(&dict(vec![(1, 3)])));
650 assert!(!dict(vec![(1, 2)]).equals(&dict(vec![(1, 2), (3, 4)])));
651 assert!(!dict(vec![]).equals(&Object::set(Set::new())));
653 }
654
655 #[test]
656 fn a_dict_and_a_set_are_not_hashable() {
657 for value in [Object::dict(Dict::new()), Object::set(Set::new())] {
658 let name = value.type_name().to_owned();
659 let refused = Key::new(value).expect_err("expected this to be refused");
660 assert_eq!(refused.message(), format!("unhashable type: '{name}'"));
661 }
662 }
663
664 #[test]
665 fn the_three_numeric_types_compare_against_each_other() {
666 assert!(Object::int(1).equals(&Object::Float(1.0)));
667 assert!(Object::int(1).equals(&Object::Bool(true)));
668 assert!(Object::int(0).equals(&Object::Bool(false)));
669 assert!(Object::Float(0.0).equals(&Object::Bool(false)));
670 assert!(Object::Float(-0.0).equals(&Object::Float(0.0)));
671 assert!(!Object::int(1).equals(&Object::Float(1.5)));
672 assert!(!Object::int(1).equals(&Object::Float(f64::INFINITY)));
673 }
674
675 #[test]
678 fn nothing_but_a_number_compares_across_types() {
679 assert!(!Object::str("abc").equals(&Object::Bytes(Rc::from(&b"abc"[..]))));
680 assert!(!Object::tuple(vec![Object::int(1)]).equals(&Object::list(vec![Object::int(1)])));
681 assert!(!Object::int(1).equals(&Object::str("1")));
682 assert!(!Object::None.equals(&Object::Bool(false)));
683 assert!(!Object::None.equals(&Object::int(0)));
684 }
685
686 #[test]
687 fn a_sequence_compares_position_by_position() {
688 let list = |items: Vec<Object>| Object::list(items);
689 assert!(list(vec![]).equals(&list(vec![])));
690 assert!(list(vec![Object::int(1)]).equals(&list(vec![Object::Float(1.0)])));
691 assert!(!list(vec![Object::int(1)]).equals(&list(vec![Object::int(1), Object::int(2)])));
692 assert!(!list(vec![Object::int(1)]).equals(&list(vec![Object::int(2)])));
693 let nested = |n| Object::tuple(vec![Object::tuple(vec![Object::int(n)])]);
695 assert!(nested(1).equals(&nested(1)));
696 assert!(!nested(1).equals(&nested(2)));
697 }
698
699 #[test]
702 fn a_list_holding_a_nan_is_equal_to_itself() {
703 let nan = Object::Float(f64::NAN);
704 let value = Object::list(vec![nan]);
705 assert!(value.equals(&value.clone()));
706 }
707
708 #[test]
711 fn a_list_compared_against_itself_does_not_borrow_it_twice() {
712 let value = Object::list(vec![Object::int(1)]);
713 assert!(value.equals(&value.clone()));
714 }
715
716 #[derive(Debug)]
719 struct Thing(&'static str);
720
721 impl crate::native::Native for Thing {
722 fn type_name(&self) -> &str {
723 "thing"
724 }
725
726 fn repr(&self) -> String {
727 format!("<thing {}>", self.0)
728 }
729
730 fn as_any(&self) -> &dyn std::any::Any {
731 self
732 }
733 }
734
735 #[test]
736 fn a_native_value_answers_for_itself() {
737 let value = Object::native(Thing("a"));
738 assert_eq!(value.type_name(), "thing");
739 assert_eq!(value.repr(), "<thing a>");
740 assert_eq!(value.display(), "<thing a>");
741 assert!(value.truthy());
744 assert_eq!(value.downcast::<Thing>().map(|thing| thing.0), Some("a"));
745 }
746
747 #[test]
750 fn a_native_value_is_equal_to_itself_and_to_nothing_else() {
751 let value = Object::native(Thing("a"));
752 assert!(value.is(&value.clone()));
753 assert!(value.equals(&value.clone()));
754 assert!(!value.is(&Object::native(Thing("a"))));
755 assert!(!value.equals(&Object::native(Thing("a"))));
756 assert!(!value.equals(&Object::int(1)));
757 let held = Object::list(vec![value.clone()]);
759 assert!(held.equals(&Object::list(vec![value])));
760 }
761
762 #[test]
765 fn a_native_value_can_be_a_key() {
766 let value = Object::native(Thing("a"));
767 let key = Key::new(value.clone()).expect("expected this to be hashable");
768 let same = Key::new(value).expect("expected this to be hashable");
769 assert_eq!(
770 crate::hash::hash(key.object()),
771 crate::hash::hash(same.object())
772 );
773
774 let mut dict = Dict::new();
775 dict.insert(key, Object::int(1));
776 assert_eq!(dict.get(&same).map(Object::repr), Some("1".to_owned()));
777 let other = Key::new(Object::native(Thing("a"))).expect("expected this to be hashable");
779 assert!(!dict.contains(&other));
780 }
781}