From 01407194de88df9209a6e38f52e3c9ee8fe274ca Mon Sep 17 00:00:00 2001 From: Bojan Date: Sun, 28 Oct 2018 21:08:28 +0100 Subject: [PATCH 1/3] Added default __and__ For all objects without defined __and__ this should be a default error --- vm/src/obj/objobject.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 8e1aa37e14..4ab4b18889 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -101,12 +101,28 @@ pub fn init(context: &PyContext) { object.set_attr("__hash__", context.new_rustfunc(object_hash)); object.set_attr("__str__", context.new_rustfunc(object_str)); object.set_attr("__repr__", context.new_rustfunc(object_repr)); + object.set_attr("__and__", context.new_rustfunc(object_and)); } fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { Ok(vm.ctx.none()) } +fn object_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [ + (zelf, None), + (other, None) + ] + ); + + let zelf_type = objtype::get_type_name(&zelf.typ()); + let other_type = objtype::get_type_name(&other.typ()); + Err(vm.new_type_error(format!("unsupported operand type(s) for &: {:?} and {:?}", zelf_type, other_type))) +} + fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { match args.args[0].borrow().kind { PyObjectKind::Class { ref dict, .. } => Ok(dict.clone()), From 0e4d3677d9fecf698f472f19aaa0a18d7e65d2f0 Mon Sep 17 00:00:00 2001 From: Bojan Date: Sun, 28 Oct 2018 23:08:14 +0100 Subject: [PATCH 2/3] Fixed formatting --- vm/src/obj/objobject.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 4ab4b18889..13481b835b 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -109,18 +109,14 @@ fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { } fn object_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (zelf, None), - (other, None) - ] - ); + arg_check!(vm, args, required = [(zelf, None), (other, None)]); let zelf_type = objtype::get_type_name(&zelf.typ()); let other_type = objtype::get_type_name(&other.typ()); - Err(vm.new_type_error(format!("unsupported operand type(s) for &: {:?} and {:?}", zelf_type, other_type))) + Err(vm.new_type_error(format!( + "unsupported operand type(s) for &: {:?} and {:?}", + zelf_type, other_type + ))) } fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { From e7cd83240c6628e45183c199212cecf98c610b6f Mon Sep 17 00:00:00 2001 From: Bojan Date: Wed, 7 Nov 2018 22:32:20 +0100 Subject: [PATCH 3/3] Changed to proper implementation in vm --- vm/src/obj/objobject.rs | 12 ----------- vm/src/vm.rs | 45 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 13481b835b..8e1aa37e14 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -101,24 +101,12 @@ pub fn init(context: &PyContext) { object.set_attr("__hash__", context.new_rustfunc(object_hash)); object.set_attr("__str__", context.new_rustfunc(object_str)); object.set_attr("__repr__", context.new_rustfunc(object_repr)); - object.set_attr("__and__", context.new_rustfunc(object_and)); } fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { Ok(vm.ctx.none()) } -fn object_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(zelf, None), (other, None)]); - - let zelf_type = objtype::get_type_name(&zelf.typ()); - let other_type = objtype::get_type_name(&other.typ()); - Err(vm.new_type_error(format!( - "unsupported operand type(s) for &: {:?} and {:?}", - zelf_type, other_type - ))) -} - fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { match args.args[0].borrow().kind { PyObjectKind::Class { ref dict, .. } => Ok(dict.clone()), diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 3c8aa09528..7cc4c024f3 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -407,7 +407,50 @@ impl VirtualMachine { } pub fn _and(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { - self.call_method(&a, "__and__", vec![b]) + // 1. Try __and__, next __rand__, next, give up + if let Ok(method) = self.get_method(a.clone(), "__and__") { + match self.invoke( + method, + PyFuncArgs { + args: vec![b.clone()], + kwargs: vec![], + }, + ) { + Ok(value) => return Ok(value), + Err(err) => { + if !objtype::isinstance(&err, &self.ctx.exceptions.not_implemented_error) { + return Err(err); + } + } + } + } + + // 2. try __rand__ + if let Ok(method) = self.get_method(b.clone(), "__rand__") { + match self.invoke( + method, + PyFuncArgs { + args: vec![a.clone()], + kwargs: vec![], + }, + ) { + Ok(value) => return Ok(value), + Err(err) => { + if !objtype::isinstance(&err, &self.ctx.exceptions.not_implemented_error) { + return Err(err); + } + } + } + } + + // 3. It all failed :( + // Cannot and a and b + let a_type_name = objtype::get_type_name(&a.typ()); + let b_type_name = objtype::get_type_name(&b.typ()); + Err(self.new_type_error(format!( + "Unsupported operand types for '&': '{}' and '{}'", + a_type_name, b_type_name + ))) } }