Skip to main content

pass_lang/
lib.rs

1//! # pass_lang
2//!
3//! A pass manager: an ordered pipeline of optimization and transform passes, and
4//! the plugin seam capability crates register their passes into.
5//!
6//! A compiler improves and lowers a program by running a series of *passes* over
7//! it — constant folding, dead-code elimination, inlining, lowering steps. The
8//! pieces those passes share — running in a defined order, repeating until the
9//! program stops changing, stopping cleanly when one fails, recording what
10//! happened — are the same regardless of *what* the passes rewrite. pass-lang is
11//! that shared machinery, and nothing more.
12//!
13//! It is generic over the unit a pass rewrites. A [`Pass<T>`] transforms a `T` —
14//! an intermediate representation, a single function, a whole module, an abstract
15//! syntax tree, or a struct bundling an IR with the diagnostics and analysis a
16//! pass needs. A [`PassManager<T>`] holds passes in registration order and runs
17//! them; it is the scheduler and never touches the unit itself. The crate owns no
18//! IR and wires no first-party dependency — the same shape as LLVM's pass manager
19//! (generic over Module / Function / Loop) or Cranelift's pass pipeline.
20//!
21//! ## Running a pipeline
22//!
23//! Implement [`Pass`] for each transform, register the transforms with
24//! [`PassManager::add`], and run them — once with [`PassManager::run`], or
25//! repeatedly to a fixpoint with [`PassManager::run_to_fixpoint`]. Each run
26//! returns a [`Report`] of what every pass did.
27//!
28//! ## Example
29//!
30//! ```
31//! use pass_lang::{Outcome, Pass, PassError, PassManager};
32//!
33//! // The unit is whatever a pass rewrites — here, a list of integers.
34//! struct DropZeros;
35//! impl Pass<Vec<i64>> for DropZeros {
36//!     fn name(&self) -> &'static str {
37//!         "drop-zeros"
38//!     }
39//!     fn run(&mut self, unit: &mut Vec<i64>) -> Result<Outcome, PassError> {
40//!         let before = unit.len();
41//!         unit.retain(|&x| x != 0);
42//!         Ok(Outcome::from_changed(unit.len() != before))
43//!     }
44//! }
45//!
46//! let mut pm = PassManager::new();
47//! pm.add(DropZeros);
48//!
49//! let mut unit = vec![0, 1, 0, 2, 3];
50//! let report = pm.run(&mut unit).expect("the pass does not fail");
51//!
52//! assert_eq!(unit, vec![1, 2, 3]);
53//! assert_eq!(report.changes(), 1);
54//! ```
55//!
56//! ## Features
57//!
58//! - `std` (default) — the standard library; without it the crate is `#![no_std]`
59//!   and needs only `alloc`.
60//! - `serde` — derives `serde::Serialize` for the reporting types ([`Outcome`],
61//!   [`PassRun`], [`Report`]) so a run report can be logged or inspected.
62//!
63//! ## Stability
64//!
65//! The public surface is frozen and stable as of `1.0.0`: it follows Semantic
66//! Versioning, with no breaking changes before `2.0`. The full surface and the
67//! SemVer promise are catalogued in
68//! [`docs/API.md`](https://github.com/jamesgober/pass-lang/blob/main/docs/API.md#semver-promise).
69
70#![cfg_attr(not(feature = "std"), no_std)]
71#![cfg_attr(docsrs, feature(doc_cfg))]
72#![deny(missing_docs)]
73#![forbid(unsafe_code)]
74#![deny(
75    clippy::unwrap_used,
76    clippy::expect_used,
77    clippy::panic,
78    clippy::todo,
79    clippy::unimplemented,
80    clippy::unreachable,
81    clippy::dbg_macro,
82    clippy::print_stdout,
83    clippy::print_stderr
84)]
85
86extern crate alloc;
87
88mod error;
89mod manager;
90mod pass;
91mod report;
92
93pub use error::PassError;
94pub use manager::PassManager;
95pub use pass::{Outcome, Pass};
96pub use report::{PassRun, Report};
97
98/// Compiles and runs the `rust` code blocks in `README.md` and `docs/API.md` as
99/// part of `cargo test`, so the published examples cannot drift from the API.
100///
101/// Present only while collecting doctests (`#[cfg(doctest)]`); it is not part of
102/// the public surface and does not appear in the built library or its docs.
103#[cfg(doctest)]
104#[doc = include_str!("../README.md")]
105#[doc = include_str!("../docs/API.md")]
106pub struct MarkdownDocTests;