The Problem
Researchers and engineers need a language that lets them write mathematical models with the same expressiveness as Lisp, but with native, zero‑overhead differentiation and high‑performance LLVM code. Existing tools either hide the differentiation logic behind libraries or impose run‑time penalties. Eshkol aims to expose calculus as a compiler primitive while keeping the familiar Scheme syntax.
What This Does
Eshkol is a Scheme‑based language that compiles to LLVM machine code and WebAssembly. The compiler, written in C++, implements forward‑ and reverse‑mode AD, vector calculus operators, and a deterministic execution model without a garbage collector. The runtime is a lightweight bytecode VM that runs in the browser via the web/ bindings. The language also ships a full documentation set and a large test suite that covers both the compiler and the VM.
Key files:
CMakeLists.txt– build system for the compiler and VM.lib/lexer.cpp,lib/parser.cpp,lib/ast.cpp– front‑end.lib/codegen.cpp,lib/llvm.cpp– backend.web/web.esk– WebAssembly bindings.tests/– 2 883 test files exercising compiler correctness and VM parity.
How It Is Wired
Execution starts with cmake configuring the build. The CMakeLists.txt pulls in all src/ and lib/ sources, producing the eshkol executable. The entry point for the compiler is src/main.cpp (built by add_executable(eshkol src/main.cpp ...)). main.cpp parses the command line, invokes lexer::tokenize(), then parser::parse() to build an ast::Node, and finally calls codegen::generate() to emit LLVM IR. The emitted IR is passed to llvm::EngineBuilder for JIT or native code generation. For WebAssembly, web/ modules are compiled via the same codegen path with a WASM target.
The VM runs bytecode produced by the compiler. Its main loop is in vm/runtime.cpp, which dispatches opcodes defined in vm/ops.hpp. The AD logic lives in vm/ad.cpp, where dual numbers propagate through op::add, op::mul, etc. No external I/O occurs during compilation or execution; the only side effects are file reads for source files and writes for produced binaries or WASM modules.
The project graph has a single hub: the lib/ directory. Changes to lexer or parser ripple through the entire build because those modules are used by all downstream code. The VM modules form a separate, loosely coupled cycle that can be replaced with a different JIT engine without touching the compiler frontend.
How To Use It
Setup
git clone https://github.com/moses-y/eshkol
cd eshkol
mkdir build && cd build
cmake -S .. -B . -DCMAKE_BUILD_TYPE=Release
cmake --build .
The above produces bin/eshkol. For a Docker image that includes CUDA support, run
docker build -f docker/cuda/Dockerfile -t eshkol-cuda .
Configuration
No runtime configuration files are required. The compiler reads source files directly. For WebAssembly, the output is placed in web/ and can be served by any static HTTP server.
Running It
Compile a script:
./bin/eshkol scripts/linear_model.esk
Run the test suite:
ctest --output-on-failure
To build the documentation:
make docs
Real‑World Use
A data‑scientist can write a model in scripts/linear_model.esk and compile it to native code for deployment on servers or to WebAssembly for in‑browser inference. The compiler automatically differentiates loss functions, enabling gradient‑based training without manual derivatives.
Code Health & Issues
- Low –
tools/vscode-eshkol/package.jsondeclares dependencies without a lockfile, making builds non‑reproducible. - Test coverage – 2 883 test files cover compiler correctness and VM parity.
- Documentation – 526 doc files provide reference and usage guides.
No other static analysis findings were available.
The Bottom Line
Eshkol delivers a Lisp‑style language with built‑in, exact automatic differentiation and high‑performance LLVM output. The codebase is large but well‑structured around a single lib/ hub; changes to the lexer or parser affect the whole compiler. The build system is straightforward (CMake + Docker), and tests are comprehensive. The main drawback is the lack of a lockfile for the VS Code extension, which could lead to non‑deterministic builds. Teams needing a mathematically rigorous compiler for scientific or ML workloads, especially those targeting both native and WebAssembly, should consider Eshkol as a viable solution.