@@@ cython and python3
[mLib-python] / atom-base.c
CommitLineData
20bce5e9 1/* -*-c-*-
2 *
20bce5e9 3 * Atom stuff
4 *
5 * (c) 2005 Straylight/Edgeware
6 */
7
d8d81d1b 8/*----- Licensing notice --------------------------------------------------*
20bce5e9 9 *
10 * This file is part of the Python interface to mLib.
11 *
12 * mLib/Python is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
d8d81d1b 16 *
20bce5e9 17 * mLib/Python is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
d8d81d1b 21 *
20bce5e9 22 * You should have received a copy of the GNU General Public License
23 * along with mLib/Python; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27/*----- Header files ------------------------------------------------------*/
28
29#include <Python.h>
30
31#include <mLib/atom.h>
32#include <mLib/assoc.h>
33#include <mLib/dstr.h>
34
35#include "atom.h"
36#include "grim.h"
37
38/*----- Data structures ---------------------------------------------------*/
39
20bce5e9 40typedef struct entry {
41 assoc_base _b;
42 PyObject *a;
43} entry;
44
45/*----- Static variables --------------------------------------------------*/
46
47static assoc_table obarray;
48
49/*----- Main code ---------------------------------------------------------*/
50
51PyObject *atom_pywrap(atom *a)
52{
efb0bf0e
MW
53 entry *e = 0;
54 atom_pyobj *ao;
20bce5e9 55 unsigned f = 0;
56
57 e = assoc_find(&obarray, a, sizeof(entry), &f);
58 if (!f) {
efb0bf0e 59 ao = PyObject_NEW(atom_pyobj, &atom_pytype); ao->a = a;
20bce5e9 60 e->a = (PyObject *)ao;
d8d81d1b 61 }
efb0bf0e
MW
62
63 /* If we just created the new `Atom' object, we get a reference, which
64 * belongs to the `obarray' table. So when we return it to the caller, we
65 * always need to increment it.
66 */
20bce5e9 67 RETURN_OBJ(e->a);
68}
69
70PyObject *atom_pyintern(PyObject *x)
71{
72 atom *a;
73 const void *p;
78911cdb 74 Py_ssize_t n;
20bce5e9 75
76 if (ATOM_PYCHECK(x))
77 RETURN_OBJ(x);
78 if (x == Py_None)
79 a = atom_gensym(ATOM_GLOBAL);
efb0bf0e
MW
80 else if (!TEXT_CHECK(x))
81 { PyErr_SetString(PyExc_TypeError, "string wanted"); return (0); }
20bce5e9 82 else {
efb0bf0e 83 TEXT_PTRLEN(x, &p, &n); if (!p) return (0);
20bce5e9 84 a = atom_nintern(ATOM_GLOBAL, p, n);
85 }
86 return (atom_pywrap(a));
87}
88
89static void atom_pydealloc(PyObject *me)
d8d81d1b 90 { fprintf(stderr, "ouch! freeing atom\n"); abort(); }
20bce5e9 91
92static PyObject *atom_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
93{
efb0bf0e
MW
94 PyObject *name = Py_None;
95 static const char *const kwlist[] = { "name", 0 };
20bce5e9 96
efb0bf0e 97 if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:new", KWLIST, &name))
20bce5e9 98 return (0);
99 return (atom_pyintern(name));
100}
101
102static PyObject *aget_name(PyObject *me, void *hunoz)
efb0bf0e 103 { return (TEXT_FROMSTRLEN(ATOM_NAME(ATOM_A(me)), ATOM_LEN(ATOM_A(me)))); }
20bce5e9 104
105static PyObject *aget_internedp(PyObject *me, void *hunoz)
106{
107 PyObject *rc = (ATOM_A(me)->f & ATOMF_GENSYM) ? Py_False : Py_True;
108 RETURN_OBJ(rc);
109}
110
111static PyGetSetDef atom_pygetset[] = {
112#define GETSETNAME(op, name) a##op##_##name
113 GET (name, "A.name -> NAME")
114 GET (internedp, "A.internedp -> BOOL")
115#undef GETSETNAME
116 { 0 }
117};
118
119static PyObject *atom_pyrichcompare(PyObject *x, PyObject *y, int op)
120{
121 PyObject *rc = 0;
122
123 switch (op) {
124 case Py_EQ: rc = (x == y) ? Py_True : Py_False; break;
125 case Py_NE: rc = (x != y) ? Py_True : Py_False; break;
126 default:
127 PyErr_SetString(PyExc_TypeError, "atoms are unordered");
128 return (0);
129 }
130 RETURN_OBJ(rc);
131}
132
133static PyObject *atom_pyrepr(PyObject *me)
134{
135 PyObject *s, *sr = 0;
136 PyObject *rc = 0;
137 char *p;
78911cdb 138 Py_ssize_t n;
20bce5e9 139 dstr d = DSTR_INIT;
140
141 if ((s = aget_name(me, 0)) == 0 ||
efb0bf0e 142 (sr = PyObject_Repr(s)) == 0)
20bce5e9 143 goto done;
efb0bf0e
MW
144 if (!TEXT_CHECK(sr))
145 { PyErr_SetString(PyExc_TypeError, "string wanted"); goto done; }
146 TEXT_PTRLEN(sr, &p, &n); if (!p) goto done;
20bce5e9 147 dstr_puts(&d, "Atom(");
148 dstr_putm(&d, p, n);
149 dstr_puts(&d, ")");
efb0bf0e 150 rc = TEXT_FROMSTRLEN(d.buf, d.len);
20bce5e9 151done:
152 Py_XDECREF(s);
153 Py_XDECREF(sr);
154 dstr_destroy(&d);
155 return (rc);
156}
157
efb0bf0e
MW
158static Py_hash_t atom_pyhash(PyObject *me)
159 { Py_hash_t h = ATOM_HASH(ATOM_A(me)); if (h == -1) h = -2; return (h); }
20bce5e9 160
579d0169 161PyTypeObject atom_pytype = {
efb0bf0e 162 PyVarObject_HEAD_INIT(0, 0) /* Header */
3655f952 163 "mLib.Atom", /* @tp_name@ */
20bce5e9 164 sizeof(atom_pyobj), /* @tp_basicsize@ */
165 0, /* @tp_itemsize@ */
166
167 atom_pydealloc, /* @tp_dealloc@ */
168 0, /* @tp_print@ */
169 0, /* @tp_getattr@ */
170 0, /* @tp_setattr@ */
171 0, /* @tp_compare@ */
172 atom_pyrepr, /* @tp_repr@ */
173 0, /* @tp_as_number@ */
174 0, /* @tp_as_sequence@ */
175 0, /* @tp_as_mapping@ */
176 atom_pyhash, /* @tp_hash@ */
177 0, /* @tp_call@ */
178 atom_pyrepr, /* @tp_str@ */
179 0, /* @tp_getattro@ */
180 0, /* @tp_setattro@ */
181 0, /* @tp_as_buffer@ */
182 Py_TPFLAGS_DEFAULT, /* @tp_flags@ */
183
184 /* @tp_doc@ */
185"Atom.",
186
187 0, /* @tp_traverse@ */
188 0, /* @tp_clear@ */
189 atom_pyrichcompare, /* @tp_richcompare@ */
190 0, /* @tp_weaklistoffset@ */
191 0, /* @tp_iter@ */
192 0, /* @tp_iternexr@ */
193 0, /* @tp_methods@ */
194 0, /* @tp_members@ */
195 atom_pygetset, /* @tp_getset@ */
196 0, /* @tp_base@ */
197 0, /* @tp_dict@ */
198 0, /* @tp_descr_get@ */
199 0, /* @tp_descr_set@ */
200 0, /* @tp_dictoffset@ */
201 0, /* @tp_init@ */
202 PyType_GenericAlloc, /* @tp_alloc@ */
203 atom_pynew, /* @tp_new@ */
204 0, /* @tp_free@ */
205 0 /* @tp_is_gc@ */
206};
207
579d0169 208void atom_pysetup(void)
209 { assoc_create(&obarray); PyType_Ready(&atom_pytype); }
20bce5e9 210
211/*----- That's all, folks -------------------------------------------------*/