@@ -4,13 +4,15 @@ use super::{
4
4
} ;
5
5
use crate :: common:: { ascii, lock:: PyRwLock } ;
6
6
use crate :: {
7
+ builtins:: dict:: PyMapping ,
7
8
function:: { FuncArgs , KwArgs , OptionalArg } ,
8
9
slots:: { self , Callable , PyTpFlags , PyTypeSlots , SlotGetattro , SlotSetattro } ,
9
10
utils:: Either ,
10
11
IdProtocol , PyAttributes , PyClassImpl , PyContext , PyLease , PyObjectRef , PyRef , PyResult ,
11
12
PyValue , TryFromObject , TypeProtocol , VirtualMachine ,
12
13
} ;
13
14
use itertools:: Itertools ;
15
+ use num_traits:: ToPrimitive ;
14
16
use std:: collections:: HashSet ;
15
17
use std:: fmt;
16
18
use std:: ops:: Deref ;
@@ -265,6 +267,54 @@ impl PyType {
265
267
|zelf, vm| vm. call_special_method ( zelf. clone ( ) , "__next__" , ( ) ) ;
266
268
update_slot ! ( iternext, func) ;
267
269
}
270
+ "__len__" | "__getitem__" | "__setitem__" | "__delitem__" => {
271
+ macro_rules! then_some_closure {
272
+ ( $cond: expr, $closure: expr) => {
273
+ if $cond {
274
+ Some ( $closure)
275
+ } else {
276
+ None
277
+ }
278
+ } ;
279
+ }
280
+
281
+ let func: slots:: MappingFunc = |zelf, _vm| {
282
+ Ok ( PyMapping {
283
+ length : then_some_closure ! ( zelf. has_class_attr( "__len__" ) , |zelf, vm| {
284
+ vm. call_special_method( zelf, "__len__" , ( ) ) . map( |obj| {
285
+ obj. payload_if_subclass:: <PyInt >( vm)
286
+ . map( |length_obj| {
287
+ length_obj. as_bigint( ) . to_usize( ) . ok_or_else( || {
288
+ vm. new_value_error(
289
+ "__len__() should return >= 0" . to_owned( ) ,
290
+ )
291
+ } )
292
+ } )
293
+ . unwrap( )
294
+ } ) ?
295
+ } ) ,
296
+ subscript : then_some_closure ! (
297
+ zelf. has_class_attr( "__getitem__" ) ,
298
+ |zelf: PyObjectRef , needle: PyObjectRef , vm: & VirtualMachine | {
299
+ vm. call_special_method( zelf, "__getitem__" , ( needle, ) )
300
+ }
301
+ ) ,
302
+ ass_subscript : then_some_closure ! (
303
+ zelf. has_class_attr( "__setitem__" ) | zelf. has_class_attr( "__delitem__" ) ,
304
+ |zelf, needle, value, vm| match value {
305
+ Some ( value) => vm
306
+ . call_special_method( zelf, "__setitem__" , ( needle, value) , )
307
+ . map( |_| Ok ( ( ) ) ) ?,
308
+ None => vm
309
+ . call_special_method( zelf, "__delitem__" , ( needle, ) )
310
+ . map( |_| Ok ( ( ) ) ) ?,
311
+ }
312
+ ) ,
313
+ } )
314
+ } ;
315
+ update_slot ! ( as_mapping, func) ;
316
+ // TODO: need to update sequence protocol too
317
+ }
268
318
_ => { }
269
319
}
270
320
}
0 commit comments