Skip to content

Commit d624ea7

Browse files
authored
feat(routines): add rooted declaration pipeline (#98)
Compose capability-relative source acquisition with the typed declaration pipeline while preserving existing APIs and stage errors. Share preparation logic and apply one limits value across source and syntax checks.
1 parent ce9750e commit d624ea7

2 files changed

Lines changed: 444 additions & 13 deletions

File tree

tools/routine-compiler/src/declaration_pipeline.rs

Lines changed: 135 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1-
//! Typed composition of declaration requirements, scalar binding, and syntax checks.
1+
//! Typed composition of declaration requirements, scalar binding, source acquisition,
2+
//! and syntax checks.
23
//!
3-
//! Requirements and binding fan out from caller-supplied source claims. Source
4-
//! bytes remain caller-owned, and successful output is the detached bound
5-
//! projection rather than persisted declaration evidence.
4+
//! Requirements and binding fan out from caller-supplied source claims. The
5+
//! in-memory entry point borrows caller-owned bytes; the root entry point reads
6+
//! them through caller-supplied directory capabilities. Successful output is
7+
//! the detached bound projection rather than persisted declaration evidence.
68
79
use std::fmt;
810

911
use crate::bound_scalars::{BoundScalarError, BoundScalarProjection, bind_scalar_source_claims};
1012
use crate::declaration_requirements::{
11-
DeclarationRequirementError, project_declaration_requirements,
13+
DeclarationRequirementError, DeclarationRequirementProjection, project_declaration_requirements,
14+
};
15+
use crate::declaration_source::{
16+
DeclarationSourceError, DeclarationSourceLimits, DeclarationSourceRoots,
17+
read_declaration_sources,
1218
};
1319
use crate::declaration_syntax::{
1420
DeclarationSourceDocument, DeclarationSyntaxError, DeclarationSyntaxLimits,
@@ -17,6 +23,43 @@ use crate::declaration_syntax::{
1723
use crate::scalar_names::NamedScalarProjection;
1824
use crate::scalar_source_claims::ScalarSourceClaimProjection;
1925

26+
/// Inclusive bounds shared by root acquisition and declaration syntax checking.
27+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28+
pub struct DeclarationRootPipelineLimits {
29+
/// Maximum number of unique source documents.
30+
pub max_documents: usize,
31+
/// Maximum number of owner declaration requirements.
32+
pub max_requirements: usize,
33+
/// Maximum byte count for one source document.
34+
pub max_source_bytes: usize,
35+
/// Maximum byte count across all source documents.
36+
pub max_total_source_bytes: usize,
37+
/// Maximum number of direct members in one parsed owner class.
38+
pub max_direct_members: usize,
39+
}
40+
41+
impl From<DeclarationRootPipelineLimits> for DeclarationSourceLimits {
42+
fn from(limits: DeclarationRootPipelineLimits) -> Self {
43+
Self {
44+
max_documents: limits.max_documents,
45+
max_source_bytes: limits.max_source_bytes,
46+
max_total_source_bytes: limits.max_total_source_bytes,
47+
}
48+
}
49+
}
50+
51+
impl From<DeclarationRootPipelineLimits> for DeclarationSyntaxLimits {
52+
fn from(limits: DeclarationRootPipelineLimits) -> Self {
53+
Self {
54+
max_documents: limits.max_documents,
55+
max_requirements: limits.max_requirements,
56+
max_source_bytes: limits.max_source_bytes,
57+
max_total_source_bytes: limits.max_total_source_bytes,
58+
max_direct_members: limits.max_direct_members,
59+
}
60+
}
61+
}
62+
2063
/// Failure from the first declaration pipeline stage that rejects its input.
2164
#[derive(Clone, Debug, PartialEq, Eq)]
2265
pub enum DeclarationPipelineError {
@@ -50,6 +93,64 @@ impl std::error::Error for DeclarationPipelineError {
5093
}
5194
}
5295

96+
/// Failure from source acquisition or the typed declaration pipeline around it.
97+
#[derive(Clone, Debug, PartialEq, Eq)]
98+
pub enum DeclarationRootPipelineError {
99+
/// Requirements, binding, or syntax checking failed.
100+
Pipeline(DeclarationPipelineError),
101+
/// Capability-relative source acquisition failed.
102+
Source(DeclarationSourceError),
103+
}
104+
105+
impl fmt::Display for DeclarationRootPipelineError {
106+
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
107+
match self {
108+
Self::Pipeline(error) => write!(formatter, "declaration pipeline failed: {error}"),
109+
Self::Source(error) => {
110+
write!(formatter, "declaration source acquisition failed: {error}")
111+
}
112+
}
113+
}
114+
}
115+
116+
impl std::error::Error for DeclarationRootPipelineError {
117+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
118+
match self {
119+
Self::Pipeline(error) => Some(error),
120+
Self::Source(error) => Some(error),
121+
}
122+
}
123+
}
124+
125+
struct PreparedDeclarationPipeline {
126+
requirements: DeclarationRequirementProjection,
127+
bound_projection: BoundScalarProjection,
128+
}
129+
130+
fn prepare_declaration_pipeline(
131+
named_projection: &NamedScalarProjection,
132+
source_claim_projection: &ScalarSourceClaimProjection,
133+
) -> Result<PreparedDeclarationPipeline, DeclarationPipelineError> {
134+
let requirements = project_declaration_requirements(source_claim_projection)
135+
.map_err(DeclarationPipelineError::Requirements)?;
136+
let bound_projection = bind_scalar_source_claims(named_projection, source_claim_projection)
137+
.map_err(DeclarationPipelineError::Binding)?;
138+
Ok(PreparedDeclarationPipeline {
139+
requirements,
140+
bound_projection,
141+
})
142+
}
143+
144+
fn complete_declaration_pipeline(
145+
prepared: PreparedDeclarationPipeline,
146+
documents: &[DeclarationSourceDocument],
147+
limits: DeclarationSyntaxLimits,
148+
) -> Result<BoundScalarProjection, DeclarationPipelineError> {
149+
check_owner_declaration_syntax(&prepared.requirements, documents, limits)
150+
.map_err(DeclarationPipelineError::Syntax)?;
151+
Ok(prepared.bound_projection)
152+
}
153+
53154
/// Projects requirements, binds scalar claims, and checks supplied source bytes.
54155
///
55156
/// Requirements are derived directly from `source_claim_projection`; the bound
@@ -65,13 +166,35 @@ pub fn check_declaration_pipeline(
65166
documents: &[DeclarationSourceDocument],
66167
limits: DeclarationSyntaxLimits,
67168
) -> Result<BoundScalarProjection, DeclarationPipelineError> {
68-
let requirements = project_declaration_requirements(source_claim_projection)
69-
.map_err(DeclarationPipelineError::Requirements)?;
70-
let bound_projection = bind_scalar_source_claims(named_projection, source_claim_projection)
71-
.map_err(DeclarationPipelineError::Binding)?;
72-
check_owner_declaration_syntax(&requirements, documents, limits)
73-
.map_err(DeclarationPipelineError::Syntax)?;
74-
Ok(bound_projection)
169+
let prepared = prepare_declaration_pipeline(named_projection, source_claim_projection)?;
170+
complete_declaration_pipeline(prepared, documents, limits)
171+
}
172+
173+
/// Projects requirements, binds scalar claims, acquires source bytes, and checks syntax.
174+
///
175+
/// Both directory capabilities remain borrowed. Requirements and binding finish
176+
/// before either root is read; acquisition finishes before syntax checking. The
177+
/// bound projection is returned only after every stage succeeds.
178+
///
179+
/// # Errors
180+
///
181+
/// Returns the first failed stage with its unchanged pipeline or source error.
182+
pub fn check_declaration_pipeline_from_roots(
183+
named_projection: &NamedScalarProjection,
184+
source_claim_projection: &ScalarSourceClaimProjection,
185+
roots: DeclarationSourceRoots<'_>,
186+
limits: DeclarationRootPipelineLimits,
187+
) -> Result<BoundScalarProjection, DeclarationRootPipelineError> {
188+
let prepared = prepare_declaration_pipeline(named_projection, source_claim_projection)
189+
.map_err(DeclarationRootPipelineError::Pipeline)?;
190+
let documents = read_declaration_sources(
191+
&prepared.requirements,
192+
roots,
193+
DeclarationSourceLimits::from(limits),
194+
)
195+
.map_err(DeclarationRootPipelineError::Source)?;
196+
complete_declaration_pipeline(prepared, &documents, DeclarationSyntaxLimits::from(limits))
197+
.map_err(DeclarationRootPipelineError::Pipeline)
75198
}
76199

77200
#[cfg(test)]

0 commit comments

Comments
 (0)