Skip to main content

macroonz_compiler/recipe/
types.rs

1//! The informed recipe, its projection vocabulary, and the capability boundary shared by both execution hosts.
2
3use super::stamp::named_vocabulary;
4use crate::bounded::{Bounded, KeyedRoster};
5use crate::diagnostic::{Diagnostic, Family};
6use crate::expansion::Expansion;
7use crate::identity::OwnerFact;
8use crate::relation::{
9    AbsencePosture, CompletenessPosture, CyclePosture, DensityPosture, EmptyPosture,
10    MembershipPosture, RelationQuestion, RepetitionPosture, SelfRelationPosture,
11};
12use crate::render::Output;
13use crate::request::Door;
14use crate::support::SupportName;
15use crate::token::{CapturedInput, GeneratedToken, GeneratedTree, SpanHandle};
16
17#[path = "account/admit.rs"]
18mod admit;
19
20#[path = "account/collisions.rs"]
21mod collisions;
22
23#[path = "account/contracts.rs"]
24mod contracts;
25
26#[path = "account/informed.rs"]
27mod informed;
28
29#[path = "account/relation.rs"]
30mod relation;
31
32#[path = "account/restore.rs"]
33mod restore;
34
35#[path = "account/settle.rs"]
36mod settle;
37
38#[path = "type_guard.rs"]
39mod guard;
40
41pub(super) use super::issue::{ExactFunctionIssue, ExactProjectionSeat, RecipeError, RecipeIssue};
42
43/// The maximum number of members in one recipe vocabulary.
44pub const VOCABULARY_LIMIT: usize = 64;
45
46/// The maximum number of named relations in one recipe.
47pub const RELATION_LIMIT: usize = 64;
48
49/// The maximum number of rows in one recipe relation.
50pub const RELATION_ROW_LIMIT: usize = 128;
51
52/// The maximum number of relation tables selected by one projection family.
53pub const RELATION_TABLE_LIMIT: usize = RELATION_LIMIT;
54
55/// The maximum number of transition rows in one recipe.
56///
57/// Transition syntax is one ergonomic lowering over the generic relation-row ceiling.
58pub const TRANSITION_LIMIT: usize = RELATION_ROW_LIMIT;
59
60/// The complete number of structural questions one relation posture may answer.
61pub const RELATION_QUESTION_LIMIT: usize = RelationQuestion::ALL.len();
62
63/// The maximum number of codec declarations carried by one recipe.
64pub const CODEC_LIMIT: usize = 16;
65
66/// The diagnostic family owned by the recipe declaration.
67pub(super) const RECIPE_FAMILY: Family = Family::declared("macroonz/recipe");
68
69/// The structural fact this recipe owner declares.
70pub(super) const RECIPE_FACT: OwnerFact = OwnerFact {
71    home: "recipe",
72    name: "one-informed-recipe-selects-and-delivers-every-requested-projection",
73};
74
75named_vocabulary! {
76    /// Whether the facade posture makes harness-owned evidence projections available.
77    pub enum HarnessPosture {
78        /// The facade carries its optional harness owner.
79        Available = "available",
80        /// The facade omits its optional harness owner.
81        Unavailable = "unavailable",
82    }
83}
84
85/// One member read from an authored Rust enum.
86#[derive(Debug, Clone, PartialEq, Eq, Hash)]
87pub struct RecipeMember {
88    spelling: String,
89    name: GeneratedToken,
90    at: SpanHandle,
91}
92
93/// One caller-named vocabulary and its informed authored members.
94#[derive(Debug, Clone, PartialEq, Eq, Hash)]
95pub struct RecipeVocabulary {
96    name: String,
97    name_token: GeneratedToken,
98    members: KeyedRoster<RecipeMember, String, VOCABULARY_LIMIT>,
99    at: SpanHandle,
100}
101
102/// The optional caller-owned material attached to one relation row.
103#[non_exhaustive]
104#[derive(Debug, Clone, PartialEq, Eq, Hash)]
105pub enum RecipeRelationPayload {
106    /// The row states only its two endpoints.
107    Unlabeled,
108    /// The row carries one ordinary caller-owned Rust path.
109    Path(GeneratedTree),
110    /// The row carries exact caller-authored Rust material.
111    ExactRust(GeneratedTree),
112    /// The row carries the target and effect required by the transition lowering.
113    Transition {
114        /// The target member spelling.
115        target: String,
116        /// The exact ordinary or raw identifier token naming the target member.
117        target_name: GeneratedToken,
118        /// The caller-authored execution form for this admitted row.
119        effect: RecipeTransitionEffect,
120    },
121}
122
123/// The caller-owned execution material attached to one informed transition row.
124#[non_exhaustive]
125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
126pub enum RecipeTransitionEffect {
127    /// Call one ordinary Rust path with no arguments, then return the declared target.
128    Path(GeneratedTree),
129    /// Evaluate exact caller-authored Rust with the declared target bound under one caller name.
130    ExactRust {
131        /// The caller-chosen binding for the structurally declared target value.
132        target_binding: GeneratedToken,
133        /// The exact caller-authored row body evaluated by the generated match arm.
134        body: GeneratedTree,
135    },
136}
137
138named_vocabulary! {
139    /// Which one row-payload contract every row in one relation follows.
140    #[non_exhaustive]
141    pub enum RecipeRelationPayloadKind {
142        /// Relation rows carry endpoints only.
143        Unlabeled = "unlabeled",
144        /// Relation rows carry ordinary caller-owned paths.
145        Path = "path",
146        /// Relation rows carry exact caller-authored Rust material.
147        ExactRust = "exact-rust",
148        /// Relation rows carry the target and effect required by transition lowering.
149        Transition = "transition",
150    }
151}
152
153/// One informed row in a caller-named binary relation.
154#[derive(Debug, Clone, PartialEq, Eq, Hash)]
155pub struct RecipeRelationRow {
156    left: String,
157    left_name: GeneratedToken,
158    left_at: SpanHandle,
159    right: String,
160    right_name: GeneratedToken,
161    right_at: SpanHandle,
162    payload: RecipeRelationPayload,
163    payload_at: SpanHandle,
164    effect_binding_at: Option<SpanHandle>,
165}
166
167/// The structural questions one relation declaration chose to answer.
168///
169/// An absent field means the recipe did not ask that question.
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
171pub struct RecipeRelationRequirements {
172    empty: Option<EmptyPosture>,
173    repetition: Option<RepetitionPosture>,
174    membership: Option<[MembershipPosture; 2]>,
175    completeness: Option<[CompletenessPosture; 2]>,
176    density: Option<DensityPosture>,
177    absence: Option<AbsencePosture>,
178    self_relation: Option<SelfRelationPosture>,
179    cycle: Option<CyclePosture>,
180}
181
182/// One caller-named binary relation over two informed vocabularies.
183#[derive(Debug, Clone, PartialEq, Eq, Hash)]
184pub struct RecipeRelation {
185    name: String,
186    name_token: GeneratedToken,
187    name_at: SpanHandle,
188    left_vocabulary: String,
189    right_vocabulary: String,
190    rows: Bounded<RecipeRelationRow, RELATION_ROW_LIMIT>,
191    payload_kind: RecipeRelationPayloadKind,
192    requirements: RecipeRelationRequirements,
193}
194
195/// Whether one generic relation came from the paved transition lowering.
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub(super) enum RelationLowering {
198    /// The caller declared one generic relation directly.
199    Generic,
200    /// The caller used the ergonomic transition grammar.
201    Transition,
202}
203
204/// One caller-named codec declaration owned semantically by the compiler codec home.
205#[derive(Debug, Clone, PartialEq, Eq)]
206pub struct RecipeCodec {
207    name: String,
208    content: crate::codec::CodecContent,
209    at: SpanHandle,
210    refusal_at: SpanHandle,
211    direction_at: SpanHandle,
212}
213
214crate::roster! {
215    /// The complete projection vocabulary understood by the first recipe slice.
216    #[non_exhaustive]
217    pub enum RecipeRole {
218        /// Enum-member and relation companions inside the generated child module.
219        Companions = "companions",
220        /// Typed membership and payload lookup tables over selected relations.
221        RelationTables = "relation-tables",
222        /// The generated sparse dispatch function and typed absence refusal.
223        Dispatch = "dispatch",
224        /// Rustc-owned compile-contract material carried to a test target.
225        CompileContract = "compile-contract",
226        /// A generated check that the dispatch output agrees with its declaring transition rows.
227        DeclarationConformance = "declaration-conformance",
228        /// One selected vocabulary projected as type-level stage markers.
229        Typestate = "typestate",
230        /// One existing descriptor trial carrier over caller-declared rows.
231        Trials = "trials",
232        /// One existing descriptor mutation surface over an explicitly selected vocabulary.
233        Mutation = "mutation",
234        /// One existing descriptor benchmark carrier over caller-declared work.
235        Benchmarks = "benchmarks",
236        /// One existing descriptor network module over caller-declared topology and schedules.
237        Network = "network",
238        /// One existing descriptor concurrency module over caller-declared exploration rows.
239        Concurrency = "concurrency",
240        /// Canonical encode and decode roads from one or more existing-owner codec declarations.
241        Codec = "codec",
242    }
243}
244
245pub(super) const PROJECTION_ROLES: &[RecipeRole] = &[
246    RecipeRole::Companions,
247    RecipeRole::RelationTables,
248    RecipeRole::Dispatch,
249    RecipeRole::CompileContract,
250    RecipeRole::DeclarationConformance,
251    RecipeRole::Typestate,
252    RecipeRole::Codec,
253];
254
255pub(super) const EVIDENCE_ROLES: &[RecipeRole] = &[
256    RecipeRole::Trials,
257    RecipeRole::Mutation,
258    RecipeRole::Benchmarks,
259    RecipeRole::Network,
260    RecipeRole::Concurrency,
261];
262
263/// The complete number of fixed recipe projection families.
264pub const PROJECTION_LIMIT: usize = RecipeRole::ALL.len();
265
266/// The complete number of projection clauses one recipe may carry.
267pub const PROJECTION_CLAUSE_LIMIT: usize = PROJECTION_ROLES.len();
268
269/// The complete number of descriptor-native evidence forms one recipe may carry.
270pub const EVIDENCE_LIMIT: usize = EVIDENCE_ROLES.len();
271
272/// Which grammar entrance admits one recipe role.
273#[derive(Debug, Clone, Copy, PartialEq, Eq)]
274pub(super) enum RecipeRoleEntrance {
275    /// The role is named inside the `projections` block.
276    Projection,
277    /// The role is named inside the `evidence` block.
278    Evidence,
279}
280
281/// Which package posture owns one recipe role.
282#[derive(Debug, Clone, Copy, PartialEq, Eq)]
283pub(super) enum RecipeRoleAvailability {
284    /// The role is available in every facade posture.
285    Always,
286    /// The role requires the optional harness package.
287    Harness,
288}
289
290/// Where one generated role is assembled into the final recipe emission.
291#[derive(Debug, Clone, Copy, PartialEq, Eq)]
292pub(super) enum RecipeRolePlacement {
293    /// The generated unit is emitted beside the authored recipe module.
294    DeclarationRoot,
295    /// The generated unit is emitted inside the recipe module's `baked` child.
296    BakedModule,
297    /// The generated unit is carried through the recipe's explicit support address.
298    SupportCarrier,
299}
300
301/// The output seat and final assembly order owned by one recipe role.
302#[derive(Debug, Clone, Copy, PartialEq, Eq)]
303pub(super) struct RecipeRoleOutput {
304    pub(super) destination: crate::kind::Destination,
305    pub(super) placement: RecipeRolePlacement,
306    pub(super) placement_position: Option<usize>,
307}
308
309/// The complete compiler-owned facts for one recipe role.
310#[derive(Debug, Clone, Copy, PartialEq, Eq)]
311pub(super) struct RecipeRoleProfile {
312    pub(super) position: usize,
313    pub(super) syntax: &'static str,
314    pub(super) entrance: RecipeRoleEntrance,
315    pub(super) availability: RecipeRoleAvailability,
316    pub(super) output: RecipeRoleOutput,
317    pub(super) evidence_position: Option<usize>,
318}
319
320/// Which informed recipe vocabulary a mutation evidence block presses.
321#[derive(Debug, Clone, PartialEq, Eq, Hash)]
322pub struct EvidenceTarget {
323    vocabulary: String,
324}
325
326/// One exact descriptor-native evidence declaration carried by the recipe.
327#[derive(Debug, Clone, PartialEq, Eq, Hash)]
328pub struct RecipeEvidence {
329    role: RecipeRole,
330    target: Option<EvidenceTarget>,
331    body: CapturedInput,
332    at: SpanHandle,
333}
334
335/// The already sealed output for each selected standard evidence projection.
336pub(crate) struct PreparedEvidence {
337    pub(super) trees: [Option<GeneratedTree>; EVIDENCE_LIMIT],
338}
339
340/// The one crate-internal preparation capability the composition root supplies.
341pub(crate) trait EvidenceCompiler {
342    /// Prepare every selected standard evidence projection without giving the recipe home adapter vocabulary.
343    fn prepared(
344        capture: &CapturedInput,
345        recipe: &Recipe,
346        door: &Door,
347        replaced: &[RecipeRole],
348    ) -> Result<PreparedEvidence, Diagnostic>;
349}
350
351/// The sealed marker whose sole implementation lives at the crate composition root.
352pub(crate) struct ConfiguredEvidence;
353
354named_vocabulary! {
355    /// Where one effective mechanical projection value came from.
356    #[non_exhaustive]
357    pub enum LoweringSource {
358        /// The projector's documented conventional spelling.
359        Preset = "preset",
360        /// A named recipe seat replaced the conventional spelling.
361        Configuration = "configuration",
362        /// Exact caller-authored Rust replaced the conventional mechanical seat.
363        ExactRust = "exact-rust",
364    }
365}
366
367/// The effective mechanical configuration of one generated projection.
368#[derive(Debug, Clone, PartialEq, Eq, Hash)]
369pub struct EffectiveProjection {
370    role: RecipeRole,
371    name: Option<String>,
372    subject: Option<String>,
373    source: LoweringSource,
374    exact_rust: Option<GeneratedTree>,
375    exact_dispatch_bindings: Option<[GeneratedToken; 2]>,
376    exact_dispatch_binding_names: Option<Box<[String; 2]>>,
377    exact_dispatch_imports: Option<[bool; 2]>,
378    relation_tables: Option<Box<Bounded<RelationTableProjection, RELATION_TABLE_LIMIT>>>,
379    at: SpanHandle,
380}
381
382/// One selected typed relation table and its effective function surface.
383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
384pub struct RelationTableProjection {
385    relation: String,
386    function: String,
387    source: LoweringSource,
388    exact_rust: Option<GeneratedTree>,
389    bindings: Option<[GeneratedToken; 2]>,
390    imports: Option<[bool; 2]>,
391    at: SpanHandle,
392}
393
394/// What happened to one role in the recipe's complete projection account.
395#[derive(Debug, Clone, PartialEq, Eq, Hash)]
396pub(super) enum ProjectionStanding {
397    /// The role enters the selected request membership under this effective lowering.
398    Generated(EffectiveProjection),
399    /// The caller deliberately did not request this role.
400    NotRequested,
401    /// The facade feature posture does not carry the harness owner this role requires.
402    FeatureUnavailable,
403    /// The caller declared that the target plane for this role is unavailable.
404    TargetUnavailable,
405}
406
407named_vocabulary! {
408    /// The public readback of what happened to one possible recipe projection.
409    pub enum ProjectionDisposition {
410        /// The role is selected and generated.
411        Generated = "generated",
412        /// The caller did not request the role.
413        NotRequested = "not-requested",
414        /// The facade feature posture does not carry the required harness owner.
415        FeatureUnavailable = "feature-unavailable",
416        /// The caller declared that the target plane is unavailable.
417        TargetUnavailable = "target-unavailable",
418    }
419}
420
421/// One informed recipe over caller-owned vocabularies, relations, and selected projections.
422#[derive(Debug, Clone, PartialEq, Eq)]
423pub struct Recipe {
424    module_name: String,
425    module_name_token: GeneratedToken,
426    module_head: GeneratedTree,
427    authored_body: GeneratedTree,
428    authored_declaration: GeneratedTree,
429    module_body_at: Option<SpanHandle>,
430    vocabularies: Option<KeyedRoster<RecipeVocabulary, String, VOCABULARY_LIMIT>>,
431    relations: Option<KeyedRoster<RecipeRelation, String, RELATION_LIMIT>>,
432    transition_relation: Option<String>,
433    codecs: Option<KeyedRoster<RecipeCodec, String, CODEC_LIMIT>>,
434    projections: [ProjectionStanding; PROJECTION_LIMIT],
435    evidence: [Option<RecipeEvidence>; EVIDENCE_LIMIT],
436    support: Option<SupportName>,
437}
438
439/// The mechanically read seats offered to the recipe invariant constructor.
440pub(super) struct RecipeParts {
441    pub(super) module_name: String,
442    pub(super) module_name_token: GeneratedToken,
443    pub(super) module_head: GeneratedTree,
444    pub(super) authored_body: GeneratedTree,
445    pub(super) authored_declaration: GeneratedTree,
446    pub(super) module_body_at: Option<SpanHandle>,
447    pub(super) vocabularies: Vec<RecipeVocabularyParts>,
448    pub(super) relations: Vec<RecipeRelationParts>,
449    pub(super) transition_relation: Option<String>,
450    pub(super) codecs: Vec<RecipeCodec>,
451    pub(super) projections: [ProjectionStanding; PROJECTION_LIMIT],
452    pub(super) evidence: [Option<RecipeEvidence>; EVIDENCE_LIMIT],
453    pub(super) support: Option<SupportName>,
454}
455
456/// The mechanically read seats offered to one vocabulary constructor.
457pub(super) struct RecipeVocabularyParts {
458    pub(super) name: String,
459    pub(super) name_token: GeneratedToken,
460    pub(super) members: Vec<RecipeMember>,
461    pub(super) at: SpanHandle,
462}
463
464/// The mechanically read seats offered to one relation constructor.
465pub(super) struct RecipeRelationParts {
466    pub(super) name: String,
467    pub(super) name_token: GeneratedToken,
468    pub(super) name_at: SpanHandle,
469    pub(super) left_vocabulary: String,
470    pub(super) left_vocabulary_at: SpanHandle,
471    pub(super) right_vocabulary: String,
472    pub(super) right_vocabulary_at: SpanHandle,
473    pub(super) rows: Vec<RecipeRelationRow>,
474    pub(super) requirements: RecipeRelationRequirements,
475}
476
477/// The kind whose selected roles are the recipe's generated projections.
478#[derive(Debug, Clone, Copy, PartialEq, Eq)]
479pub struct RecipeProjection;
480
481/// A projector's read-only view of one informed recipe.
482#[derive(Clone, Copy)]
483pub struct RecipeView<'recipe> {
484    recipe: &'recipe Recipe,
485}
486
487/// The one selected role one projector invocation answers.
488#[derive(Clone, Copy)]
489pub struct ProjectionRequest<'recipe> {
490    effective: &'recipe EffectiveProjection,
491}
492
493/// A consuming output capability already bound to one selected recipe role.
494pub struct ProjectionSink<'output, 'plan> {
495    output: &'output mut Output<'plan, RecipeProjection>,
496    role: RecipeRole,
497}
498
499/// Opaque evidence that one projector used its bound sink successfully.
500#[must_use = "a successful offer is evidence that the selected projection seat was filled"]
501pub struct ProjectionOffered {
502    _private: (),
503}
504
505/// The authority-neutral projection operation shared by built-in and caller-owned clients.
506pub trait RecipeProjector {
507    /// Project one selected role through its one-use sink.
508    ///
509    /// # Errors
510    ///
511    /// Returns the first token or render refusal established by the implementation.
512    fn project(
513        &self,
514        view: RecipeView<'_>,
515        request: ProjectionRequest<'_>,
516        sink: ProjectionSink<'_, '_>,
517    ) -> Result<ProjectionOffered, ProjectionError>;
518}
519
520/// One caller-owned projector bound to one selected recipe role for one bake.
521#[derive(Clone, Copy)]
522pub struct ProjectorReplacement<'projector> {
523    role: RecipeRole,
524    projector: &'projector dyn RecipeProjector,
525}
526
527/// The built-in projector catalog used by the paved proc host.
528pub(super) struct StandardProjector<'evidence> {
529    pub(super) evidence: &'evidence PreparedEvidence,
530}
531
532/// Why one projector invocation produced no admitted unit.
533#[must_use = "a projection refusal states why the selected role was not filled"]
534#[non_exhaustive]
535#[derive(Debug, Clone, Copy, PartialEq, Eq)]
536pub enum ProjectionError {
537    /// Token construction exceeded a generated-tree magnitude.
538    Tokens(crate::bounded::Overflow),
539    /// The existing output owner refused the offered unit.
540    Render(crate::render::RenderError),
541}
542
543/// The complete baked result: selected recipe projections plus the sealed declaration-site emission.
544#[must_use = "a baked recipe carries the selected projection expansion and its sealed emitted module"]
545pub struct RecipeBake {
546    pub(super) projection: Expansion<RecipeProjection>,
547    pub(super) emitted: Expansion<RecipeShell>,
548}
549
550/// The private final-emission kind.
551#[derive(Debug, Clone, Copy, PartialEq, Eq)]
552pub(super) struct RecipeShell;
553
554/// The semantic parentage of the final emitted module.
555#[derive(Debug, Clone, PartialEq, Eq)]
556pub(super) struct RecipeShellContent {
557    pub(super) recipe: crate::identity::ClosedExpansionId,
558    pub(super) support: Option<crate::identity::ClosedExpansionId>,
559}