Skip to content

Commit 222bafa

Browse files
committed
[GR-13313] Fix to-float conversion for native objects.
PullRequest: graalpython/352
2 parents 69bb4cd + 0054691 commit 222bafa

File tree

4 files changed

+110
-16
lines changed

4 files changed

+110
-16
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,3 +714,7 @@ int truffle_ptr_compare(void* x, void* y, int op) {
714714
return -1;
715715
}
716716
}
717+
718+
double truffle_read_ob_fval(PyFloatObject* fobj) {
719+
return fobj->ob_fval;
720+
}

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -130,13 +130,18 @@ def test_dict(self):
130130
return custom_dict;
131131
}
132132
""",
133-
ready_code="""
133+
ready_code="""PyObject* descr;
134134
custom_dict = PyDict_New();
135-
PyDict_SetItemString(custom_dict, "hello", PyUnicode_FromString("first custom property"));
135+
Py_XINCREF(custom_dict);
136+
descr = PyUnicode_FromString("first custom property");
137+
Py_INCREF(descr);
138+
PyDict_SetItemString(custom_dict, "hello", descr);
136139
TestDictType.tp_dict = custom_dict;
137140
""",
138141
post_ready_code="""
139-
PyDict_SetItemString(TestDictType.tp_dict, "world", PyUnicode_FromString("second custom property"));
142+
descr = PyUnicode_FromString("second custom property");
143+
Py_INCREF(descr);
144+
PyDict_SetItemString(TestDictType.tp_dict, "world", descr);
140145
""",
141146
tp_methods='{"get_dict", get_dict, METH_NOARGS, ""}'
142147
)
@@ -166,6 +171,7 @@ def test_new(self):
166171
typedObj = ((TestNewObject*)obj);
167172
typedObj->none = Py_None;
168173
Py_INCREF(Py_None);
174+
Py_XINCREF(obj);
169175
return obj;
170176
}
171177
static PyObject* get_none(PyObject* self) {
@@ -184,9 +190,10 @@ def test_slots(self):
184190
'',
185191
includes='#include "datetime.h"',
186192
cmembers="PyDateTime_DateTime __pyx_base;",
187-
ready_code='''PyObject* datetime_module = PyImport_ImportModule("datetime");
188-
PyTypeObject* datetime_type = (PyTypeObject*)PyObject_GetAttrString(datetime_module, "datetime");
193+
ready_code='''PyTypeObject* datetime_type = NULL;
189194
PyDateTime_IMPORT;
195+
Py_INCREF(PyDateTimeAPI);
196+
datetime_type = PyDateTimeAPI->DateTimeType;
190197
Py_XINCREF(datetime_type);
191198
TestSlotsType.tp_base = (PyTypeObject*) datetime_type;
192199
TestSlotsType.tp_new = datetime_type->tp_new;
@@ -198,7 +205,7 @@ def test_slots_initialized(self):
198205
TestSlotsInitialized = CPyExtType("TestSlotsInitialized",
199206
'''
200207
static PyTypeObject* datetime_type = NULL;
201-
208+
202209
PyObject* TestSlotsInitialized_new(PyTypeObject* self, PyObject* args, PyObject* kwargs) {
203210
PyObject* result = datetime_type->tp_new(self, args, kwargs);
204211
Py_XINCREF(result);
@@ -207,17 +214,64 @@ def test_slots_initialized(self):
207214
''',
208215
includes='#include "datetime.h"',
209216
cmembers="PyDateTime_DateTime __pyx_base;",
210-
ready_code='''PyObject* datetime_module = PyImport_ImportModule("datetime");
217+
ready_code='''
211218
PyDateTime_IMPORT;
212-
Py_INCREF(datetime_module);
213-
datetime_type = (PyTypeObject*)PyObject_GetAttrString(datetime_module, "datetime");
219+
Py_INCREF(PyDateTimeAPI);
220+
datetime_type = PyDateTimeAPI->DateTimeType;
214221
Py_INCREF(datetime_type);
215222
TestSlotsInitializedType.tp_base = datetime_type;
216223
''',
217224
tp_new="TestSlotsInitialized_new")
218225
tester = TestSlotsInitialized(2012, 4, 4)
219226
assert tester.year == 2012, "year was %s "% tester.year
220227

228+
def test_float_subclass(self):
229+
TestFloatSubclass = CPyExtType("TestFloatSubclass",
230+
"""
231+
static PyTypeObject* testFloatSubclassPtr = NULL;
232+
233+
static PyObject* new_fp(double val) {
234+
PyFloatObject* fp = PyObject_New(PyFloatObject, testFloatSubclassPtr);
235+
fp->ob_fval = val;
236+
return (PyObject*)fp;
237+
}
238+
239+
static PyObject* fp_tpnew(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
240+
double dval = 0.0;
241+
Py_XINCREF(args);
242+
if (!PyArg_ParseTuple(args, "d", &dval)) {{
243+
return NULL;
244+
}}
245+
return new_fp(dval);
246+
}
247+
248+
static PyObject* fp_add(PyObject* l, PyObject* r) {
249+
if (PyFloat_Check(l)) {
250+
if (PyFloat_Check(r)) {
251+
return new_fp(PyFloat_AS_DOUBLE(l) + PyFloat_AS_DOUBLE(r));
252+
} else if (PyLong_Check(r)) {
253+
return new_fp(PyFloat_AS_DOUBLE(l) + PyLong_AsLong(r));
254+
}
255+
} else if (PyLong_Check(l)) {
256+
if (PyFloat_Check(r)) {
257+
return new_fp(PyLong_AsLong(l) + PyFloat_AS_DOUBLE(r));
258+
} else if (PyLong_Check(r)) {
259+
return new_fp(PyLong_AsLong(l) + PyLong_AsLong(r));
260+
}
261+
}
262+
return Py_NotImplemented;
263+
}
264+
""",
265+
cmembers="PyFloatObject base;",
266+
tp_base="&PyFloat_Type",
267+
nb_add="fp_add",
268+
tp_new="fp_tpnew",
269+
post_ready_code="testFloatSubclassPtr = &TestFloatSubclassType; Py_INCREF(testFloatSubclassPtr);"
270+
)
271+
tester = TestFloatSubclass(41.0)
272+
res = tester + 1
273+
assert res == 42.0, "expected 42.0 but was %s" % res
274+
221275

222276

223277
class TestObjectFunctions(CPyExtTestCase):

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/NativeCAPISymbols.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -52,7 +52,7 @@ public abstract class NativeCAPISymbols {
5252
public static final String FUN_PY_NONE_HANDLE = "PyNoneHandle";
5353
public static final String FUN_WHCAR_SIZE = "PyTruffle_Wchar_Size";
5454
public static final String FUN_PY_TRUFFLE_CSTR_TO_STRING = "PyTruffle_CstrToString";
55-
public static final String FUN_PY_FLOAT_AS_DOUBLE = "PyFloat_AsDouble";
55+
public static final String FUN_PY_FLOAT_AS_DOUBLE = "truffle_read_ob_fval";
5656
public static final String FUN_GET_OB_TYPE = "get_ob_type";
5757
public static final String FUN_DEREF_HANDLE = "truffle_deref_handle_for_managed";
5858
public static final String FUN_GET_BYTE_ARRAY_TYPE_ID = "get_byte_array_typeid";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -891,6 +891,24 @@ boolean eqDbPI(double a, PInt b) {
891891
return a == b.doubleValue();
892892
}
893893

894+
@Specialization
895+
Object eqPDb(PythonNativeObject left, double right,
896+
@Cached("nativeFloat()") FromNativeSubclassNode<Double> getFloat) {
897+
return getFloat.execute(left) == right;
898+
}
899+
900+
@Specialization
901+
Object eqPDb(PythonNativeObject left, long right,
902+
@Cached("nativeFloat()") FromNativeSubclassNode<Double> getFloat) {
903+
return getFloat.execute(left) == right;
904+
}
905+
906+
@Specialization
907+
Object eqPDb(PythonNativeObject left, PInt right,
908+
@Cached("nativeFloat()") FromNativeSubclassNode<Double> getFloat) {
909+
return getFloat.execute(left) == right.doubleValue();
910+
}
911+
894912
@Fallback
895913
@SuppressWarnings("unused")
896914
PNotImplemented eq(Object a, Object b) {
@@ -903,20 +921,38 @@ PNotImplemented eq(Object a, Object b) {
903921
@TypeSystemReference(PythonArithmeticTypes.class)
904922
abstract static class NeNode extends PythonBinaryBuiltinNode {
905923
@Specialization
906-
boolean eqDbDb(double a, double b) {
924+
boolean neDbDb(double a, double b) {
907925
return a != b;
908926
}
909927

910928
@Specialization
911-
boolean eqDbLn(double a, long b) {
929+
boolean neDbLn(double a, long b) {
912930
return a != b;
913931
}
914932

915933
@Specialization
916-
boolean eqDbPI(double a, PInt b) {
934+
boolean neDbPI(double a, PInt b) {
917935
return a != b.doubleValue();
918936
}
919937

938+
@Specialization
939+
Object eqPDb(PythonNativeObject left, double right,
940+
@Cached("nativeFloat()") FromNativeSubclassNode<Double> getFloat) {
941+
return getFloat.execute(left) != right;
942+
}
943+
944+
@Specialization
945+
Object eqPDb(PythonNativeObject left, long right,
946+
@Cached("nativeFloat()") FromNativeSubclassNode<Double> getFloat) {
947+
return getFloat.execute(left) != right;
948+
}
949+
950+
@Specialization
951+
Object eqPDb(PythonNativeObject left, PInt right,
952+
@Cached("nativeFloat()") FromNativeSubclassNode<Double> getFloat) {
953+
return getFloat.execute(left) != right.doubleValue();
954+
}
955+
920956
@Fallback
921957
@SuppressWarnings("unused")
922958
PNotImplemented eq(Object a, Object b) {

0 commit comments

Comments
 (0)