Skip to content

Commit 7b7dfc4

Browse files
committed
[GR-16509] bigint escapes into internal value space
PullRequest: graalpython/548
2 parents 0629b84 + ef439bb commit 7b7dfc4

File tree

3 files changed

+98
-51
lines changed

3 files changed

+98
-51
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ def test_int_subclassing():
6262
assert str(MAXREPEAT) == "MAXREPEAT"
6363

6464

65+
def test_bigint():
66+
i = int(BIG_NUMBER)
67+
assert isinstance(i, int)
68+
assert i == BIG_NUMBER
69+
# from string
70+
i = int(str(BIG_NUMBER))
71+
assert isinstance(i, int)
72+
assert i == BIG_NUMBER
73+
74+
6575
def test_boolean2int():
6676
assert int(True) == 1
6777
assert int(False) == 0

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,47 @@
3939

4040
import unittest
4141

42+
BIGINT_JSON_DATA = '''
43+
{
44+
"int_values": [
45+
1521583201297000000,
46+
13,
47+
5,
48+
1521583201297000000,
49+
67,
50+
87,
51+
1521583201331000000,
52+
1521583201347000000,
53+
10
54+
]
55+
}
56+
'''
4257

43-
class JsonTest(unittest.TestCase):
4458

59+
class JsonTest(unittest.TestCase):
4560
def test_dump(self):
4661
import json
4762
import os
4863
cwd = os.getcwd()
49-
new_file_path = os.path.join(cwd , 'myFile.json')
64+
new_file_path = os.path.join(cwd, 'myFile.json')
5065
json.dump(['a', 'b', 'c'], open(new_file_path, 'w'))
5166
assert json.load(open(new_file_path)) == ['a', 'b', 'c']
5267
os.remove(new_file_path)
5368

69+
def test_load_bigin(self):
70+
import json
71+
data = json.loads(BIGINT_JSON_DATA)
72+
assert "int_values" in data
73+
int_values_ = data['int_values']
74+
assert isinstance(int_values_, list)
75+
assert set(int_values_) == {
76+
1521583201297000000,
77+
13,
78+
5,
79+
1521583201297000000,
80+
67,
81+
87,
82+
1521583201331000000,
83+
1521583201347000000,
84+
10,
85+
}

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

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ public abstract static class IntNode extends PythonBuiltinNode {
932932
public abstract Object executeWith(VirtualFrame frame, Object cls, Object arg, Object keywordArg);
933933

934934
@TruffleBoundary(transferToInterpreterOnException = false)
935-
private Object stringToInt(String num, int base) {
935+
private Object stringToIntInternal(String num, int base) {
936936
String s = num.replace("_", "");
937937
if ((base >= 2 && base <= 32) || base == 0) {
938938
BigInteger bi = asciiToBigInteger(s, base, false);
@@ -946,36 +946,63 @@ private Object stringToInt(String num, int base) {
946946
}
947947
}
948948

949-
@TruffleBoundary(transferToInterpreterOnException = false)
950-
private Object toInt(Object arg) {
951-
if (arg instanceof Integer || arg instanceof BigInteger) {
952-
return arg;
953-
} else if (arg instanceof Boolean) {
954-
return (boolean) arg ? 1 : 0;
955-
} else if (arg instanceof Double) {
956-
return doubleToInt((Double) arg);
957-
} else if (arg instanceof String) {
958-
return stringToInt((String) arg, 10);
949+
private Object convertToIntInternal(LazyPythonClass cls, Object value, Object number, int base) {
950+
if (value == null) {
951+
throw raise(ValueError, "invalid literal for int() with base %s: %s", base, number);
952+
} else if (value instanceof BigInteger) {
953+
return factory().createInt(cls, (BigInteger) value);
954+
} else if (isPrimitiveInt(cls)) {
955+
return value;
956+
} else {
957+
return factory().createInt(cls, (int) value);
959958
}
960-
return null;
961959
}
962960

963-
private Object toInt(Object arg1, Object arg2) {
964-
if (arg1 instanceof String && arg2 instanceof Integer) {
965-
return stringToInt((String) arg1, (Integer) arg2);
966-
} else {
967-
throw raise(ValueError, "invalid base or val for int()");
968-
}
961+
private Object stringToInt(LazyPythonClass cls, String number, int base) {
962+
Object value = stringToIntInternal(number, base);
963+
return convertToIntInternal(cls, value, number, base);
969964
}
970965

971-
private static Object doubleToInt(double num) {
966+
private static Object doubleToIntInternal(double num) {
972967
if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE) {
973968
return BigInteger.valueOf((long) num);
974969
} else {
975970
return (int) num;
976971
}
977972
}
978973

974+
@TruffleBoundary(transferToInterpreterOnException = false)
975+
private Object toIntInternal(Object number) {
976+
if (number instanceof Integer || number instanceof BigInteger) {
977+
return number;
978+
} else if (number instanceof Boolean) {
979+
return (boolean) number ? 1 : 0;
980+
} else if (number instanceof Double) {
981+
return doubleToIntInternal((Double) number);
982+
} else if (number instanceof String) {
983+
return stringToIntInternal((String) number, 10);
984+
}
985+
return null;
986+
}
987+
988+
private Object toIntInternal(Object number, Object base) {
989+
if (number instanceof String && base instanceof Integer) {
990+
return stringToIntInternal((String) number, (Integer) base);
991+
} else {
992+
throw raise(ValueError, "invalid base or val for int()");
993+
}
994+
}
995+
996+
private Object toInt(LazyPythonClass cls, Object number) {
997+
Object value = toIntInternal(number);
998+
return convertToIntInternal(cls, value, number, 10);
999+
}
1000+
1001+
private Object toInt(LazyPythonClass cls, Object number, int base) {
1002+
Object value = toIntInternal(number, base);
1003+
return convertToIntInternal(cls, value, number, base);
1004+
}
1005+
9791006
// Copied directly from Jython
9801007
@TruffleBoundary(transferToInterpreterOnException = false)
9811008
private static BigInteger asciiToBigInteger(String str, int possibleBase, boolean isLong) {
@@ -1123,12 +1150,7 @@ public Object createInt(LazyPythonClass cls, @SuppressWarnings("unused") PNone n
11231150
@Specialization(guards = "isNoValue(keywordArg)")
11241151
public Object createInt(LazyPythonClass cls, String arg, @SuppressWarnings("unused") PNone keywordArg) {
11251152
try {
1126-
Object value = stringToInt(arg, 10);
1127-
if (isPrimitiveInt(cls)) {
1128-
return value;
1129-
} else {
1130-
return value instanceof BigInteger ? factory().createInt(cls, (BigInteger) value) : factory().createInt(cls, (int) value);
1131-
}
1153+
return stringToInt(cls, arg, 10);
11321154
} catch (NumberFormatException e) {
11331155
throw raise(ValueError, "invalid literal for int() with base 10: %s", arg);
11341156
}
@@ -1195,40 +1217,23 @@ long parseLong(@SuppressWarnings("unused") LazyPythonClass cls, String arg, int
11951217
}
11961218

11971219
@Specialization(rewriteOn = NumberFormatException.class)
1198-
Object parsePInt(LazyPythonClass cls, String arg, int base) {
1199-
Object int2 = toInt(arg, base);
1200-
if (int2 instanceof BigInteger) {
1201-
return factory().createInt(cls, (BigInteger) int2);
1202-
} else if (isPrimitiveInt(cls)) {
1203-
return int2;
1204-
} else {
1205-
assert int2 instanceof Integer;
1206-
return factory().createInt(cls, (int) int2);
1207-
}
1220+
Object parsePInt(LazyPythonClass cls, String number, int base) {
1221+
return toInt(cls, number, base);
12081222
}
12091223

12101224
@Specialization(replaces = "parsePInt")
1211-
Object parsePIntError(LazyPythonClass cls, String arg, int base) {
1225+
Object parsePIntError(LazyPythonClass cls, String number, int base) {
12121226
try {
1213-
return parsePInt(cls, arg, base);
1227+
return parsePInt(cls, number, base);
12141228
} catch (NumberFormatException e) {
1215-
throw raise(ValueError, "invalid literal for int() with base %s: %s", base, arg);
1229+
throw raise(ValueError, "invalid literal for int() with base %s: %s", base, number);
12161230
}
12171231
}
12181232

12191233
@Specialization
1220-
public Object createInt(LazyPythonClass cls, String arg, Object keywordArg) {
1234+
public Object createInt(LazyPythonClass cls, String number, Object keywordArg) {
12211235
if (keywordArg instanceof PNone) {
1222-
Object value = toInt(arg);
1223-
if (value == null) {
1224-
throw raise(ValueError, "invalid literal for int() with base 10: %s", arg);
1225-
} else if (value instanceof BigInteger) {
1226-
return factory().createInt(cls, (BigInteger) value);
1227-
} else if (isPrimitiveInt(cls)) {
1228-
return value;
1229-
} else {
1230-
return factory().createInt(cls, (int) value);
1231-
}
1236+
return toInt(cls, number);
12321237
} else {
12331238
CompilerDirectives.transferToInterpreter();
12341239
throw new RuntimeException("Not implemented integer with base: " + keywordArg);

0 commit comments

Comments
 (0)