Skip to content

Commit 4407ce2

Browse files
committed
Support macro 'PyIndex_Check'.
1 parent 8a68eb3 commit 4407ce2

File tree

4 files changed

+182
-2
lines changed

4 files changed

+182
-2
lines changed

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,3 +707,23 @@ def compile_module(self, name):
707707
cmpfunc=unhandled_error_compare
708708
)
709709

710+
test_PyIndex_Check = CPyExtFunction(
711+
lambda args: hasattr(args[0], "__index__"),
712+
lambda: (
713+
(1, ),
714+
("not a number", ),
715+
(tuple(), ),
716+
(dict(), ),
717+
(list(), ),
718+
(DummyFloatable(), ),
719+
(DummyFloatSubclass(), ),
720+
(DummyIntable(), ),
721+
(DummyIntSubclass(), ),
722+
(NoNumber(), ),
723+
),
724+
resultspec="i",
725+
argspec='O',
726+
arguments=["PyObject* obj"],
727+
cmpfunc=unhandled_error_compare
728+
)
729+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the
17+
* Software is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
*
27+
* The above copyright notice and either this complete permission notice or at a
28+
* minimum a reference to the UPL must be included in all copies or substantial
29+
* portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37+
* SOFTWARE.
38+
*/
39+
package com.oracle.graal.python.builtins.objects.cext;
40+
41+
import com.oracle.truffle.api.interop.ForeignAccess;
42+
import com.oracle.truffle.api.interop.TruffleObject;
43+
44+
/**
45+
* Wraps a PythonObject to proviate a native view with a shape like {@code PyNumberMethods}.
46+
*/
47+
public class PyNumberMethodsWrapper implements TruffleObject {
48+
49+
private final Object delegate;
50+
51+
public PyNumberMethodsWrapper(Object delegate) {
52+
this.delegate = delegate;
53+
}
54+
55+
public Object getDelegate() {
56+
return delegate;
57+
}
58+
59+
static boolean isInstance(TruffleObject o) {
60+
return o instanceof PyNumberMethodsWrapper;
61+
}
62+
63+
public ForeignAccess getForeignAccess() {
64+
return PyNumberMethodsWrapperMRForeign.ACCESS;
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the
17+
* Software is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
*
27+
* The above copyright notice and either this complete permission notice or at a
28+
* minimum a reference to the UPL must be included in all copies or substantial
29+
* portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37+
* SOFTWARE.
38+
*/
39+
package com.oracle.graal.python.builtins.objects.cext;
40+
41+
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode;
42+
import com.oracle.graal.python.nodes.SpecialMethodNames;
43+
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
44+
import com.oracle.truffle.api.CompilerDirectives;
45+
import com.oracle.truffle.api.interop.MessageResolution;
46+
import com.oracle.truffle.api.interop.Resolve;
47+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
48+
import com.oracle.truffle.api.nodes.Node;
49+
50+
@MessageResolution(receiverType = PyNumberMethodsWrapper.class)
51+
public class PyNumberMethodsWrapperMR {
52+
53+
@Resolve(message = "READ")
54+
abstract static class ReadNode extends Node {
55+
@Child private LookupAttributeInMRONode getAttributeNode;
56+
@Child private ToSulongNode toSulongNode;
57+
58+
public Object access(PyNumberMethodsWrapper object, String key) {
59+
// translate key to attribute name
60+
String attributeName = toAttributeName(key);
61+
62+
Object execute = getReadArrayItemNode().execute(object.getDelegate(), attributeName);
63+
return getToSulongNode().execute(execute);
64+
}
65+
66+
private static String toAttributeName(String numberMethodsMember) {
67+
switch (numberMethodsMember) {
68+
case "nb_add":
69+
return SpecialMethodNames.__ADD__;
70+
case "nb_index":
71+
return SpecialMethodNames.__INDEX__;
72+
default:
73+
// TODO extend list
74+
throw UnknownIdentifierException.raise(numberMethodsMember);
75+
}
76+
}
77+
78+
private LookupAttributeInMRONode getReadArrayItemNode() {
79+
if (getAttributeNode == null) {
80+
CompilerDirectives.transferToInterpreterAndInvalidate();
81+
getAttributeNode = insert(LookupAttributeInMRONode.create());
82+
}
83+
return getAttributeNode;
84+
}
85+
86+
private ToSulongNode getToSulongNode() {
87+
if (toSulongNode == null) {
88+
CompilerDirectives.transferToInterpreterAndInvalidate();
89+
toSulongNode = insert(ToSulongNode.create());
90+
}
91+
return toSulongNode;
92+
}
93+
}
94+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ Object doTpBase(PythonClass object, @SuppressWarnings("unused") String key) {
187187

188188
@Specialization(guards = "eq(TP_AS_NUMBER, key)")
189189
Object doTpAsNumber(PythonClass object, @SuppressWarnings("unused") String key) {
190-
// TODO
191-
return getToSulongNode().execute(object);
190+
// TODO check for type and return 'NULL'
191+
return new PyNumberMethodsWrapper(object);
192192
}
193193

194194
@Specialization(guards = "eq(OB_ITEM, key)")

0 commit comments

Comments
 (0)