Skip to content

Commit 2e7ec1d

Browse files
authored
Merge pull request #3819 from qingshi163/heaptypeext
HeapTypeExt and Protocol Methods Pointer
2 parents 71e23e8 + 370c4f7 commit 2e7ec1d

30 files changed

+619
-421
lines changed

derive/src/pyclass.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,15 @@ where
564564
let slot_name = slot_ident.to_string();
565565
let tokens = {
566566
const NON_ATOMIC_SLOTS: &[&str] = &["as_buffer"];
567+
const POINTER_SLOTS: &[&str] = &["as_number"];
567568
if NON_ATOMIC_SLOTS.contains(&slot_name.as_str()) {
568569
quote_spanned! { span =>
569570
slots.#slot_ident = Some(Self::#ident as _);
570571
}
572+
} else if POINTER_SLOTS.contains(&slot_name.as_str()) {
573+
quote_spanned! { span =>
574+
slots.#slot_ident.store(Some(PointerSlot::from(Self::#ident())));
575+
}
571576
} else {
572577
quote_spanned! { span =>
573578
slots.#slot_ident.store(Some(Self::#ident as _));

stdlib/src/bisect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod _bisect {
2525
vm: &VirtualMachine,
2626
) -> PyResult<Option<isize>> {
2727
arg.into_option()
28-
.map(|v| vm.to_index(&v)?.try_to_primitive(vm))
28+
.map(|v| v.try_index(vm)?.try_to_primitive(vm))
2929
.transpose()
3030
}
3131

stdlib/src/math.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ mod math {
199199

200200
#[pyfunction]
201201
fn isqrt(x: PyObjectRef, vm: &VirtualMachine) -> PyResult<BigInt> {
202-
let index = vm.to_index(&x)?;
202+
let index = x.try_index(vm)?;
203203
let value = index.as_bigint();
204204

205205
if value.is_negative() {

stdlib/src/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ mod decl {
347347
Some(ms) => {
348348
let ms = if let Some(float) = ms.payload::<PyFloat>() {
349349
float.to_f64().to_i32()
350-
} else if let Some(int) = vm.to_index_opt(ms.clone()) {
350+
} else if let Some(int) = ms.try_index_opt(vm) {
351351
int?.as_bigint().to_i32()
352352
} else {
353353
return Err(vm.new_type_error(format!(

stdlib/src/socket.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,8 @@ mod _socket {
734734
if obj.fast_isinstance(vm.ctx.types.float_type) {
735735
return Err(vm.new_type_error("integer argument expected, got float".to_owned()));
736736
}
737-
let int = vm
738-
.to_index_opt(obj)
737+
let int = obj
738+
.try_index_opt(vm)
739739
.unwrap_or_else(|| Err(vm.new_type_error("an integer is required".to_owned())))?;
740740
int.try_to_primitive::<CastFrom>(vm)
741741
.map(|sock| sock as RawSocket)
@@ -1382,7 +1382,7 @@ mod _socket {
13821382
let (flags, address) = match arg3 {
13831383
OptionalArg::Present(arg3) => {
13841384
// should just be i32::try_from_obj but tests check for error message
1385-
let int = vm.to_index_opt(arg2).unwrap_or_else(|| {
1385+
let int = arg2.try_index_opt(vm).unwrap_or_else(|| {
13861386
Err(vm.new_type_error("an integer is required".to_owned()))
13871387
})?;
13881388
let flags = int.try_to_primitive::<i32>(vm)?;

vm/src/buffer.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -491,15 +491,15 @@ fn get_int_or_index<T>(vm: &VirtualMachine, arg: PyObjectRef) -> PyResult<T>
491491
where
492492
T: PrimInt + for<'a> TryFrom<&'a BigInt>,
493493
{
494-
match vm.to_index_opt(arg) {
495-
Some(index) => index?
496-
.try_to_primitive(vm)
497-
.map_err(|_| new_struct_error(vm, "argument out of range".to_owned())),
498-
None => Err(new_struct_error(
494+
let index = arg.try_index_opt(vm).unwrap_or_else(|| {
495+
Err(new_struct_error(
499496
vm,
500497
"required argument is not an integer".to_owned(),
501-
)),
502-
}
498+
))
499+
})?;
500+
index
501+
.try_to_primitive(vm)
502+
.map_err(|_| new_struct_error(vm, "argument out of range".to_owned()))
503503
}
504504

505505
make_pack_primint!(i8);

vm/src/builtins/bytes.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::{
33
};
44
use crate::{
55
anystr::{self, AnyStr},
6+
atomic_func,
67
bytesinner::{
78
bytes_decode, ByteInnerFindOptions, ByteInnerNewOptions, ByteInnerPaddingOptions,
89
ByteInnerSplitOptions, ByteInnerTranslateOptions, DecodeArgs, PyBytesInner,
@@ -608,14 +609,17 @@ impl AsSequence for PyBytes {
608609
}
609610

610611
impl AsNumber for PyBytes {
611-
const AS_NUMBER: PyNumberMethods = PyNumberMethods {
612-
remainder: Some(|number, other, vm| {
613-
Self::number_downcast(number)
614-
.mod_(other.to_owned(), vm)
615-
.to_pyresult(vm)
616-
}),
617-
..PyNumberMethods::NOT_IMPLEMENTED
618-
};
612+
fn as_number() -> &'static PyNumberMethods {
613+
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
614+
remainder: atomic_func!(|number, other, vm| {
615+
PyBytes::number_downcast(number)
616+
.mod_(other.to_owned(), vm)
617+
.to_pyresult(vm)
618+
}),
619+
..PyNumberMethods::NOT_IMPLEMENTED
620+
};
621+
&AS_NUMBER
622+
}
619623
}
620624

621625
impl Hashable for PyBytes {

vm/src/builtins/complex.rs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::{float, PyStr, PyType, PyTypeRef};
22
use crate::{
3+
atomic_func,
34
class::PyClassImpl,
45
convert::{ToPyObject, ToPyResult},
56
function::{
@@ -421,30 +422,44 @@ impl Hashable for PyComplex {
421422
}
422423

423424
impl AsNumber for PyComplex {
424-
const AS_NUMBER: PyNumberMethods = PyNumberMethods {
425-
add: Some(|number, other, vm| Self::number_complex_op(number, other, |a, b| a + b, vm)),
426-
subtract: Some(|number, other, vm| {
427-
Self::number_complex_op(number, other, |a, b| a - b, vm)
428-
}),
429-
multiply: Some(|number, other, vm| {
430-
Self::number_complex_op(number, other, |a, b| a * b, vm)
431-
}),
432-
power: Some(|number, other, vm| Self::number_general_op(number, other, inner_pow, vm)),
433-
negative: Some(|number, vm| {
434-
let value = Self::number_downcast(number).value;
435-
(-value).to_pyresult(vm)
436-
}),
437-
positive: Some(|number, vm| Self::number_complex(number, vm).to_pyresult(vm)),
438-
absolute: Some(|number, vm| {
439-
let value = Self::number_downcast(number).value;
440-
value.norm().to_pyresult(vm)
441-
}),
442-
boolean: Some(|number, _vm| Ok(Self::number_downcast(number).value.is_zero())),
443-
true_divide: Some(|number, other, vm| {
444-
Self::number_general_op(number, other, inner_div, vm)
445-
}),
446-
..PyNumberMethods::NOT_IMPLEMENTED
447-
};
425+
fn as_number() -> &'static PyNumberMethods {
426+
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
427+
add: atomic_func!(|number, other, vm| PyComplex::number_complex_op(
428+
number,
429+
other,
430+
|a, b| a + b,
431+
vm
432+
)),
433+
subtract: atomic_func!(|number, other, vm| {
434+
PyComplex::number_complex_op(number, other, |a, b| a - b, vm)
435+
}),
436+
multiply: atomic_func!(|number, other, vm| {
437+
PyComplex::number_complex_op(number, other, |a, b| a * b, vm)
438+
}),
439+
power: atomic_func!(|number, other, vm| PyComplex::number_general_op(
440+
number, other, inner_pow, vm
441+
)),
442+
negative: atomic_func!(|number, vm| {
443+
let value = PyComplex::number_downcast(number).value;
444+
(-value).to_pyresult(vm)
445+
}),
446+
positive: atomic_func!(
447+
|number, vm| PyComplex::number_complex(number, vm).to_pyresult(vm)
448+
),
449+
absolute: atomic_func!(|number, vm| {
450+
let value = PyComplex::number_downcast(number).value;
451+
value.norm().to_pyresult(vm)
452+
}),
453+
boolean: atomic_func!(|number, _vm| Ok(PyComplex::number_downcast(number)
454+
.value
455+
.is_zero())),
456+
true_divide: atomic_func!(|number, other, vm| {
457+
PyComplex::number_general_op(number, other, inner_div, vm)
458+
}),
459+
..PyNumberMethods::NOT_IMPLEMENTED
460+
};
461+
&AS_NUMBER
462+
}
448463
}
449464

450465
impl PyComplex {

vm/src/builtins/float.rs

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::{
22
try_bigint_to_f64, PyByteArray, PyBytes, PyInt, PyIntRef, PyStr, PyStrRef, PyType, PyTypeRef,
33
};
44
use crate::{
5+
atomic_func,
56
class::PyClassImpl,
67
common::{float_ops, hash},
78
convert::{ToPyObject, ToPyResult},
@@ -57,16 +58,6 @@ impl From<f64> for PyFloat {
5758
}
5859
}
5960

60-
impl PyObject {
61-
pub fn try_float_opt(&self, vm: &VirtualMachine) -> PyResult<Option<PyRef<PyFloat>>> {
62-
PyNumber::new(self, vm).float_opt(vm)
63-
}
64-
65-
pub fn try_float(&self, vm: &VirtualMachine) -> PyResult<PyRef<PyFloat>> {
66-
PyNumber::new(self, vm).float(vm)
67-
}
68-
}
69-
7061
pub(crate) fn to_op_float(obj: &PyObject, vm: &VirtualMachine) -> PyResult<Option<f64>> {
7162
let v = if let Some(float) = obj.payload_if_subclass::<PyFloat>(vm) {
7263
Some(float.value)
@@ -553,36 +544,63 @@ impl Hashable for PyFloat {
553544
}
554545

555546
impl AsNumber for PyFloat {
556-
const AS_NUMBER: PyNumberMethods = PyNumberMethods {
557-
add: Some(|number, other, vm| Self::number_float_op(number, other, |a, b| a + b, vm)),
558-
subtract: Some(|number, other, vm| Self::number_float_op(number, other, |a, b| a - b, vm)),
559-
multiply: Some(|number, other, vm| Self::number_float_op(number, other, |a, b| a * b, vm)),
560-
remainder: Some(|number, other, vm| Self::number_general_op(number, other, inner_mod, vm)),
561-
divmod: Some(|number, other, vm| Self::number_general_op(number, other, inner_divmod, vm)),
562-
power: Some(|number, other, vm| Self::number_general_op(number, other, float_pow, vm)),
563-
negative: Some(|number, vm| {
564-
let value = Self::number_downcast(number).value;
565-
(-value).to_pyresult(vm)
566-
}),
567-
positive: Some(|number, vm| Self::number_float(number, vm).to_pyresult(vm)),
568-
absolute: Some(|number, vm| {
569-
let value = Self::number_downcast(number).value;
570-
value.abs().to_pyresult(vm)
571-
}),
572-
boolean: Some(|number, _vm| Ok(Self::number_downcast(number).value.is_zero())),
573-
int: Some(|number, vm| {
574-
let value = Self::number_downcast(number).value;
575-
try_to_bigint(value, vm).map(|x| vm.ctx.new_int(x))
576-
}),
577-
float: Some(|number, vm| Ok(Self::number_float(number, vm))),
578-
floor_divide: Some(|number, other, vm| {
579-
Self::number_general_op(number, other, inner_floordiv, vm)
580-
}),
581-
true_divide: Some(|number, other, vm| {
582-
Self::number_general_op(number, other, inner_div, vm)
583-
}),
584-
..PyNumberMethods::NOT_IMPLEMENTED
585-
};
547+
fn as_number() -> &'static PyNumberMethods {
548+
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
549+
add: atomic_func!(|num, other, vm| PyFloat::number_float_op(
550+
num,
551+
other,
552+
|a, b| a + b,
553+
vm
554+
)),
555+
subtract: atomic_func!(|num, other, vm| PyFloat::number_float_op(
556+
num,
557+
other,
558+
|a, b| a - b,
559+
vm
560+
)),
561+
multiply: atomic_func!(|num, other, vm| PyFloat::number_float_op(
562+
num,
563+
other,
564+
|a, b| a * b,
565+
vm
566+
)),
567+
remainder: atomic_func!(|num, other, vm| PyFloat::number_general_op(
568+
num, other, inner_mod, vm
569+
)),
570+
divmod: atomic_func!(|num, other, vm| PyFloat::number_general_op(
571+
num,
572+
other,
573+
inner_divmod,
574+
vm
575+
)),
576+
power: atomic_func!(|num, other, vm| PyFloat::number_general_op(
577+
num, other, float_pow, vm
578+
)),
579+
negative: atomic_func!(|num, vm| {
580+
let value = PyFloat::number_downcast(num).value;
581+
(-value).to_pyresult(vm)
582+
}),
583+
positive: atomic_func!(|num, vm| PyFloat::number_float(num, vm).to_pyresult(vm)),
584+
absolute: atomic_func!(|num, vm| {
585+
let value = PyFloat::number_downcast(num).value;
586+
value.abs().to_pyresult(vm)
587+
}),
588+
boolean: atomic_func!(|num, _vm| Ok(PyFloat::number_downcast(num).value.is_zero())),
589+
int: atomic_func!(|num, vm| {
590+
let value = PyFloat::number_downcast(num).value;
591+
try_to_bigint(value, vm).map(|x| vm.ctx.new_int(x))
592+
}),
593+
float: atomic_func!(|num, vm| Ok(PyFloat::number_float(num, vm))),
594+
floor_divide: atomic_func!(|num, other, vm| {
595+
PyFloat::number_general_op(num, other, inner_floordiv, vm)
596+
}),
597+
true_divide: atomic_func!(|num, other, vm| {
598+
PyFloat::number_general_op(num, other, inner_div, vm)
599+
}),
600+
..PyNumberMethods::NOT_IMPLEMENTED
601+
};
602+
&AS_NUMBER
603+
}
586604
}
587605

588606
impl PyFloat {

0 commit comments

Comments
 (0)