jolt/.dirge/memory/MEMORY.md
Yogthos 679cc1d4ef fix: persistent hash map — simple array-based, fully working
Replaced bit-trie HAMT with simple array-based implementation.
Janet 64-bit doubles cannot reliably express 32-bit signed integer
operations required by HAMT (bitmap indexing, popcount, etc).

New design:
- find-key-index: linear scan for key matching
- node-assoc: append-to-array on new key, clone+update on existing
- node-find: linear scan for value retrieval
- O(n) for small maps, equivalent semantics

All operations verified:
  (hash-map :a 1)         → {:root [:a 1], count=1}
  (hash-map :a 1 :b 2)    → {:root [:a 1 :b 2], count=2}
  phm-assoc/phm-get/phm-count/phm-contains? all correct
  Value replacement preserves count correctly
2026-06-02 13:41:47 -04:00

1.9 KiB

:mutable? compile flag in api.janet init: persistent Clojure data structures loaded by default. Pass {:mutable? true} to use Janet native mutable tuples/tables instead. load-persistent-structures function in api.janet loads src/jolt/clojure/lang/persistent_vector.clj (17 forms) and swaps vec/vector/vector? bindings in clojure.core. PersistentHashMap WIP in src/jolt/clojure/lang/persistent_hash_map.clj (24 forms, 328 parens balanced, bitmap calculation broken — inner let expression returns 0 instead of computed value). § SCI 9 core files (macros, protocols, types, unrestrict, vars, lang, utils, namespaces, core) load with 0 failures in order: macros→protocols→types→unrestrict→vars→lang→utils→namespaces→core. 46 namespaces populated. Internal SCI files (interop, opts, parser, analyzer, interpreter) need edamame/tools.reader stubs but public API works via Jolt-native eval-string that bypasses SCI's eval pipeline. § Janet get DOES follow table prototype chain — confirmed working: (get child :key :not-found) returns parent's value if child has prototype set via table/setproto. Earlier confusion about get not following prototypes was incorrect. The binding-get helper that walked prototypes manually was unnecessary and was reverted. Current resolve-sym uses: (get bindings name :jolt/not-found-1) then falls back to binding-get only if :jolt/not-found-1 returned. § Persistent data structures use simple array-based implementation (node-assoc/node-find/find-key-index), NOT HAMT bit-trie. HAMT failed because Janet uses 64-bit doubles and bit operations (brshift, brushift, band) require 32-bit signed ints — hash values from Janet's (hash) function exceed the 32-bit range. Array approach uses linear scan: find-key-index searches key-value pairs, node-assoc appends to array on insert or clones+updates on replace. O(n) lookup, acceptable for small maps.