// PYTHONRS — PYTHON IN RUST

pythonrs v0.1.0 · Python on fusevm · lex/parse → AST → bytecode → Cranelift JIT · transparent rkyv cache on every run · AOT native-exe via --build · a fusevm language host (with zshrs, stryke, awkrs, elisp, rubylang) · MIT · in active development

Report GitHub Issues
// Color scheme

>_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.

ComponentStateNotes
Lexer / parser → ASTImplementedIndentation-significant tokenizer (INDENT/DEDENT/NEWLINE), f-strings (src/lexer.rs, src/parser.rs).
AST → fusevm bytecode loweringImplementedNo local VM; native arithmetic + CallBuiltin dispatch (src/compiler.rs).
Object heap & method dispatchImplementedstr / list / dict / tuple / set / instances (src/host.rs, src/builtins.rs).
Kernel builtins & per-type methodsImplementedprint / len / range / … plus str, list, dict, set methods. Growing.
Functions, closures, *args / **kwargsImplementedDef-site splat and keyword args, defaults, real closures (call-site */** unpacking not yet).
Classes, inheritance, operator dundersImplemented__init__, instance attrs, arithmetic/comparison dunders with reflected fallbacks, __getitem__/__len__/__iter__/__repr__ (src/host.rs).
Comprehensions (list/dict/set), f-stringsImplementedFormat mini-language (fill/align/sign/width/,/.prec/type); loop var currently leaks (see BUGS).
Exceptions (try/except/finally/raise)ImplementedTyped classes; with desugars to try/finally over __enter__/__exit__.
Arbitrary-precision intImplementedBignum promotion for + - * **; ///%/bitwise stay i64-range (see BUGS).
Standalone python binary + REPLImplementedRun .py files, -c one-liners, interactive REPL (src/main.rs, src/repl.rs).
Transparent rkyv bytecode cacheImplementedVersioned on-disk shard at ~/.pythonrs/scripts.rkyv, consulted on every run (src/cache.rs).
AOT native executable (--build)ImplementedStandalone binary via fusevm::aot linked to the runtime staticlib (src/aot_native.rs).
Parity harness vs reference python3ImplementedDifferential corpus diffed byte-for-byte against CPython (src/bin/parity.rs).
LSP server (--lsp)PartialInitialize/shutdown handshake, builtin/keyword completion, stub hover; no diagnostics yet (src/lsp.rs).
DAP adapter (--dap)PartialPer-statement line-marker compile mode exists; the stepping server returns "not implemented" (src/dap.rs).
Generators / async / match, stdlibPlannedyield, await, structural pattern matching, and most of the standard library beyond minimal math/sys pending.

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.

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)
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

# AOT-compile a script to a native ./script executable
./target/release/python --build script.py

# run tests
cargo test

fusevm is pulled from crates.io with the jit, jit-disk-cache, and aot features. Set PYTHONRS_TRACE=1 to log cache hit/miss to stderr.

License

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

Repository & links