@@ -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 :: objlist:: PyList ;
11
12
use super :: objstr;
13
+ use super :: objtuple:: PyTuple ;
12
14
13
15
#[ derive( Clone , Debug ) ]
14
16
pub struct PyClass {
@@ -24,6 +26,41 @@ 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
+
27
64
/*
28
65
* The magical type type
29
66
*/
@@ -60,22 +97,12 @@ pub fn init(ctx: &PyContext) {
60
97
} ) ;
61
98
}
62
99
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
- }
100
+ fn type_mro ( cls : PyClassRef , _vm : & mut VirtualMachine ) -> PyResult < PyTuple > {
101
+ Ok ( PyTuple :: from ( _mro ( & cls) ) )
69
102
}
70
103
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
- }
104
+ fn _mro ( cls : & PyClassRef ) -> Vec < PyObjectRef > {
105
+ cls. iter_mro ( ) . cloned ( ) . collect ( )
79
106
}
80
107
81
108
/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only
@@ -212,24 +239,22 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
212
239
}
213
240
}
214
241
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
- ) )
242
+ pub fn type_dir ( obj : PyClassRef , vm : & mut VirtualMachine ) -> PyList {
243
+ let attributes = get_attributes ( obj) ;
244
+ let attributes: Vec < PyObjectRef > = attributes
245
+ . keys ( )
246
+ . map ( |k| vm. ctx . new_str ( k. to_string ( ) ) )
247
+ . collect ( ) ;
248
+ PyList :: from ( attributes)
225
249
}
226
250
227
- pub fn get_attributes ( obj : & PyObjectRef ) -> PyAttributes {
251
+ pub fn get_attributes ( cls : PyClassRef ) -> PyAttributes {
228
252
// Gather all members here:
229
253
let mut attributes = PyAttributes :: new ( ) ;
230
254
231
- let mut base_classes = _mro ( obj . clone ( ) ) . expect ( "Type get_attributes on non-type" ) ;
255
+ let mut base_classes: Vec < & PyObjectRef > = cls . iter_mro ( ) . collect ( ) ;
232
256
base_classes. reverse ( ) ;
257
+
233
258
for bc in base_classes {
234
259
if let Some ( ref dict) = & bc. dict {
235
260
for ( name, value) in dict. borrow ( ) . iter ( ) {
@@ -294,7 +319,10 @@ pub fn new(
294
319
bases : Vec < PyObjectRef > ,
295
320
dict : HashMap < String , PyObjectRef > ,
296
321
) -> PyResult {
297
- let mros = bases. into_iter ( ) . map ( |x| _mro ( x) . unwrap ( ) ) . collect ( ) ;
322
+ let mros = bases
323
+ . into_iter ( )
324
+ . map ( |x| _mro ( & FromPyObjectRef :: from_pyobj ( & x) ) )
325
+ . collect ( ) ;
298
326
let mro = linearise_mro ( mros) . unwrap ( ) ;
299
327
Ok ( PyObject {
300
328
payload : Box :: new ( PyClass {
0 commit comments