Skip to content

Commit c81d0a9

Browse files
committed
list.sort builtin
1 parent 64b9a95 commit c81d0a9

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_sort.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@
1313
*graalpython.lib-python.3.test.test_sort.TestOptimizedCompares.test_unsafe_long_compare
1414
*graalpython.lib-python.3.test.test_sort.TestOptimizedCompares.test_unsafe_object_compare
1515
*graalpython.lib-python.3.test.test_sort.TestOptimizedCompares.test_unsafe_tuple_compare
16+
*graalpython.lib-python.3.test.test_sort.TestBugs.test_bug453523
17+
*graalpython.lib-python.3.test.test_sort.TestBugs.test_undetected_mutation

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ListGeneralizationNode;
6666
import com.oracle.graal.python.builtins.objects.function.PArguments;
6767
import com.oracle.graal.python.builtins.objects.function.PArguments.ThreadState;
68+
import com.oracle.graal.python.builtins.objects.function.PKeyword;
6869
import com.oracle.graal.python.builtins.objects.generator.PGenerator;
6970
import com.oracle.graal.python.builtins.objects.ints.PInt;
7071
import com.oracle.graal.python.builtins.objects.iterator.PDoubleSequenceIterator;
@@ -80,9 +81,11 @@
8081
import com.oracle.graal.python.nodes.ErrorMessages;
8182
import com.oracle.graal.python.nodes.PGuards;
8283
import com.oracle.graal.python.nodes.argument.ReadArgumentNode;
84+
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
8385
import com.oracle.graal.python.nodes.builtins.ListNodes;
8486
import com.oracle.graal.python.nodes.builtins.ListNodes.AppendNode;
8587
import com.oracle.graal.python.nodes.builtins.ListNodes.IndexNode;
88+
import com.oracle.graal.python.nodes.call.CallNode;
8689
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
8790
import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode;
8891
import com.oracle.graal.python.nodes.control.GetNextNode;
@@ -91,6 +94,7 @@
9194
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
9295
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
9396
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
97+
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
9498
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
9599
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
96100
import com.oracle.graal.python.runtime.PythonCore;
@@ -840,6 +844,65 @@ public static ListReverseNode create() {
840844
}
841845
}
842846

847+
// list.sort(key=, reverse=)
848+
@Builtin(name = "sort", minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true, needsFrame = true)
849+
@GenerateNodeFactory
850+
public abstract static class ListSortNode extends PythonVarargsBuiltinNode {
851+
852+
protected static final String SORT = "_sort";
853+
protected static final String KEY = "key";
854+
855+
protected static boolean isSortable(PList list, SequenceStorageNodes.LenNode lenNode) {
856+
return lenNode.execute(list.getSequenceStorage()) > 1;
857+
}
858+
859+
protected static boolean maySideEffect(PList list, PKeyword[] keywords) {
860+
if (PGuards.isObjectStorage(list)) {
861+
return true;
862+
}
863+
if (keywords.length > 0) {
864+
if (keywords[0].getName().equals(KEY)) {
865+
return true;
866+
}
867+
if (keywords.length > 1 && keywords[1].getName().equals(KEY)) {
868+
return true;
869+
}
870+
}
871+
return false;
872+
}
873+
874+
@Specialization(guards = "!isSortable(list, lenNode)")
875+
@SuppressWarnings("unused")
876+
Object none(VirtualFrame frame, PList list, Object[] arguments, PKeyword[] keywords,
877+
@Cached SequenceStorageNodes.LenNode lenNode) {
878+
return PNone.NONE;
879+
}
880+
881+
@Specialization(guards = {"isSortable(list, lenNode)", "maySideEffect(list, keywords)"})
882+
Object withKey(VirtualFrame frame, PList list, Object[] arguments, PKeyword[] keywords,
883+
@Cached("create(SORT)") GetAttributeNode sort,
884+
@Cached CallNode callSort,
885+
@SuppressWarnings("unused") @Cached SequenceStorageNodes.LenNode lenNode) {
886+
list.getSequenceStorage().setLock();
887+
try {
888+
defaultSort(frame, list, arguments, keywords, sort, callSort, lenNode);
889+
} finally {
890+
list.getSequenceStorage().releaseLock();
891+
}
892+
return PNone.NONE;
893+
}
894+
895+
@Specialization(guards = {"isSortable(list, lenNode)", "!maySideEffect(list, keywords)"})
896+
Object defaultSort(VirtualFrame frame, PList list, Object[] arguments, PKeyword[] keywords,
897+
@Cached("create(SORT)") GetAttributeNode sort,
898+
@Cached CallNode callSort,
899+
@SuppressWarnings("unused") @Cached SequenceStorageNodes.LenNode lenNode) {
900+
Object sortMethod = sort.executeObject(frame, list);
901+
callSort.execute(sortMethod, arguments, keywords);
902+
return PNone.NONE;
903+
}
904+
}
905+
843906
@Builtin(name = __LEN__, minNumOfPositionalArgs = 1)
844907
@GenerateNodeFactory
845908
public abstract static class LenNode extends PythonUnaryBuiltinNode {

graalpython/lib-graalpython/list.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -38,7 +38,7 @@
3838
# SOFTWARE.
3939

4040

41-
def sort(self, key=None, reverse=False):
41+
def _sort(self, key=None, reverse=False):
4242
if reverse:
4343
if key:
4444
lt = lambda a,b: key(a) > key(b)
@@ -56,4 +56,4 @@ def sort(self, key=None, reverse=False):
5656
return None
5757

5858

59-
list.sort = sort
59+
list._sort = _sort

graalpython/lib-python/3/collections/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ def extend(self, other):
11211121
self.data.extend(other.data)
11221122
else:
11231123
self.data.extend(other)
1124+
def _sort(self, /, *args, **kwds): self.data._sort(*args, **kwds) # XXX to be removed once sorting is implemented internally (mq)
11241125

11251126

11261127

0 commit comments

Comments
 (0)