@@ -164,16 +164,6 @@ pub(crate) type InitFunc = fn(PyObjectRef, FuncArgs, &VirtualMachine) -> PyResul
164164pub ( crate ) type DelFunc = fn ( & PyObject , & VirtualMachine ) -> PyResult < ( ) > ;
165165pub ( crate ) type AsSequenceFunc = fn ( & PyObject , & VirtualMachine ) -> Cow < ' static , PySequenceMethods > ;
166166
167- macro_rules! then_some_closure {
168- ( $cond: expr, $closure: expr) => {
169- if $cond {
170- Some ( $closure)
171- } else {
172- None
173- }
174- } ;
175- }
176-
177167fn length_wrapper ( obj : & PyObject , vm : & VirtualMachine ) -> PyResult < usize > {
178168 let ret = vm. call_special_method ( obj. to_owned ( ) , identifier ! ( vm, __len__) , ( ) ) ?;
179169 let len = ret. payload :: < PyInt > ( ) . ok_or_else ( || {
@@ -282,45 +272,73 @@ fn as_mapping_generic(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyMappin
282272 static_as_mapping_generic ( has_length, has_subscript, has_ass_subscript)
283273}
284274
285- fn as_sequence_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> Cow < ' static , PySequenceMethods > {
275+ pub ( crate ) fn static_as_sequence_generic (
276+ has_length : bool ,
277+ has_ass_item : bool ,
278+ ) -> & ' static PySequenceMethods {
279+ static METHODS : & [ PySequenceMethods ] = & [
280+ new_generic ( false , false ) ,
281+ new_generic ( true , false ) ,
282+ new_generic ( false , true ) ,
283+ new_generic ( true , true ) ,
284+ ] ;
285+
286+ fn length ( seq : & PySequence , vm : & VirtualMachine ) -> PyResult < usize > {
287+ length_wrapper ( seq. obj , vm)
288+ }
289+ fn item ( seq : & PySequence , i : isize , vm : & VirtualMachine ) -> PyResult {
290+ vm. call_special_method ( seq. obj . to_owned ( ) , identifier ! ( vm, __getitem__) , ( i, ) )
291+ }
292+ fn ass_item (
293+ seq : & PySequence ,
294+ i : isize ,
295+ value : Option < PyObjectRef > ,
296+ vm : & VirtualMachine ,
297+ ) -> PyResult < ( ) > {
298+ match value {
299+ Some ( value) => vm
300+ . call_special_method (
301+ seq. obj . to_owned ( ) ,
302+ identifier ! ( vm, __setitem__) ,
303+ ( i. to_pyobject ( vm) , value) ,
304+ )
305+ . map ( |_| Ok ( ( ) ) ) ?,
306+ None => vm
307+ . call_special_method (
308+ seq. obj . to_owned ( ) ,
309+ identifier ! ( vm, __delitem__) ,
310+ ( i. to_pyobject ( vm) , ) ,
311+ )
312+ . map ( |_| Ok ( ( ) ) ) ?,
313+ }
314+ }
315+
316+ const fn new_generic ( has_length : bool , has_ass_item : bool ) -> PySequenceMethods {
317+ PySequenceMethods {
318+ length : if has_length { Some ( length) } else { None } ,
319+ item : Some ( item) ,
320+ ass_item : if has_ass_item { Some ( ass_item) } else { None } ,
321+ ..PySequenceMethods :: NOT_IMPLEMENTED
322+ }
323+ }
324+
325+ let key = bool_int ( has_length) | ( bool_int ( has_ass_item) << 1 ) ;
326+
327+ & METHODS [ key]
328+ }
329+
330+ fn as_sequence_generic ( zelf : & PyObject , vm : & VirtualMachine ) -> Cow < ' static , PySequenceMethods > {
286331 if !zelf. class ( ) . has_attr ( identifier ! ( vm, __getitem__) ) {
287- return Cow :: Borrowed ( PySequenceMethods :: not_implemented ( ) ) ;
288- }
289-
290- Cow :: Owned ( PySequenceMethods {
291- length : then_some_closure ! (
292- zelf. class( ) . has_attr( identifier!( vm, __len__) ) ,
293- |seq, vm| { length_wrapper( seq. obj, vm) }
294- ) ,
295- item : Some ( |seq, i, vm| {
296- vm. call_special_method (
297- seq. obj . to_owned ( ) ,
298- identifier ! ( vm, __getitem__) ,
299- ( i. to_pyobject ( vm) , ) ,
300- )
301- } ) ,
302- ass_item : then_some_closure ! (
303- zelf. class( ) . has_attr( identifier!( vm, __setitem__) )
304- | zelf. class( ) . has_attr( identifier!( vm, __delitem__) ) ,
305- |seq, i, value, vm| match value {
306- Some ( value) => vm
307- . call_special_method(
308- seq. obj. to_owned( ) ,
309- identifier!( vm, __setitem__) ,
310- ( i. to_pyobject( vm) , value) ,
311- )
312- . map( |_| Ok ( ( ) ) ) ?,
313- None => vm
314- . call_special_method(
315- seq. obj. to_owned( ) ,
316- identifier!( vm, __delitem__) ,
317- ( i. to_pyobject( vm) , )
318- )
319- . map( |_| Ok ( ( ) ) ) ?,
320- }
321- ) ,
322- ..Default :: default ( )
323- } )
332+ return Cow :: Borrowed ( & PySequenceMethods :: NOT_IMPLEMENTED ) ;
333+ }
334+
335+ let ( has_length, has_ass_item) = (
336+ zelf. class ( ) . has_attr ( identifier ! ( vm, __len__) ) ,
337+ zelf. class ( ) . has_attr ( identifier ! ( vm, __setitem__) )
338+ | zelf. class ( ) . has_attr ( identifier ! ( vm, __delitem__) ) ,
339+ ) ;
340+
341+ Cow :: Borrowed ( static_as_sequence_generic ( has_length, has_ass_item) )
324342}
325343
326344fn hash_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> PyResult < PyHash > {
@@ -436,7 +454,7 @@ impl PyType {
436454 match name. as_str ( ) {
437455 "__len__" | "__getitem__" | "__setitem__" | "__delitem__" => {
438456 update_slot ! ( as_mapping, as_mapping_generic) ;
439- update_slot ! ( as_sequence, as_sequence_wrapper ) ;
457+ update_slot ! ( as_sequence, as_sequence_generic ) ;
440458 }
441459 "__hash__" => {
442460 update_slot ! ( hash, hash_wrapper) ;
0 commit comments