- Emacs Lisp 93.6%
- Emacs-Lisp 2.7%
- Shell 2.5%
- PowerShell 0.7%
- Makefile 0.4%
|
|
||
|---|---|---|
| .github/workflows | ||
| bench | ||
| bin | ||
| docs | ||
| examples | ||
| lisp | ||
| packages | ||
| release | ||
| scripts | ||
| src | ||
| test | ||
| tools | ||
| .codex | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| BRIEFING.org | ||
| FINDINGS.md | ||
| install.sh | ||
| LICENSE | ||
| Makefile | ||
| README-stage-d-v2.0.org | ||
| README-stage-d-v3.0.org | ||
| README-stage-d.org | ||
| README.org | ||
| RELEASE_NOTES.md | ||
NeLisp — Self-Hosted Emacs Lisp VM (v0.6.0)
- TL;DR
- Current Release Highlights
- What NeLisp is
- Standalone self-host & parallel build (2026-06)
- Pure-Elisp Substrate (v2.0, 2026-05-22)
- Cross-Platform Support (v2.0, 2026-05-22)
- Status — v0.6.0 (2026-06-26)
- Earlier status (Phase 0 — 2026-04-22) — preserved for reference
- Philosophy (short form)
- Non-goals
- The three-stage vision
- Repository layout
- Optional packages
- Related work (audited)
- License
- Contact
Note on language: I'm a non-native English speaker. The phrasing in this README is shaped with help from an LLM, but the design decisions and technical claims are mine. If something reads oddly, please ask and I'll clarify.
Note on source comments: Comments throughout
lisp/,src/, andscripts/sometimes reference paths such asbuild-tool/src/eval/builtins.rswhen documenting what each pure-Elisp unit replaced. These are historical provenance for the Rust → pure-Elisp migration — the Rustbuild-tool/tree no longer exists in this repository. Read such paths as a record of what was migrated, not as live source files.
TL;DR
NeLisp is a from-scratch Emacs Lisp runtime where essentially the entire language layer (JIT, allocator, GC, coding-system, evaluator, bytecode interp, reader, special forms, builtin dispatcher, object file writers, native code emitters, and standalone OS surface) is written in Elisp itself.
In the wider "replace Emacs" effort, this repo is Layer 1 (the
runtime / reader / AOT compiler that produces target/nelisp). It is
consumed by Layer 2 ../nelisp-emacs (Emacs 意味論) and Layer 3
../nelisp-gui (X11 描画/入力). The 3-layer responsibility boundary,
inter-layer contracts, and completion conditions are fixed in
../nelisp-gui/docs/design/00-three-layer-architecture.org.
The important claim is not merely "Elisp can call into a runtime".
NeLisp's runtime implementation is Elisp: the evaluator, reader,
compiler, allocator, GC, object writers, and native code emitters live
as Lisp source that the project can load, evaluate, redefine, compile,
and eventually self-host. The OS-facing pieces are moving the same
way: standalone file I/O, stdout/stderr, process exit, raw memory,
mmap-backed allocation, atomics, clone(2), fork(2), and the
syscall surface used by the standalone reader are expressed from Elisp
via AOT codegen and syscall-direct.
Current stable release: v0.6.0 (2026-06-26). This release keeps the
project versioned by SemVer git tags, in the same style as anvil.el:
pin users to v0.6.0, let main carry active development, and use
release notes for the exact gate status.
v0.6.0 ships:
- Pure-Elisp runtime implementation — evaluator, reader, special forms, builtins, compiler, allocator, GC, object writers, codegen, and standalone OS interaction all live in Elisp source.
- Cross-platform support on 5 targets — linux/x86_64, linux/aarch64, macos/x86_64, macos/aarch64, windows/x86_64 — with pure-elisp object-file writers (ELF, Mach-O, PE/COFF) and pure-elisp asm encoders (x86_64 with both SysV and Microsoft x64 ABIs, plus AArch64 AAPCS).
- Self-host + parallel build — a pure-elisp AOT-AOT binary
(
target/nelisp, pure Elisp) loads its own compiler and compiles Elisp source → native ELF with no Emacs in the loop, including recursion ((fact 5)→ exit 120), multi-threaded native programs (clone(2)+ atomics), and N units compiled concurrently (fork(2)workers). All CI-gated. SeeStandalone self-host & parallel build. - REPL-driven runtime development — the same pure-Elisp standalone
reader starts a REPL with no arguments; scripts can use
--repl [--no-prompt]. It keeps one live evaluator environment, so redefining a function and calling it again takes effect immediately, including through persistentnelisp--eval-source-string. - Low-footprint standalone load (2026-06) — a hybrid
refcount+tracing compacting GC (
mmap-chunked arena, segregated free-list, a moving collector that forwards live objects andmunmap=s reclaimed chunks) together with an *8-byte tagged-word container representation* (=NlConsBox72→24B; vector / record / cell slots 32→8B) cut the full 319-file vendor-load peak RSS from 1.80GB to 118MB (−93%) and the load time ≈13× (13.4s → 0.9s). A container slot (cons car/cdr, vector element, cell value) is either an immediate (=Nil=/=t=/fixnum) or an 8-byte pointer to a 32-byte child box; the GC marks, forwards, and moves them word-aware. Validated by a 50× load soak under compaction and the 4438-assertion suite. - Reader/core breadth since v0.5.1 — correctly-rounded float parse /
print paths, broader Common Lisp / Emacs Lisp prelude coverage,
additional raw syscall surface, AOT data/blob relocations, defined
varargs,
f64extern returns, bucketed hash tables, incrementalload, and native list-search hot paths for SMIE / Org-style loads.
Use cases: running Elisp on machines without Emacs, and as a substrate for Lisp Machine / new-dialect experiments.
Current Release Highlights
v0.6.0 is the current stable tag. It collects the large post-v0.5.1 develop line into one release and makes SemVer tags the user-facing versioning scheme.
| Area | What changed |
|---|---|
| Versioning | Stable users should pin v0.6.0. main remains the active development branch; historical stage-d names are retained only for installer/runbook compatibility. |
| Standalone runtime | target/nelisp is the primary no-Emacs runtime: REPL, --eval, --load, file execution, runtime-image replay, artifact loading, and self-hosting AOT compile. |
| Pure-Elisp OS/compiler surface | AOT grammar and runtime gained data blobs, frame-alloc, shr, f64-bits, defined SysV varargs, libm/f64 return bridging, and additional raw syscall helpers. |
| Float / printer correctness | Float parse/print work now covers Eisel-Lemire parsing, correctly-rounded power tables, shortest-round-trip printing, C99 hex-float, negative zero, inf/nan, and %f/%e/%g precision. |
| Stdlib breadth | The bare reader prelude gained broader CL/Elisp coverage for package loading: rx/cl-generic helpers, setf places, cl-defstruct breadth, arithmetic gaps, hash-table introspection, list search, and incremental load. |
| Memory footprint | Flat-arena cold-load + compacting GC + 8-byte container slots keep full vendor-load around 118MB peak RSS instead of the older 1.80GB path. |
| Release artifacts | Standalone tarball defaults now use v0.6.0 names: anvil-v0.6.0-<platform>.tar.gz. |
What NeLisp is
A research project to implement Emacs Lisp on a substrate other than the existing Emacs C core — modeled after SBCL (Common Lisp implemented in itself, on a small non-Lisp runtime) and deliberately not a Scheme rewrite or a rewrite of the entire Emacs C core in a different systems language.
The runtime is implemented in Elisp itself. NeLisp keeps the language surface, compiler, memory manager, object writers, OS-facing standalone driver, and development REPL in Lisp source so the system can inspect and modify itself while it is running.
Current source is centered in lisp/, src/, packages/, and
scripts/, with the AOT compiler emitting native object code from
Elisp forms.
Elisp — the language runtime (v1.0 snapshot: 45 files, 54,511 LoC)
The breakdown below is the 2026-04-27 v1.0 snapshot and is retained for
reference. Current totals (2026-05-14) are lisp/ 46 files ~20k LOC
packages/27 files ~14k LOC; seePure-Elisp Migration Progress
for what shifted.
| Subsystem | Files | LoC | Phase |
|---|---|---|---|
| JIT compiler (SSA + linear-scan, x86_64 + arm64; written in Elisp itself) | 13 | 12,196 | 7.1 |
| Memory management (allocator + GC) | 5 | 6,290 | 7.2–7.3 |
| Lisp evaluator (reader, eval, special forms, closures, macros) | 7 | 4,035 | – |
| Module loading and bootstrap | 3 | 2,147 | 7.5 |
| Coding-system (logic) | 1 | 1,928 | 7.4 |
| Bytecode interpreter | 1 | 1,845 | – |
| Emacs compatibility shims | 3 | 1,680 | – |
| Multi-threading / parallel worker pool (process-level concurrency, file-notify) | 5 | 1,405 | – |
| Buffer model | 2 | 1,076 | – |
| Other infrastructure (dev-audit, heap-types, EC bridge, entry point) | 4 | 1,094 | – |
| Character tables (JIS, data) | 1 | 20,815 | – |
v2.0 ships the four cores Emacs's C core normally gives you — native compile, allocator, GC, coding-system — all written in Elisp itself. Object file writers, asm encoders, ABI-aware codegen for 5 OS×arch targets are also pure Elisp.
Two things Emacs proper doesn't ship in the same form
- A JIT compiler written in Elisp itself. Emacs 28+ has
native-comp, but it depends on libgccjit (an external C library)
and is used as AOT in practice. NeLisp's JIT is ~12k LoC of Elisp
source you can read end-to-end and modify, with runtime codegen via
mmap+PROT_EXEC. - Real parallel execution. Emacs's
make-threadis cooperative — one Lisp thread runs at a time. NeLisp's worker pool gives process-level concurrency under the same Lisp runtime, which is what made the orchestrator and the long-running MCP handler design tractable.
Standalone self-host & parallel build (2026-06)
The pure-Elisp AOT AOT toolchain now produces a standalone
interpreter binary — target/nelisp, built by make
standalone-reader — that runs with no Emacs in the loop
at all: it starts a REPL when launched with no arguments, loads an
.el file via argv[1], evaluates it, and exits with the low byte of
the last form's integer value. It also exposes --repl [--no-prompt]
for line-oriented interactive development against one live evaluator
environment, plus short CLI options:
target/nelisp --help
target/nelisp # starts the REPL
target/nelisp --eval '(+ 40 2)' # prints 42, exits 0
target/nelisp --load /tmp/prog.el # prints the last value, exits 0
target/nelisp /tmp/prog.el # exits with the last integer value
Its OS connection is also written on the Elisp side: opening and reading files, reading stdin, writing stdout/stderr, exiting, allocating memory, spawning OS threads, and forking compile workers all flow through Elisp-generated native code and raw syscall forms.
Fed its own compiler toolchain as source (nelisp-aot-compiler +
nelisp-asm-x86_64 + nelisp-elf-write + nelisp-static-linker,
~20k lines of Elisp), this binary self-hosts: it compiles Elisp
source to a native x86_64 ELF executable, with no Emacs anywhere. The
following are all CI-gated (.github/workflows/ci.yml):
| Make target | What it proves |
|---|---|
make standalone-selfhost-test |
compiles (seq (defun fact (n) ...) (exit (fact 5))) → native ELF → run → exit 120 (recursion) |
make standalone-selfhost-mt-test |
compiles a multi-threaded program (clone(2) + SeqCst atomics, 3 OS threads) → native ELF → 42 |
make standalone-parallel-compile-test |
compiles 4 units concurrently — 4 fork(2) workers each running the full compiler → 11,22,33,44 |
The incremental standalone eval build also has a multi-process worker entry.
On POSIX use tools/build-standalone-parallel.sh [NJOBS]; on native Windows
PowerShell use .\tools\build-standalone-parallel.ps1 -Jobs 4. Both routes
drive nelisp-standalone-compile-chunk and then link once serially, using
Emacs and pure elisp only.
REPL-driven runtime development
The standalone reader is also the development REPL for NeLisp itself. The REPL runs in the AOT standalone interpreter and evaluates forms through the same reader, evaluator, builtin dispatcher, environment, and GC path used by normal file execution.
That makes the core workflow Lisp-native:
- Start one standalone NeLisp process.
- Define or redefine functions in that process.
- Call them immediately without restarting the runtime.
- Use
nelisp--eval-source-stringto evaluate generated source into the same live environment.
make standalone-reader
target/nelisp
nelisp> (defun hot () 1)
hot
nelisp> (hot)
1
nelisp> (defun hot () 42)
hot
nelisp> (hot)
42
Runtime sources can also be pre-bundled into a replay image. This is the portable bootstrap cache used before the native artifact layer:
printf '(defun cached-hot () 42)\n' >/tmp/runtime-src.el
target/nelisp dump-runtime-image /tmp/runtime.nlri --load /tmp/runtime-src.el
target/nelisp eval-runtime-image /tmp/runtime.nlri '(cached-hot)'
For repeated command execution, compile the replay image into a NeLisp
artifact cache. .nelc removes repeated source parsing/replay from
the command path. The .neln native hot path uses the same flattened
runtime-image input in the host/dev native compiler gate; wiring that
compiler into the standalone command path is tracked separately.
When a .neln artifact is loaded, native-eligible functions are
registered as ordinary NeLisp functions with a native-first wrapper and
bytecode fallback. The integer native proof path also caches the linked
driver executable under the user cache directory, so repeated calls do
not pay object extraction and link cost every time.
Generic source loading can use the same artifact layer. Compile a tree
with compile-elisp-artifacts --kind neln FILE.el DIR... to create
adjacent FILE.el.neln artifacts; nelisp-load-file probes fresh
adjacent .neln then .nelc before source replay. If
nelisp-load-auto-compile-artifacts is enabled, a missing or stale
adjacent artifact is rebuilt on demand. inspect-elisp-artifact shows
:native-report so unsupported native bodies are visible while the
portable fallback remains usable.
target/nelisp compile-runtime-image \
--kind nelc \
--input /tmp/runtime.nlri \
--output /tmp/runtime.nelc
target/nelisp eval-elisp-artifact /tmp/runtime.nelc '(cached-hot)'
For editor integration or scripted probes, use --no-prompt:
printf '(defun hot () 7)\n(hot)\n(nelisp--eval-source-string "(defun hot () 9)")\n(hot)\n(exit)\n' \
| target/nelisp --repl --no-prompt
# => hot
# => 7
# => hot
# => 9
The last example proves both parts of the development surface: top-level REPL input mutates the live environment, and persistent source-string evaluation mutates that same environment.
Two concurrency paths, exposed to interpreted code
Both are built only from existing AOT grammar ops
(syscall-direct / atomic-fetch-add / raw memory access).
(thread-spawn 'FORM)/(thread-join ADDR N)— true multi-threaded eval viaclone(2)(CLONE_VM): OS threads sharing one address space, each evaluating FORM with its own per-thread context (own recursion counter), joined through a shared atomic counter. The shared-memory model (12/12 stable for paralleleval).(fork-spawn 'FORM)—fork(2)workers with COW-isolated address spaces (each its own arena / globals / env), so N workers compiling concurrently share no mutable eval state and cannot race. This is the production parallel build path (4-way and 5-way verified 100%).
The standalone arena allocator advances its bump pointer with a SeqCst
atomic-fetch-add, so concurrent allocation is thread-safe by
construction.
The same pattern is used for ordinary OS interaction in the standalone reader: file loading, REPL stdin, stdout/stderr writes, process exit, thread creation, and worker forking are runtime behaviors driven from Elisp-generated native code. The point is not merely that Elisp logic sits above an OS bridge; the OS bridge itself is now part of the Elisp runtime surface for the standalone path.
This is the third rung of the self-host ladder, end to end and with no
Emacs: text → (the standalone interpreter running the AOT
compiler) → native ELF, scaled to concurrent multi-unit compilation.
Pure-Elisp Substrate (v2.0, 2026-05-22)
The implementation center is Elisp source. The standalone reader runs that substrate without a host Emacs process: source text is read, parsed, evaluated, compiled, linked, and used to drive OS interaction through Elisp-generated native code.
Shipped substrate
- AOT self-emission (Doc 85 / 91–97): ~7,550+ LoC of Elisp for
the x86_64 + arm64 assemblers, ELF + Mach-O + PE/COFF writers,
static linker,
crt0, the Sexp DSL, and the AOT compiler. 600+ ERT.(fact 5)compiles end-to-end to a native.o, links, and runs. - Cross-platform native emit (May 2026 — see
Cross-Platform Supportbelow): 5 OS×arch targets supported entirely from elisp. - GC pure-elisp (Doc 79 v7 Phase C Stage 5.3): Bacon-Rajan cycle
collector at
lisp/nelisp-stdlib-gc.el( 806 LoC ). - All special forms, builtins, env / mirror / frame ops, NlBox Clone/Drop, reader (lexer + parser), JIT trampolines, syscall handlers — now live in elisp via AOT .o.
Test gate
- ERT coverage for elisp .o emission: 600+ tests including Win64-ABI-specific assertions (Wave 5).
- Standalone self-host gates (zero-Emacs, CI, 2026-06):
standalone-selfhost-test(recursion → native ELF → 120),standalone-selfhost-mt-test(clone(2)+ atomics multi-thread → 42),standalone-parallel-compile-test(4 units compiled concurrently viafork(2)→ 11,22,33,44). - Standalone parallel eval build:
tools/build-standalone-parallel.sh [NJOBS]on POSIX,.\tools\build-standalone-parallel.ps1 -Jobs 4on Windows.
Cross-Platform Support (v2.0, 2026-05-22)
NeLisp v2.0 builds and runs across 5 OS × architecture targets, with all object-file writers and asm codegen written in pure Elisp:
| Target | Object writer | Asm encoder | ABI | gate |
|---|---|---|---|---|
| linux/x86_64 | nelisp-elf-write.el |
nelisp-asm-x86_64.el |
SysV AMD64 | ✓ |
| linux/aarch64 | nelisp-elf-write.el |
nelisp-asm-arm64.el |
AAPCS | ✓ |
| macos/aarch64 | nelisp-mach-o-write.el |
nelisp-asm-arm64.el |
AAPCS | ✓ |
| macos/x86_64 | nelisp-mach-o-write.el |
nelisp-asm-x86_64.el |
SysV AMD64 | ✓ |
| windows/x86_64 | nelisp-pe-write.el |
nelisp-asm-x86_64.el |
Microsoft x64 | ✓ |
The PE/COFF writer (nelisp-pe-write.el, 765 LoC) and the
Windows-specific codegen path (AOT compiler --abi 'win64 mode
with shadow space allocation + RCX/RDX/R8/R9 arg-reg remapping +
RBP/RBX/RDI/RSI/R12-R15 callee-save) are pure elisp.
Deferred: aarch64 Windows (arm64ec) — currently x86_64 Windows only.
Status — v0.6.0 (2026-06-26)
NeLisp v0.6.0 centers the runtime in Elisp, keeps the standalone path as the primary user surface, and adds cross-platform native emit across 5 OS×arch targets.
- Standalone reader —
target/nelisploads and evaluates.elfiles with no host Emacs process. - Runtime development REPL —
target/nelispkeeps a live evaluator environment for immediate redefinition. -
Standalone self-host + parallel build (2026-06) — the pure-elisp AOT AOT toolchain loads its own compiler and compiles Elisp source → native ELF with no Emacs in the loop: recursion (
(fact 5)→ exit 120), multi-threaded native programs (clone(2)- atomics), and N units compiled concurrently via
fork(2)workers.
CI-gated. See
Standalone self-host & parallel build. - atomics), and N units compiled concurrently via
Install
Two paths.
Stable tag — v0.6.0 (recommended)
For source users, pin the current stable tag:
git clone https://github.com/zawatton/nelisp ~/nelisp
cd ~/nelisp
git checkout v0.6.0
make standalone-reader
make standalone-reader-test
For release artifacts, v0.6.0 tarballs use:
anvil-v0.6.0-linux-x86_64.tar.gz
anvil-v0.6.0-macos-aarch64.tar.gz
anvil-v0.6.0-windows-x86_64.tar.gz
main is the development branch. Use it when hacking on NeLisp
itself; pin v0.6.0 when you want reproducible runtime behavior.
Prerequisites by platform
The standalone-reader build is driven by host Emacs and the pure-Elisp
AOT toolchain. Install a normal native build environment for your
platform, then run make standalone-reader.
Tier guarantees (v2.0):
linux-x86_64— 1st-class (CI blocker, every release must pass).macos-aarch64/windows-x86_64— end-to-end CI gated on real runners (macos-14/windows-latest) via.github/workflows/stage-d-v3.0-standalone.yml: native self-host (Mach-O / PE32+), OS-compat ERT, native eval/reader, cache identity, parallel build, and tarball/install of the native CLI. macOS uses ad-hoccodesignfor native execution. Not release blockers —linux-x86_64remains the hard gate.linux-aarch64/macos-x86_64— supported by the elisp object-file writers (nelisp-elf-write.el/nelisp-mach-o-write.el), but no dedicated CI runner job yet (best-effort).windows-aarch64(arm64ec) — deferred.
Linux (Debian / Ubuntu):
sudo apt install build-essential git emacs
Linux (Fedora / RHEL):
sudo dnf install gcc make git emacs
macOS (arm64 or x86_64):
xcode-select --install # one-time
brew install emacs
Windows — native x86_64 (v2.0 supported):
The elisp-side PE/COFF writer + Win64 ABI codegen produce native COFF
.o files. Use a native toolchain with host Emacs, or use WSL2/MSYS2
with the Linux-style commands above.
From source — recommended for hacking and using the Elisp API
git clone https://github.com/zawatton/nelisp ~/nelisp
cd ~/nelisp
make standalone-reader
make standalone-reader-test
Build outputs land under target/, with
target/nelisp as the primary no-Emacs runtime.
Pre-built standalone tarball — single-binary deployment
For users who want NeLisp without cloning / building. No Emacs install required at runtime:
curl -fsSL https://github.com/zawatton/nelisp/releases/latest/download/install-v3.sh | bash
On Windows PowerShell:
iwr https://github.com/zawatton/nelisp/releases/latest/download/install-v3.ps1 -OutFile install-v3.ps1
.\install-v3.ps1
Default install root: $HOME/.local/share/anvil-v0.6.0/.
On Windows the default root is under $env:LOCALAPPDATA\anvil-v0.6.0.
(The anvil- prefix is historical packaging — the tarball is the
NeLisp runtime; use bin/nelisp or bin/nelisp.exe directly.)
Full install-to-run runbook for Linux x86_64, macOS arm64, and Windows x86_64
(release install, local tarball install, PATH setup, eval, file loading,
REPL, runtime images, verification, and uninstall):
README-stage-d-v3.0.org.
Older release lines, for reference only:
README-stage-d-v2.0.org— bundled-Emacs tarball, ~25 MBREADME-stage-d.org— legacy host-Emacs-required path
Cross-PC verification
After clone + build, run the smoke script for your platform:
# Linux / macOS:
scripts/verify-cross-platform.sh --parallel-jobs 2 --include-tarball
# Windows (PowerShell):
.\scripts\verify-cross-platform.ps1 -IncludeTarball
Expected output ends with Cross-platform verify PASS.
With --include-tarball, verification also installs from the freshly built
dist tarball and executes the installed bin/nelisp or bin/nelisp.exe.
The same standalone/tarball/install gate is wired into
.github/workflows/stage-d-v3.0-standalone.yml for Linux x86_64, macOS
arm64, and Windows x86_64. macOS runs the full native Mach-O self-host,
OS-compat, eval, reader, REPL, tarball, install, and installed-binary gate.
Launch
For current source checkouts, the primary no-Emacs runtime is the pure-Elisp standalone reader:
make standalone-reader
# load + run a file; process exit is the low byte of the last integer value
printf '(+ 40 2)\n' >/tmp/prog.el
target/nelisp /tmp/prog.el
echo $? # => 42
# evaluate or load and print the result
target/nelisp --eval '(concat "hello" " " "world")'
target/nelisp --load /tmp/prog.el
# bundle runtime sources once, then evaluate forms against the image
printf '(defun cached-hot () 42)\n' >/tmp/runtime-src.el
target/nelisp dump-runtime-image /tmp/runtime.nlri --load /tmp/runtime-src.el
target/nelisp eval-runtime-image /tmp/runtime.nlri '(cached-hot)'
target/nelisp compile-runtime-image --kind nelc --input /tmp/runtime.nlri --output /tmp/runtime.nelc
target/nelisp eval-elisp-artifact /tmp/runtime.nelc '(cached-hot)'
# interactive runtime development
target/nelisp
The REPL keeps one live evaluator environment. Redefinitions are visible immediately, and generated source can be evaluated into that same environment:
printf '(defun hot () 7)\n(hot)\n(nelisp--eval-source-string "(defun hot () 9)")\n(hot)\n(exit)\n' \
| target/nelisp --repl --no-prompt
# => hot
# => 7
# => hot
# => 9
Older install tarballs may also ship a nelisp command. Current source
checkouts use the pure-Elisp standalone reader above for REPL
development and file execution.
nelisp --version # nelisp v0.6.0
nelisp --eval "(+ 1 2 3)" # => 6
nelisp --load ~/nelisp/examples/hello/hello.el
Quick start
For larger workflows the evaluator is reachable three ways; pick the one that matches your context.
From Emacs Lisp — REPL straight into NeLisp's own evaluator
(add-to-list 'load-path "~/nelisp/src") ; or the install root's src/
(require 'nelisp-bootstrap)
(nelisp-bootstrap-init) ; one-time self-host load
(nelisp-eval-string "(+ 1 2 3)") ; => 6
(nelisp-eval-string
"(mapcar (lambda (n) (* n n)) '(1 2 3 4))")
;; => (1 4 9 16)
(nelisp-load-file "~/nelisp/examples/hello/hello.el")
(nelisp-eval-string "(hello-world)")
;; => "Hello, World!"
The forms go through NeLisp's own reader + evaluator. Host Emacs is a launcher only — result and host-evaluator state stay separate.
Downstream MCP-server front ends can wrap this CLI, but the standalone tarball ships the self-contained NeLisp runtime directly as
bin/nelisporbin/nelisp.exe.
Architecture
+--------------------------------------------------+
| Optional front ends / tools |
+-----------------+--------------------------------+
| source / stdio / files
+-----------------v--------------------------------+
| target/nelisp |
| reader / evaluator / macro / compiler / loader |
| REPL / persistent eval / runtime-image replay |
+--------------------------------------------------+
| AOT Elisp substrate |
| allocator / GC / builtins / syscall-direct |
| asm encoders / object writers / static linker |
+--------------------------------------------------+
| OS substrate |
| files / stdio / exit / mmap / atomics / fork |
+--------------------------------------------------+
Two boundaries are pinned:
- Language boundary – reader, evaluator, macro expansion, compiler, loader, special forms, builtins, allocator, and GC are runtime behavior implemented as Elisp.
- OS boundary – file loading, REPL stdin, stdout/stderr writes, process exit, memory mapping, atomics, thread spawning, and worker forking are exposed through Elisp-generated code and raw syscall forms on the standalone path.
Soak gate (Doc 32 v2 §2.7)
| Tier | Duration | RSS growth ceiling | Status (2026-04-27) |
|---|---|---|---|
| blocker (CI) | 1h | < 5 MB | PASS (linux-x86_64) |
| post-ship audit | 24h | < 10 MB / 24h | scheduled, weekly |
Standalone native CLI matrix (current HEAD):
| Platform | Status |
|---|---|
| linux-x86_64 | gated by native eval, reader, REPL, cache identity, parallel, tarball/install |
| macos-aarch64 | gated by Mach-O self-host, OS ERT, signed CLI tarball/install, eval/reader/REPL |
| windows-x86_64 | gated by PE32+ self-host, OS ERT, CLI tarball/install, eval/reader/REPL |
| linux-arm64 | best-effort |
The older v1.0 arm64 time-box language is retained only in the v1.0 release
templates and tests. The current standalone path is verified by
scripts/verify-cross-platform.sh --include-tarball on POSIX and
scripts/verify-cross-platform.ps1 -IncludeTarball on Windows.
The tarball gate includes a real install smoke from the freshly built dist
directory.
What is not in v1.0
Said plainly so expectations are calibrated:
- No buffer / marker / window primitives. NeLisp is the language
runtime, not the editor.
emacs-noxis the closest existing comparison if scripting is all you need; what's different here is the 624 KB standalone tarball and a runtime small enough to read end-to-end. - Phase 8.0 evaluator is a minimal subset (25 special forms + 75
builtins): GC bridge, bignum, full backquote semantics, full
save-excursionare deferred to Phase 8.x follow-up patches. - Default
--no-emacsstill falls back toemacs --batchfor cold-init failures (3-year safety window). - Linux x86_64, macOS arm64, and Windows x86_64 native standalone CLI paths are gated by platform-specific eval, reader, REPL, cache identity, parallel build, and tarball smokes.
- Linux arm64 remains best-effort.
Test status (HEAD, 2026-05-14)
make test= 3604 tests / 3562 expected / 5 unexpected (all pre-existing flake) / 37 skipped on linux-x86_64. SeePure-Elisp Migration Progresssection above for the flake breakdown.- Standalone self-host gates (2026-06, all green, zero-Emacs):
standalone-{reader,eval,reader-prelude,selfhost,selfhost-mt,parallel-compile}-test— the standalonetarget/nelispbinary self-hosts the AOT compiler (recursion → native ELF → 120) and compiles N units concurrently viafork(2)workers (4-/5-way verified 100%). - The previous 2026-04-29 baseline was 2452 / 2409 / 0 unexpected. The ~1.5× growth in test count reflects the new sub-systems: AOT self-emission (600+ ERT), Doc 79 v7 GC, Doc 102 mirror, Doc 100/110 ABI / arithmetic, Doc 81 cons cluster, Doc 86/87 Tier 1+2 builtins.
- Cross-platform standalone gates (Linux x86_64 / macOS M1 arm64 /
Windows x86_64) now cover native reader/eval execution, REPL command
handling, cache identity, parallel build, OS compatibility ERT, and
signed standalone tarball verification. macOS arm64 uses ad-hoc
codesignfor native Mach-O execution.
Key design documents
| Doc | Topic | Status |
|---|---|---|
| 18 | Stage D launcher charter | LOCKED |
| 27 | Phase 7+ self-implemented runtime | LOCKED-2026-04-25-v2 |
| 28 | Phase 7.1 NeLisp native compiler | LOCKED-2026-04-25-v2 |
| 32 | Phase 7.5 integration + standalone E2E | LOCKED-2026-04-25-v2 |
| 76 | Phase 7 elisp-side OS surface migration | IN PROGRESS |
| 79 v7 | Pure-elisp GC (Bacon-Rajan cycle collector) | Phase C Stage 5.3 SHIPPED |
| 81 | nelisp-cc primitive trampoline extension | Stage 81.2 SHIPPED |
| 85 | AOT feasibility spike | VALIDATED |
| 91-97 | AOT ELF writer / asm / linker / DSL / build | SHIPPED |
| 100 | Runtime artifact contract | §B/C SHIPPED |
| 102 | Environment model migration to Elisp | Phase 8 Sprint A SHIPPED, Sprint B/C deferred |
| 110 | AOT f64 ABI + float/math migration to Elisp | SHIPPED |
Earlier status (Phase 0 — 2026-04-22) — preserved for reference
Phase 0 (design documents) was completed 2026-04-22. Key decisions locked at that time and still in force:
- Bootstrap strategy: Host-Emacs bootstrap (Candidate A), transferring SBCL's genesis methodology (Rhodes 2008) to Emacs as the host
- Scope: Stage A only (= Elisp substrate). Stage B (AI-native Emacs) and
Stage C (AI/Emacs boundary fusion) belong to
anvil.elsuccessors - Concurrency: Actor model as primary (Phase 4), STM experimental (Phase 4b), fiber (Phase 3), threads deferred (Phase 5)
- Division of labor: NeLisp core team focuses on AI-critical paths (buffer/event/concurrency/eval/FFI); community handles long tail (display render, primitive utilities) post-v1.0 — Linux kernel / SBCL governance model
The roadmap is in docs/05-roadmap.org.
Philosophy (short form)
Emacs Lisp is not philosophically cleaner than Scheme or Common Lisp — but decades of accumulated, lived-in Elisp is a cultural asset worth self-hosting on its own terms, rather than porting it to someone else's substrate.
Esperanto is a constructed language of philosophical elegance, but English is the international language. Elisp is English here.
The long form lives in docs/00-motivation.org.
Non-goals
- Scheme rewrite (Guile-Emacs direction) — rejected
- A replacement editor for Emacs — out of scope for NeLisp itself
(Stage B/C handled by
anvil.elor successors) - Replacing all 3000 C functions — non-goal. NeLisp core team rewrites AI-critical paths, community fills the long tail
The three-stage vision
┌─────────────────────────────────────────────────┐
│ Stage C: AI and Emacs as one │ ← anvil.el (and beyond)
│ ┌─────────────────────────────────────────────┐ │
│ │ Stage B: Emacs made AI-native │ │ ← anvil.el (and beyond)
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Stage A: Emacs internals in pure Elisp │ │ │ ← *NeLisp (this project)*
│ │ │ (no C to traverse — everything editable) │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
NeLisp builds the substrate (Stage A). Stage B and C are built on top of NeLisp, as extension packages.
Repository layout
nelisp/
├── BRIEFING.org # First-session design instructions
├── README.org # This file
├── .gitignore
├── packages/ # Extracted optional libraries
│ ├── README.org # Package split convention
│ └── nelisp-json/ # Pilot extracted library package
│ ├── README.org
│ ├── src/
│ └── test/
└── docs/
├── 00-motivation.org # Why this, why now, why not Scheme (USER voice)
├── 01-related-work.org # 7 projects audited + paper priorities
├── 02-scoping.org # Stage A/B/C + AI-critical vs long tail
├── 03-architecture.org # Bootstrap A, primitive boundary, Phase 1 subset
├── 04-concurrency.org # Actor primary Phase 4, novelty claim
├── 05-roadmap.org # Phase 1-5 timeline, release schedule
├── 90-ideas-backlog.org # Deferred interesting ideas
└── papers/ # Academic paper reading stubs
├── README.org
├── rhodes-2008-sbcl.org # Priority A: bootstrap methodology
├── corallo-2020-native-comp.org # Priority A: AOT hybrid
├── bolz-2009-meta-tracing.org # Priority A: JIT for Phase 3-4
└── maclachlan-1992-python.org # Priority A: CL-in-CL precedent
Optional packages
NeLisp v1.0 now supports an SBCL/Quicklisp-style split between the
core src/ tree and individually extractable libraries under
packages/*/. The nelisp-json package is the pilot extraction and
defines the canonical layout for future package moves:
packages/<name>/src/<name>.elpackages/<name>/test/<name>-test.elpackages/<name>/README.org
The build keeps these packages on the Emacs load-path, so existing
require forms continue to work unchanged. See packages/README.org
and packages/nelisp-json/README.org.
Related work (audited)
| Project | Approach | Status / diff with NeLisp |
|---|---|---|
| Guile-Emacs | Elisp on Guile (Scheme) | 12-year stall, relaunched EmacsConf 2024 |
| native-comp | Elisp → libgccjit → .eln | Shipped in Emacs 28+, does not rewrite VM |
| SBCL | CL in CL (CMU CL fork) | Methodology source (Rhodes 2008) |
| PyPy | Python in RPython + JIT | Successful self-host, STM branch failed |
| PicoLisp | Tiny Lisp, pil21 LLVM | pil21 self-hosts LLVM phase |
| NeLisp | Elisp in Elisp, editor-native | First editor-integrated self-host |
See docs/01-related-work.org §10 for the synthesis.
License
TBD. Leading candidate: GPLv3+ (to match Emacs) with per-module reconsideration if needed. Decided before Phase 1 push.
Contact
zawatton — kurozawawo@gmail.com