Skip to content

Commit fbd849f

Browse files
committed
PEP 227 implementation
A cell contains a reference to a single PyObject. It could be implemented as a mutable, one-element sequence, but the separate type has less overhead.
1 parent c34a5ad commit fbd849f

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

Diff for: Include/Python.h

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
#include "cobject.h"
8282
#include "traceback.h"
8383
#include "sliceobject.h"
84+
#include "cellobject.h"
8485

8586
#include "codecs.h"
8687
#include "pyerrors.h"

Diff for: Include/cellobject.h

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* Cell object interface */
2+
3+
#ifndef Py_CELLOBJECT_H
4+
#define Py_CELLOBJECT_H
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
typedef struct {
10+
PyObject_VAR_HEAD
11+
PyObject *ob_ref;
12+
} PyCellObject;
13+
14+
extern DL_IMPORT(PyTypeObject) PyCell_Type;
15+
16+
#define PyCell_Check(op) ((op)->ob_type == &PyCell_Type)
17+
18+
extern DL_IMPORT(PyObject *) PyCell_New(PyObject *);
19+
extern DL_IMPORT(PyObject *) PyCell_Get(PyObject *);
20+
extern DL_IMPORT(int) PyCell_Set(PyObject *, PyObject *);
21+
22+
#define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref)
23+
#define PyCell_SET(op, v) (((PyCellObject *)(op))->ob_ref = v)
24+
25+
#ifdef __cplusplus
26+
}
27+
#endif
28+
#endif /* !Py_TUPLEOBJECT_H */

Diff for: Makefile.pre.in

+1
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ PYTHON_OBJS= \
236236
OBJECT_OBJS= \
237237
Objects/abstract.o \
238238
Objects/bufferobject.o \
239+
Objects/cellobject.o \
239240
Objects/classobject.o \
240241
Objects/cobject.o \
241242
Objects/complexobject.o \

Diff for: Objects/cellobject.c

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* Cell object implementation */
2+
3+
#include "Python.h"
4+
5+
PyObject *
6+
PyCell_New(PyObject *obj)
7+
{
8+
PyCellObject *op;
9+
10+
op = (PyCellObject *)PyObject_New(PyCellObject, &PyCell_Type);
11+
op->ob_ref = obj;
12+
Py_XINCREF(obj);
13+
14+
PyObject_GC_Init(op);
15+
return (PyObject *)op;
16+
}
17+
18+
PyObject *
19+
PyCell_Get(PyObject *op)
20+
{
21+
if (!PyCell_Check(op)) {
22+
PyErr_BadInternalCall();
23+
return NULL;
24+
}
25+
Py_XINCREF(((PyCellObject*)op)->ob_ref);
26+
return PyCell_GET(op);
27+
}
28+
29+
int
30+
PyCell_Set(PyObject *op, PyObject *obj)
31+
{
32+
if (!PyCell_Check(op)) {
33+
PyErr_BadInternalCall();
34+
return -1;
35+
}
36+
Py_XDECREF(((PyCellObject*)op)->ob_ref);
37+
Py_XINCREF(obj);
38+
PyCell_SET(op, obj);
39+
return 0;
40+
}
41+
42+
static void
43+
cell_dealloc(PyCellObject *op)
44+
{
45+
PyObject_GC_Fini(op);
46+
Py_XDECREF(op->ob_ref);
47+
PyObject_Del(op);
48+
}
49+
50+
static int
51+
cell_compare(PyCellObject *a, PyCellObject *b)
52+
{
53+
if (a->ob_ref == NULL) {
54+
if (b->ob_ref == NULL)
55+
return 0;
56+
return -1;
57+
} else if (b->ob_ref == NULL)
58+
return 1;
59+
return PyObject_Compare(a->ob_ref, b->ob_ref);
60+
}
61+
62+
static PyObject *
63+
cell_repr(PyCellObject *op)
64+
{
65+
char buf[256];
66+
67+
if (op->ob_ref == NULL)
68+
sprintf(buf, "<cell at %p: empty>", op);
69+
else
70+
sprintf(buf, "<cell at %p: %.80s object at %p>",
71+
op, op->ob_ref->ob_type->tp_name, op->ob_ref);
72+
return PyString_FromString(buf);
73+
}
74+
75+
static int
76+
cell_traverse(PyCellObject *op, visitproc visit, void *arg)
77+
{
78+
if (op->ob_ref)
79+
return visit(op->ob_ref, arg);
80+
return 0;
81+
}
82+
83+
static int
84+
cell_clear(PyCellObject *op)
85+
{
86+
op->ob_ref = NULL;
87+
return 0;
88+
}
89+
90+
PyTypeObject PyCell_Type = {
91+
PyObject_HEAD_INIT(&PyType_Type)
92+
0,
93+
"cell",
94+
sizeof(PyCellObject) + PyGC_HEAD_SIZE,
95+
0,
96+
(destructor)cell_dealloc, /* tp_dealloc */
97+
0, /* tp_print */
98+
0, /* tp_getattr */
99+
0, /* tp_setattr */
100+
(cmpfunc)cell_compare, /* tp_compare */
101+
(reprfunc)cell_repr, /* tp_repr */
102+
0, /* tp_as_number */
103+
0, /* tp_as_sequence */
104+
0, /* tp_as_mapping */
105+
0, /* tp_hash */
106+
0, /* tp_call */
107+
0, /* tp_str */
108+
0, /* tp_getattro */
109+
0, /* tp_setattro */
110+
0, /* tp_as_buffer */
111+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
112+
0, /* tp_doc */
113+
(traverseproc)cell_traverse, /* tp_traverse */
114+
(inquiry)cell_clear, /* tp_clear */
115+
};

0 commit comments

Comments
 (0)