Commit | Line | Data |
---|---|---|
81f68b64 MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Atoms and obarrays | |
4 | * | |
5 | * (c) 2019 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
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 it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. | |
16 | * | |
17 | * mLib/Python is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * General Public License for more details. | |
21 | * | |
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 | |
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
25 | * USA. | |
26 | */ | |
27 | ||
28 | /*----- Header files ------------------------------------------------------*/ | |
29 | ||
30 | #include "mLib-python.h" | |
31 | ||
32 | /*----- Atoms -------------------------------------------------------------*/ | |
33 | ||
34 | typedef struct { | |
35 | PyObject_HEAD | |
36 | atom *a; | |
37 | PyObject *oawk; | |
38 | } atom_pyobj; | |
39 | static PyTypeObject *atom_pytype; | |
40 | #define ATOM_PYCHECK(o) PyObject_TypeCheck((o), atom_pytype) | |
41 | #define ATOM_A(o) (((atom_pyobj *)(o))->a) | |
42 | #define ATOM_OAWK(o) (((atom_pyobj *)(o))->oawk) | |
43 | #define ATOM_OAOBJ(o) (PyWeakref_GET_OBJECT(ATOM_OAWK(o))) | |
44 | ||
45 | struct obentry { | |
46 | assoc_base _b; | |
47 | PyObject *aobj; | |
48 | }; | |
49 | ||
50 | typedef struct { | |
51 | GMAP_PYOBJ_HEAD | |
52 | atom_table tab; | |
53 | assoc_table map; | |
54 | PyObject *wkls; | |
55 | } obarray_pyobj; | |
56 | static PyTypeObject *obarray_pytype; | |
57 | #define OBARRAY_PYCHECK(o) PyObject_TypeCheck((o), obarray_pytype) | |
58 | #define OBARRAY_TAB(o) (&((obarray_pyobj *)(o))->tab) | |
59 | #define OBARRAY_MAP(o) (&((obarray_pyobj *)(o))->map) | |
60 | ||
61 | static PyObject *default_obarray(void) | |
62 | { | |
63 | PyObject *oa = 0, *rc = 0; | |
64 | ||
65 | if (!home_module) SYSERR("home module not set"); | |
66 | oa = PyObject_GetAttrString(home_module, "DEFAULT_ATOMTABLE"); | |
67 | if (!oa) goto end; | |
68 | if (!OBARRAY_PYCHECK(oa)) TYERR("DEFAULT_ATOMTABLE isn't an AtomTable"); | |
69 | rc = oa; oa = 0; | |
70 | end: | |
71 | Py_XDECREF(oa); | |
72 | return (rc); | |
73 | } | |
74 | ||
75 | static PyObject *atom_pywrap(PyObject *oaobj, atom *a) | |
76 | { | |
77 | struct obentry *e; | |
78 | PyObject *oawk = 0, *rc = 0; | |
79 | atom_pyobj *aobj; | |
80 | unsigned f; | |
81 | ||
82 | e = assoc_find(OBARRAY_MAP(oaobj), a, sizeof(*e), &f); | |
83 | if (f) | |
84 | rc = e->aobj; | |
85 | else { | |
86 | oawk = PyWeakref_NewRef(oaobj, 0); if (!oawk) goto end; | |
87 | aobj = PyObject_NEW(atom_pyobj, atom_pytype); | |
88 | aobj->a = a; | |
89 | aobj->oawk = oawk; oawk = 0; | |
90 | e->aobj = (PyObject *)aobj; | |
91 | rc = (PyObject *)aobj; | |
92 | } | |
93 | Py_INCREF(rc); | |
94 | end: | |
95 | Py_XDECREF(oawk); | |
96 | if (e && !rc) assoc_remove(OBARRAY_MAP(oaobj), e); | |
97 | return (rc); | |
98 | } | |
99 | ||
100 | static PyObject *atom_pyintern(PyObject *oaobj, PyObject *x) | |
101 | { | |
102 | atom *a; | |
103 | const char *p; | |
104 | size_t sz; | |
105 | PyObject *rc = 0; | |
106 | ||
107 | if (ATOM_PYCHECK(x)) { | |
108 | if (ATOM_OAOBJ(x) != oaobj) VALERR("wrong table for existing atom"); | |
109 | RETURN_OBJ(x); | |
110 | } | |
111 | if (x == Py_None) | |
112 | a = atom_gensym(OBARRAY_TAB(oaobj)); | |
113 | else if (TEXT_CHECK(x)) | |
114 | { TEXT_PTRLEN(x, p, sz); a = atom_nintern(OBARRAY_TAB(oaobj), p, sz); } | |
115 | else | |
116 | TYERR("expected string or `None'"); | |
117 | rc = atom_pywrap(oaobj, a); | |
118 | end: | |
119 | return (rc); | |
120 | } | |
121 | ||
122 | static PyObject *atom_pynew(PyTypeObject *cls, PyObject *arg, PyObject *kw) | |
123 | { | |
124 | static const char *const kwlist[] = { "name", "table", 0 }; | |
125 | PyObject *name = Py_None, *oaobj = 0, *rc = 0; | |
126 | ||
127 | if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OO!:new", KWLIST, | |
128 | &name, obarray_pytype, &oaobj)) | |
129 | { oaobj = 0; goto end; } | |
130 | if (oaobj) Py_INCREF(oaobj); | |
131 | else { oaobj = default_obarray(); if (!oaobj) goto end; } | |
132 | rc = atom_pyintern(oaobj, name); | |
133 | end: | |
134 | Py_XDECREF(oaobj); | |
135 | return (rc); | |
136 | } | |
137 | ||
138 | static void atom_pydealloc(PyObject *me) | |
139 | { assert(!ATOM_OAWK(me)); FREEOBJ(me); } | |
140 | ||
141 | static int atom_check(PyObject *me) | |
142 | { | |
143 | if (!ATOM_A(me)) VALERR("atom is stale"); | |
144 | return (0); | |
145 | end: | |
146 | return (-1); | |
147 | } | |
148 | ||
149 | static PyObject *atomget_name(PyObject *me, void *hunoz) | |
150 | { | |
151 | atom *a; | |
152 | ||
153 | if (atom_check(me)) return (0); | |
154 | a = ATOM_A(me); return (TEXT_FROMSTRLEN(ATOM_NAME(a), ATOM_LEN(a))); | |
155 | } | |
156 | ||
157 | static PyObject *atomget_home(PyObject *me, void *hunoz) | |
158 | { | |
159 | PyObject *rc; | |
160 | ||
161 | if (atom_check(me)) return (0); | |
162 | rc = ATOM_OAOBJ(me); assert(rc != Py_None); RETURN_OBJ(rc); | |
163 | } | |
164 | ||
165 | static PyObject *atomget_internedp(PyObject *me, void *hunoz) | |
166 | { | |
167 | if (atom_check(me)) return (0); | |
168 | return (getbool(!(ATOM_A(me)->f&ATOMF_GENSYM))); | |
169 | } | |
170 | ||
171 | static PyObject *atomget_livep(PyObject *me, void *hunoz) | |
172 | { return (getbool(!!ATOM_A(me))); } | |
173 | ||
174 | static PyObject *atom_pyrichcompare(PyObject *x, PyObject *y, int op) | |
175 | { | |
176 | int r; | |
177 | ||
178 | switch (op) { | |
179 | case Py_EQ: r = (x == y); break; | |
180 | case Py_NE: r = (x != y); break; | |
181 | default: TYERR("atoms are unordered"); | |
182 | } | |
183 | return (getbool(r)); | |
184 | end: | |
185 | return (0); | |
186 | } | |
187 | ||
188 | static Py_hash_t atom_pyhash(PyObject *me) | |
189 | { return (atom_check(me) ? -1 : ATOM_HASH(ATOM_A(me))); } | |
190 | ||
191 | static const PyGetSetDef atom_pygetset[] = { | |
192 | #define GETSETNAME(op, name) atom##op##_##name | |
193 | GET (name, "A.name -> STR: atom name") | |
194 | GET (home, "A.home -> ATAB: atom home table") | |
195 | GET (internedp, "A.internedp -> BOOL: atom interned (not gensym)?") | |
196 | GET (livep, "A.livep -> BOOL: atom table still alive?") | |
197 | #undef GETSETNAME | |
198 | { 0 } | |
199 | }; | |
200 | ||
201 | static const PyTypeObject atom_pytype_skel = { | |
202 | PyVarObject_HEAD_INIT(0, 0) /* Header */ | |
203 | "Atom", /* @tp_name@ */ | |
204 | sizeof(atom_pyobj), /* @tp_basicsize@ */ | |
205 | 0, /* @tp_itemsize@ */ | |
206 | ||
207 | atom_pydealloc, /* @tp_dealloc@ */ | |
208 | 0, /* @tp_print@ */ | |
209 | 0, /* @tp_getattr@ */ | |
210 | 0, /* @tp_setattr@ */ | |
211 | 0, /* @tp_compare@ */ | |
212 | 0, /* @tp_repr@ */ | |
213 | 0, /* @tp_as_number@ */ | |
214 | 0, /* @tp_as_sequence@ */ | |
215 | 0, /* @tp_as_mapping@ */ | |
216 | atom_pyhash, /* @tp_hash@ */ | |
217 | 0, /* @tp_call@ */ | |
218 | 0, /* @tp_str@ */ | |
219 | 0, /* @tp_getattro@ */ | |
220 | 0, /* @tp_setattro@ */ | |
221 | 0, /* @tp_as_buffer@ */ | |
222 | Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ | |
223 | Py_TPFLAGS_BASETYPE, | |
224 | ||
225 | /* @tp_doc@ */ | |
226 | "Atom([name = None], [table = DEFAULT_ATOMTABLE])", | |
227 | ||
228 | 0, /* @tp_traverse@ */ | |
229 | 0, /* @tp_clear@ */ | |
230 | atom_pyrichcompare, /* @tp_richcompare@ */ | |
231 | 0, /* @tp_weaklistoffset@ */ | |
232 | 0, /* @tp_iter@ */ | |
233 | 0, /* @tp_iternext@ */ | |
234 | 0, /* @tp_methods@ */ | |
235 | 0, /* @tp_members@ */ | |
236 | PYGETSET(atom), /* @tp_getset@ */ | |
237 | 0, /* @tp_base@ */ | |
238 | 0, /* @tp_dict@ */ | |
239 | 0, /* @tp_descr_get@ */ | |
240 | 0, /* @tp_descr_set@ */ | |
241 | 0, /* @tp_dictoffset@ */ | |
242 | 0, /* @tp_init@ */ | |
243 | PyType_GenericAlloc, /* @tp_alloc@ */ | |
244 | atom_pynew, /* @tp_new@ */ | |
245 | 0, /* @tp_free@ */ | |
246 | 0 /* @tp_is_gc@ */ | |
247 | }; | |
248 | ||
249 | static void *obarray_gmlookup(PyObject *me, PyObject *key, unsigned *f) | |
250 | { | |
251 | atom *a = 0; | |
252 | const char *p; | |
253 | size_t sz; | |
254 | ||
255 | if (!TEXT_CHECK(key)) TYERR("expected string"); | |
256 | TEXT_PTRLEN(key, p, sz); a = sym_find(&OBARRAY_TAB(me)->t, p, sz, 0, f); | |
257 | end: | |
258 | return (a); | |
259 | } | |
260 | ||
261 | static void obarray_gmiterinit(PyObject *me, void *i) | |
262 | { atom_mkiter(i, OBARRAY_TAB(me)); } | |
263 | ||
264 | static void *obarray_gmiternext(PyObject *me, void *i) | |
265 | { return (atom_next(i)); } | |
266 | ||
267 | static PyObject *obarray_gmentrykey(PyObject *me, void *e) | |
268 | { return (TEXT_FROMSTRLEN(ATOM_NAME(e), ATOM_LEN(e))); } | |
269 | ||
270 | static PyObject *obarray_gmentryvalue(PyObject *me, void *e) | |
271 | { return (atom_pywrap(me, e)); } | |
272 | ||
273 | static const gmap_ops obarray_gmops = { | |
274 | sizeof(atom_iter), | |
275 | obarray_gmlookup, | |
276 | obarray_gmiterinit, | |
277 | obarray_gmiternext, | |
278 | obarray_gmentrykey, | |
279 | obarray_gmentryvalue | |
280 | }; | |
281 | ||
282 | static PyObject *obarray_pynew(PyTypeObject *cls, | |
283 | PyObject *arg, PyObject *kw) | |
284 | { | |
285 | obarray_pyobj *rc = 0; | |
286 | static const char *const kwlist[] = { 0 }; | |
287 | ||
288 | if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", KWLIST)) goto end; | |
289 | rc = PyObject_NEW(obarray_pyobj, cls); if (!rc) goto end; | |
290 | rc->gmops = &obarray_gmops; rc->wkls = 0; | |
291 | atom_createtable(&rc->tab); assoc_create(&rc->map); | |
292 | end: | |
293 | return ((PyObject *)rc); | |
294 | } | |
295 | ||
296 | static void obarray_pydealloc(PyObject *me) | |
297 | { | |
298 | assoc_iter it; | |
299 | struct obentry *e; | |
300 | ||
301 | ASSOC_MKITER(&it, OBARRAY_MAP(me)); | |
302 | for (;;) { | |
303 | ASSOC_NEXT(&it, e); if (!e) break; | |
304 | ATOM_A(e->aobj) = 0; | |
305 | Py_DECREF(ATOM_OAWK(e->aobj)); ATOM_OAWK(e->aobj) = 0; | |
306 | Py_DECREF(e->aobj); | |
307 | } | |
308 | assoc_destroy(OBARRAY_MAP(me)); | |
309 | atom_destroytable(OBARRAY_TAB(me)); | |
310 | FREEOBJ(me); | |
311 | } | |
312 | ||
313 | static PyObject *oameth_intern(PyObject *me, PyObject *arg) | |
314 | { | |
315 | char *p; | |
316 | Py_ssize_t sz; | |
317 | atom *a; | |
318 | PyObject *rc = 0; | |
319 | ||
320 | if (!PyArg_ParseTuple(arg, "s#:intern", &p, &sz)) goto end; | |
321 | a = atom_nintern(OBARRAY_TAB(me), p, sz); | |
322 | rc = atom_pywrap(me, a); | |
323 | end: | |
324 | return (rc); | |
325 | } | |
326 | ||
327 | static PyObject *oameth_gensym(PyObject *me) | |
328 | { return (atom_pywrap(me, atom_gensym(OBARRAY_TAB(me)))); } | |
329 | ||
330 | static const PyMappingMethods obarray_pymapping = { | |
331 | gmap_pysize, | |
332 | atom_pyintern, | |
333 | 0 | |
334 | }; | |
335 | ||
336 | static const PyMethodDef obarray_pymethods[] = { | |
337 | GMAP_ROMETHODS | |
338 | #define METHNAME(name) oameth_##name | |
339 | METH (intern, "ATAB.intern(STR) -> A: atom with given name") | |
340 | NAMETH(gensym, "ATAB.gensym() -> A: fresh uninterned atom") | |
341 | #undef METHNAME | |
342 | { 0 } | |
343 | }; | |
344 | ||
345 | static const PyTypeObject obarray_pytype_skel = { | |
346 | PyVarObject_HEAD_INIT(0, 0) /* Header */ | |
347 | "AtomTable", /* @tp_name@ */ | |
348 | sizeof(obarray_pyobj), /* @tp_basicsize@ */ | |
349 | 0, /* @tp_itemsize@ */ | |
350 | ||
351 | obarray_pydealloc, /* @tp_dealloc@ */ | |
352 | 0, /* @tp_print@ */ | |
353 | 0, /* @tp_getattr@ */ | |
354 | 0, /* @tp_setattr@ */ | |
355 | 0, /* @tp_compare@ */ | |
356 | 0, /* @tp_repr@ */ | |
357 | 0, /* @tp_as_number@ */ | |
358 | PYSEQUENCE(gmap), /* @tp_as_sequence@ */ | |
359 | PYMAPPING(obarray), /* @tp_as_mapping@ */ | |
360 | 0, /* @tp_hash@ */ | |
361 | 0, /* @tp_call@ */ | |
362 | 0, /* @tp_str@ */ | |
363 | 0, /* @tp_getattro@ */ | |
364 | 0, /* @tp_setattro@ */ | |
365 | 0, /* @tp_as_buffer@ */ | |
366 | Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ | |
367 | Py_TPFLAGS_BASETYPE, | |
368 | ||
369 | /* @tp_doc@ */ | |
370 | "AtomTable()", | |
371 | ||
372 | 0, /* @tp_traverse@ */ | |
373 | 0, /* @tp_clear@ */ | |
374 | 0, /* @tp_richcompare@ */ | |
375 | offsetof(obarray_pyobj, wkls), /* @tp_weaklistoffset@ */ | |
376 | gmap_pyiter, /* @tp_iter@ */ | |
377 | 0, /* @tp_iternext@ */ | |
378 | PYMETHODS(obarray), /* @tp_methods@ */ | |
379 | 0, /* @tp_members@ */ | |
380 | 0, /* @tp_getset@ */ | |
381 | 0, /* @tp_base@ */ | |
382 | 0, /* @tp_dict@ */ | |
383 | 0, /* @tp_descr_get@ */ | |
384 | 0, /* @tp_descr_set@ */ | |
385 | 0, /* @tp_dictoffset@ */ | |
386 | 0, /* @tp_init@ */ | |
387 | PyType_GenericAlloc, /* @tp_alloc@ */ | |
388 | obarray_pynew, /* @tp_new@ */ | |
389 | 0, /* @tp_free@ */ | |
390 | 0 /* @tp_is_gc@ */ | |
391 | }; | |
392 | ||
393 | /*----- Association tables ------------------------------------------------*/ | |
394 | ||
395 | typedef struct { | |
396 | GMAP_PYOBJ_HEAD | |
397 | assoc_table t; | |
398 | PyObject *oaobj; | |
399 | } assoc_pyobj; | |
400 | static PyTypeObject *assoc_pytype; | |
401 | #define ASSOC_PYCHECK(o) PyObject_TypeCheck((o), assoc_pytype) | |
402 | #define ASSOC_T(o) (&((assoc_pyobj *)(o))->t) | |
403 | #define ASSOC_OAOBJ(o) (((assoc_pyobj *)(o))->oaobj) | |
404 | ||
405 | struct aentry { | |
406 | assoc_base _b; | |
407 | PyObject *obj; | |
408 | }; | |
409 | ||
410 | static void *assoc_gmlookup(PyObject *me, PyObject *key, unsigned *f) | |
411 | { | |
412 | struct aentry *e = 0; | |
50845e59 | 413 | const char *p; |
81f68b64 MW |
414 | size_t sz; |
415 | atom *a; | |
416 | ||
417 | if (TEXT_CHECK(key)) { | |
418 | TEXT_PTRLEN(key, p, sz); | |
419 | a = atom_nintern(OBARRAY_TAB(ASSOC_OAOBJ(me)), p, sz); | |
420 | } else if (ATOM_PYCHECK(key)) { | |
421 | if (atom_check(key)) goto end; | |
422 | if (ATOM_OAOBJ(key) != ASSOC_OAOBJ(me)) | |
423 | VALERR("wrong atom table for assoc"); | |
424 | a = ATOM_A(key); | |
425 | } else | |
426 | TYERR("expected atom or string"); | |
427 | e = assoc_find(ASSOC_T(me), a, f ? sizeof(*e) : 0, f); | |
428 | if (!e) goto end; | |
429 | if (f && !*f) e->obj = 0; | |
430 | end: | |
431 | return (e); | |
432 | } | |
433 | ||
434 | static void assoc_gmiterinit(PyObject *me, void *i) | |
435 | { assoc_iter *it = i; ASSOC_MKITER(it, ASSOC_T(me)); } | |
436 | ||
437 | static void *assoc_gmiternext(PyObject *me, void *i) | |
438 | { assoc_iter *it = i; void *e; ASSOC_NEXT(it, e); return (e); } | |
439 | ||
440 | static PyObject *assoc_gmentrykey(PyObject *me, void *e) | |
441 | { return (atom_pywrap(ASSOC_OAOBJ(me), ASSOC_ATOM(e))); } | |
442 | ||
443 | static PyObject *assoc_gmentryvalue(PyObject *me, void *e) | |
444 | { struct aentry *ae = e; RETURN_OBJ(ae->obj); } | |
445 | ||
446 | static int assoc_gmsetentry(PyObject *me, void *e, PyObject *val) | |
447 | { | |
448 | struct aentry *ae = e; | |
449 | ||
450 | Py_XDECREF(ae->obj); Py_INCREF(val); ae->obj = val; | |
451 | return (0); | |
452 | } | |
453 | ||
454 | static int assoc_gmdelentry(PyObject *me, void *e) | |
455 | { assoc_remove(ASSOC_T(me), e); return (0); } | |
456 | ||
457 | static const gmap_ops assoc_gmops = { | |
458 | sizeof(atom_iter), | |
459 | assoc_gmlookup, | |
460 | assoc_gmiterinit, | |
461 | assoc_gmiternext, | |
462 | assoc_gmentrykey, | |
463 | assoc_gmentryvalue, | |
464 | assoc_gmsetentry, | |
465 | assoc_gmdelentry | |
466 | }; | |
467 | ||
468 | static PyObject *assoc_pynew(PyTypeObject *cls, PyObject *arg, PyObject *kw) | |
469 | { | |
470 | PyObject *oaobj = 0, *map = Py_None; | |
471 | assoc_pyobj *me = 0; | |
472 | ||
473 | if (!PyArg_ParseTuple(arg, "|OO!:new", &map, obarray_pytype, &oaobj)) | |
474 | { oaobj = 0; goto end; } | |
475 | if (oaobj) Py_INCREF(oaobj); | |
476 | else { oaobj = default_obarray(); if (!oaobj) goto end; } | |
477 | me = PyObject_NEW(assoc_pyobj, cls); | |
478 | me->gmops = &assoc_gmops; | |
479 | assoc_create(&me->t); | |
480 | me->oaobj = oaobj; oaobj = 0; | |
481 | if ((map != Py_None && gmap_pyupdate((PyObject *)me, map)) || | |
482 | gmap_pyupdate((PyObject *)me, kw)) | |
483 | { Py_DECREF(me); me = 0; goto end; } | |
484 | end: | |
485 | Py_XDECREF(oaobj); | |
486 | return ((PyObject *)me); | |
487 | } | |
488 | ||
489 | static void assoc_pydealloc(PyObject *me) | |
490 | { | |
491 | assoc_iter it; | |
492 | struct aentry *ae; | |
493 | ||
494 | ASSOC_MKITER(&it, ASSOC_T(me)); | |
495 | for (;;) { | |
496 | ASSOC_NEXT(&it, ae); if (!ae) break; | |
497 | Py_DECREF(ae->obj); | |
498 | } | |
499 | Py_DECREF(ASSOC_OAOBJ(me)); | |
500 | FREEOBJ(me); | |
501 | } | |
502 | ||
503 | static Py_ssize_t assoc_pysize(PyObject *me) | |
504 | { | |
505 | assoc_table *t = ASSOC_T(me); | |
506 | return (SYM_LIMIT(t->t.mask + 1) - t->load); | |
507 | } | |
508 | ||
509 | static const PyMemberDef assoc_pymembers[] = { | |
510 | #define MEMBERSTRUCT assoc_pyobj | |
511 | MEMRNM(table, T_OBJECT, oaobj, READONLY, | |
512 | "AS.table -> ATAB: home atom table") | |
513 | #undef MEMBERSTRUCT | |
514 | { 0 } | |
515 | }; | |
516 | ||
517 | static const PyMappingMethods assoc_pymapping = { | |
518 | assoc_pysize, | |
519 | gmap_pylookup, | |
520 | gmap_pystore | |
521 | }; | |
522 | ||
523 | static const PyTypeObject assoc_pytype_skel = { | |
524 | PyVarObject_HEAD_INIT(0, 0) /* Header */ | |
525 | "AssocTable", /* @tp_name@ */ | |
526 | sizeof(assoc_pyobj), /* @tp_basicsize@ */ | |
527 | 0, /* @tp_itemsize@ */ | |
528 | ||
529 | assoc_pydealloc, /* @tp_dealloc@ */ | |
530 | 0, /* @tp_print@ */ | |
531 | 0, /* @tp_getattr@ */ | |
532 | 0, /* @tp_setattr@ */ | |
533 | 0, /* @tp_compare@ */ | |
534 | 0, /* @tp_repr@ */ | |
535 | 0, /* @tp_as_number@ */ | |
536 | PYSEQUENCE(gmap), /* @tp_as_sequence@ */ | |
537 | PYMAPPING(assoc), /* @tp_as_mapping@ */ | |
538 | 0, /* @tp_hash@ */ | |
539 | 0, /* @tp_call@ */ | |
540 | 0, /* @tp_str@ */ | |
541 | 0, /* @tp_getattro@ */ | |
542 | 0, /* @tp_setattro@ */ | |
543 | 0, /* @tp_as_buffer@ */ | |
544 | Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ | |
545 | Py_TPFLAGS_BASETYPE, | |
546 | ||
547 | /* @tp_doc@ */ | |
548 | "AssocTable([MAP], [ATAB], [ATOM = VALUE, ...])", | |
549 | ||
550 | 0, /* @tp_traverse@ */ | |
551 | 0, /* @tp_clear@ */ | |
552 | 0, /* @tp_richcompare@ */ | |
553 | 0, /* @tp_weaklistoffset@ */ | |
554 | gmap_pyiter, /* @tp_iter@ */ | |
555 | 0, /* @tp_iternext@ */ | |
556 | PYMETHODS(gmap), /* @tp_methods@ */ | |
557 | PYMEMBERS(assoc), /* @tp_members@ */ | |
558 | 0, /* @tp_getset@ */ | |
559 | 0, /* @tp_base@ */ | |
560 | 0, /* @tp_dict@ */ | |
561 | 0, /* @tp_descr_get@ */ | |
562 | 0, /* @tp_descr_set@ */ | |
563 | 0, /* @tp_dictoffset@ */ | |
564 | 0, /* @tp_init@ */ | |
565 | PyType_GenericAlloc, /* @tp_alloc@ */ | |
566 | assoc_pynew, /* @tp_new@ */ | |
567 | 0, /* @tp_free@ */ | |
568 | 0 /* @tp_is_gc@ */ | |
569 | }; | |
570 | ||
571 | /*----- Main code ---------------------------------------------------------*/ | |
572 | ||
573 | void atom_pyinit(void) | |
574 | { | |
575 | INITTYPE(atom, root); | |
576 | INITTYPE(obarray, root); | |
577 | INITTYPE(assoc, root); | |
578 | } | |
579 | ||
580 | void atom_pyinsert(PyObject *mod) | |
581 | { | |
582 | INSERT("Atom", atom_pytype); | |
583 | INSERT("AtomTable", obarray_pytype); | |
584 | INSERT("AssocTable", assoc_pytype); | |
585 | }; | |
586 | ||
587 | /*----- That's all, folks -------------------------------------------------*/ |