# Архитектура: Истински Clojure върху Nim ## Философия Това не е "Clojure-подобен" език. Това е **Clojure диалект**, който компилира към Nim. Макросите, структурите от данни и семантиката са съвместими с Clojure (JVM). ### Защо истински Clojure? | Аспект | Clojure-inspired Lisp | Истински Clojure диалект | |---|---|---| | **Библиотеки** | Пишеш всичко на ново | Можеш да пренесеш `clojure.core`, `clojure.string`, `clojure.set` | | **Разработчици** | Учат нов език | Всеки Clojure програмист може да го ползва веднага | | **Инструменти** | Собствени | Работи с `clojure-mode`, CIDER, Calva (с някои адаптации) | | **Финтех/Indустрия** | Не е опция | Може да се ползва за реални проекти | ### Който го е правил успешно - **ClojureScript** — компилира Clojure до JS. Използва Google Closure. Пълна съвместимост. - **Babashka** — GraalVM native image на Clojure. Бърз старт, скриптове, портативен. - **Ferret** — Clojure → C++11 за embedded системи. Работи на 2KB RAM. - **ClojErl** — Clojure върху BEAM. Жертва част от performance заради семантиката. ## Архитектура на Компилатора ``` ┌─────────────────┐ │ .clj Файл │ ← Стандартен Clojure код └────────┬────────┘ │ ┌────▼────┐ │ Reader │ ← EDN парсер, Clojure symbols, quoted forms └────┬────┘ │ ┌────▼────┐ │ Macro │ ← defmacro, syntax-quote, unquote, unquote-splicing │ Expansion│ (работи върху Clojure структури) └────┬────┘ │ ┌────▼────┐ │ Analyzer│ ← Специални форми, locals, recur targets, │ │ closures, type hints └────┬────┘ │ ┌────▼────┐ │ Emitter │ ← Генерира Nim AST (не Nim текст!) │ (Nim) │ Използва Nim макроси за компилация └────┬────┘ │ ┌────▼────┐ │ Nim │ ← C код, после машинен код │Compiler │ оптимизация, tree-shaking, LTO └────┬────┘ │ ┌────▼────┐ │ Бинарен │ ← Единичен файл, < 10MB, бърз старт │ Файл │ └─────────┘ ``` ## Ключови Решения ### 1. Компилатор, не Интерпретатор Изборът е **AOT компилатор**, подобно на ClojureScript. Няма да пишем интерпретатор в Nim. - **Предимство:** Бърз runtime, малък footprint, компилира до C. - **Недостатък:** REPL е по-труден (но не невъзможен — виж ClojureScript self-hosted). - **Урок от calcit-runner:** Те започнаха с интерпретатор в Nim и се провалиха. Ние директно компилираме. ### 2. Clojure Макроси на Clojure Структури ```clojure ;; Това трябва да работи без промяна: (defmacro unless [condition & body] `(if (not ~condition) (do ~@body))) (unless false (println "Работи!")) ``` Макросите се разширяват **преди** да стигнем до Nim. Nim никога не вижда Clojure макрос. ### 3. Persistent Структури от Данни в Nim Clojure's Hash Array Mapped Trie (HAMT) трябва да се имплементира в Nim: ```nim # Nim runtime за Clojure Vector type NodeKind = enum nkLeaf, nkInternal Node[T] = ref object case kind: NodeKind of nkLeaf: values: seq[T] of nkInternal: children: array[32, Node[T]] PersistentVector[T] = object root: Node[T] tail: seq[T] count: int ``` - `conj`, `assoc`, `dissoc` — O(log₃₂ n) - `nth`, `get` — O(log₃₂ n) - `count` — O(1) ### 4. Nim Interop (вместо Java Interop) Тъй като нямаме JVM, interop-ът е с Nim: ```clojure ;; Извикване на Nim функция (nim/strutils.join ", " ["a" "b" "c"]) ;; Достъп до Nim тип (nim/times.DateTime) ;; FFI към C библиотека (nim/ffi.import "math.h" :functions [["sin" :double [:double]]]) ``` ### 5. Симулация на Clojure Runtime | Clojure JVM | Нашата Имплементация | |---|---| | `Var` | Глобални Nim променливи с atomic CAS | | `Namespace` | Nim модул + хеш таблица със символи | | `Atom` | `ref` тип с compare-and-swap | | `Agent` | Channel + Worker thread | | `Ref/STM` | Software transactional memory в Nim | | `Multimethod` | Диспач таблица + `isa?` проверка | | `Protocol` | Nim concepts + dispatch таблица | ## Фази с Индустриален Фокус ### Phase 1: Компилатор (не REPL!) Фокус: AOT компилация на прости Clojure файлове към Nim. ### Phase 2: Core Библиотека Фокус: Пренасяне на `clojure.core` функции. Тестове с реални Clojure тестове. ### Phase 3: Nim Interop + FFI Фокус: Извикване на Nim/C библиотеки. Това е нашето "убийствено" предимство. ### Phase 4: REPL (Self-hosted) Фокус: REPL като ClojureScript (компилира в паметта). ### Phase 5: Инструменти Фокус: nREPL съвместимост, LSP, пакетен мениджър (Nimble интеграция). ## Изисквания за Съвместимост - `clojure.core` namespace трябва да е наличен - `defn`, `let`, `if`, `do`, `recur`, `loop` — точна семантика - `->`, `->>`, `cond->` — макроси - Persistent Vector, Map, Set — стандартни операции - Keywords (`:name`) и Symbols (`'sym`) — interned ## Разлики от JVM Clojure (приемливи) | JVM Clojure | Clojure/Nim | |---|---| | Java interop | Nim interop | | JVM threads | Nim threads (no GIL!) | | Dynamic classloading | AOT компилация | | `gen-class` | `gen-nim` (генериране на Nim типове) | | Reflection | Compile-time метаданни | | Big ecosystem | Достъп до Nim + C ecosystem |