Skip to content

Commit 15ff65d

Browse files
committed
Added comments to the logic of integral type conversions in int() constructor
1 parent 6fb4f6f commit 15ff65d

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,15 @@ Object fail(LazyPythonClass cls, Object arg, Object base) {
15341534

15351535
@Specialization(guards = {"isNoValue(base)", "!isNoValue(obj)", "!isHandledType(obj)"})
15361536
Object createIntGeneric(VirtualFrame frame, LazyPythonClass cls, Object obj, @SuppressWarnings("unused") PNone base) {
1537+
// This method (together with callInt and callIndex) reflects the logic of PyNumber_Long
1538+
// in CPython. We don't use PythonObjectLibrary here since the original CPython function
1539+
// does not use any of the conversion functions (such as _PyLong_AsInt or
1540+
// PyNumber_Index) either, but it reimplements the logic in a slightly different way
1541+
// (e.g. trying __int__ before __index__ whereas _PyLong_AsInt does it the other way)
1542+
// and also with specific exception messages which are expected by Python unittests.
1543+
// This unfortunately means that this method relies on the internal logic of NO_VALUE
1544+
// return values representing missing magic methods which should be ideally hidden
1545+
// by PythonObjectLibrary.
15371546
Object result = callInt(frame, obj);
15381547
if (result == PNone.NO_VALUE) {
15391548
result = callIndex(frame, obj);
@@ -1562,10 +1571,6 @@ protected static boolean isIntegerType(Object obj) {
15621571
return PGuards.isBoolean(obj) || PGuards.isInteger(obj) || PGuards.isPInt(obj);
15631572
}
15641573

1565-
protected static boolean isIntegerTypeOrNoValue(Object obj) {
1566-
return obj == PNone.NO_VALUE || isIntegerType(obj);
1567-
}
1568-
15691574
protected static boolean isHandledType(Object obj) {
15701575
return PGuards.isInteger(obj) || obj instanceof Double || obj instanceof Boolean || PGuards.isString(obj) || PGuards.isBytes(obj) || obj instanceof PythonNativeVoidPtr;
15711576
}
@@ -1575,12 +1580,14 @@ protected static FloatBuiltins.IntNode createFloatInt() {
15751580
}
15761581

15771582
private Object callInt(VirtualFrame frame, Object obj) {
1583+
// The case when the result is NO_VALUE (i.e. the object does not provide __int__)
1584+
// is handled in createIntGeneric
15781585
if (callIntNode == null) {
15791586
CompilerDirectives.transferToInterpreterAndInvalidate();
15801587
callIntNode = insert(LookupAndCallUnaryNode.create(__INT__));
15811588
}
15821589
Object result = callIntNode.executeObject(frame, obj);
1583-
if (!isIntegerTypeOrNoValue(result)) {
1590+
if (result != PNone.NO_VALUE && !isIntegerType(result)) {
15841591
throw raise(TypeError, ErrorMessages.RETURNED_NON_INT, "__int__", result);
15851592
}
15861593
return result;
@@ -1592,7 +1599,9 @@ private Object callIndex(VirtualFrame frame, Object obj) {
15921599
callIndexNode = insert(LookupAndCallUnaryNode.create(__INDEX__));
15931600
}
15941601
Object result = callIndexNode.executeObject(frame, obj);
1595-
if (!isIntegerTypeOrNoValue(result)) {
1602+
// the case when the result is NO_VALUE (i.e. the object does not provide __index__)
1603+
// is handled in createIntGeneric
1604+
if (result != PNone.NO_VALUE && !isIntegerType(result)) {
15961605
throw raise(TypeError, ErrorMessages.RETURNED_NON_INT, "__index__", result);
15971606
}
15981607
return result;

0 commit comments

Comments
 (0)