py_dict.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. #include "pocketpy/pocketpy.h"
  2. #include "pocketpy/common/utils.h"
  3. #include "pocketpy/common/sstream.h"
  4. #include "pocketpy/objects/object.h"
  5. #include "pocketpy/interpreter/vm.h"
  6. #define PK_DICT_MAX_COLLISION 4
  7. static uint32_t Dict__next_cap(uint32_t cap) {
  8. switch(cap) {
  9. case 7: return 17;
  10. case 17: return 37;
  11. case 37: return 79;
  12. case 79: return 163;
  13. case 163: return 331;
  14. case 331: return 673;
  15. case 673: return 1361;
  16. case 1361: return 2053;
  17. case 2053: return 3083;
  18. case 3083: return 4637;
  19. case 4637: return 6959;
  20. case 6959: return 10453;
  21. case 10453: return 15683;
  22. case 15683: return 23531;
  23. case 23531: return 35311;
  24. case 35311: return 52967;
  25. case 52967: return 79451;
  26. case 79451: return 119179;
  27. case 119179: return 178781;
  28. case 178781: return 268189;
  29. case 268189: return 402299;
  30. case 402299: return 603457;
  31. case 603457: return 905189;
  32. case 905189: return 1357787;
  33. case 1357787: return 2036687;
  34. case 2036687: return 3055043;
  35. case 3055043: return 4582577;
  36. case 4582577: return 6873871;
  37. case 6873871: return 10310819;
  38. case 10310819: return 15466229;
  39. case 15466229: return 23199347;
  40. case 23199347: return 34799021;
  41. case 34799021: return 52198537;
  42. case 52198537: return 78297827;
  43. case 78297827: return 117446801;
  44. case 117446801: return 176170229;
  45. case 176170229: return 264255353;
  46. case 264255353: return 396383041;
  47. case 396383041: return 594574583;
  48. case 594574583: return 891861923;
  49. default: c11__unreachable();
  50. }
  51. }
  52. typedef struct {
  53. uint64_t hash;
  54. py_TValue key;
  55. py_TValue val;
  56. } DictEntry;
  57. typedef struct {
  58. int _[PK_DICT_MAX_COLLISION];
  59. } DictIndex;
  60. typedef struct {
  61. int length;
  62. uint32_t capacity;
  63. DictIndex* indices;
  64. c11_vector /*T=DictEntry*/ entries;
  65. } Dict;
  66. typedef struct {
  67. DictEntry* curr;
  68. DictEntry* end;
  69. } DictIterator;
  70. static void Dict__ctor(Dict* self, uint32_t capacity, int entries_capacity) {
  71. self->length = 0;
  72. self->capacity = capacity;
  73. self->indices = malloc(self->capacity * sizeof(DictIndex));
  74. memset(self->indices, -1, self->capacity * sizeof(DictIndex));
  75. c11_vector__ctor(&self->entries, sizeof(DictEntry));
  76. c11_vector__reserve(&self->entries, entries_capacity);
  77. }
  78. static void Dict__dtor(Dict* self) {
  79. self->length = 0;
  80. self->capacity = 0;
  81. free(self->indices);
  82. c11_vector__dtor(&self->entries);
  83. }
  84. static bool Dict__try_get(Dict* self, py_TValue* key, DictEntry** out) {
  85. py_i64 hash;
  86. if(!py_hash(key, &hash)) return false;
  87. int idx = (uint64_t)hash % self->capacity;
  88. for(int i = 0; i < PK_DICT_MAX_COLLISION; i++) {
  89. int idx2 = self->indices[idx]._[i];
  90. if(idx2 == -1) continue;
  91. DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
  92. int res = py_equal(&entry->key, key);
  93. if(res == 1) {
  94. *out = entry;
  95. return true;
  96. }
  97. if(res == -1) return false; // error
  98. }
  99. *out = NULL;
  100. return true;
  101. }
  102. static void Dict__clear(Dict* self) {
  103. memset(self->indices, -1, self->capacity * sizeof(DictIndex));
  104. c11_vector__clear(&self->entries);
  105. self->length = 0;
  106. }
  107. static void Dict__rehash_2x(Dict* self) {
  108. Dict old_dict = *self;
  109. uint32_t new_capacity = self->capacity;
  110. __RETRY:
  111. // use next capacity
  112. new_capacity = Dict__next_cap(new_capacity);
  113. // create a new dict with new capacity
  114. Dict__ctor(self, new_capacity, old_dict.entries.capacity);
  115. // move entries from old dict to new dict
  116. for(int i = 0; i < old_dict.entries.length; i++) {
  117. DictEntry* entry = c11__at(DictEntry, &old_dict.entries, i);
  118. if(py_isnil(&entry->key)) continue;
  119. int idx = entry->hash % new_capacity;
  120. bool success = false;
  121. for(int i = 0; i < PK_DICT_MAX_COLLISION; i++) {
  122. int idx2 = self->indices[idx]._[i];
  123. if(idx2 == -1) {
  124. // insert new entry (empty slot)
  125. c11_vector__push(DictEntry, &self->entries, *entry);
  126. self->indices[idx]._[i] = self->entries.length - 1;
  127. self->length++;
  128. success = true;
  129. break;
  130. }
  131. }
  132. if(!success) {
  133. Dict__dtor(self);
  134. goto __RETRY;
  135. }
  136. }
  137. // done
  138. Dict__dtor(&old_dict);
  139. }
  140. static void Dict__compact_entries(Dict* self) {
  141. int* mappings = malloc(self->entries.length * sizeof(int));
  142. int n = 0;
  143. for(int i = 0; i < self->entries.length; i++) {
  144. DictEntry* entry = c11__at(DictEntry, &self->entries, i);
  145. if(py_isnil(&entry->key)) continue;
  146. mappings[i] = n;
  147. if(i != n) {
  148. DictEntry* new_entry = c11__at(DictEntry, &self->entries, n);
  149. *new_entry = *entry;
  150. }
  151. n++;
  152. }
  153. self->entries.length = n;
  154. // update indices
  155. for(int i = 0; i < self->capacity; i++) {
  156. for(int j = 0; j < PK_DICT_MAX_COLLISION; j++) {
  157. int idx = self->indices[i]._[j];
  158. if(idx == -1) continue;
  159. self->indices[i]._[j] = mappings[idx];
  160. }
  161. }
  162. free(mappings);
  163. }
  164. static bool Dict__set(Dict* self, py_TValue* key, py_TValue* val) {
  165. py_i64 hash;
  166. if(!py_hash(key, &hash)) return false;
  167. int idx = (uint64_t)hash % self->capacity;
  168. for(int i = 0; i < PK_DICT_MAX_COLLISION; i++) {
  169. int idx2 = self->indices[idx]._[i];
  170. if(idx2 == -1) {
  171. // insert new entry
  172. DictEntry* new_entry = c11_vector__emplace(&self->entries);
  173. new_entry->hash = (uint64_t)hash;
  174. new_entry->key = *key;
  175. new_entry->val = *val;
  176. self->indices[idx]._[i] = self->entries.length - 1;
  177. self->length++;
  178. return true;
  179. }
  180. // update existing entry
  181. DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
  182. int res = py_equal(&entry->key, key);
  183. if(res == 1) {
  184. entry->val = *val;
  185. return true;
  186. }
  187. if(res == -1) return false; // error
  188. }
  189. // no empty slot found
  190. if(self->capacity >= self->entries.length * 10) {
  191. // raise error if we reach the minimum load factor (10%)
  192. return RuntimeError("dict has too much collision: %d/%d/%d",
  193. self->entries.length,
  194. self->entries.capacity,
  195. self->capacity);
  196. }
  197. Dict__rehash_2x(self);
  198. return Dict__set(self, key, val);
  199. }
  200. /// Delete an entry from the dict.
  201. /// -1: error, 0: not found, 1: found and deleted
  202. static int Dict__pop(Dict* self, py_Ref key) {
  203. py_i64 hash;
  204. if(!py_hash(key, &hash)) return -1;
  205. int idx = (uint64_t)hash % self->capacity;
  206. for(int i = 0; i < PK_DICT_MAX_COLLISION; i++) {
  207. int idx2 = self->indices[idx]._[i];
  208. if(idx2 == -1) continue;
  209. DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
  210. int res = py_equal(&entry->key, key);
  211. if(res == 1) {
  212. *py_retval() = entry->val;
  213. py_newnil(&entry->key);
  214. self->indices[idx]._[i] = -1;
  215. self->length--;
  216. if(self->length < self->entries.length / 2) Dict__compact_entries(self);
  217. return 1;
  218. }
  219. if(res == -1) return -1; // error
  220. }
  221. return 0;
  222. }
  223. static void DictIterator__ctor(DictIterator* self, Dict* dict) {
  224. self->curr = dict->entries.data;
  225. self->end = self->curr + dict->entries.length;
  226. }
  227. static DictEntry* DictIterator__next(DictIterator* self) {
  228. DictEntry* retval;
  229. do {
  230. if(self->curr == self->end) return NULL;
  231. retval = self->curr++;
  232. } while(py_isnil(&retval->key));
  233. return retval;
  234. }
  235. ///////////////////////////////
  236. static bool dict__new__(int argc, py_Ref argv) {
  237. py_Type cls = py_totype(argv);
  238. int slots = cls == tp_dict ? 0 : -1;
  239. Dict* ud = py_newobject(py_retval(), cls, slots, sizeof(Dict));
  240. Dict__ctor(ud, 7, 8);
  241. return true;
  242. }
  243. void py_newdict(py_Ref out) {
  244. Dict* ud = py_newobject(out, tp_dict, 0, sizeof(Dict));
  245. Dict__ctor(ud, 7, 8);
  246. }
  247. static bool dict__init__(int argc, py_Ref argv) {
  248. py_newnone(py_retval());
  249. if(argc > 2) return TypeError("dict.__init__() takes at most 2 arguments (%d given)", argc);
  250. if(argc == 1) return true;
  251. assert(argc == 2);
  252. PY_CHECK_ARG_TYPE(1, tp_list);
  253. Dict* self = py_touserdata(argv);
  254. py_Ref list = py_arg(1);
  255. for(int i = 0; i < py_list_len(list); i++) {
  256. py_Ref tuple = py_list_getitem(list, i);
  257. if(!py_istuple(tuple) || py_tuple_len(tuple) != 2) {
  258. return TypeError("dict.__init__() argument must be a list of tuple-2");
  259. }
  260. py_Ref key = py_tuple_getitem(tuple, 0);
  261. py_Ref val = py_tuple_getitem(tuple, 1);
  262. if(!Dict__set(self, key, val)) return false;
  263. }
  264. return true;
  265. }
  266. static bool dict__getitem__(int argc, py_Ref argv) {
  267. PY_CHECK_ARGC(2);
  268. Dict* self = py_touserdata(argv);
  269. DictEntry* entry;
  270. if(!Dict__try_get(self, py_arg(1), &entry)) return false;
  271. if(entry) {
  272. *py_retval() = entry->val;
  273. return true;
  274. }
  275. // try __missing__
  276. py_Ref missing = py_tpfindmagic(argv->type, __missing__);
  277. if(missing) return py_call(missing, argc, argv);
  278. return KeyError(py_arg(1));
  279. }
  280. static bool dict__setitem__(int argc, py_Ref argv) {
  281. PY_CHECK_ARGC(3);
  282. Dict* self = py_touserdata(argv);
  283. return Dict__set(self, py_arg(1), py_arg(2));
  284. }
  285. static bool dict__delitem__(int argc, py_Ref argv) {
  286. PY_CHECK_ARGC(2);
  287. Dict* self = py_touserdata(argv);
  288. int res = Dict__pop(self, py_arg(1));
  289. if(res == 1) {
  290. py_newnone(py_retval());
  291. return true;
  292. }
  293. if(res == 0) return KeyError(py_arg(1));
  294. return false;
  295. }
  296. static bool dict__contains__(int argc, py_Ref argv) {
  297. PY_CHECK_ARGC(2);
  298. Dict* self = py_touserdata(argv);
  299. DictEntry* entry;
  300. if(!Dict__try_get(self, py_arg(1), &entry)) return false;
  301. py_newbool(py_retval(), entry != NULL);
  302. return true;
  303. }
  304. static bool dict__len__(int argc, py_Ref argv) {
  305. PY_CHECK_ARGC(1);
  306. Dict* self = py_touserdata(argv);
  307. py_newint(py_retval(), self->length);
  308. return true;
  309. }
  310. static bool dict__repr__(int argc, py_Ref argv) {
  311. PY_CHECK_ARGC(1);
  312. Dict* self = py_touserdata(argv);
  313. c11_sbuf buf;
  314. c11_sbuf__ctor(&buf);
  315. c11_sbuf__write_char(&buf, '{');
  316. bool is_first = true;
  317. for(int i = 0; i < self->entries.length; i++) {
  318. DictEntry* entry = c11__at(DictEntry, &self->entries, i);
  319. if(py_isnil(&entry->key)) continue;
  320. if(!is_first) c11_sbuf__write_cstr(&buf, ", ");
  321. if(!py_repr(&entry->key)) return false;
  322. c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
  323. c11_sbuf__write_cstr(&buf, ": ");
  324. if(!py_repr(&entry->val)) return false;
  325. c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
  326. is_first = false;
  327. }
  328. c11_sbuf__write_char(&buf, '}');
  329. c11_sbuf__py_submit(&buf, py_retval());
  330. return true;
  331. }
  332. static bool dict__eq__(int argc, py_Ref argv) {
  333. PY_CHECK_ARGC(2);
  334. Dict* self = py_touserdata(py_arg(0));
  335. if(!py_isdict(py_arg(1))) {
  336. py_newnotimplemented(py_retval());
  337. return true;
  338. }
  339. Dict* other = py_touserdata(py_arg(1));
  340. if(self->length != other->length) {
  341. py_newbool(py_retval(), false);
  342. return true;
  343. }
  344. DictIterator iter;
  345. DictIterator__ctor(&iter, self);
  346. // for each self key
  347. while(1) {
  348. DictEntry* entry = DictIterator__next(&iter);
  349. if(!entry) break;
  350. DictEntry* other_entry;
  351. if(!Dict__try_get(other, &entry->key, &other_entry)) return false;
  352. if(!other_entry) {
  353. py_newbool(py_retval(), false);
  354. return true;
  355. }
  356. int res = py_equal(&entry->val, &other_entry->val);
  357. if(res == -1) return false;
  358. if(!res) {
  359. py_newbool(py_retval(), false);
  360. return true;
  361. }
  362. }
  363. py_newbool(py_retval(), true);
  364. return true;
  365. }
  366. static bool dict__ne__(int argc, py_Ref argv) {
  367. if(!dict__eq__(argc, argv)) return false;
  368. if(py_isbool(py_retval())) {
  369. bool res = py_tobool(py_retval());
  370. py_newbool(py_retval(), !res);
  371. }
  372. return true;
  373. }
  374. static bool dict_clear(int argc, py_Ref argv) {
  375. PY_CHECK_ARGC(1);
  376. Dict* self = py_touserdata(argv);
  377. Dict__clear(self);
  378. py_newnone(py_retval());
  379. return true;
  380. }
  381. static bool dict_copy(int argc, py_Ref argv) {
  382. PY_CHECK_ARGC(1);
  383. Dict* self = py_touserdata(argv);
  384. Dict* new_dict = py_newobject(py_retval(), tp_dict, 0, sizeof(Dict));
  385. new_dict->capacity = self->capacity;
  386. new_dict->length = self->length;
  387. new_dict->entries = c11_vector__copy(&self->entries);
  388. // copy indices
  389. new_dict->indices = malloc(new_dict->capacity * sizeof(DictIndex));
  390. memcpy(new_dict->indices, self->indices, new_dict->capacity * sizeof(DictIndex));
  391. return true;
  392. }
  393. static bool dict_update(int argc, py_Ref argv) {
  394. PY_CHECK_ARGC(2);
  395. PY_CHECK_ARG_TYPE(1, tp_dict);
  396. Dict* self = py_touserdata(argv);
  397. Dict* other = py_touserdata(py_arg(1));
  398. for(int i = 0; i < other->entries.length; i++) {
  399. DictEntry* entry = c11__at(DictEntry, &other->entries, i);
  400. if(py_isnil(&entry->key)) continue;
  401. if(!Dict__set(self, &entry->key, &entry->val)) return false;
  402. }
  403. py_newnone(py_retval());
  404. return true;
  405. }
  406. static bool dict_get(int argc, py_Ref argv) {
  407. Dict* self = py_touserdata(argv);
  408. if(argc > 3) return TypeError("get() takes at most 3 arguments (%d given)", argc);
  409. py_Ref default_val = argc == 3 ? py_arg(2) : py_None();
  410. DictEntry* entry;
  411. if(!Dict__try_get(self, py_arg(1), &entry)) return false;
  412. *py_retval() = entry ? entry->val : *default_val;
  413. return true;
  414. }
  415. static bool dict_pop(int argc, py_Ref argv) {
  416. Dict* self = py_touserdata(argv);
  417. if(argc < 2 || argc > 3) return TypeError("pop() takes 1 or 2 arguments (%d given)", argc - 1);
  418. py_Ref default_val = argc == 3 ? py_arg(2) : py_None();
  419. int res = Dict__pop(self, py_arg(1));
  420. if(res == -1) return false;
  421. if(res == 0) { py_assign(py_retval(), default_val); }
  422. return true;
  423. }
  424. static bool dict_items(int argc, py_Ref argv) {
  425. PY_CHECK_ARGC(1);
  426. Dict* self = py_touserdata(argv);
  427. DictIterator* ud = py_newobject(py_retval(), tp_dict_items, 1, sizeof(DictIterator));
  428. DictIterator__ctor(ud, self);
  429. py_setslot(py_retval(), 0, argv); // keep a reference to the dict
  430. return true;
  431. }
  432. static bool dict_keys(int argc, py_Ref argv) {
  433. PY_CHECK_ARGC(1);
  434. Dict* self = py_touserdata(argv);
  435. py_newtuple(py_retval(), self->length);
  436. DictIterator iter;
  437. DictIterator__ctor(&iter, self);
  438. int i = 0;
  439. while(1) {
  440. DictEntry* entry = DictIterator__next(&iter);
  441. if(!entry) break;
  442. py_tuple_setitem(py_retval(), i++, &entry->key);
  443. }
  444. assert(i == self->length);
  445. return true;
  446. }
  447. static bool dict_values(int argc, py_Ref argv) {
  448. PY_CHECK_ARGC(1);
  449. Dict* self = py_touserdata(argv);
  450. py_newtuple(py_retval(), self->length);
  451. DictIterator iter;
  452. DictIterator__ctor(&iter, self);
  453. int i = 0;
  454. while(1) {
  455. DictEntry* entry = DictIterator__next(&iter);
  456. if(!entry) break;
  457. py_tuple_setitem(py_retval(), i++, &entry->val);
  458. }
  459. assert(i == self->length);
  460. return true;
  461. }
  462. static void dict__gc_mark(void* ud) {
  463. Dict* self = ud;
  464. for(int i = 0; i < self->entries.length; i++) {
  465. DictEntry* entry = c11__at(DictEntry, &self->entries, i);
  466. if(py_isnil(&entry->key)) continue;
  467. pk__mark_value(&entry->key);
  468. pk__mark_value(&entry->val);
  469. }
  470. }
  471. py_Type pk_dict__register() {
  472. py_Type type = pk_newtype("dict", tp_object, NULL, (void (*)(void*))Dict__dtor, false, false);
  473. pk__tp_set_marker(type, dict__gc_mark);
  474. py_bindmagic(type, __new__, dict__new__);
  475. py_bindmagic(type, __init__, dict__init__);
  476. py_bindmagic(type, __getitem__, dict__getitem__);
  477. py_bindmagic(type, __setitem__, dict__setitem__);
  478. py_bindmagic(type, __delitem__, dict__delitem__);
  479. py_bindmagic(type, __contains__, dict__contains__);
  480. py_bindmagic(type, __len__, dict__len__);
  481. py_bindmagic(type, __repr__, dict__repr__);
  482. py_bindmagic(type, __eq__, dict__eq__);
  483. py_bindmagic(type, __ne__, dict__ne__);
  484. py_bindmethod(type, "clear", dict_clear);
  485. py_bindmethod(type, "copy", dict_copy);
  486. py_bindmethod(type, "update", dict_update);
  487. py_bindmethod(type, "get", dict_get);
  488. py_bindmethod(type, "pop", dict_pop);
  489. py_bindmethod(type, "items", dict_items);
  490. py_bindmethod(type, "keys", dict_keys);
  491. py_bindmethod(type, "values", dict_values);
  492. py_setdict(py_tpobject(type), __hash__, py_None());
  493. return type;
  494. }
  495. //////////////////////////
  496. static bool dict_items__next__(int argc, py_Ref argv) {
  497. PY_CHECK_ARGC(1);
  498. DictIterator* iter = py_touserdata(py_arg(0));
  499. DictEntry* entry = (DictIterator__next(iter));
  500. if(entry) {
  501. py_newtuple(py_retval(), 2);
  502. py_tuple_setitem(py_retval(), 0, &entry->key);
  503. py_tuple_setitem(py_retval(), 1, &entry->val);
  504. return true;
  505. }
  506. return StopIteration();
  507. }
  508. py_Type pk_dict_items__register() {
  509. py_Type type = pk_newtype("dict_items", tp_object, NULL, NULL, false, true);
  510. py_bindmagic(type, __iter__, pk_wrapper__self);
  511. py_bindmagic(type, __next__, dict_items__next__);
  512. return type;
  513. }
  514. //////////////////////////
  515. int py_dict_getitem(py_Ref self, py_Ref key) {
  516. assert(py_isdict(self));
  517. Dict* ud = py_touserdata(self);
  518. DictEntry* entry;
  519. if(!Dict__try_get(ud, key, &entry)) return -1;
  520. if(entry) {
  521. py_assign(py_retval(), &entry->val);
  522. return 1;
  523. }
  524. return 0;
  525. }
  526. bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) {
  527. assert(py_isdict(self));
  528. Dict* ud = py_touserdata(self);
  529. return Dict__set(ud, key, val);
  530. }
  531. int py_dict_delitem(py_Ref self, py_Ref key) {
  532. assert(py_isdict(self));
  533. Dict* ud = py_touserdata(self);
  534. return Dict__pop(ud, key);
  535. }
  536. int py_dict_getitem_by_str(py_Ref self, const char* key) {
  537. py_Ref tmp = py_pushtmp();
  538. py_newstr(tmp, key);
  539. int res = py_dict_getitem(self, tmp);
  540. py_pop();
  541. return res;
  542. }
  543. bool py_dict_setitem_by_str(py_Ref self, const char* key, py_Ref val) {
  544. py_Ref tmp = py_pushtmp();
  545. py_newstr(tmp, key);
  546. bool res = py_dict_setitem(self, tmp, val);
  547. py_pop();
  548. return res;
  549. }
  550. int py_dict_delitem_by_str(py_Ref self, const char* key) {
  551. py_Ref tmp = py_pushtmp();
  552. py_newstr(tmp, key);
  553. int res = py_dict_delitem(self, tmp);
  554. py_pop();
  555. return res;
  556. }
  557. int py_dict_len(py_Ref self) {
  558. assert(py_isdict(self));
  559. Dict* ud = py_touserdata(self);
  560. return ud->length;
  561. }
  562. bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
  563. Dict* ud = py_touserdata(self);
  564. for(int i = 0; i < ud->entries.length; i++) {
  565. DictEntry* entry = c11__at(DictEntry, &ud->entries, i);
  566. if(py_isnil(&entry->key)) continue;
  567. if(!f(&entry->key, &entry->val, ctx)) return false;
  568. }
  569. return true;
  570. }