Sisu

Contribute to Sisu

One person builds Sisu, in the open. It is a learning project at an early stage, so there is no team to hand work to yet. This page says what help fits, how to build the compiler, and which checks a change must pass.

Checked against the repository at commit 7d4d6d0.

Who runs the project

Mikko Leppänen builds and maintains Sisu, and writes most changes with an AI agent, under the same rules this page describes.

AGENTS.md holds the rules for changing the code, for people and agents alike. CONTRIBUTING.md is the route through them.

What help fits

All help is welcome.

These kinds of input match what the project's own rules care about most:

  • A program that gives a wrong answer. Correctness comes first: a program must never give a silent wrong answer. A nightly fuzzer runs generated programs and compares their builds, but it finds only what its generator writes, so a small program that shows one is valuable.
  • A program that crashes the compiler or leaks memory. The smaller the program, the easier it is to turn into a test case.
  • An error message that misleads. Diagnostics should be clear and specific, in simple technical English. Wording that is wrong, vague or full of compiler jargon counts as a bug.
  • A benchmark that disagrees. The benchmarks compare Sisu with other languages. A result you cannot reproduce, measured as the benchmark guide describes, is worth knowing.
  • A document that is wrong. A doc that states what a program prints must match a real run.

Talk before you build

Each step of work is designed before it is built. Its design is settled in a working spec, and the lasting decisions become ADRs. A proposal in the roadmap is not decided until it lands in a spec or an ADR.

So raise an idea before you write code for it. Read the open decisions first: your idea may already be one of them.

Open a GitHub issue to discuss an idea.

The maintainer's own work is tracked in the same GitHub issues.

Build from source

Sisu builds and runs on x86-64 and ARM64 Linux and on ARM64 macOS. You need:

  • The Rust toolchain pinned in rust-toolchain.toml (1.99.0). rustup installs it on first use.
  • GNU Make, which runs every command.
  • A C compiler on PATH as cc. sisu uses it to link programs.
  • On Ubuntu: libzstd-dev, libxml2-dev and zlib1g-dev, which LLVM links against. On macOS: Homebrew's zstd.
  • prek for the Git hooks, with typos and shellcheck.
  • cargo-nextest and cargo-deny, and on Linux Valgrind for the end-to-end tests.
  • uv, to build the site.
  • For make miri, a nightly toolchain with Miri: rustup toolchain install nightly --component miri --component rust-src.

You do not install LLVM yourself. make setup downloads the official LLVM 23 release and keeps what the build needs in .llvm/23, about 570 MB. The build uses that copy and leaves any system LLVM alone.

terminal
$ git clone https://github.com/sisu-lang/sisu
$ cd sisu
$ make setup     # once per clone: LLVM 23 into .llvm/23, the pre-commit hook
$ make build     # cargo build --workspace: sisu and the two runtime archives
$ target/debug/sisu build crates/sisuc/tests/run/fib.sisu
$ ./fib
832040

Build the whole workspace, not only sisu. Every program links with a runtime archive, libsisu_runtime_mimalloc.a or, with --allocator system, libsisu_runtime_system.a, which sisu looks for next to its own executable; cargo build -p sisuc does not build it. make help lists every target.

Developing Sisu has the full list of prerequisites and commands.

Checks before a pull request

The pre-commit hook runs the same checks as CI. Before you open a pull request, run these:

terminal
$ make check     # lint, test and deny, as CI requires
$ make site      # build and check the website, as CI does
$ make miri      # only when you change crates/runtime
$ make verify    # coverage, then mutants, on your diff
  • make test runs the tests with nextest, not cargo test. Its setup script builds the two runtime archives that the end-to-end tests link against. On Linux, the end-to-end tests run each program under Valgrind.
  • Clippy and the compiler run with -D warnings, so one warning fails CI. Silence a single site with #[expect(lint, reason = "...")], never a bare #[allow].
  • make miri runs the runtime's unit tests under Miri on nightly, which stops at undefined behaviour. CI runs it too.
  • make verify ends with one line, verify: PASS or verify: FAIL. Cover or explain each uncovered region, and kill or explain each surviving mutant.

Code standards

Clippy, rustfmt and the hooks enforce the mechanical rules. CODING_STANDARDS.md holds the judgement calls that no check can make. Four of them:

  • A test proves its name. It must fail when the contract it names breaks. The name says what should hold, as <subject>_should_<result>.
  • An expect message states the invariant. It says what should hold and why, so a panic reads as a broken assumption.
  • A cost claim is measured. A claimed speedup comes with instruction counts before and after. Without a measured gain, the simpler code wins.
  • Wording lives in the registry. No call site writes diagnostic text.

Use the words in the glossary, and read the design decisions that touch your change.

How a change gets reviewed

Every change arrives as a pull request. Its description says what changed and why. Then it says what a reviewer cannot see from the diff: which contract each new test proves, what was left out of scope, and what is known not to work yet.

Before you open it, bring the docs in line with the change, as the update-docs guide describes.

Reviewers apply CODING_STANDARDS.md to every diff:

  • A change is approved when it meets its done condition and adds no wrong output, crash, leak or newly rejected valid program.
  • A defect the change introduces blocks it. A defect the old code had too is a nit, fixed in a separate task.
  • A nit never blocks.

A diff can also get a review from a second AI model; AGENTS.md says how.

License

Sisu is released under the MIT license. See LICENSE.