22
33This document describes the internal architecture of ClojureWasm.
44
5+ ## Zone Architecture
6+
7+ CW uses a strict 4-zone layered architecture. Lower layers never import
8+ from higher layers. Zone dependencies are enforced by CI (0 violations).
9+
10+ ```
11+ Layer 0: src/runtime/ — Value, collections, GC, environment
12+ Layer 1: src/engine/ — Reader, Analyzer, Compiler, VM, TreeWalk
13+ Layer 2: src/lang/ — Built-in functions, interop, lib namespaces
14+ Layer 3: src/app/ — CLI, REPL, deps.edn, Wasm bridge
15+ ```
16+
17+ When a lower layer needs to call a higher layer, the vtable pattern
18+ is used (` runtime/dispatch.zig ` ): the lower layer defines function
19+ pointers that the higher layer sets during initialization.
20+
521## Pipeline Overview
622
723ClojureWasm processes Clojure source code through a four-stage pipeline:
@@ -43,7 +59,7 @@ by `EvalEngine.compare()` tests.
4359
4460## Reader
4561
46- ** Files** : ` src/reader/reader.zig ` , ` src/reader/tokenizer.zig ` , ` src/reader/form.zig `
62+ ** Files** : ` src/engine/ reader/reader.zig ` , ` src/engine/ reader/tokenizer.zig ` , ` src/engine /reader/form.zig `
4763
4864The reader converts source text into a Form tree (a syntax tree before
4965semantic analysis). It handles:
@@ -57,7 +73,7 @@ semantic analysis). It handles:
5773
5874## Analyzer
5975
60- ** Files** : ` src/analyzer/analyzer.zig ` , ` src/analyzer/node.zig `
76+ ** Files** : ` src/engine/ analyzer/analyzer.zig ` , ` src/engine /analyzer/node.zig `
6177
6278The analyzer transforms Forms into Nodes (an executable AST). It resolves
6379variable bindings, expands macros, and compiles regex patterns at analysis
@@ -71,8 +87,8 @@ Key responsibilities:
7187
7288## Compiler + VM
7389
74- ** Files** : ` src/compiler/compiler.zig ` , ` src/compiler/opcodes.zig ` ,
75- ` src/compiler/chunk.zig ` , ` src/vm/vm.zig `
90+ ** Files** : ` src/engine/ compiler/compiler.zig ` , ` src/engine /compiler/opcodes.zig ` ,
91+ ` src/engine/ compiler/chunk.zig ` , ` src/engine /vm/vm.zig `
7692
7793The compiler transforms Nodes into bytecode stored in Chunks. Each
7894instruction is a fixed 3-byte format: u8 opcode + u16 operand.
@@ -110,7 +126,7 @@ The VM is a stack-based machine with:
110126
111127### ARM64 JIT
112128
113- ** File** : ` src/vm/jit.zig `
129+ ** File** : ` src/engine/ vm/jit.zig `
114130
115131A proof-of-concept JIT compiler for hot integer loops on ARM64.
116132
@@ -122,7 +138,7 @@ A proof-of-concept JIT compiler for hot integer loops on ARM64.
122138
123139## TreeWalk Interpreter
124140
125- ** File** : ` src/evaluator/tree_walk.zig `
141+ ** File** : ` src/engine/ evaluator/tree_walk.zig `
126142
127143The TreeWalk interpreter evaluates Nodes directly without compilation.
128144It maintains a local binding stack (256 slots) and closure capture.
@@ -173,7 +189,7 @@ allocations are cached (up to 4096 blocks per pool) for O(1) reuse.
173189
174190## Bootstrap
175191
176- ** File** : ` src/runtime /bootstrap.zig `
192+ ** File** : ` src/engine /bootstrap.zig `
177193
178194ClojureWasm uses a two-phase bootstrap:
179195
@@ -193,11 +209,11 @@ in ~4ms by skipping the parse/analyze/eval cycle for core.clj.
193209
194210## Wasm Runtime
195211
196- ** Files** : ` src/wasm/*.zig `
212+ ** Files** : ` src/app/ wasm/*.zig ` , ` src/runtime/wasm_types .zig`
197213
198- A built-in WebAssembly interpreter supporting 461 opcodes (225 core + 236
199- SIMD). Clojure code can load and call Wasm modules via the ` cljw.wasm `
200- namespace.
214+ The Wasm runtime is powered by [ zwasm ] ( https://github.com/clojurewasm/zwasm ) ,
215+ supporting 523 opcodes (236 core + 256 SIMD + 31 GC). Clojure code can load
216+ and call Wasm modules via the ` cljw.wasm ` namespace.
201217
202218Key components:
203219- ** Module parser** : Decodes Wasm binary format (types, functions, tables,
@@ -207,13 +223,11 @@ Key components:
207223- ** VM** : Stack-based interpreter with switch dispatch over predecoded IR
208224- ** WASI** : File I/O, clock, random, args, environ
209225- ** Multi-module linking** : Cross-module function imports
210- - ** SIMD** : v128 type with 236 SIMD opcodes
226+ - ** SIMD** : v128 type with 256 SIMD opcodes
227+ - ** GC proposal** : 31 GC opcodes (struct, array, ref types)
211228
212- Performance: The interpreter is ~ 10-30x slower than wasmtime (JIT compiler)
213- for compute-heavy modules. This is the fundamental interpreter-vs-JIT gap —
214- wasmtime compiles Wasm to native machine code via Cranelift, while ClojureWasm
215- dispatches predecoded instructions one at a time. Module load time is faster
216- (~ 4ms vs ~ 5ms) since no compilation step is needed.
229+ Performance: zwasm uses Register IR with ARM64/x86_64 JIT compilation,
230+ winning 14/23 benchmarks against wasmtime with a ~ 43x smaller binary.
217231
218232## Regex Engine
219233
@@ -225,7 +239,7 @@ at runtime.
225239
226240## nREPL Server
227241
228- ** Files** : ` src/repl/nrepl.zig ` , ` src/repl/bencode.zig `
242+ ** Files** : ` src/app/ repl/nrepl.zig ` , ` src/app /repl/bencode.zig `
229243
230244A CIDER-compatible nREPL server supporting 14 operations: eval, load-file,
231245complete, info, lookup, stacktrace, clone, close, describe, ls-sessions,
0 commit comments