Skip to content

Commit bccfeff

Browse files
committed
feat(bigint): convert Js BigInt to pm.bigint
1 parent 3074fc4 commit bccfeff

3 files changed

Lines changed: 17 additions & 6 deletions

File tree

include/modules/pythonmonkey/pythonmonkey.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
#include <Python.h>
2121

22-
#define PythonMonkey_Null PyObject_GetAttrString(PyState_FindModule(&pythonmonkey), "null") /**< macro for python null object*/
22+
#define PythonMonkey_Null PyObject_GetAttrString(PyState_FindModule(&pythonmonkey), "null") /**< macro for pythonmonkey.null object*/
23+
#define PythonMonkey_BigInt PyObject_GetAttrString(PyState_FindModule(&pythonmonkey), "bigint") /**< macro for pythonmonkey.bigint class object */
2324

2425
static JSContext *cx; /**< pointer to PythonMonkey's JSContext */
2526
static JS::Rooted<JSObject *> *global; /**< pointer to the global object of PythonMonkey's JSContext */

src/IntType.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include "include/modules/pythonmonkey/pythonmonkey.hh"
2+
13
#include "include/IntType.hh"
24

35
#include "include/PyType.hh"
@@ -51,7 +53,7 @@ IntType::IntType(JSContext *cx, JS::BigInt *bigint) {
5153
return;
5254
}
5355
// If the native endianness is also little-endian,
54-
// we now have uniform bytes of 8-bit "digits" in little-endian order
56+
// we now have consecutive bytes of 8-bit "digits" in little-endian order
5557
auto bytes = const_cast<const uint8_t *>((uint8_t *)jsDigits);
5658
pyObject = _PyLong_FromByteArray(bytes, jsDigitCount * JS_DIGIT_BYTE, true, false);
5759

@@ -61,6 +63,10 @@ IntType::IntType(JSContext *cx, JS::BigInt *bigint) {
6163
auto pyDigitCount = Py_SIZE(pyObject);
6264
Py_SET_SIZE(pyObject, -pyDigitCount);
6365
}
66+
67+
// Cast to a pythonmonkey.bigint to differentiate it from a normal Python int,
68+
// allowing Py<->JS two-way BigInt conversion
69+
Py_SET_TYPE(pyObject, (PyTypeObject *)(PythonMonkey_BigInt));
6470
}
6571

6672
void IntType::print(std::ostream &os) const {

src/jsTypeFactory.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ JS::Value jsTypeFactory(PyObject *object) {
2222
returnType.setBoolean(PyLong_AsLong(object));
2323
}
2424
else if (PyLong_Check(object)) {
25-
long num = PyLong_AsLong(object); // FIXME: long is 32-bit on Win64 or 32bit *nix
26-
if (JS::Value::isNumberRepresentable(num)) {
27-
returnType.setNumber(num);
25+
if (PyObject_IsInstance(object, PythonMonkey_BigInt)) { // pm.bigint is a subclass of the builtin int type
26+
returnType.setBigInt(num);
2827
} else {
29-
PyErr_SetString(PyExc_TypeError, "Integer exceeds Number.MAX_SAFE_INTEGER. Use pythonmonkey.bigint instead.");
28+
long num = PyLong_AsLong(object); // FIXME: long is 32-bit on Win64 or 32bit *nix
29+
if (JS::Value::isNumberRepresentable(num)) {
30+
returnType.setNumber(num);
31+
} else {
32+
PyErr_SetString(PyExc_TypeError, "Integer exceeds Number.MAX_SAFE_INTEGER. Use pythonmonkey.bigint instead.");
33+
}
3034
}
3135
}
3236
else if (PyFloat_Check(object)) {

0 commit comments

Comments
 (0)