Generic Slices (#544)

* Changed slice fields to generics, added check to adjust_indices

* fix typecheck

* Refactored Slice class, fixed test

* fix test

* made slice fields optional, updated tests

* Fix list optimization for new slices; update tests

---------

Co-authored-by: A. R. Shajii <ars@ars.me>
jit-fixes
Philip Kaelbling 2024-02-25 11:42:31 -05:00 committed by GitHub
parent 4be3bbf9e7
commit 4400e3d849
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 67 additions and 5 deletions

View File

@ -14,7 +14,7 @@ namespace pythonic {
namespace {
static const std::string LIST = "std.internal.types.ptr.List";
static const std::string SLICE = "std.internal.types.slice.Slice";
static const std::string SLICE = "std.internal.types.slice.Slice[int,int,int]";
bool isList(Value *v) { return v->getType()->getName().rfind(LIST + "[", 0) == 0; }
bool isSlice(Value *v) { return v->getType()->getName() == SLICE; }

View File

@ -2,14 +2,36 @@
@tuple
class Slice:
start: Optional[int]
stop: Optional[int]
step: Optional[int]
start: Optional[T]
stop: Optional[U]
step: Optional[V]
T: type
U: type
V: type
def __new__(stop: Optional[int]):
def __new__(stop: Optional[U], U: type = int):
return Slice(None, stop, None)
def __new__(
start: Optional[T],
stop: Optional[U],
T: type = int,
U: type = int):
return Slice(start, stop, None)
def __new__(
start: Optional[T],
stop: Optional[U],
step: Optional[V],
T: type = int,
U: type = int,
V: type = int) -> Slice[T, U, V]:
return (start, stop, step)
def adjust_indices(self, length: int) -> Tuple[int, int, int, int]:
if not (T is int and U is int and V is int):
compile_error("slice indices must be integers or None")
step: int = self.step if self.step is not None else 1
start: int = 0
stop: int = 0
@ -58,4 +80,10 @@ class Slice:
def __repr__(self):
return f"slice({self.start}, {self.stop}, {self.step})"
def __eq__(self, other: Slice):
return self.start == other.start and self.step == other.step and self.stop == other.stop
def __ne__(self, other: Slice):
return not self.__eq__(other)
slice = Slice

View File

@ -764,6 +764,40 @@ def test_slice():
x = X(tmp)
x[1:2] = 42
assert tmp == [(slice(1, 2), 42)]
# Non-int elements
def check_types(s, T: type, U: type, V: type):
return (type(s.start) is Optional[T] and
type(s.stop) is Optional[U] and
type(s.step) is Optional[V])
assert check_types(slice(1j, 'x', 3.14), complex, str, float)
assert check_types(slice(None, 'x', 3.14), int, str, float)
assert check_types(slice(1j, None, 3.14), complex, int, float)
assert check_types(slice(1j, 'x', None), complex, str, int)
assert check_types(slice(1j, None, None), complex, int, int)
assert check_types(slice(None, 'x', None), int, str, int)
assert check_types(slice(None, None, 3.14), int, int, float)
assert check_types(slice(None, None, None), int, int, int)
assert check_types(slice(1j, 'x'), complex, str, int)
assert check_types(slice(None, 'x'), int, str, int)
assert check_types(slice(1j, None), complex, int, int)
assert check_types(slice(None, None), int, int, int)
assert check_types(slice(1j), int, complex, int)
assert check_types(slice(None), int, int, int)
# eq / ne
assert slice(1, 2, 3) == slice(1, 2, 3)
assert slice(0, 2, 3) != slice(1, 2, 3)
assert slice(1, 0, 3) != slice(1, 2, 3)
assert slice(1, 2, 0) != slice(1, 2, 3)
assert slice(None, None, None) == slice(None, None, None)
assert slice(None, 42, None) == slice(None, 42, None)
assert slice(None, 42, None) != slice(None, 43, None)
assert slice(1, None, 3) == slice(1, None, 3)
assert slice(1, None, 3) != slice(1, None, 0)
assert slice(1, None, 3) != slice(0, None, 3)
assert slice(1) == slice(1)
assert slice(1) != slice(2)
test_slice()
@test