Skip to content

Commit 1f59e75

Browse files
committed
Ensure that slicing works on TupleOf as well as ListOf in the compiler.
1 parent 3d3cf70 commit 1f59e75

File tree

3 files changed

+103
-91
lines changed

3 files changed

+103
-91
lines changed

typed_python/compiler/tests/tuple_of_compilation_test.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,17 @@ def makeT(aList: ListOf(int)):
218218
return TupleOf(int)(aList)
219219

220220
assert len(makeT([])) == 0
221+
222+
def test_slice_list_of_compiled(self):
223+
@Entrypoint
224+
def sliceIt(aLst: ListOf(int), x: int):
225+
return aLst[:x]
226+
227+
assert sliceIt((1, 2, 3), 1) == [1]
228+
229+
def test_slice_tuple_of_compiled(self):
230+
@Entrypoint
231+
def sliceIt(aTup: TupleOf(int), x: int):
232+
return aTup[:x]
233+
234+
assert sliceIt((1, 2, 3), 1) == (1,)

typed_python/compiler/type_wrappers/list_of_wrapper.py

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -37,85 +37,6 @@ def list_of_extend(aList, extendWith):
3737
aList.append(thing)
3838

3939

40-
def min(a, b):
41-
return a if a < b else b
42-
43-
44-
def max(a, b):
45-
return b if a < b else a
46-
47-
48-
def list_of_slice(aList, start, stop, step):
49-
if step is None:
50-
return list_of_slice(aList, start, stop, 1)
51-
if step == 0:
52-
raise ValueError("slice step cannot be zero")
53-
if step > 0:
54-
if start is None:
55-
return list_of_slice(aList, 0, stop, step)
56-
57-
if stop is None:
58-
return list_of_slice(aList, start, len(aList), step)
59-
60-
if start < 0:
61-
start += len(aList)
62-
if stop < 0:
63-
stop += len(aList)
64-
65-
start = max(0, start)
66-
stop = min(len(aList), stop)
67-
68-
outList = type(aList)()
69-
70-
count = max(0, (stop - start + (step - 1)) // step)
71-
72-
outList.reserve(count)
73-
outList.setSizeUnsafe(count)
74-
75-
writeP = outList.pointerUnsafe(0)
76-
readP = aList.pointerUnsafe(start)
77-
78-
i = start
79-
while i < stop:
80-
writeP.initialize(readP.get())
81-
writeP += 1
82-
i += step
83-
readP += step
84-
85-
return outList
86-
else:
87-
if start is None:
88-
return list_of_slice(aList, len(aList) - 1, stop, step)
89-
if stop is None:
90-
return list_of_slice(aList, start, -1 - len(aList), step)
91-
92-
if start < 0:
93-
start += len(aList)
94-
if stop < 0:
95-
stop += len(aList)
96-
97-
start = min(len(aList) - 1, start)
98-
stop = max(-1, stop)
99-
100-
outList = type(aList)()
101-
count = max(0, (start - stop + (-step - 1)) // (-step))
102-
103-
outList.reserve(count)
104-
outList.setSizeUnsafe(count)
105-
106-
writeP = outList.pointerUnsafe(0)
107-
readP = aList.pointerUnsafe(start)
108-
109-
i = start
110-
while i > stop:
111-
writeP.initialize(readP.get())
112-
writeP += 1
113-
i += step
114-
readP += step
115-
116-
return outList
117-
118-
11940
class ListOfWrapper(TupleOrListOfWrapper):
12041
is_pod = False
12142
is_empty = False
@@ -448,18 +369,6 @@ def createEmptyList(self, context, out):
448369
) # data
449370
)
450371

451-
def convert_getslice(self, context, instance, lower, upper, step):
452-
return context.call_py_function(
453-
list_of_slice,
454-
(
455-
instance,
456-
lower or context.constant(None),
457-
upper or context.constant(None),
458-
step or context.constant(None)
459-
),
460-
{}
461-
)
462-
463372
def convert_setitem(self, context, expr, index, item):
464373
if item is None:
465374
return None

typed_python/compiler/type_wrappers/tuple_of_wrapper.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ def tuple_of_hash(instance):
110110
return val
111111

112112

113+
def min(a, b):
114+
return a if a < b else b
115+
116+
117+
def max(a, b):
118+
return b if a < b else a
119+
120+
113121
class PreReservedTupleOrList(CompilableBuiltin):
114122
def __init__(self, tupleType):
115123
super().__init__()
@@ -210,6 +218,75 @@ def concatenate_tuple_or_list(l, r):
210218
return result
211219

212220

221+
def list_or_tupleof_of_slice(aList, start, stop, step):
222+
if step is None:
223+
return list_or_tupleof_of_slice(aList, start, stop, 1)
224+
if step == 0:
225+
raise ValueError("slice step cannot be zero")
226+
if step > 0:
227+
if start is None:
228+
return list_or_tupleof_of_slice(aList, 0, stop, step)
229+
230+
if stop is None:
231+
return list_or_tupleof_of_slice(aList, start, len(aList), step)
232+
233+
if start < 0:
234+
start += len(aList)
235+
if stop < 0:
236+
stop += len(aList)
237+
238+
start = max(0, start)
239+
stop = min(len(aList), stop)
240+
241+
count = max(0, (stop - start + (step - 1)) // step)
242+
243+
outLstOrTup = PreReservedTupleOrList(type(aList))(count)
244+
245+
outLstOrTup.setSizeUnsafe(count)
246+
247+
writeP = outLstOrTup.pointerUnsafe(0)
248+
readP = aList.pointerUnsafe(start)
249+
250+
i = start
251+
while i < stop:
252+
writeP.initialize(readP.get())
253+
writeP += 1
254+
i += step
255+
readP += step
256+
257+
return outLstOrTup
258+
else:
259+
if start is None:
260+
return list_or_tupleof_of_slice(aList, len(aList) - 1, stop, step)
261+
if stop is None:
262+
return list_or_tupleof_of_slice(aList, start, -1 - len(aList), step)
263+
264+
if start < 0:
265+
start += len(aList)
266+
if stop < 0:
267+
stop += len(aList)
268+
269+
start = min(len(aList) - 1, start)
270+
stop = max(-1, stop)
271+
272+
count = max(0, (start - stop + (-step - 1)) // (-step))
273+
274+
outLstOrTup = PreReservedTupleOrList(type(aList))(count)
275+
outLstOrTup.setSizeUnsafe(count)
276+
277+
writeP = outLstOrTup.pointerUnsafe(0)
278+
readP = aList.pointerUnsafe(start)
279+
280+
i = start
281+
while i > stop:
282+
writeP.initialize(readP.get())
283+
writeP += 1
284+
i += step
285+
readP += step
286+
287+
return outLstOrTup
288+
289+
213290
class TupleOrListOfWrapper(RefcountedWrapper):
214291
is_pod = False
215292
is_empty = False
@@ -364,6 +441,18 @@ def convert_set_attribute(self, context, expr, attr, val):
364441
def convert_hash(self, context, expr):
365442
return context.call_py_function(tuple_of_hash, (expr,), {})
366443

444+
def convert_getslice(self, context, instance, lower, upper, step):
445+
return context.call_py_function(
446+
list_or_tupleof_of_slice,
447+
(
448+
instance,
449+
lower or context.constant(None),
450+
upper or context.constant(None),
451+
step or context.constant(None)
452+
),
453+
{}
454+
)
455+
367456
def convert_getitem(self, context, expr, item):
368457
if item is None or expr is None:
369458
return None

0 commit comments

Comments
 (0)