A Python compiler–interpreter written in Zig
Enso is an implementation of Python in Zig that treats compilation and interpretation as two backends of the same system.
Instead of a JIT-first architecture, Enso prioritizes ahead-of-time compilation, beginning with a QBE backend, while embedding an interpreter for the parts of a program that can only be resolved at runtime. The result is a system where Python code can be partially evaluated, partially compiled, and partially interpreted—all from a single, shared core representation.
The name Enso comes from the Zen circle, often associated with infinity, recursion, and self-reference. Like the ouroboros, Enso consumes itself:
Python is implemented in Python, which is compiled by Enso.
- Why Enso?
- Core Ideas
- Architecture Overview
- Goals
- Non-Goals (for now)
- Development Environment
- Testing
- Tour of the Source
- Roadmap
- Related Work & Inspiration
- License
Python today lives at two extremes:
- CPython: ubiquitous, stable, but constrained by its C API and interpreter-centric design
- PyPy: brilliant research, but limited adoption due largely to C-extension compatibility
Enso takes a different path:
- Python is treated as a compilable language first
- Interpretation exists as a fallback mechanism, not the core execution model
- The entire stack—language, standard library, and packages—can be optimized end-to-end
This enables optimizations that resemble whole-program compilation and LTO, even for a dynamic language like Python.
Enso parses Python source into bytecode-equivalent IR that is semantically identical to CPython’s dis output:
python -m dis source.pyEvery instruction in this IR can be:
- compiled (e.g. to QBE → native code), or
- interpreted (when runtime values prevent static resolution)
There is no separate interpreter and compiler — just different execution strategies over the same representation.
- Partial Evaluation as the Primary Optimization
The first pass of a program is interpreted. Any values discovered to be compile-time constants are partially applied, enabling subsequent compilation.
This allows Enso to:
- specialize aggressively
- eliminate dynamic overhead
- avoid JIT complexity entirely
- Python Implemented in Python
Long-term, Enso aims to follow the philosophy articulated by Chris Seaton (TruffleRuby):
Implement the language in itself, not in a foreign runtime.
This means:
- The Python standard library is written in Python
- Core runtime logic migrates out of Zig over time
- Zig becomes the substrate, not the language definition
Python Source
│
▼
Lexer / Parser
│
▼
CPython-equivalent IR
│
├──► Interpreter (runtime-only paths)
│
└──► Compiler
├─ QBE → native (today)
├─ Zig backend (future)
├─ WASM (future)
└─ SPIR-V (future)
At link time, the interpreter is only included if needed.
- Single, statically-linked binaries
- Minimal dynamic dependencies (Go-style deployment)
- Zero-overhead Python
- hello_world.py should produce identical object code to hello_world.c
- Freestanding targets
- A viable alternative to MicroPython
- Multiple backends
- Native via QBE
- WASM (via Zig backend)
- SPIR-V for GPU / compute use-cases
- End-to-end optimization
- Standard library and packages compiled together
- Long-term C API compatibility
- Enabled by CPython bytecode equivalence
- JIT compilation
- Perfect CPython C-extension compatibility on day one
- Immediate parity with CPython’s full stdlib
In order to enable stable dev environments across hosts we rely on nix. We expect the nix command and flake experimental features to be enabled.
Once nix is installed and configured you may start a development shell this way:
nix developzig build testor optionally filter tests from the CLI:
zig build test -Dtest-filter='lex'Zig build will omit test results when they are cached:
$ zig build test -Dtest-filter='ir' --summary all
Build Summary: 3/3 steps succeeded; 9/10 tests passed; 1 skipped
test success
└─ run enso_tests 9 passed 1 skipped 1ms MaxRSS:3M
└─ zig test enso_tests Debug native success 1s MaxRSS:227M
# Now they are cached
$ zig build test -Dtest-filter='ir' --summary all
Build Summary: 3/3 steps succeeded
test cached
└─ run enso_tests cached
└─ zig test enso_tests Debug native cached 5ms MaxRSS:50M
- lex.zig
Lexer{ .buffer = "..." }#next()
- parse.zig
Parser.init(allocator, "...")- `ast_result = parser.parse()``
- bytecode.zig
IrGen.init(allocator, intern_pool, ast)instructions = ir_gen.generate()
- CPython bytecode parity
- QBE backend stabilization
- Interpreter ↔ compiler handoff
- Self-hosted Python runtime
- Zig backend (WASM)
- Freestanding runtime profile
- SPIR-V experimentation
- pip-distributed toolchain
- CPython
- PyPy
- TruffleRuby – Chris Seaton - https://www.youtube.com/watch?v=-iVh_8_J-Uo
- Rubinius
- Natalie
- QBE
- Zig
TBD.
The project intends to remain free software, while carefully navigating the tradeoffs around commercial reuse and ecosystem sustainability.
Enso is a circle without beginning or end — a language that understands itself.