Skip to main content

python_ast/datamodel/
mod.rs

1//! Module representing the Python Data Model in Rust form.
2//! See: [here](https://docs.python.org/3/reference/datamodel.html).
3
4/// The Python Object. Anything that implements this trait is a Python Object.
5pub trait Object: Sized {
6    /// Returns the unique identifier of the object, which is the memory address of the object.
7    fn id(&self) -> usize {
8        std::ptr::addr_of!(*self) as usize
9    }
10
11    /// Returns the type name of the object.
12    fn r#type(&self) -> String {
13        std::any::type_name::<Self>().to_string()
14    }
15
16    /// Returns the type name of the object.
17    fn is<T: Object>(&self, other: &Option<T>) -> bool {
18        self.id() == other.id()
19    }
20
21    /// __getattribute__ is called to look up an attribute of the object.
22    fn __getattribute__(&self, _name: impl AsRef<str>) -> Option<impl Object> {
23        std::option::Option::<i32>::None
24    }
25
26    /// __dir__ is called to list the attributes of the object.
27    fn __dir__(&self) -> Vec<impl AsRef<str>> {
28        // TODO: Implement proper attribute introspection
29        vec![
30            "__class__",
31            "__class_getitem__",
32            "__contains__",
33            "__delattr__",
34            "__delitem__",
35            "__dir__",
36            "__doc__",
37            "__eq__",
38            "__format__",
39            "__ge__",
40            "__getattribute__",
41            "__getitem__",
42            "__getstate__",
43            "__gt__",
44            "__hash__",
45            "__init__",
46            "__init_subclass__",
47            "__ior__",
48            "__iter__",
49            "__le__",
50            "__len__",
51            "__lt__",
52            "__ne__",
53            "__new__",
54            "__or__",
55            "__reduce__",
56            "__reduce_ex__",
57            "__repr__",
58            "__reversed__",
59            "__ror__",
60            "__setattr__",
61            "__setitem__",
62            "__sizeof__",
63            "__str__",
64            "__subclasshook__",
65            "clear",
66            "copy",
67            "fromkeys",
68            "get",
69            "items",
70            "keys",
71            "pop",
72            "popitem",
73            "setdefault",
74            "update",
75            "values",
76        ]
77    }
78}
79
80impl Object for i8 {}
81impl Object for i16 {}
82impl Object for i32 {}
83impl Object for i64 {}
84impl Object for i128 {}
85impl Object for u8 {}
86impl Object for u16 {}
87impl Object for u32 {}
88impl Object for u64 {}
89impl Object for u128 {}
90impl Object for String {}
91impl Object for &str {}
92impl Object for bool {}
93impl Object for f32 {}
94impl Object for f64 {}
95impl Object for char {}
96
97// There is a special implementation for the Option type, which allows Option<T>::None to be None in all cases.
98impl<T: Object> Object for Option<T> {
99    fn is<U: Object>(&self, other: &Option<U>) -> bool {
100        match (self, other) {
101            (Some(_), std::option::Option::None) => false,
102            (std::option::Option::None, Some(_)) => false,
103            (Some(a), Some(_b)) => a.is(other),
104            (std::option::Option::None, std::option::Option::None) => true,
105        }
106    }
107}
108
109/// The Python None object.
110#[allow(non_upper_case_globals)]
111pub static None: Option<String> = std::option::Option::<String>::None;
112
113/// The Python NotImplemented object.
114#[allow(non_upper_case_globals)]
115pub static NotImplemented: Option<&str> = Some("NotImplemented");
116
117/// The Python NotImplemented object.
118#[allow(non_upper_case_globals)]
119pub static Ellipsis: &str = "...";
120
121pub mod number;
122//pub use number::*;
123
124pub mod namespace;
125pub use namespace::*;
126
127pub mod class;
128pub use class::*;
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[test]
135    fn test_id() {
136        let x = 5;
137        let y = 6;
138        println!("x: {:p}, type: {}", &x, x.r#type());
139        assert_eq!(Object::id(&x), Object::id(&x));
140        assert_ne!(Object::id(&x), Object::id(&y));
141    }
142
143    #[test]
144    fn test_none() {
145        let x = &None;
146        let y: Option<i32> = std::option::Option::None;
147
148        assert_eq!(x.is(&None), true);
149        assert_ne!(x.is(&NotImplemented), true);
150        assert_eq!(y.is(&None), true);
151        assert_ne!(y.is(&NotImplemented), true);
152    }
153}