Expand description
use("name") — how a blue program consumes a bidama.
§The gap this closes
Before this, blue’s packaging had a manifest (Bluefile), a resolver
(blue-lang-pkg), a git registry and a nix derivation per package — and
no way for a program to consume any of it. retsu/Bluefile declared
needs("kazu", "^0.1") while retsu’s source never referenced a single
thing from kazu, because the language had no import form at all. The
dependency graph was described by four layers and traversed by none.
That is the difference between packaging that exists and packaging that works, and it is why this is a load-bearing addition rather than a convenience: a distribution whose packages cannot see each other is a directory of unrelated files wearing a distribution’s name.
§Why a pipeline pass and not a builtin
A register_fn native takes (&[Value], &mut H, Span). It cannot define
anything, because it never sees the interpreter — so use implemented as a
builtin could load a package’s text and would have nowhere to put its
definitions. Resolution therefore happens on the FORM tree, before
evaluation: a use is replaced by the forms of the package it names, and
the whole program is then checked and run as one unit.
That ordering is deliberate and worth stating, because it decides a real
behaviour: the type checker sees the imported code, so a package that fails
blue-lang-check fails at the point its consumer imports it rather than at
whatever later moment its code first ran.
§Why the loader is a trait
Loading a package means reading a filesystem, and this crate compiles to
wasm32-unknown-unknown with zero host imports (blue-lang-wasm). A
direct std::fs call here would break that target for every consumer,
including ones that never call use.
So the capability is injected — Loader here, the real filesystem
implementation in blue-lang-pkg, which is native-only. This is the
fleet’s mockable-Environment seam, and it buys the usual thing: every
test below drives the whole resolution pass against an in-memory loader,
with no temp directories and no fixture files on disk.
§Why this module also owns file identity
Splicing several files into one program is exactly the act that destroys a
byte offset’s meaning, so the record of where each form came from is kept by
the pass that does the splicing rather than reconstructed downstream by
something that no longer has the sources. ResolvedProgram is that
record, and ResolvedProgram::locate spends it.
Structs§
- Entry
- The program the pipeline was handed, and what to call it.
- FileId
- Identity of one source file inside a
ResolvedProgram. - Located
- A diagnostic rendered against the file it came from:
path:line:col: text. - NoLoader
- A loader that resolves nothing, and says so.
- Resolved
Program - A program with its imports spliced in, and the file each top-level form came from.
- Source
File - One file that contributed forms to a
ResolvedProgram.
Traits§
- Loader
- Supplies the source of a named bidama.
Functions§
- is_
test_ form - Is this form a lowered
testblock? - resolve_
uses - Replace every
use(...)with the forms of the package it names.