Phase 5: HAMT Persistent Map + Persistent Set, 86 tests pass

- T5.3: HAMT Persistent Map (lib/cljnim_pmap.nim)
  O(log32 n) assoc/dissoc/get with structural sharing
  16 unit tests, ckMap migrated from seq to HAMT

- T5.4: Persistent Set backed by HAMT map
  ckSet with conj/disj/contains?/get, set literal #{}

- Fix: cljContains/cljCount return CljVal (not bool/int)
- Fix: equality in generics via explicit cljEq parameter
- Updated roadmap, task board, CI/Makefile
This commit is contained in:
2026-05-08 19:13:09 +03:00
parent d763e25638
commit 6dfc2a9308
9 changed files with 864 additions and 165 deletions
+19
View File
@@ -108,6 +108,7 @@ proc runtimeName(op: string): string =
of "git/push": "cljGitPush"
of "git/diff": "cljGitDiff"
of "git/log": "cljGitLog"
of "disj": "cljDisj"
else: ""
proc emitArgs(args: seq[CljVal]): string =
@@ -759,6 +760,24 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
raise newException(EmitterError, "set! target must be a symbol")
return sp & mangleName(target.symName) & " = " & emitExpr(items[2], 0)
of "set":
if items.len != 2:
raise newException(EmitterError, "set requires exactly 1 argument")
let arg = items[1]
case arg.kind
of ckVector:
var parts: seq[string] = @[]
for item in arg.items:
parts.add(emitExpr(item, 0))
return sp & "cljSet(@[" & parts.join(", ") & "])"
of ckList:
var parts: seq[string] = @[]
for item in arg.items:
parts.add(emitExpr(item, 0))
return sp & "cljSet(@[" & parts.join(", ") & "])"
else:
return sp & "cljSet(@[" & emitExpr(arg, 0) & "])"
of "range":
if items.len < 1 or items.len > 3:
raise newException(EmitterError, "range requires 0, 1, or 2 arguments")