p2w compiles a substantial subset of Python to WebAssembly, leveraging WASM GC for automatic memory management.
- Data types: integers (arbitrary precision), floats, booleans, strings, bytes, lists, tuples, dicts, sets
- Control flow: if/elif/else, for/while loops, break/continue, match statements
- Functions: definitions, default arguments, *args/**kwargs, closures, lambdas, decorators
- Classes: inheritance, properties, static/class methods, special methods (
__init__,__str__, etc.) - Comprehensions: list, dict, set, generator expressions
- Exception handling: try/except/finally, raise, exception chaining
- Context managers:
withstatement - Generators: yield, generator functions
- Other: f-strings, type annotations (ignored at runtime), walrus operator, unpacking
p2w provides seamless JavaScript interoperability via the js module:
import js
canvas = js.document.getElementById("chart")
ctx = canvas.getContext("2d")
ctx.fillRect(0, 0, 100, 100)
js.console.log("Hello from Python!")The demos/ directory contains two (somewhat) working browser demos:
- data-dashboard: Bar chart visualization using Canvas API
- simulation: Physics simulation with real-time rendering
The programs/internal/ directory contains 104 test programs covering the supported Python subset. These serve as both regression tests and documentation of working features, including:
- Classes with inheritance, properties, and special methods
- Generators and comprehensions
- Exception handling with chaining
- Context managers
- Match statements
- F-strings and string operations
- Collection types and methods
Two benchmark suites validate correctness and measure performance:
programs/benchmarks/ - Classic benchmarks adapted for p2w:
- fibonacci, primes, sieve, matmul
- fannkuch, binarytrees, nbody
- mandelbrot, spectralnorm, fasta
- pystone
programs/benchmarks-alioth/ - Benchmarks from the Debian Benchmark Game with GCC baseline comparison:
- binarytrees, nbody, spectralnorm, mandelbrot, fannkuchredux
- Includes a runner script for automated comparison against GCC (
-O3 -ffast-math)
# Clone the repository
git clone https://git.sr.ht/~sfermigier/p2w
cd p2w
# Install with uv
uv syncGiven a Python source file fib.py:
def fib(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
print(fib(30))The simplest way to compile and run it:
uv run p2w -r fib.py
# Output: 832040If you want to inspect or keep the intermediate files:
# 1. Compile Python to WAT (WebAssembly Text format)
uv run p2w fib.py -o fib.wat
# 2. Convert WAT to WASM binary (requires wasm-tools)
wasm-tools parse fib.wat -o fib.wasmThe generated WASM cannot run standalone — it imports host functions for I/O (write_char, write_i32, etc.). The p2w -r flag handles this automatically by generating a Node.js loader that provides these imports and runs the module. For browser execution, see the demos in demos/.
p2w [-h] [-o OUTPUT] [-r] [-v] [-d] [-V] source
-o, --output FILE write WAT to file instead of stdout
-r, --run compile and run immediately (requires wasm-tools + Node.js)
-v, --verbose show compilation details on stderr
-d, --debug dump AST and debug info to stderr
-V, --version show version
from p2w import compile_to_wat
wat_code = compile_to_wat('print("hello")')def fib(n: int) -> int:
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
print(f"fib(30) = {fib(30)}")The demos/ directory contains browser examples:
- data-dashboard: Interactive bar chart visualization
- simulation: Physics simulation
To run a demo:
cd demos/data-dashboard
make # Builds app.wasm
# Serve with any HTTP server and open index.html# Run tests
make test
# Run linting and type checking
make lint
# Format code
make format
# Run tests with coverage
make test-covtests/a_unit/- Unit teststests/b_integration/- Integration teststests/c_e2e/- End-to-end tests
p2w follows a straightforward compilation pipeline:
- Parse: Python source -> AST (using Python's
astmodule) - Analyze: Scope analysis, type inference
- Compile: AST -> WAT (WebAssembly Text format)
- Assemble: WAT -> WASM (via
wasm-tools)
The compiler generates WAT code that uses WASM 3.0 GC features for automatic memory management of Python objects.
- Python 3.12+
- wasm-tools (for WAT to WASM conversion)
- Node.js 22+ (for running compiled WASM via
p2w -r) - For browser execution: any browser with WASM GC support (recent Chrome/Firefox)
It's too long at this point to cite every influence and/or alternative. Here are a few that stand out:
- Compiling Scheme to WebAssembly - Huge influence on unstucking the project
- Compylo - A previous attempt, started by Ethan Zouzoulkowsky (then student at EPITA) in 2023
- Prescrypt - A Python->JS compiler, itself based on PScript
MIT