|
51 | 51 |
|
52 | 52 | import java.math.BigInteger;
|
53 | 53 | import java.util.List;
|
54 |
| -import java.util.function.Supplier; |
55 | 54 |
|
56 | 55 | import com.oracle.graal.python.builtins.Builtin;
|
57 | 56 | import com.oracle.graal.python.builtins.CoreFunctions;
|
|
71 | 70 | import com.oracle.graal.python.nodes.PGuards;
|
72 | 71 | import com.oracle.graal.python.nodes.PNode;
|
73 | 72 | import com.oracle.graal.python.nodes.builtins.ListNodes;
|
| 73 | +import com.oracle.graal.python.nodes.builtins.ListNodes.IndexNode; |
74 | 74 | import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
|
75 | 75 | import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
|
76 |
| -import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode.NoAttributeHandler; |
77 | 76 | import com.oracle.graal.python.nodes.control.GetIteratorNode;
|
78 | 77 | import com.oracle.graal.python.nodes.control.GetNextNode;
|
79 | 78 | import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
|
@@ -243,17 +242,21 @@ protected PNone doPListSlice(PList self, PSlice slice) {
|
243 | 242 | return PNone.NONE;
|
244 | 243 | }
|
245 | 244 |
|
246 |
| - @SuppressWarnings("unused") |
247 |
| - @Fallback |
248 |
| - protected Object doGeneric(Object self, Object idx) { |
249 |
| - if (!isValidIndexType(idx)) { |
250 |
| - throw raise(TypeError, "list indices must be integers or slices, not %p", idx); |
251 |
| - } |
252 |
| - throw raise(TypeError, "descriptor '__delitem__' requires a 'list' object but received a '%p'", idx); |
| 245 | + protected static DelItemNode create() { |
| 246 | + return ListBuiltinsFactory.DelItemNodeFactory.create(new PNode[0]); |
253 | 247 | }
|
254 | 248 |
|
255 |
| - protected boolean isValidIndexType(Object idx) { |
256 |
| - return PGuards.isInteger(idx) || idx instanceof PSlice; |
| 249 | + @Specialization |
| 250 | + protected Object doObjectIndex(PList self, Object objectIdx, |
| 251 | + @Cached("create()") IndexNode getIndexNode, |
| 252 | + @Cached("create()") DelItemNode getRecursiveNode) { |
| 253 | + return getRecursiveNode.execute(self, getIndexNode.execute(objectIdx)); |
| 254 | + } |
| 255 | + |
| 256 | + @SuppressWarnings("unused") |
| 257 | + @Fallback |
| 258 | + protected Object doGeneric(Object self, Object objectIdx) { |
| 259 | + throw raise(TypeError, "descriptor '__delitem__' requires a 'list' object but received a '%p'", self); |
257 | 260 | }
|
258 | 261 | }
|
259 | 262 |
|
@@ -329,34 +332,22 @@ protected Object doPListSlice(PList self, PSlice slice) {
|
329 | 332 | return self.getSlice(factory(), slice);
|
330 | 333 | }
|
331 | 334 |
|
332 |
| - protected static final Supplier<NoAttributeHandler> NO_INDEX = () -> new NoAttributeHandler() { |
333 |
| - @Override |
334 |
| - public Object execute(Object receiver) { |
335 |
| - throw raise(TypeError, "list indices must be integers or slices, not %p", receiver); |
336 |
| - } |
337 |
| - }; |
| 335 | + protected static GetItemNode create() { |
| 336 | + return ListBuiltinsFactory.GetItemNodeFactory.create(new PNode[0]); |
| 337 | + } |
338 | 338 |
|
339 | 339 | @Specialization
|
340 | 340 | protected Object doObjectIndex(PList self, Object objectIdx,
|
341 |
| - @Cached("create(__INDEX__, NO_INDEX)") LookupAndCallUnaryNode getIndexNode, |
342 |
| - @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getRecursiveNode) { |
343 |
| - Object idx = getIndexNode.executeObject(objectIdx); |
344 |
| - if (isValidIndexType(idx)) { |
345 |
| - return getRecursiveNode.executeObject(self, idx); |
346 |
| - } else { |
347 |
| - throw raise(TypeError, "list indices must be integers or slices, not %p", idx); |
348 |
| - } |
| 341 | + @Cached("create()") IndexNode getIndexNode, |
| 342 | + @Cached("create()") GetItemNode getRecursiveNode) { |
| 343 | + return getRecursiveNode.execute(self, getIndexNode.execute(objectIdx)); |
349 | 344 | }
|
350 | 345 |
|
351 | 346 | @SuppressWarnings("unused")
|
352 | 347 | @Fallback
|
353 | 348 | protected Object doGeneric(Object self, Object objectIdx) {
|
354 | 349 | throw raise(TypeError, "descriptor '__getitem__' requires a 'list' object but received a '%p'", self);
|
355 | 350 | }
|
356 |
| - |
357 |
| - protected boolean isValidIndexType(Object idx) { |
358 |
| - return PGuards.isInteger(idx) || idx instanceof PSlice || idx instanceof PInt; |
359 |
| - } |
360 | 351 | }
|
361 | 352 |
|
362 | 353 | @Builtin(name = __SETITEM__, fixedNumOfArguments = 3)
|
@@ -427,17 +418,21 @@ public Object doPList(PList list, long idx, Object value,
|
427 | 418 | return PNone.NONE;
|
428 | 419 | }
|
429 | 420 |
|
430 |
| - @SuppressWarnings("unused") |
431 |
| - @Fallback |
432 |
| - protected Object doGeneric(Object self, Object idx, Object value) { |
433 |
| - if (!isValidIndexType(idx)) { |
434 |
| - throw raise(TypeError, "list indices must be integers or slices, not %p", idx); |
435 |
| - } |
436 |
| - throw raise(TypeError, "descriptor '__setitem__' requires a 'list' object but received a '%p'", idx); |
| 421 | + protected static SetItemNode create() { |
| 422 | + return ListBuiltinsFactory.SetItemNodeFactory.create(new PNode[0]); |
437 | 423 | }
|
438 | 424 |
|
439 |
| - protected boolean isValidIndexType(Object idx) { |
440 |
| - return PGuards.isInteger(idx) || idx instanceof PSlice; |
| 425 | + @Specialization |
| 426 | + protected Object doObjectIndex(PList self, Object objectIdx, Object value, |
| 427 | + @Cached("create()") IndexNode getIndexNode, |
| 428 | + @Cached("create()") SetItemNode getRecursiveNode) { |
| 429 | + return getRecursiveNode.execute(self, getIndexNode.execute(objectIdx), value); |
| 430 | + } |
| 431 | + |
| 432 | + @SuppressWarnings("unused") |
| 433 | + @Fallback |
| 434 | + protected Object doGeneric(Object self, Object objectIdx, Object value) { |
| 435 | + throw raise(TypeError, "descriptor '__setitem__' requires a 'list' object but received a '%p'", self); |
441 | 436 | }
|
442 | 437 | }
|
443 | 438 |
|
@@ -568,6 +563,7 @@ protected boolean isPSequenceWithStorage(Object source) {
|
568 | 563 | @Builtin(name = "insert", fixedNumOfArguments = 3)
|
569 | 564 | @GenerateNodeFactory
|
570 | 565 | public abstract static class ListInsertNode extends PythonBuiltinNode {
|
| 566 | + protected static final String ERROR_MSG = "'%p' object cannot be interpreted as an integer"; |
571 | 567 |
|
572 | 568 | public abstract PNone execute(PList list, Object index, Object value);
|
573 | 569 |
|
@@ -623,12 +619,9 @@ public PNone insertPIntIndex(PList list, PInt index, Object value,
|
623 | 619 |
|
624 | 620 | @Specialization(guards = {"!isIntegerOrPInt(i)"})
|
625 | 621 | public PNone insert(PList list, Object i, Object value,
|
626 |
| - @Cached("create(__INDEX__)") LookupAndCallUnaryNode indexNode, |
| 622 | + @Cached("createInteger(ERROR_MSG)") IndexNode indexNode, |
627 | 623 | @Cached("createListInsertNode()") ListInsertNode insertNode) {
|
628 |
| - Object indexValue = indexNode.executeObject(i); |
629 |
| - if (PNone.NO_VALUE == indexValue) { |
630 |
| - throw raise(TypeError, "'%p' object cannot be interpreted as an integer", i); |
631 |
| - } |
| 624 | + Object indexValue = indexNode.execute(i); |
632 | 625 | return insertNode.execute(list, indexValue, value);
|
633 | 626 | }
|
634 | 627 |
|
@@ -845,7 +838,7 @@ private Object popOnIndex(PList list, int index, ConditionProfile cp) {
|
845 | 838 | @ImportStatic(MathGuards.class)
|
846 | 839 | @GenerateNodeFactory
|
847 | 840 | public abstract static class ListIndexNode extends PythonBuiltinNode {
|
848 |
| - private final static String ERROR_TYPE_MESSAGE = "slice indices must be integers or have an __index__ method"; |
| 841 | + protected final static String ERROR_TYPE_MESSAGE = "slice indices must be integers or have an __index__ method"; |
849 | 842 |
|
850 | 843 | public abstract int execute(Object arg1, Object arg2, Object arg3, Object arg4);
|
851 | 844 |
|
@@ -939,42 +932,27 @@ int indexOD(PTuple self, Object value, Object start, double end) {
|
939 | 932 |
|
940 | 933 | @Specialization(guards = "!isNumber(start)")
|
941 | 934 | int indexO(PTuple self, Object value, Object start, PNone end,
|
942 |
| - @Cached("create(__INDEX__)") LookupAndCallUnaryNode startNode, |
| 935 | + @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode startNode, |
943 | 936 | @Cached("createIndexNode()") ListIndexNode indexNode) {
|
944 |
| - |
945 |
| - Object startValue = startNode.executeObject(start); |
946 |
| - if (PNone.NO_VALUE == startValue || !MathGuards.isNumber(startValue)) { |
947 |
| - throw raise(TypeError, ERROR_TYPE_MESSAGE); |
948 |
| - } |
| 937 | + Object startValue = startNode.execute(start); |
949 | 938 | return indexNode.execute(self, value, startValue, end);
|
950 | 939 | }
|
951 | 940 |
|
952 | 941 | @Specialization(guards = {"!isNumber(end)",})
|
953 | 942 | int indexLO(PTuple self, Object value, long start, Object end,
|
954 |
| - @Cached("create(__INDEX__)") LookupAndCallUnaryNode endNode, |
| 943 | + @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode endNode, |
955 | 944 | @Cached("createIndexNode()") ListIndexNode indexNode) {
|
956 |
| - |
957 |
| - Object endValue = endNode.executeObject(end); |
958 |
| - if (PNone.NO_VALUE == endValue || !MathGuards.isNumber(endValue)) { |
959 |
| - throw raise(TypeError, ERROR_TYPE_MESSAGE); |
960 |
| - } |
| 945 | + Object endValue = endNode.execute(end); |
961 | 946 | return indexNode.execute(self, value, start, endValue);
|
962 | 947 | }
|
963 | 948 |
|
964 | 949 | @Specialization(guards = {"!isNumber(start) || !isNumber(end)",})
|
965 | 950 | int indexOO(PTuple self, Object value, Object start, Object end,
|
966 |
| - @Cached("create(__INDEX__)") LookupAndCallUnaryNode startNode, |
967 |
| - @Cached("create(__INDEX__)") LookupAndCallUnaryNode endNode, |
| 951 | + @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode startNode, |
| 952 | + @Cached("createNumber(ERROR_TYPE_MESSAGE)") IndexNode endNode, |
968 | 953 | @Cached("createIndexNode()") ListIndexNode indexNode) {
|
969 |
| - |
970 |
| - Object startValue = startNode.executeObject(start); |
971 |
| - if (PNone.NO_VALUE == startValue || !MathGuards.isNumber(startValue)) { |
972 |
| - throw raise(TypeError, ERROR_TYPE_MESSAGE); |
973 |
| - } |
974 |
| - Object endValue = endNode.executeObject(end); |
975 |
| - if (PNone.NO_VALUE == endValue || !MathGuards.isNumber(endValue)) { |
976 |
| - throw raise(TypeError, ERROR_TYPE_MESSAGE); |
977 |
| - } |
| 954 | + Object startValue = startNode.execute(start); |
| 955 | + Object endValue = endNode.execute(end); |
978 | 956 | return indexNode.execute(self, value, startValue, endValue);
|
979 | 957 | }
|
980 | 958 |
|
@@ -1232,6 +1210,7 @@ Object doGeneric(Object left, Object right) {
|
1232 | 1210 | @Builtin(name = __IMUL__, fixedNumOfArguments = 2)
|
1233 | 1211 | @GenerateNodeFactory
|
1234 | 1212 | abstract static class IMulNode extends PythonBuiltinNode {
|
| 1213 | + protected static final String ERROR_MSG = "can't multiply sequence by non-int of type '%p'"; |
1235 | 1214 |
|
1236 | 1215 | public abstract PList execute(PList list, Object value);
|
1237 | 1216 |
|
@@ -1439,36 +1418,29 @@ PList doObjectPInt(PList list, PInt right) {
|
1439 | 1418 |
|
1440 | 1419 | @Specialization(guards = {"!isInt(right)"})
|
1441 | 1420 | Object doGeneric(PList list, Object right,
|
1442 |
| - @Cached("create(__INDEX__)") LookupAndCallUnaryNode dispatchIndex, |
| 1421 | + @Cached("createInteger(ERROR_MSG)") IndexNode dispatchIndex, |
1443 | 1422 | @Cached("createIMulNode()") IMulNode imulNode) {
|
1444 |
| - Object index = dispatchIndex.executeObject(right); |
1445 |
| - if (index != PNone.NO_VALUE) { |
1446 |
| - int iIndex; |
1447 |
| - try { |
1448 |
| - iIndex = convertToInt(index); |
1449 |
| - } catch (ArithmeticException e) { |
1450 |
| - throw raise(OverflowError, "cannot fit '%p' into an index-sized integer", index); |
1451 |
| - } |
1452 |
| - |
1453 |
| - return imulNode.execute(list, iIndex); |
| 1423 | + Object index = dispatchIndex.execute(right); |
| 1424 | + int iIndex; |
| 1425 | + try { |
| 1426 | + iIndex = convertToInt(index); |
| 1427 | + } catch (ArithmeticException e) { |
| 1428 | + throw raise(OverflowError, "cannot fit '%p' into an index-sized integer", index); |
1454 | 1429 | }
|
1455 |
| - throw raise(TypeError, "can't multiply sequence by non-int of type '%p'", right); |
| 1430 | + return imulNode.execute(list, iIndex); |
1456 | 1431 | }
|
1457 | 1432 |
|
1458 |
| - private int convertToInt(Object value) throws ArithmeticException { |
| 1433 | + private static int convertToInt(Object value) throws ArithmeticException { |
1459 | 1434 | if (value instanceof Integer) {
|
1460 | 1435 | return (Integer) value;
|
1461 |
| - } |
1462 |
| - if (value instanceof Boolean) { |
| 1436 | + } else if (value instanceof Boolean) { |
1463 | 1437 | return (Boolean) value ? 0 : 1;
|
1464 |
| - } |
1465 |
| - if (value instanceof Long) { |
| 1438 | + } else if (value instanceof Long) { |
1466 | 1439 | return PInt.intValueExact((Long) value);
|
1467 |
| - } |
1468 |
| - if (value instanceof PInt) { |
| 1440 | + } else { |
| 1441 | + assert value instanceof PInt; |
1469 | 1442 | return ((PInt) value).intValueExact();
|
1470 | 1443 | }
|
1471 |
| - throw raise(TypeError, "can't multiply sequence by non-int of type '%p'", value); |
1472 | 1444 | }
|
1473 | 1445 |
|
1474 | 1446 | protected IMulNode createIMulNode() {
|
|
0 commit comments