diff --git a/src/python2js.c b/src/python2js.c index ab490bc03..efea44683 100644 --- a/src/python2js.c +++ b/src/python2js.c @@ -131,6 +131,21 @@ _python2js(PyObject* x, PyObject* map) if (x_long == -1 && PyErr_Occurred()) { return HW_ERROR; } + // Since Javascript doesn't support > 32-bit ints, use floats + // when the Python int gets too large. This will lose precision, + // but is less problematic than truncation. + if ((unsigned long)x_long > 0x7fffffff) { + PyObject *py_float = PyNumber_Float(x); + if (py_float == NULL) { + return HW_ERROR; + } + double x_double = PyFloat_AsDouble(py_float); + Py_DECREF(py_float); + if (x_double == -1.0 && PyErr_Occurred()) { + return HW_ERROR; + } + return hiwire_double(x_double); + } return hiwire_int(x_long); } else if (PyFloat_Check(x)) { double x_double = PyFloat_AsDouble(x); diff --git a/test/test_python.py b/test/test_python.py index 00cff7e3a..279384ab8 100644 --- a/test/test_python.py +++ b/test/test_python.py @@ -58,6 +58,13 @@ def test_python2js(selenium): """) +def test_python2js_long_ints(selenium): + assert selenium.run('2**30') == 2**30 + assert selenium.run('2**31') == 2**31 + assert selenium.run('2**30 - 1 + 2**30') == (2**30 - 1 + 2**30) + assert selenium.run('2**32 / 2**4') == (2**32 / 2**4) + + def test_pythonexc2js(selenium): try: selenium.run_js('return pyodide.runPython("5 / 0")')