Skip to content

Commit 8e03cf1

Browse files
committed
Support native subtypes in the tuple constructor.
1 parent 45f10e0 commit 8e03cf1

File tree

5 files changed

+107
-6
lines changed

5 files changed

+107
-6
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ Py_ssize_t get_tp_basicsize(PyTypeObject* obj) {
303303
return obj->tp_basicsize;
304304
}
305305

306+
/** to be used from Java code only; reads native 'tp_alloc' field */
307+
allocfunc get_tp_alloc(PyTypeObject* obj) {
308+
return obj->tp_alloc;
309+
}
310+
306311
/** to be used from Java code only; returns the type ID for a byte array */
307312
polyglot_typeid get_byte_array_typeid(uint64_t len) {
308313
return polyglot_array_typeid(polyglot_i8_typeid(), len);

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,36 @@ PyObject* PyTuple_Pack(Py_ssize_t n, ...) {
7979
}
8080
return result;
8181
}
82+
83+
MUST_INLINE
84+
static PyObject * tuple_create(PyObject *iterable) {
85+
if (iterable == NULL) {
86+
return PyTuple_New(0);
87+
}
88+
return PySequence_Tuple(iterable);
89+
}
90+
91+
PyObject * tuple_subtype_new(PyTypeObject *type, PyObject *iterable) {
92+
PyObject *tmp, *newobj, *item;
93+
Py_ssize_t i, n;
94+
95+
assert(PyType_IsSubtype(type, &PyTuple_Type));
96+
tmp = tuple_create(iterable);
97+
if (tmp == NULL) {
98+
return NULL;
99+
}
100+
assert(PyTuple_Check(tmp));
101+
n = PyTuple_GET_SIZE(tmp);
102+
103+
newobj = type->tp_alloc(type, n);
104+
if (newobj == NULL) {
105+
return NULL;
106+
}
107+
for (i = 0; i < n; i++) {
108+
item = PyTuple_GetItem(tmp, i);
109+
Py_INCREF(item);
110+
PyTuple_SetItem(newobj, i, item);
111+
}
112+
Py_DECREF(tmp);
113+
return newobj;
114+
}

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,16 +1818,27 @@ private ConditionProfile getIsPStringProfile() {
18181818
@GenerateNodeFactory
18191819
public abstract static class TupleNode extends PythonBinaryBuiltinNode {
18201820

1821-
@Specialization
1822-
protected PTuple constructTuple(VirtualFrame frame, LazyPythonClass cls, Object value,
1821+
@Specialization(guards = "!isNativeClass(cls)")
1822+
protected PTuple constructTuple(VirtualFrame frame, LazyPythonClass cls, Object iterable,
18231823
@Cached("create()") TupleNodes.ConstructTupleNode constructTupleNode) {
1824-
return constructTupleNode.execute(frame, cls, value);
1824+
return constructTupleNode.execute(frame, cls, iterable);
1825+
}
1826+
1827+
// delegate to tuple_subtype_new(PyTypeObject *type, PyObject *x)
1828+
@Specialization(guards = "isSubtypeOfTuple(frame, isSubtype, cls)", limit = "1")
1829+
Object doNative(@SuppressWarnings("unused") VirtualFrame frame, PythonNativeClass cls, Object iterable,
1830+
@Cached @SuppressWarnings("unused") IsSubtypeNode isSubtype,
1831+
@Cached CExtNodes.TupleSubtypeNew subtypeNew) {
1832+
return subtypeNew.execute(cls, iterable);
1833+
}
1834+
1835+
protected static boolean isSubtypeOfTuple(VirtualFrame frame, IsSubtypeNode isSubtypeNode, PythonNativeClass cls) {
1836+
return isSubtypeNode.execute(frame, cls, PythonBuiltinClassType.PTuple);
18251837
}
18261838

18271839
@Fallback
1828-
public PTuple tupleObject(@SuppressWarnings("unused") Object cls, Object arg) {
1829-
CompilerAsserts.neverPartOfCompilation();
1830-
throw new RuntimeException("tuple does not support iterable object " + arg);
1840+
public PTuple tupleObject(Object cls, @SuppressWarnings("unused") Object arg) {
1841+
throw raise(PythonBuiltinClassType.TypeError, "'cls' is not a type object (%p)", cls);
18311842
}
18321843
}
18331844

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,17 @@ public static FloatSubtypeNew create() {
259259
}
260260
}
261261

262+
public abstract static class TupleSubtypeNew extends SubtypeNew {
263+
@Override
264+
protected final String getTypenamePrefix() {
265+
return "tuple";
266+
}
267+
268+
public static TupleSubtypeNew create() {
269+
return CExtNodesFactory.TupleSubtypeNewNodeGen.create();
270+
}
271+
}
272+
262273
// -----------------------------------------------------------------------------------------------------------------
263274
public abstract static class FromNativeSubclassNode extends CExtBaseNode {
264275

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__MRO__;
3737
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__NAME__;
3838
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__;
39+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ALLOC__;
3940
import static com.oracle.graal.python.nodes.SpecialMethodNames.__CALL__;
4041
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELETE__;
4142
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
@@ -78,6 +79,7 @@
7879
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode;
7980
import com.oracle.graal.python.nodes.PGuards;
8081
import com.oracle.graal.python.nodes.SpecialAttributeNames;
82+
import com.oracle.graal.python.nodes.SpecialMethodNames;
8183
import com.oracle.graal.python.nodes.argument.positional.PositionalArgumentsNode;
8284
import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetFixedAttributeNode;
8385
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
@@ -123,6 +125,7 @@ public class TypeBuiltins extends PythonBuiltins {
123125
public static final HiddenKey TYPE_DICTOFFSET = new HiddenKey(__DICTOFFSET__);
124126
public static final HiddenKey TYPE_ITEMSIZE = new HiddenKey(__ITEMSIZE__);
125127
public static final HiddenKey TYPE_BASICSIZE = new HiddenKey(__BASICSIZE__);
128+
public static final HiddenKey TYPE_ALLOC = new HiddenKey(__ALLOC__);
126129

127130
@Override
128131
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
@@ -887,4 +890,42 @@ Object flags(PythonAbstractClass self) {
887890
return getFlagsNode.execute(self);
888891
}
889892
}
893+
894+
@Builtin(name = __ALLOC__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
895+
abstract static class AllocNode extends AbstractSlotNode {
896+
897+
@Specialization(guards = "isNoValue(value)")
898+
Object getAlloc(PythonManagedClass cls, @SuppressWarnings("unused") PNone value,
899+
@Cached("create()") IsBuiltinClassProfile profile,
900+
@Cached("create()") ReadAttributeFromObjectNode getName) {
901+
// recursion anchor; since the metaclass of 'type' is 'type'
902+
if (profile.profileClass(cls, PythonBuiltinClassType.PythonClass)) {
903+
return getName.execute(cls, TYPE_ALLOC);
904+
}
905+
return getName.execute(cls, __ALLOC__);
906+
}
907+
908+
@Specialization(guards = "!isNoValue(value)")
909+
Object setName(@SuppressWarnings("unused") PythonBuiltinClass cls, @SuppressWarnings("unused") Object value) {
910+
throw raise(PythonErrorType.RuntimeError, "can't set attributes of built-in/extension 'type'");
911+
}
912+
913+
@Specialization(guards = {"!isNoValue(value)", "!isPythonBuiltinClass(cls)"})
914+
Object setName(PythonClass cls, Object value,
915+
@Cached WriteAttributeToObjectNode setName) {
916+
return setName.execute(cls, __ALLOC__, value);
917+
}
918+
919+
@Specialization(guards = "isNoValue(value)")
920+
Object getNative(PythonNativeClass cls, @SuppressWarnings("unused") PNone value,
921+
@Cached("create()") GetTypeMemberNode getTpAllocNode) {
922+
return getTpAllocNode.execute(cls, NativeMemberNames.TP_ALLOC);
923+
}
924+
925+
@Specialization(guards = "!isNoValue(value)")
926+
Object setNative(@SuppressWarnings("unused") PythonAbstractNativeObject cls, @SuppressWarnings("unused") Object value) {
927+
throw raise(PythonErrorType.RuntimeError, "can't set attributes of native type");
928+
}
929+
}
930+
890931
}

0 commit comments

Comments
 (0)