Skip to content

32 bit support #1952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Lib/test/seq_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ def test_repeat(self):
self.assertEqual(self.type2test(s)*(-4), self.type2test([]))
self.assertEqual(id(s), id(s*1))

@unittest.skip("TODO: RUSTPYTHON")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this 32bit specific issue, adding 32bit note with RUSTPYTHON would be helpful

def test_bigrepeat(self):
if sys.maxsize <= 2147483647:
x = self.type2test([0])
Expand Down
4 changes: 3 additions & 1 deletion Lib/test/string_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,8 @@ def test_expandtabs(self):

self.checkraises(TypeError, 'hello', 'expandtabs', 42, 42)
# This test is only valid when sizeof(int) == sizeof(void*) == 4.
if sys.maxsize < (1 << 32) and struct.calcsize('P') == 4:
# XXX RUSTPYTHON TODO: expandtabs overflow checks
if sys.maxsize < (1 << 32) and struct.calcsize('P') == 4 and False:
self.checkraises(OverflowError,
'\ta\n\tb', 'expandtabs', sys.maxsize)

Expand Down Expand Up @@ -672,6 +673,7 @@ def test_replace(self):
self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
self.checkraises(TypeError, 'hello', 'replace', 'h', 42)

@unittest.skip("TODO: RUSTPYTHON")
@unittest.skipIf(sys.maxsize > (1 << 32) or struct.calcsize('P') != 4,
'only applies to 32-bit platforms')
def test_replace_overflow(self):
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ def test_copy(self):
self.assertEqual(a, b)
self.assertEqual(type(a), type(b))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_empty_sequence(self):
b = self.type2test()
self.assertEqual(len(b), 0)
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def test_basic(self):
self.assertEqual(list(x for x in range(10) if x % 2),
[1, 3, 5, 7, 9])

if sys.maxsize == 0x7fffffff:
# XXX RUSTPYTHON TODO: catch ooms
if sys.maxsize == 0x7fffffff and False:
# This test can currently only work on 32-bit machines.
# XXX If/when PySequence_Length() returns a ssize_t, it should be
# XXX re-enabled.
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_memoryview.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ def check_getitem_with_type(self, tp):
m = None
self.assertEqual(sys.getrefcount(b), oldrefcount)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_getitem(self):
for tp in self._types:
self.check_getitem_with_type(tp)
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ def __str__(self): return self.sval
self.checkraises(TypeError, ' ', 'join', [1, 2, 3])
self.checkraises(TypeError, ' ', 'join', ['1', '2', 3])

@unittest.skip("TODO: RUSTPYTHON, oom handling")
@unittest.skipIf(sys.maxsize > 2**32,
'needs too much memory on a 64-bit platform')
def test_join_overflow(self):
Expand Down Expand Up @@ -2357,6 +2358,7 @@ def test_printable_repr(self):
# This test only affects 32-bit platforms because expandtabs can only take
# an int as the max value, not a 64-bit C long. If expandtabs is changed
# to take a 64-bit long, this test should apply to all platforms.
@unittest.skip("TODO: RUSTPYTHON, oom handling")
@unittest.skipIf(sys.maxsize > (1 << 32) or struct.calcsize('P') != 4,
'only applies to 32-bit platforms')
def test_expandtabs_overflows_gracefully(self):
Expand Down
8 changes: 2 additions & 6 deletions tests/snippets/index_overflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
def expect_cannot_fit_index_error(s, index):
try:
s[index]
except IndexError:
pass
# TODO: Replace current except block with commented
# after solving https://github.com/RustPython/RustPython/issues/322
# except IndexError as error:
# assert str(error) == "cannot fit 'int' into an index-sized integer"
except IndexError as error:
assert str(error) == "cannot fit 'int' into an index-sized integer"
else:
assert False

Expand Down
13 changes: 4 additions & 9 deletions vm/src/obj/objbytearray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::objbyteinner::{
};
use super::objint::PyIntRef;
use super::objiter;
use super::objslice::PySliceRef;
use super::objsequence::SequenceIndex;
use super::objstr::{PyString, PyStringRef};
use super::objtype::PyClassRef;
use super::pystr::{self, PyCommonString};
Expand Down Expand Up @@ -172,22 +172,17 @@ impl PyByteArray {
}

#[pymethod(name = "__getitem__")]
fn getitem(&self, needle: Either<i32, PySliceRef>, vm: &VirtualMachine) -> PyResult {
fn getitem(&self, needle: SequenceIndex, vm: &VirtualMachine) -> PyResult {
self.borrow_value().getitem(needle, vm)
}

#[pymethod(name = "__setitem__")]
fn setitem(
&self,
needle: Either<i32, PySliceRef>,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
fn setitem(&self, needle: SequenceIndex, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
self.borrow_value_mut().setitem(needle, value, vm)
}

#[pymethod(name = "__delitem__")]
fn delitem(&self, needle: Either<i32, PySliceRef>, vm: &VirtualMachine) -> PyResult<()> {
fn delitem(&self, needle: SequenceIndex, vm: &VirtualMachine) -> PyResult<()> {
self.borrow_value_mut().delitem(needle, vm)
}

Expand Down
34 changes: 14 additions & 20 deletions vm/src/obj/objbyteinner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::objint::{self, PyInt, PyIntRef};
use super::objlist::PyList;
use super::objmemory::PyMemoryView;
use super::objnone::PyNoneRef;
use super::objsequence::PySliceableSequence;
use super::objsequence::{PySliceableSequence, SequenceIndex};
use super::objslice::PySliceRef;
use super::objstr::{self, PyString, PyStringRef};
use super::pystr::{self, PyCommonString, PyCommonStringWrapper};
Expand Down Expand Up @@ -327,22 +327,22 @@ impl PyByteInner {
})
}

pub fn getitem(&self, needle: Either<i32, PySliceRef>, vm: &VirtualMachine) -> PyResult {
pub fn getitem(&self, needle: SequenceIndex, vm: &VirtualMachine) -> PyResult {
match needle {
Either::A(int) => {
SequenceIndex::Int(int) => {
if let Some(idx) = self.elements.get_pos(int) {
Ok(vm.new_int(self.elements[idx]))
} else {
Err(vm.new_index_error("index out of range".to_owned()))
}
}
Either::B(slice) => Ok(vm
.ctx
.new_bytes(self.elements.get_slice_items(vm, slice.as_object())?)),
SequenceIndex::Slice(slice) => {
Ok(vm.ctx.new_bytes(self.elements.get_slice_items(vm, &slice)?))
}
}
}

fn setindex(&mut self, int: i32, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn setindex(&mut self, int: isize, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(idx) = self.elements.get_pos(int) {
let result = match_class!(match object {
i @ PyInt => {
Expand Down Expand Up @@ -392,38 +392,32 @@ impl PyByteInner {
range.end = range.start;
}
self.elements.splice(range, items);
Ok(vm
.ctx
.new_bytes(self.elements.get_slice_items(vm, slice.as_object())?))
Ok(vm.ctx.new_bytes(self.elements.get_slice_items(vm, &slice)?))
}

pub fn setitem(
&mut self,
needle: Either<i32, PySliceRef>,
needle: SequenceIndex,
object: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
match needle {
Either::A(int) => self.setindex(int, object, vm),
Either::B(slice) => self.setslice(slice, object, vm),
SequenceIndex::Int(int) => self.setindex(int, object, vm),
SequenceIndex::Slice(slice) => self.setslice(slice, object, vm),
}
}

pub fn delitem(
&mut self,
needle: Either<i32, PySliceRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
pub fn delitem(&mut self, needle: SequenceIndex, vm: &VirtualMachine) -> PyResult<()> {
match needle {
Either::A(int) => {
SequenceIndex::Int(int) => {
if let Some(idx) = self.elements.get_pos(int) {
self.elements.remove(idx);
Ok(())
} else {
Err(vm.new_index_error("index out of range".to_owned()))
}
}
Either::B(slice) => self.delslice(slice, vm),
SequenceIndex::Slice(slice) => self.delslice(slice, vm),
}
}

Expand Down
4 changes: 2 additions & 2 deletions vm/src/obj/objbytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::objbyteinner::{
};
use super::objint::PyIntRef;
use super::objiter;
use super::objslice::PySliceRef;
use super::objsequence::SequenceIndex;
use super::objstr::{PyString, PyStringRef};
use super::objtype::PyClassRef;
use super::pystr::{self, PyCommonString};
Expand Down Expand Up @@ -172,7 +172,7 @@ impl PyBytes {
}

#[pymethod(name = "__getitem__")]
fn getitem(&self, needle: Either<i32, PySliceRef>, vm: &VirtualMachine) -> PyResult {
fn getitem(&self, needle: SequenceIndex, vm: &VirtualMachine) -> PyResult {
self.inner.getitem(needle, vm)
}

Expand Down
75 changes: 15 additions & 60 deletions vm/src/obj/objlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::objbool;
use super::objbyteinner;
use super::objint::PyIntRef;
use super::objiter;
use super::objsequence::{get_item, SequenceIndex};
use super::objsequence::{get_item, get_pos, get_slice_range, SequenceIndex};
use super::objslice::PySliceRef;
use super::objtype::PyClassRef;
use crate::function::OptionalArg;
Expand Down Expand Up @@ -62,51 +62,6 @@ impl PyList {
self.elements.write().unwrap()
}

fn get_pos(p: i32, len: usize) -> Option<usize> {
// convert a (potentially negative) positon into a real index
if p < 0 {
if -p as usize > len {
None
} else {
Some(len - ((-p) as usize))
}
} else if p as usize >= len {
None
} else {
Some(p as usize)
}
}

fn get_slice_pos(slice_pos: &BigInt, len: usize) -> usize {
if let Some(pos) = slice_pos.to_i32() {
if let Some(index) = PyList::get_pos(pos, len) {
// within bounds
return index;
}
}

if slice_pos.is_negative() {
// slice past start bound, round to start
0
} else {
// slice past end bound, round to end
len
}
}

fn get_slice_range(start: &Option<BigInt>, stop: &Option<BigInt>, len: usize) -> Range<usize> {
let start = start
.as_ref()
.map(|x| PyList::get_slice_pos(x, len))
.unwrap_or(0);
let stop = stop
.as_ref()
.map(|x| PyList::get_slice_pos(x, len))
.unwrap_or_else(|| len);

start..stop
}

pub(crate) fn get_byte_inner(
&self,
vm: &VirtualMachine,
Expand Down Expand Up @@ -273,9 +228,9 @@ impl PyList {
}
}

fn setindex(&self, index: i32, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn setindex(&self, index: isize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
let mut elements = self.borrow_elements_mut();
if let Some(pos_index) = PyList::get_pos(index, elements.len()) {
if let Some(pos_index) = get_pos(index, elements.len()) {
elements[pos_index] = value;
Ok(vm.get_none())
} else {
Expand All @@ -297,16 +252,16 @@ impl PyList {
if step.is_zero() {
Err(vm.new_value_error("slice step cannot be zero".to_owned()))
} else if step.is_positive() {
let range = PyList::get_slice_range(&start, &stop, elements.len());
let range = get_slice_range(&start, &stop, elements.len());
if range.start < range.end {
match step.to_i32() {
match step.to_isize() {
Some(1) => PyList::_set_slice(elements, range, items, vm),
Some(num) => {
// assign to extended slice
PyList::_set_stepped_slice(elements, range, num as usize, items, vm)
}
None => {
// not sure how this is reached, step too big for i32?
// not sure how this is reached, step too big for isize?
// then step is bigger than the than len of the list, no question
#[allow(clippy::range_plus_one)]
PyList::_set_stepped_slice(
Expand Down Expand Up @@ -339,13 +294,13 @@ impl PyList {
x + 1
}
});
let range = PyList::get_slice_range(&stop, &start, elements.len());
match (-step).to_i32() {
let range = get_slice_range(&stop, &start, elements.len());
match (-step).to_isize() {
Some(num) => {
PyList::_set_stepped_slice_reverse(elements, range, num as usize, items, vm)
}
None => {
// not sure how this is reached, step too big for i32?
// not sure how this is reached, step too big for isize?
// then step is bigger than the than len of the list no question
PyList::_set_stepped_slice_reverse(
elements,
Expand Down Expand Up @@ -638,9 +593,9 @@ impl PyList {
}
}

fn delindex(&self, index: i32, vm: &VirtualMachine) -> PyResult<()> {
fn delindex(&self, index: isize, vm: &VirtualMachine) -> PyResult<()> {
let mut elements = self.borrow_elements_mut();
if let Some(pos_index) = PyList::get_pos(index, elements.len()) {
if let Some(pos_index) = get_pos(index, elements.len()) {
elements.remove(pos_index);
Ok(())
} else {
Expand All @@ -657,10 +612,10 @@ impl PyList {
if step.is_zero() {
Err(vm.new_value_error("slice step cannot be zero".to_owned()))
} else if step.is_positive() {
let range = PyList::get_slice_range(&start, &stop, elements.len());
let range = get_slice_range(&start, &stop, elements.len());
if range.start < range.end {
#[allow(clippy::range_plus_one)]
match step.to_i32() {
match step.to_isize() {
Some(1) => {
PyList::_del_slice(elements, range);
Ok(())
Expand Down Expand Up @@ -695,9 +650,9 @@ impl PyList {
x + 1
}
});
let range = PyList::get_slice_range(&stop, &start, elements.len());
let range = get_slice_range(&stop, &start, elements.len());
if range.start < range.end {
match (-step).to_i32() {
match (-step).to_isize() {
Some(1) => {
PyList::_del_slice(elements, range);
Ok(())
Expand Down
Loading