@@ -2,13 +2,15 @@ use std::cell::RefCell;
2
2
use std:: collections:: HashMap ;
3
3
4
4
use crate :: pyobject:: {
5
- AttributeProtocol , IdProtocol , PyAttributes , PyContext , PyFuncArgs , PyObject , PyObjectRef ,
6
- PyRef , PyResult , PyValue , TypeProtocol ,
5
+ AttributeProtocol , FromPyObjectRef , IdProtocol , PyAttributes , PyContext , PyFuncArgs , PyObject ,
6
+ PyObjectRef , PyRef , PyResult , PyValue , TypeProtocol ,
7
7
} ;
8
8
use crate :: vm:: VirtualMachine ;
9
9
10
10
use super :: objdict;
11
- use super :: objstr;
11
+ use super :: objlist:: PyList ;
12
+ use super :: objstr:: { self , PyStringRef } ;
13
+ use super :: objtuple:: PyTuple ;
12
14
13
15
#[ derive( Clone , Debug ) ]
14
16
pub struct PyClass {
@@ -24,6 +26,70 @@ impl PyValue for PyClass {
24
26
}
25
27
}
26
28
29
+ struct IterMro < ' a > {
30
+ cls : & ' a PyClassRef ,
31
+ offset : Option < usize > ,
32
+ }
33
+
34
+ impl < ' a > Iterator for IterMro < ' a > {
35
+ type Item = & ' a PyObjectRef ;
36
+
37
+ fn next ( & mut self ) -> Option < Self :: Item > {
38
+ match self . offset {
39
+ None => {
40
+ self . offset = Some ( 0 ) ;
41
+ Some ( & self . cls . as_object ( ) )
42
+ }
43
+ Some ( offset) => {
44
+ if offset < self . cls . mro . len ( ) {
45
+ self . offset = Some ( offset + 1 ) ;
46
+ Some ( & self . cls . mro [ offset] )
47
+ } else {
48
+ None
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ impl PyClassRef {
56
+ fn iter_mro ( & self ) -> IterMro {
57
+ IterMro {
58
+ cls : self ,
59
+ offset : None ,
60
+ }
61
+ }
62
+
63
+ fn mro ( self , _vm : & mut VirtualMachine ) -> PyTuple {
64
+ PyTuple :: from ( _mro ( & self ) )
65
+ }
66
+
67
+ fn dir ( self , vm : & mut VirtualMachine ) -> PyList {
68
+ let attributes = get_attributes ( self ) ;
69
+ let attributes: Vec < PyObjectRef > = attributes
70
+ . keys ( )
71
+ . map ( |k| vm. ctx . new_str ( k. to_string ( ) ) )
72
+ . collect ( ) ;
73
+ PyList :: from ( attributes)
74
+ }
75
+
76
+ fn instance_check ( self , obj : PyObjectRef , _vm : & mut VirtualMachine ) -> bool {
77
+ isinstance ( & obj, self . as_object ( ) )
78
+ }
79
+
80
+ fn subclass_check ( self , subclass : PyObjectRef , _vm : & mut VirtualMachine ) -> bool {
81
+ issubclass ( & subclass, self . as_object ( ) )
82
+ }
83
+
84
+ fn repr ( self , _vm : & mut VirtualMachine ) -> String {
85
+ format ! ( "<class '{}'>" , self . name)
86
+ }
87
+
88
+ fn prepare ( _name : PyStringRef , _bases : PyObjectRef , vm : & mut VirtualMachine ) -> PyObjectRef {
89
+ vm. new_dict ( )
90
+ }
91
+ }
92
+
27
93
/*
28
94
* The magical type type
29
95
*/
@@ -49,33 +115,19 @@ pub fn init(ctx: &PyContext) {
49
115
extend_class ! ( & ctx, & ctx. type_type, {
50
116
"__call__" => ctx. new_rustfunc( type_call) ,
51
117
"__new__" => ctx. new_rustfunc( type_new) ,
52
- "__mro__" => ctx. new_property( type_mro ) ,
53
- "__repr__" => ctx. new_rustfunc( type_repr ) ,
54
- "__prepare__" => ctx. new_rustfunc( type_prepare ) ,
118
+ "__mro__" => ctx. new_property( PyClassRef :: mro ) ,
119
+ "__repr__" => ctx. new_rustfunc( PyClassRef :: repr ) ,
120
+ "__prepare__" => ctx. new_rustfunc( PyClassRef :: prepare ) ,
55
121
"__getattribute__" => ctx. new_rustfunc( type_getattribute) ,
56
- "__instancecheck__" => ctx. new_rustfunc( type_instance_check ) ,
57
- "__subclasscheck__" => ctx. new_rustfunc( type_subclass_check ) ,
122
+ "__instancecheck__" => ctx. new_rustfunc( PyClassRef :: instance_check ) ,
123
+ "__subclasscheck__" => ctx. new_rustfunc( PyClassRef :: subclass_check ) ,
58
124
"__doc__" => ctx. new_str( type_doc. to_string( ) ) ,
59
- "__dir__" => ctx. new_rustfunc( type_dir ) ,
125
+ "__dir__" => ctx. new_rustfunc( PyClassRef :: dir ) ,
60
126
} ) ;
61
127
}
62
128
63
- fn type_mro ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
64
- arg_check ! ( vm, args, required = [ ( cls, Some ( vm. ctx. type_type( ) ) ) ] ) ;
65
- match _mro ( cls. clone ( ) ) {
66
- Some ( mro) => Ok ( vm. context ( ) . new_tuple ( mro) ) ,
67
- None => Err ( vm. new_type_error ( "Only classes have an MRO." . to_string ( ) ) ) ,
68
- }
69
- }
70
-
71
- fn _mro ( cls : PyObjectRef ) -> Option < Vec < PyObjectRef > > {
72
- if let Some ( PyClass { ref mro, .. } ) = cls. payload :: < PyClass > ( ) {
73
- let mut mro = mro. clone ( ) ;
74
- mro. insert ( 0 , cls. clone ( ) ) ;
75
- Some ( mro)
76
- } else {
77
- None
78
- }
129
+ fn _mro ( cls : & PyClassRef ) -> Vec < PyObjectRef > {
130
+ cls. iter_mro ( ) . cloned ( ) . collect ( )
79
131
}
80
132
81
133
/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only
@@ -84,15 +136,6 @@ pub fn isinstance(obj: &PyObjectRef, cls: &PyObjectRef) -> bool {
84
136
issubclass ( obj. type_ref ( ) , & cls)
85
137
}
86
138
87
- fn type_instance_check ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
88
- arg_check ! (
89
- vm,
90
- args,
91
- required = [ ( typ, Some ( vm. ctx. type_type( ) ) ) , ( obj, None ) ]
92
- ) ;
93
- Ok ( vm. new_bool ( isinstance ( obj, typ) ) )
94
- }
95
-
96
139
/// Determines if `subclass` is actually a subclass of `cls`, this doesn't call __subclasscheck__,
97
140
/// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic
98
141
/// method.
@@ -101,18 +144,6 @@ pub fn issubclass(subclass: &PyObjectRef, cls: &PyObjectRef) -> bool {
101
144
subclass. is ( & cls) || mro. iter ( ) . any ( |c| c. is ( & cls) )
102
145
}
103
146
104
- fn type_subclass_check ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
105
- arg_check ! (
106
- vm,
107
- args,
108
- required = [
109
- ( cls, Some ( vm. ctx. type_type( ) ) ) ,
110
- ( subclass, Some ( vm. ctx. type_type( ) ) )
111
- ]
112
- ) ;
113
- Ok ( vm. new_bool ( issubclass ( subclass, cls) ) )
114
- }
115
-
116
147
pub fn get_type_name ( typ : & PyObjectRef ) -> String {
117
148
if let Some ( PyClass { name, .. } ) = & typ. payload :: < PyClass > ( ) {
118
149
name. clone ( )
@@ -212,24 +243,13 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
212
243
}
213
244
}
214
245
215
- pub fn type_dir ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
216
- arg_check ! ( vm, args, required = [ ( obj, None ) ] ) ;
217
-
218
- let attributes = get_attributes ( & obj) ;
219
- Ok ( vm. ctx . new_list (
220
- attributes
221
- . keys ( )
222
- . map ( |k| vm. ctx . new_str ( k. to_string ( ) ) )
223
- . collect ( ) ,
224
- ) )
225
- }
226
-
227
- pub fn get_attributes ( obj : & PyObjectRef ) -> PyAttributes {
246
+ pub fn get_attributes ( cls : PyClassRef ) -> PyAttributes {
228
247
// Gather all members here:
229
248
let mut attributes = PyAttributes :: new ( ) ;
230
249
231
- let mut base_classes = _mro ( obj . clone ( ) ) . expect ( "Type get_attributes on non-type" ) ;
250
+ let mut base_classes: Vec < & PyObjectRef > = cls . iter_mro ( ) . collect ( ) ;
232
251
base_classes. reverse ( ) ;
252
+
233
253
for bc in base_classes {
234
254
if let Some ( ref dict) = & bc. dict {
235
255
for ( name, value) in dict. borrow ( ) . iter ( ) {
@@ -294,7 +314,10 @@ pub fn new(
294
314
bases : Vec < PyObjectRef > ,
295
315
dict : HashMap < String , PyObjectRef > ,
296
316
) -> PyResult {
297
- let mros = bases. into_iter ( ) . map ( |x| _mro ( x) . unwrap ( ) ) . collect ( ) ;
317
+ let mros = bases
318
+ . into_iter ( )
319
+ . map ( |x| _mro ( & FromPyObjectRef :: from_pyobj ( & x) ) )
320
+ . collect ( ) ;
298
321
let mro = linearise_mro ( mros) . unwrap ( ) ;
299
322
Ok ( PyObject {
300
323
payload : Box :: new ( PyClass {
@@ -307,16 +330,6 @@ pub fn new(
307
330
. into_ref ( ) )
308
331
}
309
332
310
- fn type_repr ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
311
- arg_check ! ( vm, args, required = [ ( obj, Some ( vm. ctx. type_type( ) ) ) ] ) ;
312
- let type_name = get_type_name ( & obj) ;
313
- Ok ( vm. new_str ( format ! ( "<class '{}'>" , type_name) ) )
314
- }
315
-
316
- fn type_prepare ( vm : & mut VirtualMachine , _args : PyFuncArgs ) -> PyResult {
317
- Ok ( vm. new_dict ( ) )
318
- }
319
-
320
333
#[ cfg( test) ]
321
334
mod tests {
322
335
use super :: { linearise_mro, new} ;
0 commit comments