Skip to content

Commit 4d33844

Browse files
committed
fix(list): slice with negative value causes RangeDefect
1 parent c9518e8 commit 4d33844

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

src/pylib/builtins/list.nim

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,15 @@ func `[]=`*[T](self: var PyList[T], s: BackwardsIndex, x: T) =
4444
proc list*[T](iter: Iterable[T]): PyList[T] # front decl
4545
func `[]=`*[T](self: var PyList[T], s: HSlice, x: Iterable[T]) =
4646
self[s] = list(x)
47+
48+
49+
func normSlice(s: PySlice, le: int): PySlice =
50+
template norm(idx: int): untyped =
51+
(if idx < 0: le+idx else: idx)
52+
slice(s.start.norm, s.stop.norm, s.step)
53+
4754
func `[]=`*[T](self: var PyList[T], s: PySlice, x: Sequence[T]) =
55+
let s = normSlice(s, self.len)
4856
if s.step == 1:
4957
self[s.toNimSlice] = x
5058
return
@@ -63,12 +71,17 @@ func `[]=`*[T](self: var PyList[T], s: PySlice,
6371
for i in x: sequ.add i
6472
self[s] = sequ
6573
74+
func append*[T](self: var PyList[T], x: T) = self.asSeq.add x
75+
func `+=`*[T](self: var PyList[T], ls: openArray[T]) = self.asSeq.add ls
76+
func `+=`*[T](self: var PyList[T], ls: PyList[T]) = self += ls.asSeq
77+
6678
func `[]`*[T](self: PyList[T], s: HSlice): PyList[T] =
6779
newPyList system.`[]`(self.asSeq, s)
6880
func `[]`*[T](self: PyList[T], s: BackwardsIndex): T =
6981
system.`[]`(self.asSeq, s)
7082
# PySlice1 is handled by: converter -> Slice
7183
func `[]`*[T](self: PyList[T], s: PySlice): PyList[T] =
84+
let s = normSlice(s, self.len)
7285
if s.step == 1:
7386
return self[s.toNimSlice]
7487
result = newPyList[T]()
@@ -79,10 +92,6 @@ func `[]`*[T](self: PyList[T], s: PySlice): PyList[T] =
7992
8093
func reverse*(self: var PyList) = reverse(self.asSeq)
8194
82-
func append*[T](self: var PyList[T], x: T) = self.asSeq.add x
83-
func `+=`*[T](self: var PyList[T], ls: openArray[T]) = self.asSeq.add ls
84-
func `+=`*[T](self: var PyList[T], ls: PyList[T]) = self += ls.asSeq
85-
8695
func pop*[T](self: var PyList[T]): T{.discardable.} = self.asSeq.pop()
8796
func pop*[T](self: var PyList[T], index: int): T{.discardable.} =
8897
## `index` can be negative to index backwards.

tests/testaments/builtins/list.nim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,14 @@ test "list methods":
5858
ls[slice(0, 2, 2)] = range(4)
5959

6060

61+
test "list slice":
62+
def emptySlice():
63+
ls = [1,2,3,4]
64+
return ls[1:-1]
65+
check emptySlice() == [2,3]
66+
67+
def s():
68+
ls = [1,2,3,4]
69+
return ls[-4:-1]
70+
check s() == [1,2,3]
71+

0 commit comments

Comments
 (0)