Skip to content

Commit 05d2faa

Browse files
committed
Added call_or_unsupported to vm.rs
This is to prevent code duplication
1 parent 96c1c5a commit 05d2faa

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

vm/src/vm.rs

+71-1
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,76 @@ impl VirtualMachine {
455455
}
456456
}
457457

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+
458528
pub fn _sub(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
459529
// 1. Try __sub__, next __rsub__, next, give up
460530
if let Ok(method) = self.get_method(a.clone(), "__sub__") {
@@ -527,7 +597,7 @@ impl VirtualMachine {
527597
}
528598

529599
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__", "|")
531601
}
532602

533603
pub fn _and(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {

0 commit comments

Comments
 (0)