pith currently has one active compiler pipeline:
self-host/: the Pith frontend, tools, import resolution, checking, and IR emissioncranelift/: the Rust/Cranelift backend, runtime, object generation, and linking
the active pipeline is:
- lex source text into tokens
- parse tokens into an AST
- type-check and resolve imports
- emit Pith text IR
- lower text IR to Cranelift IR
- emit an object file and link it with the Rust runtime using
gcc
end to end, that is:
pith source (.pith)
-> self-hosted frontend: lex, parse, check
-> self-hosted ir emitter (ir_emitter_core.pith and satellites) -> text ir
-> ir_consumer.rs (text ir -> cranelift ir)
-> cranelift native code generation
-> object file (.o)
-> system linker (gcc)
-> native executable
steps 1 through 4 are pith compiling pith: the frontend builds itself.
make bootstrap rebuilds the compiler with the cranelift-compiled version of
itself, and make bootstrap-ir-checks verifies the ir contract, its
invariants, and that the emitted ir reaches a fixed point on the deterministic
corpus.
the older Zig bootstrap and C transpiler are historical implementation paths. they are useful context when reading old notes, but they are not tracked as the current build/run path.
networking and protocol layers now live mostly in the Pith stdlib. that
includes std.net.http, std.net.websocket, and the native TLS stack (1.3 with a 1.2 fallback) in
std.net.tls / std.net.tls13 / std.net.tls12. Rust stays on the lower-level runtime side for
storage, syscall-facing helpers, and the Cranelift backend.
- lexer/parser own syntax-only concerns and should never guess at types
- checker owns name resolution, type resolution, imports, and diagnostics
- IR emission assumes checked input and focuses on stable text IR
- CLI modules should only coordinate user-facing flows; they should not duplicate compiler setup
- stdlib protocol layers should own wire semantics and user-facing behavior; lower-level runtime code should stay boring and explicit
if a change requires repeated lex/parse/check setup, it belongs in
self-host/driver.pith or the relevant self-hosted tool module.
if a change only affects object output or linking, it belongs in cranelift/.
- self-hosted compiler:
self-host/lexer.pith - if syntax changes: update
docs/grammar.ebnf
- parser:
self-host/parser.pith - AST shape:
self-host/ast.pith - examples/docs: add or update an example under
examples/
- self-hosted checker:
self-host/checker.pith - diagnostics reference:
docs/errors.mdif a new stable code is introduced
- lowering engine (expressions, statements, ownership, function
lifecycle):
self-host/ir_emitter_core.pith - its satellites, each owning one concern:
ir_builder(output buffer and per-function state),ir_alias_registry(aliases, import renames, global kinds),ir_struct_registryandir_method_tables(shapes and symbols),ir_generics(declarations and specializations),ir_decode_emit(json/toml/ config decode calls),ir_match_emit(match lowering),ir_call_emit(call/label wrappers) - the satellites never import the core back; where one needs an
expression emitted in place it takes the emitter as an explicit
fn-value parameter (grep for
emit_expr) - IR driver:
self-host/ir_driver.pith - Cranelift lowering:
cranelift/codegen/src/ir_consumer.rs(the ir instruction format is specified in ir-contract.md, which is authoritative for both sides) - runtime support:
cranelift/runtime/src/if native code needs new helpers
- Pith stdlib protocol logic:
std/net/tls.pith,std/net/tls13.pith,std/net/http.pith,std/net/websocket.pith - crypto helpers used by tls:
std/crypto/*.pith - only add Rust runtime support when the stdlib truly needs a new low-level primitive
- self-hosted CLI:
self-host/pith_main.pith - native backend CLI:
cranelift/cli/src/main.rs
- server loop and routing:
self-host/lsp_server.pith - documents and position conversion:
self-host/lsp_state.pith - diagnostics/hover/symbols/formatting:
self-host/lsp_features.pith - framing and json-rpc envelope:
std/lsp/transport.pith,std/lsp/protocol.pith
start at the CLI entrypoint, then follow one command end to end:
cranelift/cli/src/main.rsself-host/pith_main.pithself-host/driver.pithself-host/checker.pith
that path shows most of the compiler lifecycle with minimal generated-output noise.