Files
bara-lang/ARCHITECTURE.md
T
2026-05-08 14:51:47 +03:00

7.0 KiB
Raw Blame History

Архитектура: Истински 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 Структури

;; Това трябва да работи без промяна:
(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 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:

;; Извикване на 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