1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! Module representing the Python Data Model in Rust form.
//! See: [here](https://docs.python.org/3/reference/datamodel.html).

/// The Python Object. Anything that implements this trait is a Python Object.
pub trait Object: Sized {
    /// Returns the unique identifier of the object, which is the memory address of the object.
    fn id(&self) -> usize {
        std::ptr::addr_of!(*self) as usize
    }

    /// Returns the type name of the object.
    fn r#type(&self) -> String {
        std::any::type_name::<Self>().to_string()
    }

    /// Returns the type name of the object.
    fn is<T: Object>(&self, other: &Option<T>) -> bool {
        self.id() == other.id()
    }

    /// __getattribute__ is called to look up an attribute of the object.
    fn __getattribute__(&self, _name: impl AsRef<str>) -> Option<impl Object> {
        std::option::Option::<i32>::None
    }

    /// __setattribute__ is called to set an attribute of the object.
    fn __setattribute__<T: Object>(&mut self, _name: impl AsRef<str>, _value: T) {
        unimplemented!()
    }

    /// __delattribute__ is called to delete an attribute of the object.
    fn __delattribute__(&mut self, _name: impl AsRef<str>) {
        unimplemented!()
    }

    /// __dir__ is called to list the attributes of the object.
    fn __dir__(&self) -> Vec<impl AsRef<str>> {
        unimplemented!();
        vec![
            "__class__",
            "__class_getitem__",
            "__contains__",
            "__delattr__",
            "__delitem__",
            "__dir__",
            "__doc__",
            "__eq__",
            "__format__",
            "__ge__",
            "__getattribute__",
            "__getitem__",
            "__getstate__",
            "__gt__",
            "__hash__",
            "__init__",
            "__init_subclass__",
            "__ior__",
            "__iter__",
            "__le__",
            "__len__",
            "__lt__",
            "__ne__",
            "__new__",
            "__or__",
            "__reduce__",
            "__reduce_ex__",
            "__repr__",
            "__reversed__",
            "__ror__",
            "__setattr__",
            "__setitem__",
            "__sizeof__",
            "__str__",
            "__subclasshook__",
            "clear",
            "copy",
            "fromkeys",
            "get",
            "items",
            "keys",
            "pop",
            "popitem",
            "setdefault",
            "update",
            "values",
        ]
    }
}

impl Object for i8 {}
impl Object for i16 {}
impl Object for i32 {}
impl Object for i64 {}
impl Object for i128 {}
impl Object for u8 {}
impl Object for u16 {}
impl Object for u32 {}
impl Object for u64 {}
impl Object for u128 {}
impl Object for String {}
impl Object for &str {}
impl Object for bool {}
impl Object for f32 {}
impl Object for f64 {}
impl Object for char {}

// There is a special implementation for the Option type, which allows Option<T>::None to be None in all cases.
impl<T: Object> Object for Option<T> {
    fn is<U: Object>(&self, other: &Option<U>) -> bool {
        match (self, other) {
            (Some(_), std::option::Option::None) => false,
            (std::option::Option::None, Some(_)) => false,
            (Some(a), Some(_b)) => a.is(other),
            (std::option::Option::None, std::option::Option::None) => true,
        }
    }
}

/// The Python None object.
#[allow(non_upper_case_globals)]
pub static None: Option<String> = std::option::Option::<String>::None;

/// The Python NotImplemented object.
#[allow(non_upper_case_globals)]
pub static NotImplemented: Option<&str> = Some("NotImplemented");

/// The Python NotImplemented object.
#[allow(non_upper_case_globals)]
pub static Ellipsis: &str = "...";

pub mod number;
//pub use number::*;

pub mod namespace;
pub use namespace::*;

pub mod class;
pub use class::*;

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_id() {
        let x = 5;
        let y = 6;
        println!("x: {:p}, type: {}", &x, x.r#type());
        assert_eq!(Object::id(&x), Object::id(&x));
        assert_ne!(Object::id(&x), Object::id(&y));
    }

    #[test]
    fn test_none() {
        let x = &None;
        let y: Option<i32> = std::option::Option::None;

        assert_eq!(x.is(&None), true);
        assert_ne!(x.is(&NotImplemented), true);
        assert_eq!(y.is(&None), true);
        assert_ne!(y.is(&NotImplemented), true);
    }
}