Skip to main content

polydat_core/kernel/subcontext/
spec.rs

1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! Typed import / export contracts (per SRD-13e §1.2).
5//!
6//! The specs carry the SRD-13e taxonomy (lifecycle
7//! classifications, port types, binding modifiers) as data.
8//! What [`crate::kernel::subcontext::SubcontextBuilder::finalize`]
9//! enforces from them is fixed by
10//! `docs/design/subcontext_construction.md` §2.2: every import
11//! name must exist on the parent (`UnboundImport`), a child
12//! export may not shadow a parent `const` output (`FinalShadow`),
13//! and a child export matching an in-scope shared cell becomes a
14//! write-through binding. `port_type` and `classification` are
15//! preserved in the public `ScopeContract` but are not compared
16//! against a typed parent manifest; the child's input slots and
17//! shared-cell writes are protected by the compiler's slot type
18//! checks and by `kernel::state::check_write_through_type`.
19
20use crate::ast::PortType;
21use crate::dsl::ast::BindingModifier;
22
23/// Lifecycle classification for an import — taxonomically what
24/// SRD-13e §1.2 specifies. Drives the spawn-time validation
25/// decisions per SRD-67 Rule 1.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum ImportClassification {
28    /// `final X: T` — fold the parent's value into the child at
29    /// compile/init time.
30    CompileConst,
31    /// `extern X: T` — wire to the parent's value via an input
32    /// slot. Most common shape.
33    Extern,
34    /// `shared X: T` — share-cell-attach against a parent's
35    /// `shared`-modifier export.
36    Shared,
37    /// Iteration extern: parent's coordinate / iteration variable
38    /// (SRD-67 Rule 4 routes through the parent's coordinate
39    /// buffer).
40    IterationExtern,
41}
42
43/// Lifecycle classification for an export — what kind of
44/// downstream contract this export carries.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum ExportClassification {
47    /// Locally-defined output of the body. The default shape.
48    Local,
49    /// `const` modifier on the body's binding.
50    Final,
51    /// `shared` modifier on the body's binding — shared cell
52    /// available to descendants.
53    Shared,
54    /// Iteration variable (comprehension coordinate). Routed
55    /// through the parent's coord buffer at spawn (Rule 4).
56    Coordinate,
57    /// `volatile` modifier — excluded from const-fold identity.
58    Volatile,
59}
60
61/// Typed import declaration: a name the child's body will
62/// reference, expecting the parent to export it.
63#[derive(Debug, Clone)]
64pub struct ImportSpec {
65    /// Name as referenced inside the child body.
66    pub name: String,
67    /// Expected port type. Spawn validates against the parent's
68    /// matching export (Rule 1).
69    pub port_type: PortType,
70    /// Lifecycle classification.
71    pub classification: ImportClassification,
72}
73
74impl ImportSpec {
75    /// An import written to by the host, as an `extern` port.
76    pub fn extern_(name: impl Into<String>, port_type: PortType) -> Self {
77        Self {
78            name: name.into(),
79            port_type,
80            classification: ImportClassification::Extern,
81        }
82    }
83
84    /// An import fixed at compile time, from a parent `final` export.
85    pub fn final_(name: impl Into<String>, port_type: PortType) -> Self {
86        Self {
87            name: name.into(),
88            port_type,
89            classification: ImportClassification::CompileConst,
90        }
91    }
92
93    /// An import bound to a shared cell.
94    pub fn shared(name: impl Into<String>, port_type: PortType) -> Self {
95        Self {
96            name: name.into(),
97            port_type,
98            classification: ImportClassification::Shared,
99        }
100    }
101
102    /// An import rebound per activation of an enclosing iteration.
103    pub fn iter_var(name: impl Into<String>, port_type: PortType) -> Self {
104        Self {
105            name: name.into(),
106            port_type,
107            classification: ImportClassification::IterationExtern,
108        }
109    }
110}
111
112/// Typed export declaration: a named value the child produces,
113/// available to its own descendants.
114#[derive(Debug, Clone)]
115pub struct ExportSpec {
116    /// Name as it appears in the child's body.
117    pub name: String,
118    /// Port type the child binds.
119    pub port_type: PortType,
120    /// Modifier (`final` / `shared` / none) — the standard GK
121    /// modifier set; spawn uses it to apply Rule 2.
122    pub modifier: BindingModifier,
123    /// Lifecycle classification.
124    pub classification: ExportClassification,
125}
126
127impl ExportSpec {
128    /// A local export with no modifier.
129    pub fn local(name: impl Into<String>, port_type: PortType) -> Self {
130        Self {
131            name: name.into(),
132            port_type,
133            modifier: BindingModifier::NONE,
134            classification: ExportClassification::Local,
135        }
136    }
137
138    /// A `final` export: fixed once bound.
139    pub fn final_(name: impl Into<String>, port_type: PortType) -> Self {
140        Self {
141            name: name.into(),
142            port_type,
143            modifier: BindingModifier::CONST,
144            classification: ExportClassification::Final,
145        }
146    }
147
148    /// A `shared` export: a cell the descendants write through.
149    pub fn shared(name: impl Into<String>, port_type: PortType) -> Self {
150        Self {
151            name: name.into(),
152            port_type,
153            modifier: BindingModifier::SHARED,
154            classification: ExportClassification::Shared,
155        }
156    }
157
158    /// An export rebound per activation of an enclosing iteration.
159    pub fn iter_var(name: impl Into<String>, port_type: PortType) -> Self {
160        Self {
161            name: name.into(),
162            port_type,
163            modifier: BindingModifier::NONE,
164            classification: ExportClassification::Coordinate,
165        }
166    }
167}