Skip to content

Commit f5f665b

Browse files
committed
[GR-9549] List set items doesn't work for all slices combinations.
PullRequest: graalpython-open/24
2 parents 71c27c9 + c6e408d commit f5f665b

File tree

17 files changed

+984
-31
lines changed

17 files changed

+984
-31
lines changed

graalpython/com.oracle.graal.python.test/src/tests/list_tests.py

Lines changed: 632 additions & 0 deletions
Large diffs are not rendered by default.

graalpython/com.oracle.graal.python.test/src/tests/test_list.py

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@
3939

4040
LONG_NUMBER = 6227020800;
4141

42+
import list_tests
4243

4344

44-
class ListTest(seq_tests.CommonTest):
45-
46-
type2test = tuple
47-
45+
class ListTest(list_tests.CommonTest):
46+
type2test = list
47+
4848
# ======== Specific test for Graal Python ======
49+
4950
def test_getitem(self):
5051
l = [1, 2, 3]
5152
self.assertEqual(1, l[False])
@@ -161,7 +162,6 @@ def test_slice(self):
161162
self.slice_test(list(range(0,20)), slice(-15,6,-5), [])
162163
self.slice_test(list(range(0,20)), slice(-2, -21, -4), [18, 14, 10, 6, 2])
163164

164-
165165
def del_slice(self, l, s, expected):
166166
tmplist = list(l)
167167
del(tmplist[s])
@@ -172,7 +172,6 @@ def del_slice(self, l, s, expected):
172172
else:
173173
del(tmplist[s.start:s.stop:s.step])
174174
self.assertEqual(tmplist, expected, "del(list( slice({}, {}, {}))) expected: {}, get: {}".format(s.start, s.stop, s.step, expected, tmplist))
175-
176175

177176
def test_del_slice(self):
178177
self.del_slice(list(range(0, 20)), slice(1, 19), [0, 19])
@@ -202,3 +201,81 @@ def test_del_slice_step(self):
202201
self.del_slice(list(range(0, 20)), slice(-4, -18, -3), [0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 19])
203202
self.del_slice(list(range(0, 20)), slice(-3, -55, -4), [0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19])
204203
self.del_slice(list(range(0, 20)), slice(-1, -55, -4), [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18])
204+
205+
def test_ininicialization_with_slice(self):
206+
r = []
207+
l = [1,2,3,4]
208+
r[:] = l
209+
self.assertEqual(l, r)
210+
211+
def test_set_slice(self):
212+
a = [1,2]
213+
a[1:2] = [7,6,5,4]
214+
self.assertEqual([1, 7, 6, 5, 4], a)
215+
a = [1, 2, 3, 4]
216+
a[1:8] = [33]
217+
self.assertEqual([1, 33], a)
218+
a = [1,2,3,4]
219+
a[1:8] = [33,34,35,36,37,38]
220+
self.assertEqual([1, 33,34,35,36,37,38], a)
221+
a = list(range(20))
222+
a[1:19] = [55, 55]
223+
self.assertEqual([0,55,55,19],a)
224+
a = [1,2,3,4]
225+
a[1:3] =[11]
226+
self.assertEqual([1, 11, 4], a)
227+
a = [1,2,3,4]
228+
a[1:3] =[11,12,13,14,15,16]
229+
self.assertEqual([1, 11,12,13,14,15,16, 4], a)
230+
a = [1,2]
231+
a[:] = (1, 2, 4, 5)
232+
self.assertEqual([1,2,4,5], a)
233+
234+
def test_set_slice_class_iter(self):
235+
class MyIter():
236+
def __init__(self, base):
237+
self.itera = iter(base)
238+
def __next__(self):
239+
return next(self.itera)
240+
def __iter__(self):
241+
return self
242+
243+
a = list(range(10))
244+
a[::2] = MyIter(tuple(range(5)))
245+
self.assertEqual([0, 1, 1, 3, 2, 5, 3, 7, 4, 9], a)
246+
247+
def test_set_slice_class_getitem(self):
248+
class MyIter2():
249+
def __init__(self, base):
250+
self.base = base
251+
def __getitem__(self, key):
252+
return self.base[key]
253+
254+
a = [1,2,3,4]
255+
a[2:] = MyIter2([33,44,55,66])
256+
self.assertEqual([1,2,33,44,55,66], a)
257+
258+
def test_set_strange_slice(self):
259+
a = list(range(20))
260+
a[18:2] = [4,3,5]
261+
self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 4, 3, 5, 18, 19], a)
262+
a = list(range(20))
263+
a[18:0:-2] = [11,22,33,44,55,66,77,88,99]
264+
self.assertEqual([0, 1, 99, 3, 88, 5, 77, 7, 66, 9, 55, 11, 44, 13, 33, 15, 22, 17, 11, 19], a)
265+
a = list(range(20))
266+
a[18:-5] = [11,22,33,44,55,66,77,88,99]
267+
self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 11, 22, 33, 44, 55, 66, 77, 88, 99, 18, 19], a)
268+
a = list(range(20))
269+
a[-2:-20:-2] = [11,22,33,44,55,66,77,88,99]
270+
self.assertEqual([0, 1, 99, 3, 88, 5, 77, 7, 66, 9, 55, 11, 44, 13, 33, 15, 22, 17, 11, 19], a)
271+
a = list(range(20))
272+
a[20:-20] = [11,22,33,44,55,66,77,88,99]
273+
self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 11, 22, 33, 44, 55, 66, 77, 88, 99], a)
274+
275+
def test_set_slice_generalize_storage(self):
276+
a = [1,2]
277+
a[:] = 'ahoj'
278+
self.assertEqual(['a', 'h', 'o', 'j'], a)
279+
a = [1,2]
280+
a[1:5] = [1.1, 2.2, 3.3]
281+
self.assertEqual([1,1.1, 2.2, 3.3], a)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import com.oracle.graal.python.nodes.PGuards;
5555
import com.oracle.graal.python.nodes.PNode;
5656
import com.oracle.graal.python.nodes.SpecialMethodNames;
57+
import com.oracle.graal.python.nodes.builtins.ListNodes;
5758
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
5859
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
5960
import com.oracle.graal.python.nodes.control.GetIteratorNode;
@@ -326,9 +327,9 @@ public abstract static class SetItemNode extends PythonTernaryBuiltinNode {
326327
@Child private NormalizeIndexNode normalize = NormalizeIndexNode.create();
327328

328329
@Specialization
329-
public Object doPList(PList primary, PSlice slice, PSequence value) {
330-
primary.setSlice(slice, value);
331-
return PNone.NONE;
330+
public PNone doPList(PList list, PSlice slice, Object value,
331+
@Cached("create()") ListNodes.SetSliceNode sliceNode) {
332+
return sliceNode.execute(list, slice, value);
332333
}
333334

334335
@Specialization(guards = "isIntStorage(primary)")
@@ -401,7 +402,7 @@ protected boolean isValidIndexType(Object idx) {
401402
// list.append(x)
402403
@Builtin(name = "append", fixedNumOfArguments = 2)
403404
@GenerateNodeFactory
404-
public abstract static class ListAppendNode extends PythonBuiltinNode {
405+
public abstract static class ListAppendNode extends PythonBinaryBuiltinNode {
405406

406407
@Specialization(guards = "isEmptyStorage(list)")
407408
public PNone appendEmpty(PList list, Object arg) {
@@ -444,7 +445,7 @@ public PNone appendTuple(PList list, PTuple arg) {
444445
return PNone.NONE;
445446
}
446447

447-
@Specialization(rewriteOn = {SequenceStoreException.class})
448+
@Specialization(guards = {"!isKnownStorage(list)"}, rewriteOn = {SequenceStoreException.class})
448449
public PNone appendObject(PList list, Object arg) throws SequenceStoreException {
449450
list.getSequenceStorage().append(arg);
450451
return PNone.NONE;
@@ -455,6 +456,11 @@ public PNone appendObjectGeneric(PList list, Object arg) {
455456
list.append(arg);
456457
return PNone.NONE;
457458
}
459+
460+
protected boolean isKnownStorage(PList list) {
461+
return PGuards.isEmptyStorage(list) || PGuards.isIntStorage(list) || PGuards.isLongStorage(list) || PGuards.isDoubleStorage(list) || PGuards.isListStorage(list) ||
462+
PGuards.isTupleStorage(list);
463+
}
458464
}
459465

460466
// list.extend(L)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/PList.java

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,15 @@ public final Object getSlice(PythonObjectFactory factory, int start, int stop, i
6767

6868
@Override
6969
public final void setSlice(PSlice slice, PSequence value) {
70-
setSlice(slice.getStart(), slice.getStop(), slice.getStep(), value);
70+
// Should not be used. Replaces with ListNodes.SetSliceNode.
71+
// When it will be replaced in other PSequence implementeations,
72+
// then the setSlice from PSequence can be removed.
73+
throw new UnsupportedOperationException();
7174
}
7275

7376
@Override
7477
public final void setSlice(int start, int stop, int step, PSequence value) {
75-
final int normalizedStart = SequenceUtil.normalizeSliceStart(start, step, store.length(), "list assignment index out of range");
76-
int normalizedStop = SequenceUtil.normalizeSliceStop(stop, step, store.length(), "list assignment index out of range");
77-
78-
if (normalizedStop < normalizedStart) {
79-
normalizedStop = normalizedStart;
80-
}
81-
82-
try {
83-
store.setSliceInBound(normalizedStart, normalizedStop, step, value.getSequenceStorage());
84-
} catch (SequenceStoreException e) {
85-
store = store.generalizeFor(value.getSequenceStorage().getIndicativeValue());
86-
87-
try {
88-
store.setSliceInBound(start, stop, step, value.getSequenceStorage());
89-
} catch (SequenceStoreException ex) {
90-
throw new IllegalStateException();
91-
}
92-
}
78+
throw new UnsupportedOperationException();
9379
}
9480

9581
@Override

0 commit comments

Comments
 (0)