Initial commit
This commit is contained in:
+169
@@ -0,0 +1,169 @@
|
||||
# Архитектура: Истински 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 |
|
||||
Reference in New Issue
Block a user