chiark / gitweb /
*.pyx: Replace __new__ with __cinit__ like the program says.
[mLib-python] / atom-base.c
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
42 typedef struct entry {
43   assoc_base _b;
44   PyObject *a;
45 } entry;
46
47 /*----- Static variables --------------------------------------------------*/
48
49 static assoc_table obarray;
50
51 /*----- Main code ---------------------------------------------------------*/
52
53 PyObject *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
67 PyObject *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
84 static void atom_pydealloc(PyObject *me)
85   { fprintf(stderr, "ouch!  freeing atom\n"); abort();  }
86
87 static 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
97 static 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
103 static 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
109 static 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
117 static 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
131 static 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);
147 done:
148   Py_XDECREF(s);
149   Py_XDECREF(sr);
150   dstr_destroy(&d);
151   return (rc);
152 }
153
154 static long atom_pyhash(PyObject *me)
155   { long h = ATOM_HASH(ATOM_A(me)); if (h == -1) h = -2; return (h); }
156
157 PyTypeObject atom_pytype = {
158   PyObject_HEAD_INIT(0) 0,              /* Header */
159   "mLib.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
204 void atom_pysetup(void)
205   { assoc_create(&obarray); PyType_Ready(&atom_pytype); }
206
207 /*----- That's all, folks -------------------------------------------------*/