- cljMinMax now handles float and mixed int/float arguments
- cljType* covers ckSet, ckTransient, ckAgent
- cljConj and cljVec return vectors instead of lists
- rem uses truncated division semantics (matches Clojure)
- range with negative step terminates correctly
- reduce of empty collection with no init errors instead of returning nil
- swap! extra args flatten correctly
- remove duplicate not definition (dead code)
- ratio literals (1/5) parse correctly
- scientific notation uses correct variable (numTok not tok)
- readSet returns proper set value instead of (set [...]) form
- TCP REPL catches specific exceptions instead of bare except
- initBuiltinMacros guards against duplicate registration
- doseq :while clause no longer generates dead code or infinite loop
- emitter resets all global state on each emitProgram call
- pushLeaf fills gaps with internal nodes instead of nil children
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add needsValue parameter to emitExpr/emitSpecialForm to track expression context
- loop wraps in (proc(): CljVal = ... )() when needsValue=true
- Function call args, let/def values, vector/map literals pass needsValue=true
- emitProgramInternal passes needsValue=isLast for top-level forms
- Fixes: loop as function arg, loop in let RHS, loopResult at top level
User-defined defn functions can now be passed as values to other
functions (e.g. bring/run-server, apply-fn, map, filter).
- Track function arities in definedFnArities table
- Register defn/defn- arities during emission
- Emit cljFn wrapper when a defn symbol is used as a value:
* Multi-arity / rest: cljFn(procName) (already seq[CljVal])
* Single-arity: cljFn(proc(args): procName(args[0], ...))
- Direct calls remain unchanged (fast path)
- All existing emitter tests pass
The clj_ prefix added in fb8928e broke nim/module/proc interop because
native Nim identifiers were being mangled to clj_foo instead of foo.
- Extract sanitizeNimIdent from mangleName (does all cleanups except prefix)
- Use sanitizeNimIdent for nim/ interop function chains
- Regular Clojure symbols still get clj_ prefix via mangleName
Fixes BRing bringRunServer and other native Nim proc calls.
- #9: Add clj_ prefix to all mangled identifiers to avoid Nim
case-insensitive name conflicts (parseQueryString ≡ parse_query_string)
- #11: Fix finally block - discard expression results
- #11: Fix catch handler - use original name for scope tracking
- Fix loop handler - use original name for addToScope
- Update emitter tests for clj_ prefix
- #1: Support docstrings in defn/defn-
- #2: Support multi-arity defn with dispatch by args.len
- #3: (:key map) keyword-as-function syntax (cljGet)
- #4: & rest parameters in defn/defn-
- #5: Nim interop name mangling for nim/ module calls
- #6: getLibPath() checks CLJNIM_LIB_PATH env and cwd first
- #7: Parse :paths from deps.edn
- #8: loop+if/else discard fix with loopResult variable
- #10: emitProgramLib skips when isMainModule guard
- Добавени JSON runtime функции в cljnim_runtime.nim
(write-value-as-string, read-value, file I/O, keyword-keys, pretty print)
- Регистрирани json/* функции в emitter.nim
- Създаден production пример examples/jsonista.clj
(моделиран след metosin/jsonista, без Java зависимости)
- Добавен README examples/jsonista.md
- Поправен cljGetIn да приема vectors
- Поправен cljOptBool за ?-suffixed ключове
- Добавен пример в Makefile check
- Обновен .gitignore
Major changes:
- fn handler wraps with cljFn for higher-order functions (rand, rand_int, rand_nth)
- def handler emits raw proc for (def f (fn ...)) context
- Local fn calls use .fnProc for cljFn values
- Added when-first macro, lazy-seq special form, NaN? predicate
- Added delay, rseq, listEmpty runtime functions
- doseq macro uses next instead of rest, recur inside when body
- loop handler pushScope/popScope for proper variable scoping
- let handler: var/while/proc statement checks, block last-line discard
- when handler: proper statement detection for body forms
- defn/defn- allow empty body
- Fix: = now uses cljEqual/cljMultiEqual instead of numeric-only cljNumEq,
so (= :a :a), (= "a" "a"), (= [1 2] [1 2]), (= nil nil) etc return true
- Fix: ns forms inside unwrapped (do ...) are skipped instead of emitting
broken Nim comments inside cljRepr()
- Fix: defmacro forms go to defs section, not wrapped in discard cljRepr()
- Add 18 type predicates: keyword?, symbol?, string?, number?, integer?,
float?, vector?, map?, set?, list?, seq?, coll?, sequential?, fn?,
boolean?, true?, false?, some?
- Add collection fns: second, ffirst, nfirst, peek, pop
- Add keyword/symbol ops: keyword, symbol, name, namespace, key, val
- Update eval interpreter = to handle structural collection equality
- Add test_single.py + test_vals.clj for Clojure test suite runner
- Add docs/en/07 and docs/bg/07 for cross-dialect test suite compatibility
- Update README with test suite documentation link
- New TUI screens: Main Menu, Compile, Run, REPL, AI Generator, AI Settings, Help
- AI configuration persisted in ~/.config/cljnim/config.json
- Added illwill dependency for terminal UI
- Updated experiments, examples, docs, and core modules
T5.5 Transients (transient/persistent!/conj!/assoc!)
- Mutable builder for batch vector/map operations
- Use with let bindings for proper ordering
T6.10 meta/with-meta — metadata on any CljVal via ref object field
T6.11 instance? — type predicate (instance? :integer 42)
Also marked T9.1 Atoms as done (already implemented earlier)
86 tests pass, all examples work.
Phases 0-6 now complete. Phase 7: 2/4 tasks done.
- Add lib/cljnim_pvec.nim: 32-way HAMT Persistent Vector with structural sharing
- Migrate ckVector from seq[CljVal] to PersistentVector[CljVal] in runtime
- Fix recursive pushLeaf bug (nil nodes at depth > 2)
- Fix defn/if return value bug: replace discard with result = in proc bodies
- Fix cljNth to accept CljVal index
- Add len and [] overloads for PersistentVector seq compatibility
- Add tests/test_pvec.nim (14 tests)
- Update .gitlab-ci.yml to nim:2.2.10 and add test_pvec
- Update docs/ROADMAP.md and add PHASE5_HAMT.md