Skip to content

Commit 06cbcb8

Browse files
committed
[GR-9687] Reimplement list.remove node.
1 parent c5885b3 commit 06cbcb8

File tree

3 files changed

+95
-11
lines changed

3 files changed

+95
-11
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def test_pop(self):
316316
# self.assertRaises(IndexError, a.pop)
317317
self.assertRaises(TypeError, a.pop, 42, 42)
318318
a = self.type2test([0, 10, 20, 30, 40])
319-
'''
319+
320320
def test_remove(self):
321321
a = self.type2test([0, 0, 1])
322322
a.remove(1)
@@ -361,7 +361,7 @@ def __eq__(self, other):
361361
for x, y in zip(d, e):
362362
# verify that original order and values are retained.
363363
self.assertIs(x, y)
364-
364+
'''
365365
def test_count(self):
366366
a = self.type2test([0, 1, 2])*3
367367
self.assertEqual(a.count(0), 3)

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,27 @@ def test_set_slice_generalize_storage(self):
279279
a = [1,2]
280280
a[1:5] = [1.1, 2.2, 3.3]
281281
self.assertEqual([1,1.1, 2.2, 3.3], a)
282+
283+
def test_remove_spec(self):
284+
a = [1,2]
285+
a.remove(2);
286+
self.assertEqual([1], a)
287+
a.remove(1)
288+
self.assertEqual([], a)
289+
290+
a = [0,1,0,1,2]
291+
a.remove(True)
292+
self.assertEqual([0,0,1,2], a)
293+
a.remove(False)
294+
self.assertEqual([0,1,2], a)
295+
296+
a = list([LONG_NUMBER, LONG_NUMBER + 1])
297+
a.remove(LONG_NUMBER + 1)
298+
self.assertEqual([LONG_NUMBER], a)
299+
300+
class MyInt(int):
301+
pass
302+
303+
a = [1,2,3]
304+
a.remove(MyInt(2))
305+
self.assertEqual([1,3], a)

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

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -519,16 +519,76 @@ public PList insert(PList list, Object i, Object arg1) {
519519
@Builtin(name = "remove", fixedNumOfArguments = 2)
520520
@GenerateNodeFactory
521521
public abstract static class ListRemoveNode extends PythonBuiltinNode {
522-
523-
@Specialization
524-
public PList remove(PList list, Object arg) {
525-
int index = list.index(arg);
526-
if (index >= 0) {
527-
list.delItem(index);
528-
return list;
529-
} else {
530-
throw raise(PythonErrorType.ValueError, "list.remove(x): x not in list");
522+
523+
private static String NOT_IN_LIST_MESSAGE = "list.index(x): x not in list";
524+
525+
@Specialization(guards = "isIntStorage(list)")
526+
public PNone removeInt(PList list, int value) {
527+
IntSequenceStorage store = (IntSequenceStorage)list.getSequenceStorage();
528+
for(int index = 0; index < store.length(); index++) {
529+
if (value == store.getIntItemNormalized(index)) {
530+
store.popInBound(index);
531+
return PNone.NONE;
532+
}
533+
}
534+
throw raise(PythonErrorType.ValueError, NOT_IN_LIST_MESSAGE);
535+
}
536+
537+
@Specialization(guards = "isLongStorage(list)")
538+
public PNone removeLong(PList list, int value) {
539+
LongSequenceStorage store = (LongSequenceStorage)list.getSequenceStorage();
540+
for(int index = 0; index < store.length(); index++) {
541+
if (value == store.getLongItemNormalized(index)) {
542+
store.popInBound(index);
543+
return PNone.NONE;
544+
}
545+
}
546+
throw raise(PythonErrorType.ValueError, NOT_IN_LIST_MESSAGE);
547+
}
548+
549+
@Specialization(guards = "isLongStorage(list)")
550+
public PNone removeLong(PList list, long value) {
551+
LongSequenceStorage store = (LongSequenceStorage)list.getSequenceStorage();
552+
for(int index = 0; index < store.length(); index++) {
553+
if (value == store.getLongItemNormalized(index)) {
554+
store.popInBound(index);
555+
return PNone.NONE;
556+
}
557+
}
558+
throw raise(PythonErrorType.ValueError, NOT_IN_LIST_MESSAGE);
559+
}
560+
561+
@Specialization(guards = "isDoubleStorage(list)")
562+
public PNone removeLong(PList list, double value) {
563+
DoubleSequenceStorage store = (DoubleSequenceStorage)list.getSequenceStorage();
564+
for(int index = 0; index < store.length(); index++) {
565+
if (value == store.getDoubleItemNormalized(index)) {
566+
store.popInBound(index);
567+
return PNone.NONE;
568+
}
569+
}
570+
throw raise(PythonErrorType.ValueError, NOT_IN_LIST_MESSAGE);
571+
}
572+
573+
@Specialization(guards = "isNotSpecialCase(list, value)")
574+
public PNone remove(PList list, Object value,
575+
@Cached("createBinaryProfile()") ConditionProfile errorProfile,
576+
@Cached("create(__EQ__, __EQ__, __EQ__)") BinaryComparisonNode eqNode) {
577+
int len = list.len();
578+
for (int i = 0; i < len; i++) {
579+
Object object = list.getItem(i);
580+
if (eqNode.executeBool(object, value)) {
581+
list.delItem(i);
582+
return PNone.NONE;
583+
}
531584
}
585+
throw raise(PythonErrorType.ValueError, NOT_IN_LIST_MESSAGE);
586+
}
587+
588+
protected boolean isNotSpecialCase(PList list, Object value) {
589+
return !((PGuards.isIntStorage(list) && value instanceof Integer)
590+
|| (PGuards.isLongStorage(list) && (value instanceof Integer || value instanceof Long))
591+
|| PGuards.isDoubleStorage(list) && value instanceof Double);
532592
}
533593
}
534594

0 commit comments

Comments
 (0)