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