Commit Graph

38 Commits

Author SHA1 Message Date
dimgigov 11fca52282 fix: 18 bugs across interpreter, reader, emitter, and runtime
- 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>
2026-05-20 12:25:53 +03:00
dimgigov 7cb8aa1ee0 feat: project build system with lib/bin separation
- Add src/project.nim: parse bara.edn manifest (name, version, lib, bins)
- Add cljnim build / cljnim build --mono commands
- Compile lib modules once to target/nim/lib_*.nim with exported defs
- Cross-module symbol resolution via from/import nil + fully qualified names
- Emitter: lib mode with * export markers, variadic seq[CljVal] handling
2026-05-16 19:20:23 +03:00
dimgigov 4b208dbe55 fix: threading macros, REPL stability, and CI coverage
- fix(emitter): emitFnWrapper now uses runtimeName for builtin operators
- fix(emitter): map/reduce handlers support variadic runtime functions (+, -, etc.)
- fix(emitter): variadic runtime functions list extracted to variadicRuntimeFns constant
- fix(macros): restore correct thread-first behavior (->) and fix result shadowing
- fix(macros): and/or/as->/some->/some->> macro result variable fixes
- fix(repl): add macroexpand step before interpreter eval
- fix(runtime): cljReduceSeq handles nil init (uses first coll element)
- fix(eval): add macroexpand/macroexpand-1 special forms to interpreter
- fix(eval): add macros module import for macroexpand access
- fix(warnings): eliminate ResultShadowed and UnusedImport warnings
- chore(.gitignore): remove artifact entries (-o, =0.4.0), unignore lib/bring_http.nim
- chore(ci): run all examples + threading macro + macroexpand REPL smoke tests
2026-05-12 20:02:58 +03:00
dimgigov 014a192c5d fix(runtime): cljAssocIn handles vectors as keys path
fix(emitter): remove contains? from special-forms list (handled elsewhere)
2026-05-12 18:55:27 +03:00
dimgigov a1a65f1c27 fix(emitter): loop in expression context via needsValue + IIFE wrapper
- 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
2026-05-12 12:54:00 +03:00
dimgigov aac39a08ca feat(emitter): first-class defn functions via cljFn wrapper
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
2026-05-12 11:42:07 +03:00
dimgigov 3aaf3c0548 fix(emitter): avoid clj_ prefix on nim/ interop identifiers
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.
2026-05-12 11:16:16 +03:00
dimgigov fb8928e830 fix: clj_ prefix for identifiers + try/catch/finally fixes
- #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
2026-05-12 00:48:50 +03:00
dimgigov e36bf4e362 fix: implement cljnim compiler recommendations (10 fixes)
- #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
2026-05-12 00:42:17 +03:00
dimgigov 79cd9c08d8 chore: rebrand Clojure/Nim → Bara Lang across codebase
- Bulk replace Clojure/Nim → Bara Lang in src/, lib/, examples/, benchmarks/,
  experiments/, books/, LICENSE, cljnim.nimble, PLAN.md, AI_AGENT.md
- Rename book chapters: 05-clojure-nim.md → 05-bara-lang.md (en + bg)
- Update all chapter index links and anchors
- Replace project-specific 'Clojure' references with 'Bara Lang' in
  experiments/, src/ai_assist.nim, src/tui_screens.nim, src/emitter.nim,
  src/reader.nim, src/types.nim, lib/cljnim_runtime*.nim
- Keep legitimate JVM Clojure/ClojureScript/Clojure CLR references intact
2026-05-11 12:23:29 +03:00
dimgigov 55f0cd842c feat: jsonista-style production JSON example
- Добавени 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
2026-05-11 10:54:29 +03:00
dimgigov 456636700c feat: 80/80 unit tests, real-world examples (FizzBuzz, WordFreq)
- Emitter: def registry (definedGlobals) for symbol emit distinction
- Emitter: cond emits return statements
- Emitter: reduce wraps named functions in closure adapter
- Emitter: clojure.string/* function mappings (split, lower-case, etc.)
- Emitter: statement detection for echo cljRepr wrapping
- Runtime: cljGet supports default value (3 args)
- Runtime: cljStrSplit supports regex patterns via re module
- Examples: fizzbuzz.clj and wordfreq.clj both compile and run correctly
- Tests: emit symbol / emit mangled symbol now pass (80/80)
- Compliance: 233/233 (100%) maintained
2026-05-11 10:08:46 +03:00
dimgigov 4afef5a264 feat: 233/233 (100%) — STM refs, multi-file ns requires, NaN/Inf float emit
- add ref/ref-set/dosync/alter runtime mappings + cljRef/cljRefSet/cljDosync/cljAlter impl
- extractRequires now walks do forms for ns; resolveNsToPath tries .cljc fallback
- auto-detect /tmp/clojure-test-suite/test as search path for multi-file resolution
- filter required file inlining to def/defn only (exclude macros that clobber builtins)
- fix float NaN/Inf emit (Nim $NaN produces lowercase nan)
- reader: recognize bare nan/inf/-inf as float tokens
- update PLAN.md to 100% compliance
2026-05-11 04:52:31 +03:00
dimgigov 14fc765c78 fix: var hoisting in emitBlock for def inside deftest bodies
- emitBlock now hoists 'var' declarations out of IIFE wrappers
- emitProgramInternal cleaned up (removed debug output)
- Exception type mapping: unknown types preserved (e.g. ValueError)
- 230/233 compliance (98.7%), 78/80 unit tests (97.5%)
2026-05-11 03:44:59 +03:00
dimgigov d7e5697f3a fix: 230/233 (98.7%) — reader :default preference, cond/new/definterface, runtime stubs, seq overloads
- Reader: prefer :default over :clj in reader conditionals
- Emitter: add cond, definterface, new special forms
- Emitter: ns handler registers namespace aliases from :require
- Emitter: when body always discarded (fixes type mismatch with else)
- Emitter: try/catch maps clojure.lang.ExceptionInfo → ExInfo, scope catch vars
- Emitter: def inside proc uses var (not {.global.}), removed debug output
- Runtime: cljRandomUuid, cljSystemGetProperty, cljVresetB, cljRestartAgent
- Runtime: cljRequire, cljEvalStub, cljResolve no-op stubs
- Runtime: Boolean/Object/Integer/Long/Float/Double constructors
- Runtime: seq overloads for cljAssoc, cljDissoc, cljGet, cljExInfo, cljTransduce
- Unit tests: 78/80 (was 77/80)
- 3 remaining: not_eq (cross-namespace), add_watch/remove_watch (def hoisting)
2026-05-11 03:36:53 +03:00
dimgigov e5897125fd chore: emitter/runtime improvements from previous session 2026-05-11 01:49:48 +03:00
dimgigov 549e04f24d feat: +12 tests (210/233, 90%) — fn wrapping, doseq, when-first, NaN?, delay, loop scope
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
2026-05-09 23:17:02 +03:00
dimgigov 48e64aec7f fix: +1 test (198/233, 85%) — identity/conj variadic for update test 2026-05-09 20:37:37 +03:00
dimgigov fb13f15c39 fix: +3 tests (197/233, 85%) — bigint overflow, var_qmark indent, merge double discard 2026-05-09 20:34:26 +03:00
dimgigov 88a04f8b67 feat: +11 more tests (194/233, 83%) — array stubs, cons/atom/cycle variadic, string escaping, empty/case 2026-05-09 20:14:31 +03:00
dimgigov 6633c3708d feat: +13 tests (184/233, 79%) — case, hex/radix, protocol/record stubs, doseq destructuring 2026-05-09 19:53:08 +03:00
dimgigov f79a2591d4 fix: expand variadic list + add runtime stubs — 174/233 (74%)
Runtime: cljCompare, cljSubvec, cljRand, cljRandInt, cljRandNth,
cljRandomSample with native Nim implementations
Emitter: expanded variadic function list for correct seq[CljVal] calling

Results: 174/233 passed (74%)
  clojure.string: 8/8 (100%)
  clojure.core: 166/225 (74%)
2026-05-09 18:21:14 +03:00
dimgigov cb69df4ee2 fix: reader #" #uuid dispatch, emitter metadata/fn/def fixes, runtime stubs
Reader: #" regex literals and #uuid"..." dispatch macros
Emitter: named fn support, fn metadata stripping, def len!=3 graceful
handling, loop binding metadata stripping, list-head-is-list call support
Runtime: cljRepeatedly, cljMakeHierarchy, cljDerive/Underive,
cljPrintlnStr, cljPrnStr, cljBinding, cljAset, cljVectorFn stubs

Results: 164/233 passed (70%), clojure.string 8/8 (100%)
2026-05-09 17:59:24 +03:00
dimgigov 624837ac7a fix: 70% test suite pass rate (164/233)
Emitter: iterative worklist-based form processing (no more stack overflow),
type conversion functions (float/int/double/long/short/byte/boolean),
metadata stripping in def/defn/defn-, to-array runtime mapping

Macros: namespace-qualified macro resolution (t/deftest -> deftest),
when-var-exists macro restored, are/testing/is/thrown? built-in macros

Runtime: cljToFloat, cljToInt, cljToBool, cljToArray conversion wrappers,
cljVolatileBang, cljDeliver, cljDoall, cljDorun, cljDropLast,
cljShuffle, cljFnil, cljIntern stubs

Results: 164/233 passed (70%)
  clojure.string: 8/8 (100%)
  clojure.core: 156/225 (69%)
2026-05-09 17:33:12 +03:00
dimgigov e6859568b3 fix: clojure test suite compatibility — 145/225 passing (64%)
Reader: #? reader conditionals with :default, #?@ splicing, char literals,
N/M suffix and ratio parsing, comma as whitespace, number parsing fix
for negative BigInt/Decimal/Ratio literals

Emitter: mangleName trailing/double underscore fixes, scope stack for
local var tracking, symbol-as-value emits cljSymbol() not bare identifier,
macro-expanded do-unwrap in processForm, emitBlock multiline wrap,
indentCode helper, when-var-exists emitter form, variadic apply fix,
fn proc spacing fix, def indent fix

Macros: deftest, is, testing, thrown?, are, when-var-exists builtins;
rewritten and/or using gensym; improved for/doseq/dotimes; cond->
and cond->> threading fixes; threading macro insert fixes

Runtime: sorted-map, sorted-set, sorted?, array-map, object-array,
hash-map, hash-set, inf, nan; assoc extended to vectors

Test runner: #?@ splice unwrapping, removed conflicting defmacro stubs
2026-05-09 16:14:44 +03:00
dimgigov a9ad83c509 fix: general equality (=) for all types, add type predicates & collection fns, test suite docs
- 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
2026-05-09 12:17:10 +03:00
dimgigov ba0b300917 feat: add fullscreen TUI and project updates
- 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
2026-05-09 01:53:23 +03:00
dimgigov 88866872be Bugfixes: add cljQuot/cljRem to runtime, quot/rem to interpreter. Cleanup: remove unused processAgentActions and sequtils import. 164 tests pass. 2026-05-08 20:45:36 +03:00
dimgigov 30fde68fed Phase 9: Agents (send/await/deref) + core.async channels (chan, >!, <!, close!, go). All phases complete. 2026-05-08 20:28:51 +03:00
dimgigov b67962dbba Phase 5/6 complete: Transients, meta/with-meta, instance?
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.
2026-05-08 19:48:35 +03:00
dimgigov 66d91cd086 Phase 7: ns declaration + multi-file compilation
T7.1: Namespace declaration parsing
  (ns my.app (:require [lib :as l])) with :require/:as support
  Hyphen-to-underscore filename convention (math-utils -> math_utils.clj)

T7.2: Multi-file compilation
  Resolves requires, recursively loads dependencies
  Inlines all defs into single Nim file
  Namespace alias resolution (mu/square -> square)

86 tests pass, all examples work.
2026-05-08 19:37:35 +03:00
dimgigov 19ef69bf5b Phase 6: slurp, spit, read-line, range 3-arg, repeat/cycle/iterate, interleave
Phase 6 Clojure Core Library now complete (except meta):
- T6.3: slurp (alias for file/read)
- T6.4: spit (alias for file/write)
- T6.5: read-line (stdin input)
- T6.6: range with 3 args (start, end, step)
- T6.7: repeat, cycle, iterate (eager implementations)
- T6.9: interleave
- Updated TASKS.md and ROADMAP.md
2026-05-08 19:24:06 +03:00
dimgigov 6dfc2a9308 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
2026-05-08 19:13:09 +03:00
dimgigov d763e25638 Phase 5: HAMT Persistent Vector + CI fixes
- 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
2026-05-08 17:58:00 +03:00
dimgigov b239dd959b AI git commit test from Clojure 2026-05-08 17:11:12 +03:00
dimgigov 5971c062d1 Add AI-first REPL with JSON mode 2026-05-08 16:51:05 +03:00
dimgigov 87d6028487 Phase 1-4: Reader, Runtime, Macros, Nim Interop — 543x faster than JVM Clojure
- Reader: maps, sets, syntax-quote, dispatch macros, metadata
- Runtime: CljVal type system, 80+ core functions (collections, strings, math, IO)
- Emitter: full CljVal-based code generation, macro expansion, inline fns
- Macros: defmacro with compile-time evaluator, ->, ->>, and, or, when, cond, for, doseq
- Nim Interop: nim/module/function syntax, auto-import, type mapping
- CLI: cljnim -e '<code>' for quick evaluation
- Tests: 60 unit tests (reader + emitter)
- Benchmarks: AOT suite showing 543x startup, 679x factorial vs JVM Clojure
- CI: GitLab CI pipeline
- Runtime library: lib/cljnim_runtime.nim (1070+ lines)
2026-05-08 16:34:39 +03:00
dimgigov f89b381fdb Initial commit 2026-05-08 14:51:47 +03:00