@@ -455,6 +455,76 @@ impl VirtualMachine {
455
455
}
456
456
}
457
457
458
+ /// Calls default method, reverse method or exception
459
+ ///
460
+ /// * `a` - First argument.
461
+ /// * `b` - Second argument.
462
+ /// * `d` - Default method to try and call (such as `__sub__`).
463
+ /// * `r` - Reverse method to try and call (such as `__rsub__`), in case first one fails.
464
+ /// * `op` - Operator for the exception text, for example `-`.
465
+ ///
466
+ /// Given the above example, it will
467
+ /// 1. Try to call `__sub__` with `a` and `b`
468
+ /// 2. If above fails try to call `__rsub__` with `a` and `b`
469
+ /// 3. If above fails throw an exception:
470
+ /// `Unsupported operand types for '-': 'int' and 'float'`
471
+ /// if `a` is of type int and `b` of type float
472
+ ///
473
+ pub fn call_or_unsupported (
474
+ & mut self ,
475
+ a : PyObjectRef ,
476
+ b : PyObjectRef ,
477
+ d : & str ,
478
+ r : & str ,
479
+ op : & str ,
480
+ ) -> PyResult {
481
+ // Try to call the first method
482
+ if let Ok ( method) = self . get_method ( a. clone ( ) , d) {
483
+ match self . invoke (
484
+ method,
485
+ PyFuncArgs {
486
+ args : vec ! [ b. clone( ) ] ,
487
+ kwargs : vec ! [ ] ,
488
+ } ,
489
+ ) {
490
+ Ok ( value) => return Ok ( value) ,
491
+ Err ( err) => {
492
+ if !objtype:: isinstance ( & err, & self . ctx . exceptions . not_implemented_error ) {
493
+ return Err ( err) ;
494
+ }
495
+ }
496
+ }
497
+ }
498
+
499
+ // 2. Try to call reverse method
500
+ if let Ok ( method) = self . get_method ( b. clone ( ) , r) {
501
+ match self . invoke (
502
+ method,
503
+ PyFuncArgs {
504
+ args : vec ! [ a. clone( ) ] ,
505
+ kwargs : vec ! [ ] ,
506
+ } ,
507
+ ) {
508
+ Ok ( value) => return Ok ( value) ,
509
+ Err ( err) => {
510
+ if !objtype:: isinstance ( & err, & self . ctx . exceptions . not_implemented_error ) {
511
+ return Err ( err) ;
512
+ }
513
+ }
514
+ }
515
+ }
516
+
517
+ // 3. Both failed, throw an exception
518
+ // TODO: Move this chunk somewhere else, it should be
519
+ // called in other methods as well (for example objint.rs)
520
+ let a_type_name = objtype:: get_type_name ( & a. typ ( ) ) ;
521
+ let b_type_name = objtype:: get_type_name ( & b. typ ( ) ) ;
522
+ Err ( self . new_type_error ( format ! (
523
+ "Unsupported operand types for '{}': '{}' and '{}'" ,
524
+ op, a_type_name, b_type_name
525
+ ) ) )
526
+ }
527
+
458
528
pub fn _sub ( & mut self , a : PyObjectRef , b : PyObjectRef ) -> PyResult {
459
529
// 1. Try __sub__, next __rsub__, next, give up
460
530
if let Ok ( method) = self . get_method ( a. clone ( ) , "__sub__" ) {
@@ -527,7 +597,7 @@ impl VirtualMachine {
527
597
}
528
598
529
599
pub fn _or ( & mut self , a : PyObjectRef , b : PyObjectRef ) -> PyResult {
530
- self . call_method ( & a, "__or__" , vec ! [ b ] )
600
+ self . call_or_unsupported ( a, b , "__or__" , "__ror__" , "|" )
531
601
}
532
602
533
603
pub fn _and ( & mut self , a : PyObjectRef , b : PyObjectRef ) -> PyResult {
0 commit comments