>_PYTHONRS REFERENCE
A compiled Python runtime written in Rust. 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, awkrs, elisp, and rubylang. Every run transparently caches its bytecode via rkyv, and python --build bakes a script into a native executable. In active development.
What it is
pythonrs runs Python programs as ordinary compiled bytecode: it lexes and parses the source, lowers it to fusevm instructions, and lets the shared engine execute and JIT-compile them. There is no bespoke VM or tree-walker — arithmetic and comparisons lower to native fusevm ops so the Cranelift JIT can trace hot loops, while Python-specific behaviour (truthiness, attribute and method dispatch, str/list concatenation, bignum promotion, object construction) is served by the PyHost object heap.
It is another language hosted on fusevm, the shared bytecode VM and Cranelift JIT behind zshrs (the shell), stryke (the language), awkrs (AWK), elisp (Emacs Lisp), and rubylang (Ruby). pythonrs carries no VM or JIT of its own.
To our knowledge it is the first compiled standalone Python runtime that both transparently caches bytecode via rkyv on every run and AOT-compiles a script to a native executable.
Architecture
The pipeline mirrors how zshrs hosts zsh and rubylang hosts Ruby:
Python source → lexer → parser (AST) → lower to fusevm bytecode → fusevm VM + Cranelift JIT
│
PyHost object heap (str/list/dict/tuple/set/instances)
fusevm-hosted
No local vm.rs / jit.rs. Python is lowered to fusevm bytecode and executed on the shared three-tier Cranelift JIT; jit-disk-cache persists native code across runs.
Transparent rkyv cache
python foo.py hashes the source, consults ~/.pythonrs/scripts.rkyv, and on a hit runs the compiled chunks directly — lex/parse/lower skipped. No flags, no separate build step, no __pycache__ ritual.
AOT native executable
python --build foo.py emits a standalone native binary via fusevm::aot, linked against the pythonrs runtime staticlib, that runs the script with no interpreter present.
Reference-typed objects
str, list, dict, tuple, set, and instances live on the PyHost heap behind Value::Obj handles, so a.append(x) mutates in place — real Python reference semantics, not value copies.
Example
def fib(n):
return n if n < 2 else fib(n - 1) + fib(n - 2)
print(", ".join(str(fib(i)) for i in range(11)))
# => 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
total = 0
for x in [1, 2, 3, 4]:
total += x
print(total) # => 10
squares = [n * n for n in range(5)]
print(squares) # => [0, 1, 4, 9, 16]
print(len({**{"a": 1, "b": 2}}.keys())) # => 2
print(f"{fib(10):,}") # => 55
Status & roadmap
The table below reflects the current state of the tree. See BUGS.md for the honest ledger of what is not yet carried.
| Component | State | Notes |
|---|---|---|
| Lexer / parser → AST | Implemented | Indentation-significant tokenizer (INDENT/DEDENT/NEWLINE), f-strings (src/lexer.rs, src/parser.rs). |
| AST → fusevm bytecode lowering | Implemented | No local VM; native arithmetic + CallBuiltin dispatch (src/compiler.rs). |
| Object heap & method dispatch | Implemented | str / list / dict / tuple / set / instances (src/host.rs, src/builtins.rs). |
| Kernel builtins & per-type methods | Implemented | print / len / range / … plus str, list, dict, set methods. Growing. |
Functions, closures, *args / **kwargs | Implemented | Def-site splat and keyword args, defaults, real closures, and full call-site */** unpacking plus literal spreads. |
| Classes, inheritance, operator dunders | Implemented | __init__, instance attrs, arithmetic/comparison dunders with reflected fallbacks, __getitem__/__len__/__iter__/__repr__ (src/host.rs). |
| Comprehensions (list/dict/set), f-strings | Implemented | Format mini-language (fill/align/sign/width/,/.prec/type); comprehensions get their own scope, so the loop variable does not leak. |
Exceptions (try/except/finally/raise) | Implemented | Typed classes; with desugars to try/finally over __enter__/__exit__. |
Arbitrary-precision int | Implemented | Bignum promotion across + - * ** // % and the bitwise ops & | ^ << >> — the earlier i64 cap is gone. |
Standalone python binary + REPL | Implemented | Run .py files, -c one-liners, interactive REPL (src/main.rs, src/repl.rs). |
| Transparent rkyv bytecode cache | Implemented | Versioned on-disk shard at ~/.pythonrs/scripts.rkyv, consulted on every run (src/cache.rs). |
AOT native executable (--build) | Implemented | Standalone binary via fusevm::aot linked to the runtime staticlib (src/aot_native.rs). Requires the libpython-free build — a stdlib-ffi binary refuses up front. |
Parity harness vs reference python3 | Implemented | Differential corpus diffed byte-for-byte against CPython (src/bin/parity.rs). |
Generators, async/await, match/case | Implemented | Stackful corosensei generators with full yield from delegation, a native fusevm asyncio event loop, and PEP 634 structural pattern matching. |
LSP server (--lsp) | Partial | Builtin/keyword/method completion, position-aware hover, and diagnostics from the real parser; go-to-def and signature help not yet (src/lsp.rs). |
DAP adapter (--dap) | Partial | Breakpoints, step in/out/over/continue, stack trace, locals, expression evaluate, and program-stdout capture; watch expressions not yet (src/dap.rs). |
| Standard library | Partial | The stdlib-ffi bridge (on by default) serves the real CPython stdlib over an embedded libpython; sys stays wholly native and math/collections/functools/contextlib resolve native arms first. A --no-default-features build drops the bridge and serves import from the vendored pylib/ tree. See BUGS.md. |
Diagnostics (--doctor, --cacheview, --tiers) | Implemented | Runtime/CPython/cache/env report, an rkyv-shard listing, and a per-chunk fusevm execution-tier report (src/tiers.rs). |
Why pythonrs
Compiled, not bytecode-walked
CPython compiles to its own bytecode and walks it in C; pythonrs lowers Python to fusevm bytecode and JITs hot paths through Cranelift — the same architecture that makes zshrs and stryke fast.
Cache on every run
No __pycache__ dance and no separate build step: the rkyv shard is consulted transparently on every python foo.py, so warm starts skip lex/parse/lower entirely.
One shared engine
Bug fixes and JIT improvements in fusevm benefit zshrs, stryke, awkrs, elisp, rubylang, and pythonrs at once.
AOP intercepts
A glob-matched before/after/around method-intercept registry (src/intercepts.rs) — aspect weaving over Python method calls, the same design as zshrs's function intercepts.
Cache benchmark
The rkyv shard skips lex/parse/lower on a warm run — including every imported module, which is where the win lands. The gain scales with how much source a run compiles: a tiny import-free script is already sub-parse-time, so warm ≈ cold; a run that pulls in stdlib modules amortizes their compilation once and reads them back from the shard on every later run.
| Workload | Cold (first run: compile + store) | Warm (cache hit: load only) | Speedup |
|---|---|---|---|
| 6-line script, no imports | 7.3 ± 0.6 ms | 6.4 ± 0.4 ms | ≈1× (neutral — nothing to skip) |
| 3 stdlib imports (~a dozen modules transitively) | 69.1 ± 3.4 ms | 19.7 ± 0.8 ms | 3.5× (−49 ms) |
| 10 stdlib imports (21 cached modules) | 102.2 ± 4.5 ms | 28.6 ± 1.0 ms | 3.6× (−74 ms) |
cargo build --release binary, hyperfine -N (80 runs each), isolated cache dir. Cold clears ~/.pythonrs/scripts.rkyv before each run so it pays the full compile plus the shard write; warm is a straight cache hit. The shard is a single content-keyed store shared across concurrent processes (an exclusive flock serializes writers so no entry is lost), deduped by source hash — the 10-import run leaves 21 module entries in a 3.1 MiB shard. Import-free scripts see no benefit by design; the cache pays off precisely when a run compiles real amounts of source.
Building from source
pythonrs builds as a standalone Rust crate (it is not a workspace member of the meta repo):
# clone git clone https://github.com/MenkeTechnologies/pythonrs cd pythonrs # build (release; produces target/release/python + libpythonrs.a) # the default build links an embedded libpython (the stdlib-ffi bridge), # so CPython must be present at build time cargo build --release # run a script, a one-liner, or the REPL ./target/release/python script.py ./target/release/python -c 'print(sum(range(1, 101)))' ./target/release/python --repl # diagnostics ./target/release/python --doctor ./target/release/python --cacheview ./target/release/python --tiers script.py # AOT-compile a script to a native ./script executable # --build needs the libpython-free runtime; a stdlib-ffi binary refuses up front cargo build --release --no-default-features ./target/release/python --build script.py # run tests cargo test
fusevm is pulled from crates.io with the jit, jit-disk-cache, aot, and ffi features. Set PYTHONRS_TRACE=1 to log cache hit/miss to stderr, or PYTHONRS_CACHE=0 to disable the bytecode cache entirely.
License
pythonrs is MIT licensed — free and open source. See LICENSE.
Repository & links
- Engineering report — report.html (architecture, fusevm hosting, roadmap, dependency posture)
- Builtin reference — reference.html (Kernel builtins and core methods)
- Source — github.com/MenkeTechnologies/pythonrs
- Issues — github.com/MenkeTechnologies/pythonrs/issues
- The shared VM — fusevm (also behind
zshrs,stryke,awkrs,elisp,rubylang)