iter 22b.3.1: mono pass skeleton — identity for class-free workspaces
This commit is contained in:
@@ -251,9 +251,11 @@ fn unify(a: &Type, b: &Type, subst: &mut Subst) -> Result<()> {
|
||||
pub mod builtins;
|
||||
pub mod diagnostic;
|
||||
pub mod lift;
|
||||
mod mono;
|
||||
|
||||
pub use diagnostic::{Diagnostic, Severity};
|
||||
pub use lift::lift_letrecs;
|
||||
pub use mono::monomorphise_workspace;
|
||||
|
||||
/// Internal error type produced by the typechecker.
|
||||
///
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
//! Iter 22b.3: workspace monomorphisation pass.
|
||||
//!
|
||||
//! Slots into the build pipeline after [`crate::lift_letrecs`] and
|
||||
//! before `ailang_codegen::lower_workspace_with_alloc`. The pass
|
||||
//! consumes the workspace's typeclass [`Registry`] and the per-
|
||||
//! module class-method tables (already populated by
|
||||
//! [`crate::check_in_workspace`]) and produces a workspace with:
|
||||
//!
|
||||
//! 1. Synthesised [`Def::Fn`] entries — one per unique
|
||||
//! `(class, method, type-hash)` triple observed at any
|
||||
//! class-method call site — appended to the [`Registry`]'s
|
||||
//! `defining_module` for that instance.
|
||||
//! 2. Rewritten call sites — every `Term::Var { name }` whose
|
||||
//! `name` resolves through [`Env::class_methods`] is replaced
|
||||
//! by the corresponding mono-symbol name (qualified with the
|
||||
//! instance's `defining_module` iff that module differs from
|
||||
//! the calling module).
|
||||
//!
|
||||
//! Pre-existing `Def::Class` and `Def::Instance` entries are
|
||||
//! preserved verbatim — codegen ignores them, but downstream
|
||||
//! tooling (e.g. `ail describe`) may still consult them.
|
||||
//!
|
||||
//! Class-free workspaces are byte-identical through the pass:
|
||||
//! the early-out check at the top of [`monomorphise_workspace`]
|
||||
//! returns the input clone untouched.
|
||||
//!
|
||||
//! ## Symbol-hashing invariant
|
||||
//!
|
||||
//! Synthesised FnDefs are post-typecheck artefacts. They do NOT
|
||||
//! enter `CheckedModule.symbols` (built from the original module
|
||||
//! at typecheck time and used by `ail diff` / `ail manifest`).
|
||||
//! Same convention as [`crate::lift_letrecs`].
|
||||
|
||||
use ailang_core::ast::Def;
|
||||
use ailang_core::workspace::Workspace;
|
||||
use crate::Result;
|
||||
|
||||
/// Iter 22b.3: workspace-wide monomorphisation pass entry. See the
|
||||
/// module-level doc for the architecture and contract.
|
||||
///
|
||||
/// Pre-condition: `ws` has been typechecked (`check_workspace(ws)`
|
||||
/// returned no errors) and lifted (`lift_letrecs` per module). The
|
||||
/// pass does not perform new type checking — it queries types via
|
||||
/// `synth` on already-typechecked bodies.
|
||||
pub fn monomorphise_workspace(ws: &Workspace) -> Result<Workspace> {
|
||||
// Fast path — no class / instance defs anywhere → nothing to do.
|
||||
// The pass also has no targets when there are class defs but no
|
||||
// instance defs (no callable methods at concrete types), but
|
||||
// the body walks would still be a wasted traversal; the
|
||||
// class-free check is the cheap way to opt out.
|
||||
if !workspace_has_typeclasses(ws) {
|
||||
return Ok(ws.clone());
|
||||
}
|
||||
|
||||
// Skeleton in Task 1: even with classes present, return the
|
||||
// workspace clone unchanged. Subsequent tasks fill in collection,
|
||||
// synthesis, and rewriting.
|
||||
Ok(ws.clone())
|
||||
}
|
||||
|
||||
/// Iter 22b.3: returns `true` iff any module in `ws` declares at
|
||||
/// least one [`Def::Class`] or [`Def::Instance`]. Cheap workspace
|
||||
/// scan; the early-out keeps class-free workspaces byte-identical
|
||||
/// through the pass.
|
||||
fn workspace_has_typeclasses(ws: &Workspace) -> bool {
|
||||
ws.modules.values().any(|m| {
|
||||
m.defs.iter().any(|d| matches!(d, Def::Class(_) | Def::Instance(_)))
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user