omlish-cext 0.0.0.dev553__tar.gz → 0.0.0.dev554__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/PKG-INFO +2 -2
  2. omlish_cext-0.0.0.dev554/omlish/collections/fixed/_fixedmap.cc +1023 -0
  3. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish_cext.egg-info/PKG-INFO +2 -2
  4. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish_cext.egg-info/SOURCES.txt +1 -0
  5. omlish_cext-0.0.0.dev554/omlish_cext.egg-info/requires.txt +1 -0
  6. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/pyproject.toml +2 -2
  7. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/setup.py +5 -0
  8. omlish_cext-0.0.0.dev553/omlish_cext.egg-info/requires.txt +0 -1
  9. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/LICENSE +0 -0
  10. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/README.md +0 -0
  11. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/_check.cc +0 -0
  12. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/collections/hamt/_hamt.c +0 -0
  13. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/collections/treap/_treap.cc +0 -0
  14. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/dispatch/_dispatch.cc +0 -0
  15. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/dispatch/_methods.cc +0 -0
  16. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/lang/_asyncs.cc +0 -0
  17. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/lang/_comparison.cc +0 -0
  18. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/lang/imports/_capture.cc +0 -0
  19. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish/typedvalues/_collection.cc +0 -0
  20. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish_cext.egg-info/dependency_links.txt +0 -0
  21. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/omlish_cext.egg-info/top_level.txt +0 -0
  22. {omlish_cext-0.0.0.dev553 → omlish_cext-0.0.0.dev554}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish-cext
3
- Version: 0.0.0.dev553
3
+ Version: 0.0.0.dev554
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev553
17
+ Requires-Dist: omlish==0.0.0.dev554
18
18
  Dynamic: license-file
19
19
 
20
20
  # Overview
@@ -0,0 +1,1023 @@
1
+ // @omlish-cext
2
+ #define PY_SSIZE_T_CLEAN
3
+ #include <Python.h>
4
+ #include <structmember.h>
5
+ #include <atomic>
6
+
7
+ #define _MODULE_NAME "_fixedmap"
8
+ #define _PACKAGE_NAME "omlish.collections.fixed"
9
+ #define _MODULE_FULL_NAME _PACKAGE_NAME "." _MODULE_NAME
10
+
11
+ //
12
+ // Types & Structs
13
+ //
14
+
15
+ struct FixedMapKeysObject {
16
+ PyObject_HEAD
17
+ PyObject* keys_tuple;
18
+ PyObject* key_indexes;
19
+ Py_hash_t* key_hashes;
20
+ Py_ssize_t* table;
21
+ Py_ssize_t table_size;
22
+ Py_hash_t hash;
23
+ };
24
+
25
+ struct FixedMapObject {
26
+ PyObject_HEAD
27
+ FixedMapKeysObject* keys;
28
+ PyObject* values_tuple;
29
+ Py_hash_t hash_cache;
30
+ };
31
+
32
+ // Views for FixedMap
33
+ struct FixedMapViewObject {
34
+ PyObject_HEAD
35
+ FixedMapObject* map;
36
+ };
37
+
38
+ // Iterator modes
39
+ enum IterMode {
40
+ ITER_KEYS_VALUES = 0,
41
+ ITER_KEYS_ITEMS = 1,
42
+ ITER_MAP_ITEMS = 2
43
+ };
44
+
45
+ struct FixedMapIterObject {
46
+ PyObject_HEAD
47
+ PyObject* source;
48
+ int mode;
49
+ Py_ssize_t index;
50
+ };
51
+
52
+ typedef struct fixedmap_state {
53
+ PyTypeObject* FixedMapKeys_Type;
54
+ PyTypeObject* FixedMap_Type;
55
+ PyTypeObject* FixedMapIter_Type;
56
+ PyTypeObject* FixedMapValuesView_Type;
57
+ PyTypeObject* FixedMapItemsView_Type;
58
+ } fixedmap_state;
59
+
60
+ static inline fixedmap_state* get_module_state(PyObject* module) {
61
+ void* state = PyModule_GetState(module);
62
+ assert(state != NULL);
63
+ return (fixedmap_state*)state;
64
+ }
65
+
66
+ static inline fixedmap_state* get_type_state(PyTypeObject* type) {
67
+ PyTypeObject* current = type;
68
+ while (current != NULL) {
69
+ void* state = PyType_GetModuleState(current);
70
+ if (state != NULL) {
71
+ return (fixedmap_state*)state;
72
+ }
73
+ current = current->tp_base;
74
+ }
75
+ Py_FatalError("_fixedmap state not found in type hierarchy");
76
+ return NULL;
77
+ }
78
+
79
+ //
80
+ // Utilities
81
+ //
82
+
83
+ static int dummy_init(PyObject* self, PyObject* args, PyObject* kwds) {
84
+ // Swallow the arguments since everything is handled in tp_new
85
+ return 0;
86
+ }
87
+
88
+ //
89
+ // FixedMapIter Implementation
90
+ //
91
+
92
+ static int FixedMapIter_traverse(FixedMapIterObject* self, visitproc visit, void* arg) {
93
+ Py_VISIT(self->source);
94
+ return 0;
95
+ }
96
+
97
+ static int FixedMapIter_clear(FixedMapIterObject* self) {
98
+ Py_CLEAR(self->source);
99
+ return 0;
100
+ }
101
+
102
+ static void FixedMapIter_dealloc(FixedMapIterObject* self) {
103
+ PyObject_GC_UnTrack(self);
104
+ FixedMapIter_clear(self);
105
+ Py_TYPE(self)->tp_free((PyObject*)self);
106
+ }
107
+
108
+ static PyObject* FixedMapIter_iternext(FixedMapIterObject* self) {
109
+ std::atomic_ref<Py_ssize_t> index_ref(self->index);
110
+ Py_ssize_t i = index_ref.fetch_add(1, std::memory_order_relaxed);
111
+
112
+ if (self->mode == ITER_KEYS_VALUES || self->mode == ITER_KEYS_ITEMS) {
113
+ FixedMapKeysObject* keys = (FixedMapKeysObject*)self->source;
114
+ if (i >= PyTuple_GET_SIZE(keys->keys_tuple)) {
115
+ return NULL;
116
+ }
117
+
118
+ if (self->mode == ITER_KEYS_VALUES) {
119
+ return PyLong_FromSsize_t(i);
120
+ } else { // ITER_KEYS_ITEMS
121
+ PyObject* key = PyTuple_GET_ITEM(keys->keys_tuple, i);
122
+ PyObject* val = PyLong_FromSsize_t(i);
123
+ if (!val) {
124
+ return NULL;
125
+ }
126
+ PyObject* tuple = PyTuple_Pack(2, key, val);
127
+ Py_DECREF(val);
128
+ return tuple;
129
+ }
130
+ } else {
131
+ FixedMapObject* map = (FixedMapObject*)self->source;
132
+ if (i >= PyTuple_GET_SIZE(map->values_tuple)) {
133
+ return NULL;
134
+ }
135
+
136
+ PyObject* key = PyTuple_GET_ITEM(map->keys->keys_tuple, i);
137
+ PyObject* val = PyTuple_GET_ITEM(map->values_tuple, i);
138
+ return PyTuple_Pack(2, key, val);
139
+ }
140
+ }
141
+
142
+ static PyType_Slot FixedMapIter_slots[] = {
143
+ {Py_tp_dealloc, (void*)FixedMapIter_dealloc},
144
+ {Py_tp_traverse, (void*)FixedMapIter_traverse},
145
+ {Py_tp_clear, (void*)FixedMapIter_clear},
146
+ {Py_tp_iter, (void*)PyObject_SelfIter},
147
+ {Py_tp_iternext, (void*)FixedMapIter_iternext},
148
+ {0, NULL}
149
+ };
150
+
151
+ static PyType_Spec FixedMapIter_spec = {
152
+ .name = _MODULE_FULL_NAME ".FixedMapIter",
153
+ .basicsize = sizeof(FixedMapIterObject),
154
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
155
+ .slots = FixedMapIter_slots,
156
+ };
157
+
158
+ static PyObject* new_iterator(PyObject* source, int mode, fixedmap_state* state) {
159
+ FixedMapIterObject* iter = PyObject_GC_New(FixedMapIterObject, state->FixedMapIter_Type);
160
+ if (!iter) {
161
+ return NULL;
162
+ }
163
+ iter->source = Py_NewRef(source);
164
+ iter->mode = mode;
165
+ iter->index = 0;
166
+ PyObject_GC_Track(iter);
167
+ return (PyObject*)iter;
168
+ }
169
+
170
+ //
171
+ // View Implementations (ValuesView and ItemsView)
172
+ //
173
+
174
+ static int FixedMapView_traverse(FixedMapViewObject* self, visitproc visit, void* arg) {
175
+ Py_VISIT(self->map);
176
+ return 0;
177
+ }
178
+
179
+ static int FixedMapView_clear(FixedMapViewObject* self) {
180
+ Py_CLEAR(self->map);
181
+ return 0;
182
+ }
183
+
184
+ static void FixedMapView_dealloc(FixedMapViewObject* self) {
185
+ PyObject_GC_UnTrack(self);
186
+ FixedMapView_clear(self);
187
+ Py_TYPE(self)->tp_free((PyObject*)self);
188
+ }
189
+
190
+ static Py_ssize_t FixedMapView_len(FixedMapViewObject* self) {
191
+ return PyTuple_GET_SIZE(self->map->values_tuple);
192
+ }
193
+
194
+ static PyObject* FixedMapValuesView_iter(FixedMapViewObject* self) {
195
+ return PyObject_GetIter(self->map->values_tuple);
196
+ }
197
+
198
+ static PyObject* FixedMapItemsView_iter(FixedMapViewObject* self) {
199
+ fixedmap_state* state = get_type_state(Py_TYPE(self));
200
+ return new_iterator((PyObject*)self->map, ITER_MAP_ITEMS, state);
201
+ }
202
+
203
+ static PyType_Slot FixedMapValuesView_slots[] = {
204
+ {Py_tp_dealloc, (void*)FixedMapView_dealloc},
205
+ {Py_tp_traverse, (void*)FixedMapView_traverse},
206
+ {Py_tp_clear, (void*)FixedMapView_clear},
207
+ {Py_tp_iter, (void*)FixedMapValuesView_iter},
208
+ {Py_mp_length, (void*)FixedMapView_len},
209
+ {0, NULL}
210
+ };
211
+
212
+ static PyType_Spec FixedMapValuesView_spec = {
213
+ .name = _MODULE_FULL_NAME ".FixedMapValuesView",
214
+ .basicsize = sizeof(FixedMapViewObject),
215
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
216
+ .slots = FixedMapValuesView_slots,
217
+ };
218
+
219
+ static PyType_Slot FixedMapItemsView_slots[] = {
220
+ {Py_tp_dealloc, (void*)FixedMapView_dealloc},
221
+ {Py_tp_traverse, (void*)FixedMapView_traverse},
222
+ {Py_tp_clear, (void*)FixedMapView_clear},
223
+ {Py_tp_iter, (void*)FixedMapItemsView_iter},
224
+ {Py_mp_length, (void*)FixedMapView_len},
225
+ {0, NULL}
226
+ };
227
+
228
+ static PyType_Spec FixedMapItemsView_spec = {
229
+ .name = _MODULE_FULL_NAME ".FixedMapItemsView",
230
+ .basicsize = sizeof(FixedMapViewObject),
231
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
232
+ .slots = FixedMapItemsView_slots,
233
+ };
234
+
235
+ static PyObject* new_view(FixedMapObject* map, PyTypeObject* type) {
236
+ FixedMapViewObject* view = PyObject_GC_New(FixedMapViewObject, type);
237
+ if (!view) {
238
+ return NULL;
239
+ }
240
+ view->map = (FixedMapObject*)Py_NewRef(map);
241
+ PyObject_GC_Track(view);
242
+ return (PyObject*)view;
243
+ }
244
+
245
+ //
246
+ // FixedMapKeys Implementation
247
+ //
248
+
249
+ static int FixedMapKeys_traverse(FixedMapKeysObject* self, visitproc visit, void* arg) {
250
+ Py_VISIT(self->keys_tuple);
251
+ Py_VISIT(self->key_indexes);
252
+ return 0;
253
+ }
254
+
255
+ static int FixedMapKeys_clear(FixedMapKeysObject* self) {
256
+ Py_CLEAR(self->keys_tuple);
257
+ Py_CLEAR(self->key_indexes);
258
+ PyMem_Free(self->key_hashes);
259
+ self->key_hashes = NULL;
260
+ PyMem_Free(self->table);
261
+ self->table = NULL;
262
+ self->table_size = 0;
263
+ return 0;
264
+ }
265
+
266
+ static void FixedMapKeys_dealloc(FixedMapKeysObject* self) {
267
+ PyObject_GC_UnTrack(self);
268
+ FixedMapKeys_clear(self);
269
+ Py_TYPE(self)->tp_free((PyObject*)self);
270
+ }
271
+
272
+ static int FixedMapKeys_lookup_index(FixedMapKeysObject* self, PyObject* key, Py_ssize_t* out_idx) {
273
+ Py_ssize_t size = PyTuple_GET_SIZE(self->keys_tuple);
274
+ if (size == 0) {
275
+ return 0;
276
+ }
277
+
278
+ if (!self->table || !self->key_hashes || self->table_size <= 0) {
279
+ PyErr_SetString(PyExc_RuntimeError, "corrupt FixedMapKeys table");
280
+ return -1;
281
+ }
282
+
283
+ Py_hash_t h = PyObject_Hash(key);
284
+ if (h == -1) {
285
+ return -1;
286
+ }
287
+
288
+ Py_ssize_t mask = self->table_size - 1;
289
+ Py_ssize_t slot = (Py_ssize_t)((Py_uhash_t)h & (Py_uhash_t)mask);
290
+ for (;;) {
291
+ Py_ssize_t idx = self->table[slot];
292
+ if (idx == -1) {
293
+ return 0;
294
+ }
295
+
296
+ if (idx < 0 || idx >= size) {
297
+ PyErr_SetString(PyExc_RuntimeError, "corrupt FixedMapKeys table");
298
+ return -1;
299
+ }
300
+
301
+ PyObject* stored_key = PyTuple_GET_ITEM(self->keys_tuple, idx);
302
+ if (stored_key == key) {
303
+ *out_idx = idx;
304
+ return 1;
305
+ }
306
+
307
+ if (self->key_hashes[idx] == h) {
308
+ int eq = PyObject_RichCompareBool(stored_key, key, Py_EQ);
309
+ if (eq < 0) {
310
+ return -1;
311
+ }
312
+ if (eq > 0) {
313
+ *out_idx = idx;
314
+ return 1;
315
+ }
316
+ }
317
+
318
+ slot = (slot + 1) & mask;
319
+ }
320
+ }
321
+
322
+ static PyObject* FixedMapKeys_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
323
+ PyObject* keys_arg;
324
+ if (!PyArg_ParseTuple(args, "O", &keys_arg)) {
325
+ return NULL;
326
+ }
327
+
328
+ FixedMapKeysObject* self = (FixedMapKeysObject*)type->tp_alloc(type, 0);
329
+ if (!self) {
330
+ return NULL;
331
+ }
332
+
333
+ self->keys_tuple = PySequence_Tuple(keys_arg);
334
+ if (!self->keys_tuple) {
335
+ Py_DECREF(self);
336
+ return NULL;
337
+ }
338
+
339
+ Py_ssize_t size = PyTuple_GET_SIZE(self->keys_tuple);
340
+ self->table_size = 1;
341
+ while (self->table_size < size * 2) {
342
+ self->table_size <<= 1;
343
+ }
344
+
345
+ if (size > 0) {
346
+ self->key_hashes = PyMem_New(Py_hash_t, size);
347
+ if (!self->key_hashes) {
348
+ PyErr_NoMemory();
349
+ Py_DECREF(self);
350
+ return NULL;
351
+ }
352
+ }
353
+
354
+ self->table = PyMem_New(Py_ssize_t, self->table_size);
355
+ if (!self->table) {
356
+ PyErr_NoMemory();
357
+ Py_DECREF(self);
358
+ return NULL;
359
+ }
360
+ for (Py_ssize_t i = 0; i < self->table_size; i++) {
361
+ self->table[i] = -1;
362
+ }
363
+
364
+ PyObject* seen = PyDict_New();
365
+ if (!seen) {
366
+ Py_DECREF(self);
367
+ return NULL;
368
+ }
369
+
370
+ Py_ssize_t mask = self->table_size - 1;
371
+ for (Py_ssize_t i = 0; i < size; i++) {
372
+ PyObject* key = PyTuple_GET_ITEM(self->keys_tuple, i);
373
+
374
+ Py_hash_t h = PyObject_Hash(key);
375
+ if (h == -1) {
376
+ Py_DECREF(seen);
377
+ Py_DECREF(self);
378
+ return NULL;
379
+ }
380
+
381
+ int contains = PyDict_Contains(seen, key);
382
+ if (contains == -1 || contains == 1) {
383
+ if (contains == 1) {
384
+ PyErr_SetObject(PyExc_KeyError, key);
385
+ }
386
+ Py_DECREF(seen);
387
+ Py_DECREF(self);
388
+ return NULL;
389
+ }
390
+
391
+ PyObject* val = PyLong_FromSsize_t(i);
392
+ if (!val) {
393
+ Py_DECREF(seen);
394
+ Py_DECREF(self);
395
+ return NULL;
396
+ }
397
+ if (PyDict_SetItem(seen, key, val) < 0) {
398
+ Py_DECREF(val);
399
+ Py_DECREF(seen);
400
+ Py_DECREF(self);
401
+ return NULL;
402
+ }
403
+ Py_DECREF(val);
404
+
405
+ self->key_hashes[i] = h;
406
+
407
+ Py_ssize_t slot = (Py_ssize_t)((Py_uhash_t)h & (Py_uhash_t)mask);
408
+ while (self->table[slot] != -1) {
409
+ slot = (slot + 1) & mask;
410
+ }
411
+ self->table[slot] = i;
412
+ }
413
+
414
+ self->key_indexes = seen;
415
+
416
+ self->hash = PyObject_Hash(self->keys_tuple);
417
+ if (self->hash == -1) {
418
+ Py_DECREF(self);
419
+ return NULL;
420
+ }
421
+
422
+ if (!PyObject_GC_IsTracked((PyObject*)self)) {
423
+ PyObject_GC_Track(self);
424
+ }
425
+ return (PyObject*)self;
426
+ }
427
+
428
+ static Py_ssize_t FixedMapKeys_len(FixedMapKeysObject* self) {
429
+ return PyTuple_GET_SIZE(self->keys_tuple);
430
+ }
431
+
432
+ static PyObject* FixedMapKeys_getitem(FixedMapKeysObject* self, PyObject* key) {
433
+ Py_ssize_t idx;
434
+ int rc = FixedMapKeys_lookup_index(self, key, &idx);
435
+ if (rc < 0) {
436
+ return NULL;
437
+ }
438
+ if (!rc) {
439
+ PyErr_SetObject(PyExc_KeyError, key);
440
+ return NULL;
441
+ }
442
+ return PyLong_FromSsize_t(idx);
443
+ }
444
+
445
+ static PyObject* FixedMapKeys_get(FixedMapKeysObject* self, PyObject* args) {
446
+ PyObject *key = Py_None;
447
+ PyObject *def = Py_None;
448
+ if (!PyArg_ParseTuple(args, "O|O", &key, &def)) {
449
+ return NULL;
450
+ }
451
+
452
+ Py_ssize_t idx;
453
+ int rc = FixedMapKeys_lookup_index(self, key, &idx);
454
+ if (rc < 0) {
455
+ return NULL;
456
+ }
457
+ if (!rc) {
458
+ return Py_NewRef(def);
459
+ }
460
+ return PyLong_FromSsize_t(idx);
461
+ }
462
+
463
+ static Py_hash_t FixedMapKeys_hash(FixedMapKeysObject* self) {
464
+ return self->hash;
465
+ }
466
+
467
+ static PyObject* FixedMapKeys_richcompare(PyObject* a, PyObject* b, int op) {
468
+ if (op != Py_EQ && op != Py_NE) {
469
+ Py_RETURN_NOTIMPLEMENTED;
470
+ }
471
+ if (a == b) {
472
+ if (op == Py_EQ) {
473
+ Py_RETURN_TRUE;
474
+ } else {
475
+ Py_RETURN_FALSE;
476
+ }
477
+ }
478
+ fixedmap_state* state = get_type_state(Py_TYPE(a));
479
+ if (!PyObject_TypeCheck(a, state->FixedMapKeys_Type)) {
480
+ Py_RETURN_NOTIMPLEMENTED;
481
+ }
482
+ if (PyObject_TypeCheck(b, state->FixedMapKeys_Type)) {
483
+ return PyObject_RichCompare(((FixedMapKeysObject*)a)->keys_tuple, ((FixedMapKeysObject*)b)->keys_tuple, op);
484
+ }
485
+ Py_RETURN_NOTIMPLEMENTED;
486
+ }
487
+
488
+ static PyObject* FixedMapKeys_keys(FixedMapKeysObject* self, PyObject* Py_UNUSED(ignored)) {
489
+ return PyObject_CallMethod(self->key_indexes, "keys", NULL);
490
+ }
491
+
492
+ static PyObject* FixedMapKeys_values(FixedMapKeysObject* self, PyObject* Py_UNUSED(ignored)) {
493
+ return PyObject_CallMethod(self->key_indexes, "values", NULL);
494
+ }
495
+
496
+ static PyObject* FixedMapKeys_items(FixedMapKeysObject* self, PyObject* Py_UNUSED(ignored)) {
497
+ return PyObject_CallMethod(self->key_indexes, "items", NULL);
498
+ }
499
+
500
+ static PyMethodDef FixedMapKeys_methods[] = {
501
+ {"get", (PyCFunction)FixedMapKeys_get, METH_VARARGS, NULL},
502
+ {"keys", (PyCFunction)FixedMapKeys_keys, METH_NOARGS, NULL},
503
+ {"values", (PyCFunction)FixedMapKeys_values, METH_NOARGS, NULL},
504
+ {"items", (PyCFunction)FixedMapKeys_items, METH_NOARGS, NULL},
505
+ {NULL, NULL, 0, NULL}
506
+ };
507
+
508
+ static PyObject* FixedMapKeys_get_fixed_keys(FixedMapKeysObject* self, void* Py_UNUSED(closure)) {
509
+ return Py_NewRef(self->keys_tuple);
510
+ }
511
+
512
+ static PyObject* FixedMapKeys_get_debug(FixedMapKeysObject* self, void* Py_UNUSED(closure)) {
513
+ return PyDictProxy_New(self->key_indexes);
514
+ }
515
+
516
+ static PyObject* FixedMapKeys_repr(FixedMapKeysObject* self) {
517
+ PyObject* name = PyType_GetName(Py_TYPE(self));
518
+ if (!name) {
519
+ return NULL;
520
+ }
521
+ PyObject *repr = PyUnicode_FromFormat("%U(%R)", name, self->key_indexes);
522
+ Py_DECREF(name);
523
+ return repr;
524
+ }
525
+
526
+ static PyObject* FixedMapKeys_iter(FixedMapKeysObject* self) {
527
+ return PyObject_GetIter(self->keys_tuple);
528
+ }
529
+
530
+ static int FixedMapKeys_contains(FixedMapKeysObject* self, PyObject* key) {
531
+ Py_ssize_t idx;
532
+ int rc = FixedMapKeys_lookup_index(self, key, &idx);
533
+ if (rc < 0) {
534
+ return -1;
535
+ }
536
+ return rc > 0;
537
+ }
538
+
539
+ static PyGetSetDef FixedMapKeys_getsets[] = {
540
+ {"fixed_keys", (getter)FixedMapKeys_get_fixed_keys, NULL, NULL, NULL},
541
+ {"debug", (getter)FixedMapKeys_get_debug, NULL, NULL, NULL},
542
+ {NULL, NULL, NULL, NULL, NULL}
543
+ };
544
+
545
+ static PyType_Slot FixedMapKeys_slots[] = {
546
+ {Py_tp_dealloc, (void*)FixedMapKeys_dealloc},
547
+ {Py_tp_traverse, (void*)FixedMapKeys_traverse},
548
+ {Py_tp_clear, (void*)FixedMapKeys_clear},
549
+ {Py_tp_hash, (void*)FixedMapKeys_hash},
550
+ {Py_tp_richcompare, (void*)FixedMapKeys_richcompare},
551
+ {Py_tp_repr, (void*)FixedMapKeys_repr},
552
+ {Py_tp_iter, (void*)FixedMapKeys_iter},
553
+ {Py_tp_methods, (void*)FixedMapKeys_methods},
554
+ {Py_tp_getset, (void*)FixedMapKeys_getsets},
555
+ {Py_mp_length, (void*)FixedMapKeys_len},
556
+ {Py_mp_subscript, (void*)FixedMapKeys_getitem},
557
+ {Py_sq_contains, (void*)FixedMapKeys_contains},
558
+ {Py_tp_new, (void*)FixedMapKeys_new},
559
+ {Py_tp_init, (void*)dummy_init},
560
+ {0, NULL}
561
+ };
562
+
563
+ static PyType_Spec FixedMapKeys_spec = {
564
+ .name = _MODULE_FULL_NAME ".FixedMapKeys",
565
+ .basicsize = sizeof(FixedMapKeysObject),
566
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
567
+ .slots = FixedMapKeys_slots,
568
+ };
569
+
570
+ //
571
+ // FixedMap Implementation
572
+ //
573
+
574
+ static int FixedMap_traverse(FixedMapObject* self, visitproc visit, void* arg) {
575
+ Py_VISIT(self->keys);
576
+ Py_VISIT(self->values_tuple);
577
+ return 0;
578
+ }
579
+
580
+ static int FixedMap_clear(FixedMapObject* self) {
581
+ Py_CLEAR(self->keys);
582
+ Py_CLEAR(self->values_tuple);
583
+ return 0;
584
+ }
585
+
586
+ static void FixedMap_dealloc(FixedMapObject* self) {
587
+ PyObject_GC_UnTrack(self);
588
+ FixedMap_clear(self);
589
+ Py_TYPE(self)->tp_free((PyObject*)self);
590
+ }
591
+
592
+ static PyObject* FixedMap_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
593
+ PyObject* keys_arg;
594
+ PyObject* values_arg;
595
+
596
+ fixedmap_state* state = get_type_state(type);
597
+
598
+ if (!PyArg_ParseTuple(args, "O!O", state->FixedMapKeys_Type, &keys_arg, &values_arg)) {
599
+ return NULL;
600
+ }
601
+
602
+ FixedMapObject* self = (FixedMapObject*)type->tp_alloc(type, 0);
603
+ if (!self) {
604
+ return NULL;
605
+ }
606
+
607
+ self->values_tuple = PyTuple_CheckExact(values_arg) ? Py_NewRef(values_arg) : PySequence_Tuple(values_arg);
608
+ if (!self->values_tuple) {
609
+ Py_DECREF(self);
610
+ return NULL;
611
+ }
612
+
613
+ FixedMapKeysObject* keys_obj = (FixedMapKeysObject*)keys_arg;
614
+ if (PyTuple_GET_SIZE(self->values_tuple) != PyTuple_GET_SIZE(keys_obj->keys_tuple)) {
615
+ PyErr_SetString(PyExc_ValueError, "length mismatch");
616
+ Py_DECREF(self);
617
+ return NULL;
618
+ }
619
+
620
+ self->keys = (FixedMapKeysObject*)Py_NewRef(keys_obj);
621
+ self->hash_cache = 0;
622
+ if (!PyObject_GC_IsTracked((PyObject*)self)) {
623
+ PyObject_GC_Track(self);
624
+ }
625
+ return (PyObject*)self;
626
+ }
627
+
628
+ static Py_hash_t FixedMap_hash(FixedMapObject* self) {
629
+ std::atomic_ref<Py_hash_t> cache(self->hash_cache);
630
+ Py_hash_t h = cache.load(std::memory_order_acquire);
631
+ if (h != 0) {
632
+ return h;
633
+ }
634
+ if (Py_EnterRecursiveCall(" in FixedMap hash")) {
635
+ return -1;
636
+ }
637
+
638
+ Py_hash_t kh = PyObject_Hash((PyObject*)self->keys);
639
+ if (kh == -1) {
640
+ Py_LeaveRecursiveCall();
641
+ return -1;
642
+ }
643
+
644
+ Py_ssize_t size = PyTuple_GET_SIZE(self->values_tuple);
645
+ Py_hash_t res = 0x9e3779b9;
646
+ for (Py_ssize_t i = 0; i < size; i++) {
647
+ Py_hash_t vh = PyObject_Hash(PyTuple_GET_ITEM(self->values_tuple, i));
648
+ if (vh == -1) {
649
+ Py_LeaveRecursiveCall();
650
+ return -1;
651
+ }
652
+ res = (res ^ vh) * 1000003 + (82520L + size + size + 2);
653
+ }
654
+ res ^= kh;
655
+ Py_LeaveRecursiveCall();
656
+ if (res == -1) {
657
+ res = -2;
658
+ } else if (res == 0) {
659
+ res = 1;
660
+ }
661
+ cache.store(res, std::memory_order_release);
662
+ return res;
663
+ }
664
+
665
+ static PyObject* FixedMap_richcompare(PyObject* a, PyObject* b, int op) {
666
+ if (op != Py_EQ && op != Py_NE) {
667
+ Py_RETURN_NOTIMPLEMENTED;
668
+ }
669
+ if (a == b) {
670
+ if (op == Py_EQ) {
671
+ Py_RETURN_TRUE;
672
+ } else {
673
+ Py_RETURN_FALSE;
674
+ }
675
+ }
676
+
677
+ if (Py_EnterRecursiveCall(" in FixedMap richcompare")) {
678
+ return NULL;
679
+ }
680
+
681
+ fixedmap_state* state = get_type_state(Py_TYPE(a));
682
+ if (PyObject_TypeCheck(b, state->FixedMap_Type)) {
683
+ FixedMapObject *ma = (FixedMapObject*)a, *mb = (FixedMapObject*)b;
684
+ if (PyTuple_GET_SIZE(ma->values_tuple) != PyTuple_GET_SIZE(mb->values_tuple)) {
685
+ Py_LeaveRecursiveCall();
686
+ if (op == Py_EQ) {
687
+ Py_RETURN_FALSE;
688
+ } else {
689
+ Py_RETURN_TRUE;
690
+ }
691
+ }
692
+ if (ma->keys == mb->keys) {
693
+ PyObject* ret = PyObject_RichCompare(ma->values_tuple, mb->values_tuple, op);
694
+ Py_LeaveRecursiveCall();
695
+ return ret;
696
+ }
697
+ }
698
+
699
+ Py_ssize_t al = PyObject_Length(a);
700
+ if (al < 0) {
701
+ PyErr_Clear();
702
+ }
703
+ Py_ssize_t bl = PyObject_Length(b);
704
+ if (bl < 0) {
705
+ PyErr_Clear();
706
+ }
707
+ if (al >= 0 && bl >= 0 && al != bl) {
708
+ Py_LeaveRecursiveCall();
709
+ if (op == Py_EQ) {
710
+ Py_RETURN_FALSE;
711
+ } else {
712
+ Py_RETURN_TRUE;
713
+ }
714
+ }
715
+
716
+ PyObject *it = PyObject_GetIter(a), *k;
717
+ if (!it) {
718
+ PyErr_Clear();
719
+ Py_LeaveRecursiveCall();
720
+ Py_RETURN_NOTIMPLEMENTED;
721
+ }
722
+ while ((k = PyIter_Next(it))) {
723
+ PyObject *va = PyObject_GetItem(a, k), *vb = PyObject_GetItem(b, k);
724
+ if (!va || !vb) {
725
+ Py_XDECREF(va);
726
+ Py_XDECREF(vb);
727
+ Py_DECREF(k);
728
+ Py_DECREF(it);
729
+ if (!vb && PyErr_ExceptionMatches(PyExc_KeyError)) {
730
+ PyErr_Clear();
731
+ Py_LeaveRecursiveCall();
732
+ if (op == Py_EQ) {
733
+ Py_RETURN_FALSE;
734
+ } else {
735
+ Py_RETURN_TRUE;
736
+ }
737
+ }
738
+ Py_LeaveRecursiveCall();
739
+ return NULL;
740
+ }
741
+ int eq = PyObject_RichCompareBool(va, vb, Py_EQ);
742
+ Py_DECREF(va);
743
+ Py_DECREF(vb);
744
+ Py_DECREF(k);
745
+ if (eq <= 0) {
746
+ Py_DECREF(it);
747
+ if (eq < 0) {
748
+ Py_LeaveRecursiveCall();
749
+ return NULL;
750
+ } else {
751
+ Py_LeaveRecursiveCall();
752
+ if (op == Py_EQ) {
753
+ Py_RETURN_FALSE;
754
+ } else {
755
+ Py_RETURN_TRUE;
756
+ }
757
+ }
758
+ }
759
+ }
760
+ Py_DECREF(it);
761
+ if (PyErr_Occurred()) {
762
+ Py_LeaveRecursiveCall();
763
+ return NULL;
764
+ }
765
+ Py_LeaveRecursiveCall();
766
+ if (op == Py_EQ) {
767
+ Py_RETURN_TRUE;
768
+ } else {
769
+ Py_RETURN_FALSE;
770
+ }
771
+ }
772
+
773
+ static PyObject* FixedMap_getitem(FixedMapObject* self, PyObject* key) {
774
+ Py_ssize_t idx;
775
+ int rc = FixedMapKeys_lookup_index(self->keys, key, &idx);
776
+ if (rc < 0) {
777
+ return NULL;
778
+ }
779
+ if (!rc) {
780
+ PyErr_SetObject(PyExc_KeyError, key);
781
+ return NULL;
782
+ }
783
+
784
+ if (idx < 0 || idx >= PyTuple_GET_SIZE(self->values_tuple)) {
785
+ PyErr_SetString(PyExc_RuntimeError, "corrupt FixedMap index");
786
+ return NULL;
787
+ }
788
+
789
+ return Py_NewRef(PyTuple_GET_ITEM(self->values_tuple, idx));
790
+ }
791
+
792
+ static PyObject* FixedMap_get(FixedMapObject* self, PyObject* args) {
793
+ PyObject *key, *def = Py_None;
794
+ if (!PyArg_ParseTuple(args, "O|O", &key, &def)) {
795
+ return NULL;
796
+ }
797
+
798
+ Py_ssize_t idx;
799
+ int rc = FixedMapKeys_lookup_index(self->keys, key, &idx);
800
+ if (rc < 0) {
801
+ return NULL;
802
+ }
803
+ if (!rc) {
804
+ return Py_NewRef(def);
805
+ }
806
+
807
+ if (idx < 0 || idx >= PyTuple_GET_SIZE(self->values_tuple)) {
808
+ PyErr_SetString(PyExc_RuntimeError, "corrupt FixedMap index");
809
+ return NULL;
810
+ }
811
+
812
+ return Py_NewRef(PyTuple_GET_ITEM(self->values_tuple, idx));
813
+ }
814
+
815
+ static PyObject* FixedMap_get_fixed_keys(FixedMapObject* self, void* closure) {
816
+ return Py_NewRef(self->keys);
817
+ }
818
+
819
+ static PyObject* FixedMap_get_fixed_values(FixedMapObject* self, void* closure) {
820
+ return Py_NewRef(self->values_tuple);
821
+ }
822
+
823
+ static PyObject* FixedMap_get_debug(FixedMapObject* self, void* closure) {
824
+ PyObject* d = PyDict_New();
825
+ if (!d) {
826
+ return NULL;
827
+ }
828
+
829
+ Py_ssize_t size = PyTuple_GET_SIZE(self->values_tuple);
830
+ for (Py_ssize_t i = 0; i < size; i++) {
831
+ PyObject* k = PyTuple_GET_ITEM(self->keys->keys_tuple, i);
832
+ PyObject* v = PyTuple_GET_ITEM(self->values_tuple, i);
833
+ if (PyDict_SetItem(d, k, v) < 0) {
834
+ Py_DECREF(d);
835
+ return NULL;
836
+ }
837
+ }
838
+ return d;
839
+ }
840
+
841
+ static PyObject* FixedMap_keys(FixedMapObject* self, PyObject* Py_UNUSED(ignored)) {
842
+ return Py_NewRef(self->keys);
843
+ }
844
+
845
+ static PyObject* FixedMap_values(FixedMapObject* self, PyObject* Py_UNUSED(ignored)) {
846
+ return new_view(self, get_type_state(Py_TYPE(self))->FixedMapValuesView_Type);
847
+ }
848
+
849
+ static PyObject* FixedMap_items(FixedMapObject* self, PyObject* Py_UNUSED(ignored)) {
850
+ return new_view(self, get_type_state(Py_TYPE(self))->FixedMapItemsView_Type);
851
+ }
852
+
853
+ static PyObject* FixedMap_itervalues(FixedMapObject* self, PyObject* Py_UNUSED(ignored)) {
854
+ return PyObject_GetIter(self->values_tuple);
855
+ }
856
+
857
+ static PyObject* FixedMap_iteritems(FixedMapObject* self, PyObject* Py_UNUSED(ignored)) {
858
+ return new_iterator((PyObject*)self, ITER_MAP_ITEMS, get_type_state(Py_TYPE(self)));
859
+ }
860
+
861
+ static PyObject* FixedMap_iter(FixedMapObject* self) {
862
+ return PyObject_GetIter(self->keys->keys_tuple);
863
+ }
864
+
865
+ static Py_ssize_t FixedMap_len(FixedMapObject* self) {
866
+ return PyTuple_GET_SIZE(self->values_tuple);
867
+ }
868
+
869
+ static int FixedMap_contains(FixedMapObject* self, PyObject* key) {
870
+ Py_ssize_t idx;
871
+ int rc = FixedMapKeys_lookup_index(self->keys, key, &idx);
872
+ if (rc < 0) {
873
+ return -1;
874
+ }
875
+ return rc > 0;
876
+ }
877
+
878
+
879
+ static PyMethodDef FixedMap_methods[] = {
880
+ {"get", (PyCFunction)FixedMap_get, METH_VARARGS, NULL},
881
+ {"keys", (PyCFunction)FixedMap_keys, METH_NOARGS, NULL},
882
+ {"values", (PyCFunction)FixedMap_values, METH_NOARGS, NULL},
883
+ {"items", (PyCFunction)FixedMap_items, METH_NOARGS, NULL},
884
+ {"itervalues", (PyCFunction)FixedMap_itervalues, METH_NOARGS, NULL},
885
+ {"iteritems", (PyCFunction)FixedMap_iteritems, METH_NOARGS, NULL},
886
+ {NULL, NULL, 0, NULL}
887
+ };
888
+
889
+ static PyGetSetDef FixedMap_getsets[] = {
890
+ {"fixed_keys", (getter)FixedMap_get_fixed_keys, NULL, NULL, NULL},
891
+ {"fixed_values", (getter)FixedMap_get_fixed_values, NULL, NULL, NULL},
892
+ {"debug", (getter)FixedMap_get_debug, NULL, NULL, NULL},
893
+ {NULL, NULL, NULL, NULL, NULL}
894
+ };
895
+
896
+ static PyType_Slot FixedMap_slots[] = {
897
+ {Py_tp_dealloc, (void*)FixedMap_dealloc},
898
+ {Py_tp_traverse, (void*)FixedMap_traverse},
899
+ {Py_tp_clear, (void*)FixedMap_clear},
900
+ {Py_tp_hash, (void*)FixedMap_hash},
901
+ {Py_tp_richcompare, (void*)FixedMap_richcompare},
902
+ {Py_tp_iter, (void*)FixedMap_iter},
903
+ {Py_tp_methods, (void*)FixedMap_methods},
904
+ {Py_tp_getset, (void*)FixedMap_getsets},
905
+ {Py_mp_length, (void*)FixedMap_len},
906
+ {Py_mp_subscript, (void*)FixedMap_getitem},
907
+ {Py_sq_contains, (void*)FixedMap_contains},
908
+ {Py_tp_new, (void*)FixedMap_new},
909
+ {Py_tp_init, (void*)dummy_init},
910
+ {0, NULL}
911
+ };
912
+
913
+ static PyType_Spec FixedMap_spec = {
914
+ .name = _MODULE_FULL_NAME ".FixedMap",
915
+ .basicsize = sizeof(FixedMapObject),
916
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
917
+ .slots = FixedMap_slots,
918
+ };
919
+
920
+ //
921
+ // Module Initialization
922
+ //
923
+
924
+ PyDoc_STRVAR(fixedmap_doc, "C++ optimized implementation of FixedMap.");
925
+
926
+ static int fixedmap_exec(PyObject* module) {
927
+ fixedmap_state* state = get_module_state(module);
928
+
929
+ state->FixedMapKeys_Type = (PyTypeObject*)PyType_FromModuleAndSpec(module, &FixedMapKeys_spec, NULL);
930
+ if (!state->FixedMapKeys_Type) {
931
+ return -1;
932
+ }
933
+ if (PyModule_AddType(module, state->FixedMapKeys_Type) < 0) {
934
+ return -1;
935
+ }
936
+
937
+ state->FixedMap_Type = (PyTypeObject*)PyType_FromModuleAndSpec(module, &FixedMap_spec, NULL);
938
+ if (!state->FixedMap_Type) {
939
+ return -1;
940
+ }
941
+ if (PyModule_AddType(module, state->FixedMap_Type) < 0) {
942
+ return -1;
943
+ }
944
+
945
+ state->FixedMapIter_Type = (PyTypeObject*)PyType_FromModuleAndSpec(module, &FixedMapIter_spec, NULL);
946
+ if (!state->FixedMapIter_Type) {
947
+ return -1;
948
+ }
949
+ if (PyModule_AddType(module, state->FixedMapIter_Type) < 0) {
950
+ return -1;
951
+ }
952
+
953
+ state->FixedMapValuesView_Type = (PyTypeObject*)PyType_FromModuleAndSpec(module, &FixedMapValuesView_spec, NULL);
954
+ if (!state->FixedMapValuesView_Type) {
955
+ return -1;
956
+ }
957
+ if (PyModule_AddType(module, state->FixedMapValuesView_Type) < 0) {
958
+ return -1;
959
+ }
960
+
961
+ state->FixedMapItemsView_Type = (PyTypeObject*)PyType_FromModuleAndSpec(module, &FixedMapItemsView_spec, NULL);
962
+ if (!state->FixedMapItemsView_Type) {
963
+ return -1;
964
+ }
965
+ if (PyModule_AddType(module, state->FixedMapItemsView_Type) < 0) {
966
+ return -1;
967
+ }
968
+
969
+ return 0;
970
+ }
971
+
972
+ static int fixedmap_traverse(PyObject* module, visitproc visit, void* arg) {
973
+ fixedmap_state* state = get_module_state(module);
974
+ Py_VISIT(state->FixedMapKeys_Type);
975
+ Py_VISIT(state->FixedMap_Type);
976
+ Py_VISIT(state->FixedMapIter_Type);
977
+ Py_VISIT(state->FixedMapValuesView_Type);
978
+ Py_VISIT(state->FixedMapItemsView_Type);
979
+ return 0;
980
+ }
981
+
982
+ static int fixedmap_clear(PyObject* module) {
983
+ fixedmap_state* state = get_module_state(module);
984
+ Py_CLEAR(state->FixedMapKeys_Type);
985
+ Py_CLEAR(state->FixedMap_Type);
986
+ Py_CLEAR(state->FixedMapIter_Type);
987
+ Py_CLEAR(state->FixedMapValuesView_Type);
988
+ Py_CLEAR(state->FixedMapItemsView_Type);
989
+ return 0;
990
+ }
991
+
992
+ static void fixedmap_free(void* module) {
993
+ fixedmap_clear((PyObject*)module);
994
+ }
995
+
996
+ static PyMethodDef fixedmap_methods[] = {
997
+ {NULL, NULL, 0, NULL}
998
+ };
999
+
1000
+ static struct PyModuleDef_Slot fixedmap_slots[] = {
1001
+ {Py_mod_exec, (void*)fixedmap_exec},
1002
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
1003
+ {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED},
1004
+ {0, NULL}
1005
+ };
1006
+
1007
+ static struct PyModuleDef fixedmap_module = {
1008
+ .m_base = PyModuleDef_HEAD_INIT,
1009
+ .m_name = _MODULE_NAME,
1010
+ .m_doc = fixedmap_doc,
1011
+ .m_size = sizeof(fixedmap_state),
1012
+ .m_methods = fixedmap_methods,
1013
+ .m_slots = fixedmap_slots,
1014
+ .m_traverse = fixedmap_traverse,
1015
+ .m_clear = fixedmap_clear,
1016
+ .m_free = fixedmap_free,
1017
+ };
1018
+
1019
+ extern "C" {
1020
+ PyMODINIT_FUNC PyInit__fixedmap(void) {
1021
+ return PyModuleDef_Init(&fixedmap_module);
1022
+ }
1023
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish-cext
3
- Version: 0.0.0.dev553
3
+ Version: 0.0.0.dev554
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev553
17
+ Requires-Dist: omlish==0.0.0.dev554
18
18
  Dynamic: license-file
19
19
 
20
20
  # Overview
@@ -3,6 +3,7 @@ README.md
3
3
  pyproject.toml
4
4
  setup.py
5
5
  omlish/_check.cc
6
+ omlish/collections/fixed/_fixedmap.cc
6
7
  omlish/collections/hamt/_hamt.c
7
8
  omlish/collections/treap/_treap.cc
8
9
  omlish/dispatch/_dispatch.cc
@@ -0,0 +1 @@
1
+ omlish==0.0.0.dev554
@@ -13,7 +13,7 @@ urls = {source = 'https://github.com/wrmsr/omlish'}
13
13
  license = 'BSD-3-Clause'
14
14
  readme = 'README.md'
15
15
  requires-python = '>=3.13'
16
- version = '0.0.0.dev553'
16
+ version = '0.0.0.dev554'
17
17
  classifiers = [
18
18
  'Development Status :: 2 - Pre-Alpha',
19
19
  'Intended Audience :: Developers',
@@ -24,7 +24,7 @@ classifiers = [
24
24
  ]
25
25
  description = 'omlish'
26
26
  dependencies = [
27
- 'omlish == 0.0.0.dev553',
27
+ 'omlish == 0.0.0.dev554',
28
28
  ]
29
29
 
30
30
  [tool.setuptools]
@@ -8,6 +8,11 @@ st.setup(
8
8
  sources=['omlish/_check.cc'],
9
9
  extra_compile_args=['-std=c++20'],
10
10
  ),
11
+ st.Extension(
12
+ name='omlish.collections.fixed._fixedmap',
13
+ sources=['omlish/collections/fixed/_fixedmap.cc'],
14
+ extra_compile_args=['-std=c++20'],
15
+ ),
11
16
  st.Extension(
12
17
  name='omlish.collections.hamt._hamt',
13
18
  sources=['omlish/collections/hamt/_hamt.c'],
@@ -1 +0,0 @@
1
- omlish==0.0.0.dev553