|
1 | | -use super::objfloat; |
2 | | -use super::objstr; |
3 | | -use super::objtype; |
4 | | -use crate::format::FormatSpec; |
5 | | -use crate::pyobject::{ |
6 | | - FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, |
7 | | - PyResult, TryFromObject, TypeProtocol, |
8 | | -}; |
9 | | -use crate::vm::VirtualMachine; |
| 1 | +use std::hash::{Hash, Hasher}; |
| 2 | + |
10 | 3 | use num_bigint::{BigInt, ToBigInt}; |
11 | 4 | use num_integer::Integer; |
12 | 5 | use num_traits::{Pow, Signed, ToPrimitive, Zero}; |
13 | | -use std::hash::{Hash, Hasher}; |
14 | 6 |
|
15 | | -// This proxy allows for easy switching between types. |
16 | | -type IntType = BigInt; |
| 7 | +use crate::format::FormatSpec; |
| 8 | +use crate::function::PyRef; |
| 9 | +use crate::pyobject::{ |
| 10 | + FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, |
| 11 | + PyObjectPayload2, PyObjectRef, PyResult, TryFromObject, TypeProtocol, |
| 12 | +}; |
| 13 | +use crate::vm::VirtualMachine; |
17 | 14 |
|
18 | | -pub type PyInt = BigInt; |
| 15 | +use super::objfloat; |
| 16 | +use super::objstr; |
| 17 | +use super::objtype; |
19 | 18 |
|
20 | | -impl IntoPyObject for PyInt { |
21 | | - fn into_pyobject(self, ctx: &PyContext) -> PyResult { |
22 | | - Ok(ctx.new_int(self)) |
23 | | - } |
| 19 | +#[derive(Debug)] |
| 20 | +pub struct PyInt { |
| 21 | + // TODO: shouldn't be public |
| 22 | + pub value: BigInt, |
24 | 23 | } |
25 | 24 |
|
26 | | -// TODO: macro to impl for all primitive ints |
| 25 | +pub type PyIntRef = PyRef<PyInt>; |
27 | 26 |
|
28 | | -impl IntoPyObject for usize { |
29 | | - fn into_pyobject(self, ctx: &PyContext) -> PyResult { |
30 | | - Ok(ctx.new_int(self)) |
| 27 | +impl PyInt { |
| 28 | + pub fn new<T: ToBigInt>(i: T) -> Self { |
| 29 | + PyInt { |
| 30 | + value: i.to_bigint().unwrap(), |
| 31 | + } |
31 | 32 | } |
32 | 33 | } |
33 | 34 |
|
34 | | -impl TryFromObject for usize { |
35 | | - fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<Self> { |
36 | | - // FIXME: don't use get_value |
37 | | - match get_value(&obj).to_usize() { |
38 | | - Some(value) => Ok(value), |
39 | | - None => Err(vm.new_overflow_error("Int value cannot fit into Rust usize".to_string())), |
40 | | - } |
| 35 | +impl PyObjectPayload2 for PyInt { |
| 36 | + fn required_type(ctx: &PyContext) -> PyObjectRef { |
| 37 | + ctx.int_type() |
41 | 38 | } |
42 | 39 | } |
43 | 40 |
|
44 | | -impl TryFromObject for isize { |
45 | | - fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<Self> { |
46 | | - // FIXME: don't use get_value |
47 | | - match get_value(&obj).to_isize() { |
48 | | - Some(value) => Ok(value), |
49 | | - None => Err(vm.new_overflow_error("Int value cannot fit into Rust isize".to_string())), |
| 41 | +macro_rules! impl_into_pyobject_int { |
| 42 | + ($($t:ty)*) => {$( |
| 43 | + impl IntoPyObject for $t { |
| 44 | + fn into_pyobject(self, ctx: &PyContext) -> PyResult { |
| 45 | + Ok(ctx.new_int(self)) |
| 46 | + } |
50 | 47 | } |
51 | | - } |
52 | | -} |
| 48 | + )*}; |
| 49 | +} |
| 50 | + |
| 51 | +impl_into_pyobject_int!(isize i8 i16 i32 i64 usize u8 u16 u32 u64) ; |
| 52 | + |
| 53 | +macro_rules! impl_try_from_object_int { |
| 54 | + ($(($t:ty, $to_prim:ident),)*) => {$( |
| 55 | + impl TryFromObject for $t { |
| 56 | + fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<Self> { |
| 57 | + match PyRef::<PyInt>::try_from_object(vm, obj)?.value.$to_prim() { |
| 58 | + Some(value) => Ok(value), |
| 59 | + None => Err( |
| 60 | + vm.new_overflow_error(concat!( |
| 61 | + "Int value cannot fit into Rust ", |
| 62 | + stringify!($t) |
| 63 | + ).to_string()) |
| 64 | + ), |
| 65 | + } |
| 66 | + } |
| 67 | + } |
| 68 | + )*}; |
| 69 | +} |
| 70 | + |
| 71 | +impl_try_from_object_int!( |
| 72 | + (isize, to_isize), |
| 73 | + (i8, to_i8), |
| 74 | + (i16, to_i16), |
| 75 | + (i32, to_i32), |
| 76 | + (i64, to_i64), |
| 77 | + (usize, to_usize), |
| 78 | + (u8, to_u8), |
| 79 | + (u16, to_u16), |
| 80 | + (u32, to_u32), |
| 81 | + (u64, to_u64), |
| 82 | +); |
53 | 83 |
|
54 | 84 | fn int_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { |
55 | 85 | arg_check!(vm, args, required = [(int, Some(vm.ctx.int_type()))]); |
@@ -77,13 +107,15 @@ fn int_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { |
77 | 107 | None => Zero::zero(), |
78 | 108 | }; |
79 | 109 | Ok(PyObject::new( |
80 | | - PyObjectPayload::Integer { value: val }, |
| 110 | + PyObjectPayload::AnyRustValue { |
| 111 | + value: Box::new(PyInt::new(val)), |
| 112 | + }, |
81 | 113 | cls.clone(), |
82 | 114 | )) |
83 | 115 | } |
84 | 116 |
|
85 | 117 | // Casting function: |
86 | | -pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<IntType> { |
| 118 | +pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<BigInt> { |
87 | 119 | let val = if objtype::isinstance(obj, &vm.ctx.int_type()) { |
88 | 120 | get_value(obj) |
89 | 121 | } else if objtype::isinstance(obj, &vm.ctx.float_type()) { |
@@ -111,12 +143,8 @@ pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult |
111 | 143 | } |
112 | 144 |
|
113 | 145 | // Retrieve inner int value: |
114 | | -pub fn get_value(obj: &PyObjectRef) -> IntType { |
115 | | - if let PyObjectPayload::Integer { value } = &obj.payload { |
116 | | - value.clone() |
117 | | - } else { |
118 | | - panic!("Inner error getting int {:?}", obj); |
119 | | - } |
| 146 | +pub fn get_value(obj: &PyObjectRef) -> BigInt { |
| 147 | + obj.payload::<PyInt>().unwrap().value.clone() |
120 | 148 | } |
121 | 149 |
|
122 | 150 | impl FromPyObjectRef for BigInt { |
|
0 commit comments