[pypy-commit] pypy _PySet_NextEntry: start to implement _PySet_NextEntry

mattip pypy.commits at gmail.com
Thu Oct 31 09:14:26 EDT 2019


Author: Matti Picus <matti.picus at gmail.com>
Branch: _PySet_NextEntry
Changeset: r97906:386490448614
Date: 2019-10-31 15:13 +0200
http://bitbucket.org/pypy/pypy/changeset/386490448614/

Log:	start to implement _PySet_NextEntry

diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -7,6 +7,34 @@
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject, newset
 
+PySetObjectStruct = lltype.ForwardReference()
+PySetObject = lltype.Ptr(PySetObjectStruct)
+PySetObjectFields = PyObjectFields + \
+    (("_tmpset", PyObject),)
+cpython_struct("PySetObject", PySetObjectFields, PySetObjectStruct)
+
+ at bootstrap_function
+def init_dictobject(space):
+    "Type description of PyDictObject"
+    make_typedescr(space.w_dict.layout.typedef,
+                   basestruct=PySetObject.TO,
+                   attach=set_attach,
+                   dealloc=set_dealloc,
+                  )
+
+def set_attach(space, py_obj, w_obj, w_userdata=None):
+    """
+    Fills a newly allocated PySetObject with the given set object.
+    """
+    py_set = rffi.cast(PySettObject, py_obj)
+    py_set.c__tmpset = lltype.nullptr(PyObject.TO)
+
+ at slot_function([PyObject], lltype.Void)
+def dict_dealloc(space, py_obj):
+    py_set = rffi.cast(PySetObject, py_obj)
+    decref(space, py_set.c__tmpset)
+    py_set.c__tmpset = lltype.nullptr(PyObject.TO)
+    _dealloc(space, py_obj)
 
 PySet_Check, PySet_CheckExact = build_type_checkers("Set")
 PyFrozenSet_Check, PyFrozenSet_CheckExact = build_type_checkers("FrozenSet")
@@ -23,7 +51,7 @@
     """Return true if obj is a set object or a frozenset object but
     not an instance of a subtype."""
     w_obj_type = space.type(w_obj)
-    return (space.is_w(w_obj_type, space.gettypefor(W_SetObject)) or 
+    return (space.is_w(w_obj_type, space.gettypefor(W_SetObject)) or
             space.is_w(w_obj_type, space.gettypefor(W_FrozensetObject)))
 
 @cpython_api([PyObject], PyObject)
@@ -126,4 +154,30 @@
     else:
         return space.call_function(space.w_frozenset, w_iterable)
 
-
+ at cpython_api([PyObject, Py_ssize_tP, PyObjectP, Py_ssize_tP], rffi.INT_real, error=-1)
+def _PySet_NextEntry(space, w_set, ppos, pkey, phash):
+    if w_set is None or not space.isinstance_w(w_set, space.w_set):
+        PyErr_BadInternalCall(space)
+        return -1
+    if not key:
+        PyErr_BadInternalCall(space)
+        return -1
+    py_obj = as_pyobj(space, w_set)
+    py_set = rffi.cast(PySetObject, py_obj)
+    if not py_set.c__tmpkeys:
+        w_keyview = space.call_method(space.w_set, "list", w_set)
+        # w_keys must use the object strategy in order to keep the keys alive
+        w_keys = space.newlist(space.listview(w_keyview))
+        w_keys.switch_to_object_strategy()
+        py_set.c__tmpkeys = create_ref(space, w_keys)
+        incref(space, py_set.c__tmpkeys)
+    else:
+        w_keys = from_ref(space, py_set.c__tmpkeys)
+    pos = pos[0]
+    if pos >= space.len_w(w_keys):
+        return 0
+    w_key = space.listview(w_keys)[pos]
+    key[0] = create_ref(space, w_key)
+    # steals a reference
+    hash[0] = -1 # meaningless in PyPy
+    return 1


More information about the pypy-commit mailing list