Skip to content

Repository files navigation

purescript-rs

purescript-rs is a learning compiler that compiles a growing subset of PureScript to portable WebAssembly and runs it on a WASI 0.2 runtime. It is built as a sequence of small, testable stages and is not a replacement for the official PureScript compiler.

Status

The compiler currently:

  • inspects source through every frontend stage: lex, layout, parse, ast, hir, check, check-program, and check-program-kinds;
  • lowers the supported subset through Typed Core, closure-converted CC IR, and a MIR/CFG to a validated WASI 0.2 Component Model artifact, and prints the corresponding WAT;
  • exports wasi:cli/run@0.2.12, so main's result becomes the process exit code through wasi:cli/exit; log and error write to wasi:cli/stdout and wasi:cli/stderr, and now reads the monotonic clock.

The supported subset includes linked source modules, direct and higher-order functions with scalar-capturing closures, Int/Boolean/Number/Char/ String/Unit, arithmetic and comparisons, scalar let, if, case, nullary and field data types, newtypes, closed concrete records and record updates, concrete scalar arrays, parameterized ADTs with the erased representation, and the console, clock, and random WASI capabilities.

Still open:

  • type classes and dictionary passing, open rows, and generic aggregates;
  • the complete scalar and numeric operation set (scalars);
  • broader aggregate coverage for the target-neutral variant representation and the canonical ABI boundary (CC IR, linear ABI boundary);
  • the broader canonical ABI and ownership rules (canonical ABI).

General PureScript compatibility and the official runtime suite remain future work.

Quick start

# Frontend inspection
cargo run -- lex examples/basic.purs
cargo run -- layout examples/basic.purs
cargo run -- parse examples/basic.purs
cargo run -- ast examples/basic.purs
cargo run -- hir examples/resolved.purs
cargo run -- check examples/basic.purs
cargo run -- check-program-kinds examples/basic.purs
cargo run -- dump mir examples/basic.purs

# Build, print, and run
cargo run -- build examples/basic.purs -o /tmp/basic.wasm
wasmtime run /tmp/basic.wasm; echo $?   # prints 42
cargo run -- wat examples/basic.purs -o /tmp/basic.wat

cargo run -- build examples/hello.purs -o /tmp/hello.wasm
wasmtime run /tmp/hello.wasm            # prints "hello world"

build <file.purs>... resolves and links every listed module with the embedded Prelude and writes the artifact. wat <file.purs>... renders the text form. dump <core|cc|mir> <file.purs> prints an intermediate IR for debugging.

Workspace

Crate Responsibility
psrs-span Source text, byte ranges, and line/column mapping.
psrs-syntax Lexing, layout insertion, and parsing.
psrs-cst Concrete syntax tree with source ranges.
psrs-ast Normalized AST and CST-to-AST lowering.
psrs-resolve Locals, same-module names, and whole-program module graphs into HIR.
psrs-hir Resolved HIR nodes and stable declaration/local IDs.
psrs-kind Kind inference and unification with official kind diagnostics.
psrs-thir Typed expressions.
psrs-typecheck Rank-1 polymorphic type inference.
psrs-desugar Operator desugaring while preserving HIR.
psrs-core Typed Core and its HIR lowering.
psrs-backend CC IR, MIR/CFG, structured Wasm encoding, validation, and WAT.
psrs-driver Wires the compiler passes together.
psrs-cli Source inspection, build, wat, and dump commands.

The architecture defines twelve major passes across six long-lived IR families; see D-01.

Target and capability profile

The artifact contract is an explicit capability profile for a pinned wasmtime release, not every feature a runtime happens to support. The stable profile enables Wasm GC, reference types, typed function references, and the synchronous WASI 0.2 Component Model path; SIMD, tail calls, exceptions, threads, memory64, and WASI 0.3 stay disabled until their lowerings and tests land. Wasm GC is the only language heap; linear memory is reserved for the canonical ABI boundary (DEC-09). See DEC-05 and capability profile.

Project documents

The user-facing goals are F-01 and F-02. Their implementations are specified by D-01 and wasm encoding. The backend is split across capability profile (capability profile), IR boundaries (IR boundaries and verification), canonical ABI (WIT imports and canonical ABI), erasure (generic values), scalars (scalar and numeric lowering), and linear ABI boundary (canonical ABI boundary), with the concrete GC layouts and execution-evidence matrix in data representation. The frontend design includes the PureScript type system; D-04 tracks feature coverage and official-suite progress under DEC-04.

For a guided, interactive overview of P0 through P11, use the React application in psrs-explorer/. It labels compact teaching forms as curated and links to CLI commands for real compiler output.

Decision records:

  • DEC-01 — distinct IR boundaries
  • DEC-02 — thin structured Wasm encoding
  • DEC-03 — PureScript-faithful type system and effect encoding
  • DEC-04 — frontend and backend feature matrices
  • DEC-05 — Wasmtime feature set
  • DEC-06 — runtime interface via WIT
  • DEC-07 — parameterized-ADT representation

Development checks

cargo fmt --all --check
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings

The optional upstream differential test checks the front end against the official purs compiler on a small manifest of cases. It skips when purs or a PureScript checkout is unavailable:

PURESCRIPT_REPO=/path/to/purescript cargo test -p psrs-driver --test upstream

About

a toy compiler that compiles puresrcipt to wasm/wasi, written in rust

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages