// VIMLRS — VIML IN RUST

vimlrs v0.2.0 · VimL on fusevm · lex/parse → AST → bytecode → Cranelift JIT · the 4th fusevm language host (with zshrs, stryke, awkrs) · MIT · in active development

Report GitHub Issues
// Color scheme

>_VIMLRS REFERENCE

A standalone interpreter for VimL (Vimscript) written in Rust — a faithful port of Neovim's C eval engine, run outside Vim. Source is lexed and parsed to an AST, lowered to fusevm bytecode, and executed on the same language-agnostic VM + three-tier Cranelift JIT that hosts zshrs, stryke, and awkrs. In active development.

What it is

Vimscript has only ever run embedded inside Vim or Neovim. vimlrs is the first compiled standalone VimL interpreter: it takes the eval engine out of the editor and runs .vim scripts as ordinary programs from the command line. The language semantics are ported faithfully from Neovim's C eval/* tree — the C source is the spec — rather than re-invented, so behaviour tracks the reference implementation.

It is the fourth language to be hosted on fusevm, the shared bytecode VM and Cranelift JIT behind zshrs (the shell), stryke (the language), and awkrs (AWK). vimlrs carries no VM or JIT of its own: it lowers VimL to fusevm bytecode and lets the shared engine run it.

Architecture

The pipeline mirrors how zshrs hosts zsh:

VimL source  →  lexer  →  parser (AST)  →  lower to fusevm bytecode  →  fusevm VM + Cranelift JIT

fusevm-hosted

No local vm.rs / jit.rs. VimL is lowered to fusevm bytecode and executed on the shared three-tier Cranelift JIT; jit-disk-cache persists native code across runs.

Faithful port

Lexer, parser, and builtin semantics are ported from Neovim's C eval/* engine — not an ad-hoc re-implementation. The C source is the specification.

Vim-native values

The runtime value layer is ported directly: typval, list, insertion-ordered dict (matching Vim's observable hashtab iteration), and blob.

Versioned caches

The rkyv-backed bytecode script cache is wired from day one so the on-disk format is versioned and migration-safe — a cached .vim that worked must keep working.

Status & roadmap

The table below reflects the current state of the tree.

ComponentStateNotes
Value layer — typval, list, dict, blobPortedInsertion-ordered dict; deterministic string() / echo output.
Lexer / parser → ASTImplementedPorted from the Neovim eval engine.
AST → fusevm bytecode loweringImplementedNo local VM; targets the shared fusevm opcode set.
Builtin function surfaceImplementedPorted from eval/funcs.c; the surface keeps growing.
Standalone vimlrs binaryImplementedRun .vim scripts from the CLI (src/main.rs).
rkyv bytecode script cacheImplementedVersioned, migration-safe on-disk cache (src/script_cache.rs).
DAP debugger (--dap)ImplementedBreakpoints, stepping, variable inspection (src/dap.rs).
LSP server (--lsp)ImplementedDiagnostics, hover, completion for .vim (src/lsp.rs).

Why vimlrs

World first

Every Vimscript engine to date runs only inside an editor. vimlrs is the first compiled VimL interpreter that runs standalone.

Compiled, not interpreted in C

VimL lowers to bytecode and JITs through Cranelift instead of walking a tree in C — the same architecture that makes zshrs and stryke fast.

One shared engine

Bug fixes and JIT improvements in fusevm benefit zshrs, stryke, awkrs, and vimlrs at once.

Faithful semantics

Ported from the Neovim eval engine, so script behaviour tracks the reference rather than diverging.

Building from source

vimlrs builds as a standalone Rust crate (it is not a workspace member of the meta repo). While the interpreter is in development, build the library and run the test suite:

# clone
git clone https://github.com/MenkeTechnologies/vimlrs
cd vimlrs

# build (debug)
cargo build

# run tests
cargo test

fusevm is pulled from crates.io with the jit and jit-disk-cache features. The vendored Neovim C eval sources under vendor/ are the porting spec and are excluded from the crate build.

License

vimlrs is MIT licensed — free and open source. See LICENSE.

Repository & links