Files
bara-lang/PLAN.md
T

5.6 KiB

Clojure/Nim — Test Suite Compliance Plan

Current Status: 198/233 (85%)

Component Pass Total %
clojure.string 8 8 100%
clojure.core 190 225 84%
Total 198 233 85%

Progress This Session (2026-05-09)

Started: 171/233 (73%) → Current: 198/233 (85%) — +27 tests

Newly Passing Tests

  • Priority 1 (5): case, derive, underive, dissoc, ifn_qmark
  • Priority 2 (3): hash_set, conj, conj_bang
  • Priority 3 (5): bit_and, bit_and_not, bit_flip, bit_set, bit_shift_left (ALL!)
  • Runtime fixes (8): aclone, empty, constantly, transient, cons, bigint, var_qmark, update
  • Emitter fixes (7): compare, drop_last, fnil, vec, shuffle, merge
  • Runtime additions (4): bit operations, identity, conj variadic

Key Changes Made

  • Emitter: Added case special form, defprotocol/defrecord/deftype/defmulti/defmethod minimal support, var special form, bound-fn delegation to fn, . constructor stripping
  • Runtime: Added var?, ifn?, ancestors, descendants, parents, isa?, promise, future, make-hierarchy stubs; fixed cljTake/cljDrop to accept CljVal
  • Reader: Fixed hex literal parsing (0xff), added radix literal support (2r1111, 16rFF)
  • Macros: Added doseq destructuring support for [[a b] coll] patterns
  • Test runner: Removed #{} regex replacement (reader now handles natively)
  • When-var-exists: Extended to recognize new special forms

What's Working (184 tests passing)

Core Infrastructure

  • Reader: Clojure syntax parsing, #? reader conditionals, #uuid"...", #"regex", char literals, N/M/ratio suffixes, comma as whitespace, hex literals (0xFF), radix literals (2r101)
  • Emitter: Macro expansion, scope tracking, iterative worklist form processing, metadata stripping, namespace-qualified macro resolution
  • Macros: deftest, is, testing, are, thrown?, when-var-exists, and, or, when, when-not, cond, for, doseq, dotimes, ->, ->>, some->, some->>, cond->, cond->>, doto, as->, defmacro, comment
  • HAMT Data Structures: Persistent Vector, Map, Set — all native Nim, zero Java dependency
  • Runtime: 100+ functions implemented (arithmetic, collections, predicates, I/O, agents, channels)

clojure.string

All 8 tests pass: blank?, capitalize, ends-with?, escape, lower-case, reverse, starts-with?, upper-case

Remaining Failures (49 tests)

Priority 1 — Advanced Features (~7 tests remaining)

New emitter support added for defprotocol, defrecord, deftype, defmulti, defmethod. Remaining issues:

  • ancestors, descendants, parents — double discard in generated Nim from doseq destructuring
  • bound_fn, bound_fn_starfuture type mismatch in generated code
  • var_qmarkdefn indentation in value position
  • not_eq — cross-file namespace import issues

Priority 2 — Reader/Preprocessing (~3 tests remaining)

Fixed #{} regex removal. Remaining:

  • add_watch — catch form error
  • remove_watch — Nim indentation error
  • reduce — map reader requires even number of forms

Priority 3 — are_arity (0 tests)

ALL 5 TESTS PASSING! Fixed hex and radix literal parsing in reader.

Priority 4 — Missing Runtime Functions (~10 tests)

Simple stubs needed:

  • aclone, int-array — Java array interop stubs
  • rseq — reverse sequence
  • empty — empty collection (different from empty?)
  • delay — lazy evaluation
  • create-ns — namespace creation
  • sorted-map-by — sorted map with comparator

Priority 5 — Type Mismatches (~9 tests)

Nim type errors from edge cases in macro expansion:

  • compare, cons, drop_last, fnil, get, shuffle, vec, update, taps

Priority 6 — Other (~13 tests)

  • bigint — integer overflow on big numbers
  • constantly, atom, transient — closing quote errors in generated Nim
  • merge — syntax error in generated code
  • portability — unquote-splicing edge case
  • random_uuid, uuid_qmark, parse_uuid — UUID dispatch reader issue
  • realized_qmark, when_first, when_let — indentation issues

Architecture Notes

Compilation Pipeline

Clojure source → Reader (AST) → Macro expansion → Emitter (Nim code) → Nim compiler → C compiler → native binary

Key Files

  • src/reader.nim — Clojure parser (~530 lines, added hex/radix support)
  • src/emitter.nim — Nim code generator (~1660 lines, added case/record/protocol/type support)
  • src/macros.nim — Macro system (~542 lines, added doseq destructuring)
  • lib/cljnim_runtime.nim — Runtime library (~1960 lines, added var?/ifn?/ancestors/hierarchy)
  • lib/cljnim_pvec.nim — HAMT Persistent Vector
  • lib/cljnim_pmap.nim — HAMT Persistent Map
  • test_single.py — Test runner for clojure-test-suite

What Makes This Different from Other Clojure Dialects

  • No JVM — compiles to native via Nim → C
  • Native HAMT — persistent data structures written in Nim, not Java
  • Zero dependencies — no GraalVM, no JVM, no Google Closure Compiler
  • Multi-target — native, shared library, WASM, JavaScript

Next Steps to Reach 90%+

  1. Fix ancestors/descendants/parents emitter issues (~3 tests)
  2. Fix bound_fn/bound_fn_star future type mismatch (~2 tests)
  3. Fix var_qmark defn value-position issue (~1 test)
  4. Add remaining runtime function stubs (~10 tests)
  5. Fix Nim type edge cases in emitter (~5 tests)
  6. Fix Priority 6 edge cases (~13 tests)

Estimated effort: 2-3 more focused sessions to reach 90%+ (210+/233).