Expand description
Multi-module compilation: check against signatures, then link.
docs/03-type-and-effect-system.md §3.6’s
consequence, spelled out: “modules compile against signatures (true separate compilation,
parallel builds); body edits don’t invalidate downstream modules”.
§Two passes, and the difference between them is the whole point
Checking a module needs the interfaces of what it imports and nothing else. Its types unify against imported types, its rows widen with imported rows, and its placement is solved within the module — because §3.6 makes placement part of the published signature, so an imported name’s tier is a given rather than a variable. That is why editing a body downstream is free: there is nothing in the interface for it to change.
Linking needs the bodies, because a program that runs has to have code in it. This is the
.mli/.ml division, and it is worth being explicit that the two halves have different inputs:
an interface is enough to compile against, and never enough to run.
§What the link step does and does not do
It merges checked modules into one crate::check::Program and slices that. Every imported
definition arrives with its placement already decided and marked as such, so the root module’s
solve cannot move it — a downstream edit re-placing an upstream function would be exactly the
failure §3.6 exists to prevent.
It does not namespace: two modules that define the same name are an error rather than a shadowing rule, because Phase 2 has no qualified references to disambiguate with. Named, rather than discovered.
§Where a module comes from
A Loader answers for the program being compiled — for the CLI, the directory the root module
lives in. What it cannot answer for, crate::stdlib does: the standard library’s Beck half is
carried in the compiler, so import bignum resolves from any directory
(10 D23,
adr/0018).
The order is loader first, library second, and it is not arbitrary: a project must be able to
keep the name of a module it already has when the standard library grows one, and a library
being worked on — lib/decimal.beck importing bignum — must get the file beside it rather
than the copy the compiler was built with.
Structs§
- Checked
- A module, checked and placed, with its published interface.
- Project
- A checked, linked project, before it is sliced.
- Sources
- One module’s sources: its implementation, and its published interface if one is checked in.
Constants§
- NOT_
AN_ APPLICATION - The diagnostics that mean “this module is a library”, not “this module is wrong”.
Traits§
- Loader
- Where modules come from.
Functions§
- check_
one - Check one module against its imports’ interfaces, and solve its placement.
- check_
one_ in - The same, against a caller’s source map so that diagnostics point at the right file.
- check_
project - Check and link a project, stopping before the slicer.
- compile_
project - Compile a whole project: check, link, and slice.
- imports_
of - The modules a source file imports, in source order.
- slice
- Slice a checked project into the roles the runtime drives.
- slice_
or_ library - Slice a project, or wrap it as a library if the only thing wrong with it is that it is one.