Skip to content

Commit

Permalink
Generic Slices (#544)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
pakaelbling and arshajii committed Feb 25, 2024
1 parent 4be3bbf commit 4400e3d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 5 deletions.
2 changes: 1 addition & 1 deletion codon/cir/transform/pythonic/list.cpp
Expand Up @@ -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; }
Expand Down
36 changes: 32 additions & 4 deletions stdlib/internal/types/slice.codon
Expand Up @@ -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
Expand Down Expand Up @@ -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
34 changes: 34 additions & 0 deletions test/core/containers.codon
Expand Up @@ -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
Expand Down

0 comments on commit 4400e3d

Please sign in to comment.