Thank you for taking a look. Pyfun is an F#-inspired, functional-first language whose compiler is written in Rust and emits readable Python. Contributions of every size are welcome: a clearer error message, a missing test, a lesson that explains something better, or a compiler change.
You need two things.
- Rust. The repository pins its toolchain in
rust-toolchain.toml, andrustupselects it automatically inside the repo. The crate has no dependencies, so the first build is quick. - Python 3.12 or newer on your
PATHaspythonorpython3. The end-to-end tests run the emitted Python, and emitted code usesmatchstatements and PEP 701 f-strings. CI runs them on 3.12 on all three systems and on 3.14 on Linux, so a difference between the two ends of the supported range fails there even when your local run passes.
Then:
cargo build
cargo test # the whole suite
cargo test parse_print # one test, by substring
cargo run -- run examples/hello.pyfun # compile and run a program
cargo run -- compile examples/hello.pyfun # see the Python it emitsOn Windows, an editor running the Pyfun language server keeps target/debug/pyfun.exe open, so a
build can fail with "Access is denied". Stop the pyfun process, or build into a second directory
with CARGO_TARGET_DIR=target-test.
Start with the compiler tour, which walks the pipeline from lexing to emission one chapter at a time. Every chapter ends with a "Where you would add..." note naming the first file and function you would touch for a typical change at that stage:
| You want to... | Read |
|---|---|
| add a token or keyword | Lexing |
| add an expression form | Parsing |
| add syntax sugar | Desugaring |
| give a builtin its type | Inference |
| add a pattern form | Exhaustiveness |
| add a measure or root | Units |
| lower a stdlib function | Lowering |
| emit a new Python construct | Emission |
| improve an error message | Diagnostics |
| add an editor feature | Tooling |
Three documents at the root carry the detail. DESIGN.md is the source of truth for
what the language means and why; read the relevant section before changing a language rule.
INTERNALS.md maps each rule to the code that implements it. ROADMAP.md
holds the backlog, including the non-goals, each with the reason it was decided against.
The issues labelled good first issue are small and self-contained, and each one names the file to start from.
-
Open an issue first for anything that changes the language itself, so the design can be agreed before you spend time on code. Bug fixes, tests, diagnostics and docs can go straight to a PR.
-
Add a test next to the ones like it.
tests/roundtrip.rscovers parsing,tests/typecheck.rsthe checker and its messages,tests/compile.rsthe emitted Python and what it prints, andsrc/lsp/mod.rsthe language server. -
Run the same checks CI runs:
cargo fmt cargo clippy --all-targets cargo test -
Update
DESIGN.mdorINTERNALS.mdin the same PR when your change touches what they describe, and strike through anyROADMAP.mditem it closes.
A few principles shape what gets merged:
- The emitted Python should read as if a person wrote it. Lowering builds a Python syntax tree
in Rust and prints it, and a fully applied curried call becomes a plain
f(a, b). - New syntax mirrors a form Python programmers already know. Ask how Python spells the idea before inventing a spelling.
- Error messages say what to do next. A message that names the fix is worth more than a new feature.
- The scope is deliberately small. Proposals for type classes, macros and similar are listed as
non-goals in
ROADMAP.md, with the reasoning.
The learning site lives in docs/src and builds with mdBook. Lessons talk to the reader as "you",
show an example before stating a rule, and keep to plain prose. Every code block in a lesson is
checked against the real compiler, so after editing one run:
cargo build
python docs/verify_lessons.py
python docs/build_notebooks.pyThe first checks that each playground link decodes to the starter shown beside it and that each
solution prints what the lesson says it prints. The second regenerates the lesson's notebook in
docs/src/notebooks/, which CI compares against the lessons.
Code contributions are made under the Apache License 2.0, the licence of the project. Teaching prose on the learning site is licensed CC BY 4.0.