Skip to main content

polydat_core/kernel/subcontext/
mod.rs

1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! Parent-gated Polydat sub-context construction.
5//!
6//! This module is the typed entry point for constructing a Polydat
7//! child kernel as a function of a parent kernel. It implements
8//! the protocol from
9//! `crates/polydat/docs/design/subcontext_construction.md`:
10//!
11//! 1. Parent yields a builder via [`ScopeKernel::subcontext_builder`].
12//! 2. Builder accumulates module matter (imports, exports, body
13//!    fragments, pull consumers) via [`SubcontextBuilder`].
14//! 3. `finalize` closes the builder, validates imports against the
15//!    parent's exports, compiles the body into a [`ScopeModule`] with
16//!    a typed [`ScopeContract`].
17//! 4. Parent spawns the child via [`ScopeKernel::spawn`] — the single
18//!    chokepoint where every cross-binding is resolved.
19//!
20//! ## Cross-binding rules
21//!
22//! The comments in this module name the cross-binding rules by
23//! number. They are enforced at [`SubcontextBuilder::finalize`] and
24//! [`ScopeKernel::spawn`]:
25//!
26//! * Rule 1 — import resolution at finalize
27//!   (subcontext_construction.md §2.2, SC4).
28//! * Rule 2 — export collision with a `const` parent output surfaces
29//!   as [`ContractViolation::FinalShadow`]; collision with a `shared`
30//!   cell visible at the parent rewrites the body's `X := <expr>` into
31//!   `extern X: <type>` + `__write_X := <expr>` and records a
32//!   `WriteThroughBinding` on the artifact (§3.1). Per-cycle eval
33//!   calls [`ScopeKernel::commit_write_throughs`] to fan values
34//!   through the parent's `SharedCell` (§5).
35//! * Rule 3 — the child is initialized after binding, so its consts
36//!   see the bound inputs (§4, §9).
37//! * Rule 4 — coordinate routing handled by `materialize_wiring_from_outer`'s
38//!   IterationExtern input-kind.
39//! * Rule 5 — closure-binding economy: magic externs are injected only
40//!   when referenced (§3.2), and unused imports surface as finalize
41//!   diagnostics rather than errors (§2.2).
42//!
43//! ## Cross-crate boundary
44//!
45//! [`PullConsumer`] is defined as a trait so that `nbrs-runtime`'s
46//! `ScopeFixture` can implement it without `polydat-core`
47//! depending on `nbrs-runtime` (the crate dependency runs the
48//! other way). The trait carries a minimal shape — the names a
49//! consumer wants to pull at cycle time — sufficient for the
50//! activity-side `ScopeFixture::register_consumer` adapter to
51//! absorb. Sealing the host's pull plan happens on the activity
52//! side; the artifact only carries the requested names
53//! (subcontext_construction.md §2.4).
54//!
55//! ## Walled-off invariant
56//!
57//! The low-level cross-binding primitives are sealed
58//! (subcontext_construction.md §8, SC1): `PolydatKernel::from_program` is
59//! `pub(crate)` and `materialize_wiring_from_outer` is private to the kernel.
60//! External consumers must go through the typed surface:
61//! [`SubcontextBuilder`] / [`ScopeKernel::spawn`] or [`PolydatMatter::build_under`]
62//! for child construction, and `Construction::root` / `KernelProgram::create_kernel`
63//! for parentless re-instancing of a compiled program.
64//!
65//! The compile-fail cases under the facade crate's `crates/polydat/tests/ui/seal/` guard the seal: one
66//! calls `materialize_wiring_from_outer` from outside the crate, one
67//! calls `PolydatKernel::from_program`, and neither may compile. If
68//! either starts compiling, the seal is broken.
69
70mod builder;
71mod error;
72mod kernel;
73mod module;
74mod name;
75mod pull;
76mod spec;
77
78#[cfg(test)]
79mod tests;
80
81pub use builder::{CompileOptions, ParentView, SubcontextBuilder};
82pub use error::{ContractViolation, SourceContext};
83pub(crate) use kernel::PolydatMatterInner;
84pub use kernel::{Child, PolydatMatter, PolydatMatterBuilder, RootMarker};
85pub use kernel::{ScopeKernel, SharedCellInScope, wrap_root_kernel};
86pub use module::{BodyFragment, ScopeContract, ScopeModule};
87pub use name::ChildName;
88pub use pull::{NamedPullConsumer, PullConsumer, RegisteredPullConsumer};
89pub use spec::{ExportClassification, ExportSpec, ImportClassification, ImportSpec};