From 34bab04861ce6ec5c94a45e605294f4c66e8367c Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 25 Dec 2019 20:12:59 +0900 Subject: [PATCH 1/5] Refactor objint --- vm/src/obj/objint.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index fafcc6980..4db985aeb 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -223,8 +223,8 @@ impl PyInt { where F: Fn(&BigInt, &BigInt) -> bool, { - if objtype::isinstance(&other, &vm.ctx.int_type()) { - vm.ctx.new_bool(op(&self.value, get_value(&other))) + if let Some(other) = other.payload_if_subclass::(vm) { + vm.ctx.new_bool(op(&self.value, &other.value)) } else { vm.ctx.not_implemented() } @@ -265,8 +265,8 @@ impl PyInt { where F: Fn(&BigInt, &BigInt) -> BigInt, { - if objtype::isinstance(&other, &vm.ctx.int_type()) { - vm.ctx.new_int(op(&self.value, get_value(&other))) + if let Some(other) = other.payload_if_subclass::(vm) { + vm.ctx.new_int(op(&self.value, &other.value)) } else { vm.ctx.not_implemented() } @@ -277,8 +277,8 @@ impl PyInt { where F: Fn(&BigInt, &BigInt) -> PyResult, { - if objtype::isinstance(&other, &vm.ctx.int_type()) { - op(&self.value, get_value(&other)) + if let Some(other) = other.payload_if_subclass::(vm) { + op(&self.value, &other.value) } else { Ok(vm.ctx.not_implemented()) } From 801d01161cf9f191a5688b9be7eefb0be644f149 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Fri, 20 Dec 2019 23:17:22 +0900 Subject: [PATCH 2/5] Refactor PyFloat cmp/op --- vm/src/obj/objfloat.rs | 268 ++++++++++++++++------------------------- vm/src/obj/objint.rs | 2 +- vm/src/stdlib/math.rs | 4 +- 3 files changed, 109 insertions(+), 165 deletions(-) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index ab8c51533..0610a2302 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -90,7 +90,7 @@ fn inner_mod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult { } } -pub fn try_to_bigint(value: f64, vm: &VirtualMachine) -> PyResult { +pub fn try_bigint(value: f64, vm: &VirtualMachine) -> PyResult { match value.to_bigint() { Some(int) => Ok(int), None => { @@ -154,12 +154,20 @@ fn inner_gt_int(value: f64, other_int: &BigInt) -> bool { } } -pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult { +pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult { if v1.is_zero() { let msg = format!("{} cannot be raised to a negative power", v1); Err(vm.new_zero_division_error(msg)) } else { - v1.powf(v2).into_pyobject(vm) + Ok(v1.powf(v2)) + } +} + +fn int_eq(value: f64, other: &BigInt) -> bool { + if let (Some(self_int), Some(other_float)) = (value.to_bigint(), other.to_f64()) { + value == other_float && self_int == *other + } else { + false } } @@ -179,117 +187,78 @@ impl PyFloat { PyFloat::from(float_val?).into_ref_with_type(vm, cls) } - fn float_eq(&self, other: PyObjectRef) -> bool { - let other = get_value(&other); - self.value == other - } - - fn int_eq(&self, other: PyObjectRef) -> bool { - let other_int = objint::get_value(&other); - let value = self.value; - if let (Some(self_int), Some(other_float)) = (value.to_bigint(), other_int.to_f64()) { - value == other_float && self_int == *other_int + #[inline] + fn cmp( + &self, + other: PyObjectRef, + float_op: F, + int_op: G, + vm: &VirtualMachine, + ) -> PyObjectRef + where + F: Fn(f64, f64) -> bool, + G: Fn(f64, &BigInt) -> bool, + { + let result = if let Some(other) = other.payload_if_subclass::(vm) { + float_op(self.value, other.value) + } else if let Some(other) = other.payload_if_subclass::(vm) { + int_op(self.value, other.as_bigint()) } else { - false - } + return vm.ctx.not_implemented(); + }; + vm.ctx.new_bool(result) } #[pymethod(name = "__eq__")] fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let result = if objtype::isinstance(&other, &vm.ctx.float_type()) { - self.float_eq(other) - } else if objtype::isinstance(&other, &vm.ctx.int_type()) { - self.int_eq(other) - } else { - return vm.ctx.not_implemented(); - }; - vm.ctx.new_bool(result) + self.cmp(other, |a, b| a == b, |a, b| int_eq(a, b), vm) } #[pymethod(name = "__ne__")] fn ne(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let result = if objtype::isinstance(&other, &vm.ctx.float_type()) { - !self.float_eq(other) - } else if objtype::isinstance(&other, &vm.ctx.int_type()) { - !self.int_eq(other) - } else { - return vm.ctx.not_implemented(); - }; - vm.ctx.new_bool(result) + self.cmp(other, |a, b| a != b, |a, b| !int_eq(a, b), vm) } #[pymethod(name = "__lt__")] - fn lt(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let v1 = self.value; - if objtype::isinstance(&i2, &vm.ctx.float_type()) { - vm.ctx.new_bool(v1 < get_value(&i2)) - } else if objtype::isinstance(&i2, &vm.ctx.int_type()) { - let other_int = objint::get_value(&i2); - - vm.ctx.new_bool(inner_lt_int(self.value, other_int)) - } else { - vm.ctx.not_implemented() - } + fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { + self.cmp(other, |a, b| a < b, |a, b| inner_lt_int(a, b), vm) } #[pymethod(name = "__le__")] - fn le(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let v1 = self.value; - if objtype::isinstance(&i2, &vm.ctx.float_type()) { - vm.ctx.new_bool(v1 <= get_value(&i2)) - } else if objtype::isinstance(&i2, &vm.ctx.int_type()) { - let other_int = objint::get_value(&i2); - - let result = if let (Some(self_int), Some(other_float)) = - (self.value.to_bigint(), other_int.to_f64()) - { - self.value <= other_float && self_int <= *other_int - } else { - // certainly not equal, forward to inner_lt_int - inner_lt_int(self.value, other_int) - }; - - vm.ctx.new_bool(result) - } else { - vm.ctx.not_implemented() - } + fn le(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { + self.cmp( + other, + |a, b| a <= b, + |a, b| { + if let (Some(a_int), Some(b_float)) = (a.to_bigint(), b.to_f64()) { + a <= b_float && a_int <= *b + } else { + inner_lt_int(a, b) + } + }, + vm, + ) } #[pymethod(name = "__gt__")] - fn gt(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let v1 = self.value; - if objtype::isinstance(&i2, &vm.ctx.float_type()) { - vm.ctx.new_bool(v1 > get_value(&i2)) - } else if objtype::isinstance(&i2, &vm.ctx.int_type()) { - let other_int = objint::get_value(&i2); - - vm.ctx.new_bool(inner_gt_int(self.value, other_int)) - } else { - vm.ctx.not_implemented() - } + fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { + self.cmp(other, |a, b| a > b, |a, b| inner_gt_int(a, b), vm) } #[pymethod(name = "__ge__")] - fn ge(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let v1 = self.value; - if objtype::isinstance(&i2, &vm.ctx.float_type()) { - vm.ctx.new_bool(v1 >= get_value(&i2)) - } else if objtype::isinstance(&i2, &vm.ctx.int_type()) { - let other_int = objint::get_value(&i2); - - let result = if let (Some(self_int), Some(other_float)) = - (self.value.to_bigint(), other_int.to_f64()) - { - self.value >= other_float && self_int >= *other_int - } else { - // certainly not equal, forward to inner_gt_int - inner_gt_int(self.value, other_int) - }; - - vm.ctx.new_bool(result) - } else { - vm.ctx.not_implemented() - } + fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { + self.cmp( + other, + |a, b| a >= b, + |a, b| { + if let (Some(a_int), Some(b_float)) = (a.to_bigint(), b.to_f64()) { + a >= b_float && a_int >= *b + } else { + inner_gt_int(a, b) + } + }, + vm, + ) } #[pymethod(name = "__abs__")] @@ -297,14 +266,38 @@ impl PyFloat { self.value.abs() } - #[pymethod(name = "__add__")] - fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + #[inline] + fn simple_op(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult + where + F: Fn(f64, f64) -> PyResult, + { try_float(&other, vm)?.map_or_else( || Ok(vm.ctx.not_implemented()), - |other| (self.value + other).into_pyobject(vm), + |other| op(self.value, other).into_pyobject(vm), ) } + #[inline] + fn tuple_op(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult + where + F: Fn(f64, f64) -> PyResult<(f64, f64)>, + { + try_float(&other, vm)?.map_or_else( + || Ok(vm.ctx.not_implemented()), + |other| { + let (r1, r2) = op(self.value, other)?; + Ok(vm + .ctx + .new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)])) + }, + ) + } + + #[pymethod(name = "__add__")] + fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + self.simple_op(other, |a, b| Ok(a + b), vm) + } + #[pymethod(name = "__radd__")] fn radd(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { self.add(other, vm) @@ -317,60 +310,32 @@ impl PyFloat { #[pymethod(name = "__divmod__")] fn divmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| { - let (r1, r2) = inner_divmod(self.value, other, vm)?; - Ok(vm - .ctx - .new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)])) - }, - ) + self.tuple_op(other, |a, b| inner_divmod(a, b, vm), vm) } #[pymethod(name = "__rdivmod__")] fn rdivmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| { - let (r1, r2) = inner_divmod(other, self.value, vm)?; - Ok(vm - .ctx - .new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)])) - }, - ) + self.tuple_op(other, |a, b| inner_divmod(b, a, vm), vm) } #[pymethod(name = "__floordiv__")] fn floordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| inner_floordiv(self.value, other, vm)?.into_pyobject(vm), - ) + self.simple_op(other, |a, b| inner_floordiv(a, b, vm), vm) } #[pymethod(name = "__rfloordiv__")] fn rfloordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| inner_floordiv(other, self.value, vm)?.into_pyobject(vm), - ) + self.simple_op(other, |a, b| inner_floordiv(b, a, vm), vm) } #[pymethod(name = "__mod__")] fn mod_(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| inner_mod(self.value, other, vm)?.into_pyobject(vm), - ) + self.simple_op(other, |a, b| inner_mod(a, b, vm), vm) } #[pymethod(name = "__rmod__")] fn rmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| inner_mod(other, self.value, vm)?.into_pyobject(vm), - ) + self.simple_op(other, |a, b| inner_mod(b, a, vm), vm) } #[pymethod(name = "__pos__")] @@ -385,34 +350,22 @@ impl PyFloat { #[pymethod(name = "__pow__")] fn pow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| float_pow(self.value, other, vm), - ) + self.simple_op(other, |a, b| float_pow(a, b, vm), vm) } #[pymethod(name = "__rpow__")] fn rpow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| float_pow(other, self.value, vm), - ) + self.simple_op(other, |a, b| float_pow(b, a, vm), vm) } #[pymethod(name = "__sub__")] fn sub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (self.value - other).into_pyobject(vm), - ) + self.simple_op(other, |a, b| Ok(a - b), vm) } #[pymethod(name = "__rsub__")] fn rsub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (other - self.value).into_pyobject(vm), - ) + self.simple_op(other, |a, b| Ok(b - a), vm) } #[pymethod(name = "__repr__")] @@ -438,26 +391,17 @@ impl PyFloat { #[pymethod(name = "__truediv__")] fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| inner_div(self.value, other, vm)?.into_pyobject(vm), - ) + self.simple_op(other, |a, b| inner_div(a, b, vm), vm) } #[pymethod(name = "__rtruediv__")] fn rtruediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| inner_div(other, self.value, vm)?.into_pyobject(vm), - ) + self.simple_op(other, |a, b| inner_div(b, a, vm), vm) } #[pymethod(name = "__mul__")] fn mul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (self.value * other).into_pyobject(vm), - ) + self.simple_op(other, |a, b| Ok(a * b), vm) } #[pymethod(name = "__rmul__")] @@ -467,7 +411,7 @@ impl PyFloat { #[pymethod(name = "__trunc__")] fn trunc(&self, vm: &VirtualMachine) -> PyResult { - try_to_bigint(self.value, vm) + try_bigint(self.value, vm) } #[pymethod(name = "__round__")] @@ -523,7 +467,7 @@ impl PyFloat { } else { self.value.round() }; - let int = try_to_bigint(value, vm)?; + let int = try_bigint(value, vm)?; Ok(vm.ctx.new_int(int)) } } @@ -757,8 +701,8 @@ pub fn get_value(obj: &PyObjectRef) -> f64 { } fn make_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { - if objtype::isinstance(obj, &vm.ctx.float_type()) { - Ok(get_value(obj)) + if let Some(float) = obj.payload_if_subclass::(vm) { + Ok(float.value) } else { let method = vm.get_method_or_type_error(obj.clone(), "__float__", || { format!( diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 4db985aeb..748ccf7b4 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -120,7 +120,7 @@ fn inner_pow(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult { if int2.is_negative() { let v1 = try_float(int1, vm)?; let v2 = try_float(int2, vm)?; - objfloat::float_pow(v1, v2, vm) + objfloat::float_pow(v1, v2, vm).into_pyobject(vm) } else { Ok(if let Some(v2) = int2.to_u64() { vm.ctx.new_int(int1.pow(v2)) diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index 4a0fa3842..d875d9ba1 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -225,7 +225,7 @@ fn math_trunc(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { if objtype::isinstance(&value, &vm.ctx.float_type()) { let v = objfloat::get_value(&value); - let v = objfloat::try_to_bigint(v.ceil(), vm)?; + let v = objfloat::try_bigint(v.ceil(), vm)?; Ok(vm.ctx.new_int(v)) } else { try_magic_method("__ceil__", vm, &value) @@ -241,7 +241,7 @@ fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { if objtype::isinstance(&value, &vm.ctx.float_type()) { let v = objfloat::get_value(&value); - let v = objfloat::try_to_bigint(v.floor(), vm)?; + let v = objfloat::try_bigint(v.floor(), vm)?; Ok(vm.ctx.new_int(v)) } else { try_magic_method("__floor__", vm, &value) From cbbacbaa47149c0b8f3d5685cbcce4afe80d88ce Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sat, 21 Dec 2019 18:32:31 +0900 Subject: [PATCH 3/5] Refactor PyComplex --- vm/src/obj/objcomplex.rs | 66 +++++++++++++++------------------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index 360371d38..80534a6cb 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -3,7 +3,7 @@ use num_traits::Zero; use std::num::Wrapping; use super::objfloat::{self, IntoPyFloat}; -use super::objtype::{self, PyClassRef}; +use super::objtype::PyClassRef; use crate::function::OptionalArg; use crate::pyhash; use crate::pyobject::{ @@ -43,18 +43,15 @@ pub fn init(context: &PyContext) { PyComplex::extend_class(context, &context.types.complex_type); } -pub fn get_value(obj: &PyObjectRef) -> Complex64 { - obj.payload::().unwrap().value -} - fn try_complex(value: &PyObjectRef, vm: &VirtualMachine) -> PyResult> { - Ok(if objtype::isinstance(&value, &vm.ctx.complex_type()) { - Some(get_value(&value)) + let r = if let Some(complex) = value.payload_if_subclass::(vm) { + Some(complex.value) } else if let Some(float) = objfloat::try_float(value, vm)? { Some(Complex64::new(float, 0.0)) } else { None - }) + }; + Ok(r) } #[pyimpl] @@ -75,14 +72,22 @@ impl PyComplex { re.hypot(im) } - #[pymethod(name = "__add__")] - fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + #[inline] + fn op(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult + where + F: Fn(Complex64, Complex64) -> Complex64, + { try_complex(&other, vm)?.map_or_else( || Ok(vm.ctx.not_implemented()), - |other| (self.value + other).into_pyobject(vm), + |other| op(self.value, other).into_pyobject(vm), ) } + #[pymethod(name = "__add__")] + fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + self.op(other, |a, b| a + b, vm) + } + #[pymethod(name = "__radd__")] fn radd(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { self.add(other, vm) @@ -90,18 +95,12 @@ impl PyComplex { #[pymethod(name = "__sub__")] fn sub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (self.value - other).into_pyobject(vm), - ) + self.op(other, |a, b| a - b, vm) } #[pymethod(name = "__rsub__")] fn rsub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (other - self.value).into_pyobject(vm), - ) + self.op(other, |a, b| b - a, vm) } #[pymethod(name = "conjugate")] @@ -111,8 +110,8 @@ impl PyComplex { #[pymethod(name = "__eq__")] fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - let result = if objtype::isinstance(&other, &vm.ctx.complex_type()) { - self.value == get_value(&other) + let result = if let Some(other) = other.payload_if_subclass::(vm) { + self.value == other.value } else { match objfloat::try_float(&other, vm) { Ok(Some(other)) => self.value.im == 0.0f64 && self.value.re == other, @@ -136,10 +135,7 @@ impl PyComplex { #[pymethod(name = "__mul__")] fn mul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (self.value * other).into_pyobject(vm), - ) + self.op(other, |a, b| a * b, vm) } #[pymethod(name = "__rmul__")] @@ -149,18 +145,12 @@ impl PyComplex { #[pymethod(name = "__truediv__")] fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (self.value / other).into_pyobject(vm), - ) + self.op(other, |a, b| a / b, vm) } #[pymethod(name = "__rtruediv__")] fn rtruediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (other / self.value).into_pyobject(vm), - ) + self.op(other, |a, b| b / a, vm) } #[pymethod(name = "__mod__")] @@ -210,18 +200,12 @@ impl PyComplex { #[pymethod(name = "__pow__")] fn pow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (self.value.powc(other)).into_pyobject(vm), - ) + self.op(other, |a, b| a.powc(b), vm) } #[pymethod(name = "__rpow__")] fn rpow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - try_complex(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| (other.powc(self.value)).into_pyobject(vm), - ) + self.op(other, |a, b| b.powc(a), vm) } #[pymethod(name = "__bool__")] From b7eeba24db3d6c555e7bdc9126c3cccfa7d6c8ee Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sat, 21 Dec 2019 18:48:19 +0900 Subject: [PATCH 4/5] Refactor PyString --- vm/src/obj/objstr.rs | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 71e39f205..0e0f3fb22 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -280,39 +280,23 @@ impl PyString { } #[pymethod(name = "__gt__")] - fn gt(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if objtype::isinstance(&rhs, &vm.ctx.str_type()) { - Ok(self.value > get_value(&rhs)) - } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs))) - } + fn gt(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool { + self.value > other.value } #[pymethod(name = "__ge__")] - fn ge(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if objtype::isinstance(&rhs, &vm.ctx.str_type()) { - Ok(self.value >= get_value(&rhs)) - } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs))) - } + fn ge(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool { + self.value >= other.value } #[pymethod(name = "__lt__")] - fn lt(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if objtype::isinstance(&rhs, &vm.ctx.str_type()) { - Ok(self.value < get_value(&rhs)) - } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs))) - } + fn lt(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool { + self.value < other.value } #[pymethod(name = "__le__")] - fn le(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if objtype::isinstance(&rhs, &vm.ctx.str_type()) { - Ok(self.value <= get_value(&rhs)) - } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs))) - } + fn le(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool { + self.value <= other.value } #[pymethod(name = "__hash__")] From 266bdceb8d0108d971232b4cb7ed27fbab68d035 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 22 Dec 2019 01:34:37 +0900 Subject: [PATCH 5/5] impl PyNoneRef -> impl PyNone --- vm/src/obj/objnone.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/vm/src/obj/objnone.rs b/vm/src/obj/objnone.rs index 6821fd6ab..25201de4b 100644 --- a/vm/src/obj/objnone.rs +++ b/vm/src/obj/objnone.rs @@ -36,26 +36,26 @@ impl IntoPyObject for Option { } #[pyimpl] -impl PyNoneRef { +impl PyNone { #[pyslot(new)] fn tp_new(_: PyClassRef, vm: &VirtualMachine) -> PyNoneRef { vm.ctx.none.clone() } #[pymethod(name = "__repr__")] - fn repr(self, _vm: &VirtualMachine) -> PyResult { + fn repr(&self, _vm: &VirtualMachine) -> PyResult { Ok("None".to_string()) } #[pymethod(name = "__bool__")] - fn bool(self, _vm: &VirtualMachine) -> PyResult { + fn bool(&self, _vm: &VirtualMachine) -> PyResult { Ok(false) } #[pymethod(name = "__getattribute__")] - fn get_attribute(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { + fn get_attribute(zelf: PyRef, name: PyStringRef, vm: &VirtualMachine) -> PyResult { vm_trace!("None.__getattribute__({:?}, {:?})", self, name); - let cls = self.class(); + let cls = zelf.class(); // Properties use a comparision with None to determine if they are either invoked by am // instance binding or a class binding. But if the object itself is None then this detection @@ -86,7 +86,7 @@ impl PyNoneRef { return call_descriptor( attr, get_func, - self.into_object(), + zelf.into_object(), cls.into_object(), vm, ); @@ -95,25 +95,25 @@ impl PyNoneRef { } // None has no attributes and cannot have attributes set on it. - // if let Some(obj_attr) = self.as_object().get_attr(name.as_str()) { + // if let Some(obj_attr) = zelf.as_object().get_attr(name.as_str()) { // Ok(obj_attr) // } else if let Some(attr) = class_get_attr(&cls, name.as_str()) { let attr_class = attr.class(); if let Some(get_func) = class_get_attr(&attr_class, "__get__") { - call_descriptor(attr, get_func, self.into_object(), cls.into_object(), vm) + call_descriptor(attr, get_func, zelf.into_object(), cls.into_object(), vm) } else { Ok(attr) } } else if let Some(getter) = class_get_attr(&cls, "__getattr__") { - vm.invoke(&getter, vec![self.into_object(), name.into_object()]) + vm.invoke(&getter, vec![zelf.into_object(), name.into_object()]) } else { - Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self.as_object(), name))) + Err(vm.new_attribute_error(format!("{} has no attribute '{}'", zelf.as_object(), name))) } } #[pymethod(name = "__eq__")] - fn eq(self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { + fn eq(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { if vm.is_none(&rhs) { vm.ctx.new_bool(true) } else { @@ -122,7 +122,7 @@ impl PyNoneRef { } #[pymethod(name = "__ne__")] - fn ne(self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { + fn ne(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { if vm.is_none(&rhs) { vm.ctx.new_bool(false) } else { @@ -132,5 +132,5 @@ impl PyNoneRef { } pub fn init(context: &PyContext) { - PyNoneRef::extend_class(context, &context.none.class()); + PyNone::extend_class(context, &context.none.class()); }