281fd2e00b
- Documented 3 remaining failures with root causes - Roadmap: Phase A (closure scoping), Phase B (multi-file), Phase C (symbol emit)
3.6 KiB
3.6 KiB
Clojure/Nim — Test Suite Compliance Plan
Current Status: 230/233 (98.7%)
| Component | Pass | Total | % |
|---|---|---|---|
| clojure.string | 8 | 8 | 100% |
| clojure.core | 222 | 225 | 98.7% |
| Total | 230 | 233 | 98.7% |
Unit Tests: 78/80 (97.5%)
| Status | Test | Issue |
|---|---|---|
| ✅ | 78 tests | All passing |
| ❌ | emit symbol |
Returns cljSymbol("x") instead of raw "x" |
| ❌ | emit mangled symbol |
Same — symbol emit returns data instead of name |
3 Remaining Compliance Failures
1. not_eq — Cross-namespace dependency
- Error:
undeclared identifier: 'eq_SLASH_tests' - Cause: Test calls
(eq/tests (complement not=))whereeq/testsis a function defined inclojure.core-test.eqnamespace (separate file). Our compiler processes each test file independently — it doesn't load required namespaces. - Fix needed: Multi-file compilation —
ns :requireshould inline/compile required files and make their functions available.
2. add_watch — Closure scoping with fn params
- Error:
undeclared identifier: 'ref1' - Cause: The test defines functions like
(fn [key ref old new] ...)whererefgets mangled toref1. These fn params are used inside deeply nested closures (try/catch inside fn inside testing block). The IIFE wrapping byemitBlockcreates scope boundaries that prevent fn params from being visible in inner closures. - Fix needed: IIFE-wrapped closures must capture enclosing scope variables. Either stop wrapping non-last forms in IIFEs, or use Nim closures that properly capture outer variables.
3. remove_watch — Same closure scoping issue
- Error:
undeclared identifier: 'ref1' - Cause: Same as
add_watch— fn params not visible across IIFE boundaries. - Fix needed: Same as
add_watch.
Roadmap to 100%
Phase A: Closure Scoping Fix (fixes add_watch + remove_watch)
- Approach: Instead of wrapping non-last forms in
discard ((proc(): CljVal = ...)()), emit them as direct statements. The IIFE wrapping was added to handle multi-line expressions as non-last forms, but it breaks variable scoping. - Alternative: Use Nim's
{.inline.}procs orblock:labels instead of IIFEs for scope isolation. - Impact: +2 tests (232/233)
Phase B: Multi-file Compilation (fixes not_eq)
- Approach: When
ns :requireencounters a namespace, find and compile the corresponding.cljc/.cljfile, inline its top-level defs into the current compilation unit. - Key files:
src/cljnim.nim(file resolution),src/emitter.nim(ns handler) - Impact: +1 test (233/233)
Phase C: Symbol Emit Fix (fixes 2 unit tests)
- Approach: When emitting a bare symbol that's not a local var and not a runtime function, check if it was defined as a
def/defnin the current compilation unit. If so, emit the mangled name directly instead ofcljSymbol(...). - Impact: +2 unit tests (80/80)
Session Log
2026-05-11 (late session) — Bulk fixes
- Reader: prefer
:defaultover:cljin conditionals - Emitter:
cond,definterface,newspecial forms - Emitter:
nsalias registration,whendiscard,try/catchscope + type mapping - Emitter:
emitBlockvar hoisting out of IIFEs - Emitter: removed all DEBUG stderr output
- Runtime:
random-uuid,System/getProperty,vreset!,restart-agent,require/eval/resolvestubs - Runtime:
Boolean/Object/Integerconstructors - Runtime: seq overloads for
cljAssoc,cljDissoc,cljGet,cljExInfo,cljTransduce - Result: 220/233 → 230/233 compliance, 77/80 → 78/80 unit tests