1use 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
43pub const VOCABULARY_LIMIT: usize = 64;
45
46pub const RELATION_LIMIT: usize = 64;
48
49pub const RELATION_ROW_LIMIT: usize = 128;
51
52pub const RELATION_TABLE_LIMIT: usize = RELATION_LIMIT;
54
55pub const TRANSITION_LIMIT: usize = RELATION_ROW_LIMIT;
59
60pub const RELATION_QUESTION_LIMIT: usize = RelationQuestion::ALL.len();
62
63pub const CODEC_LIMIT: usize = 16;
65
66pub(super) const RECIPE_FAMILY: Family = Family::declared("macroonz/recipe");
68
69pub(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 pub enum HarnessPosture {
78 Available = "available",
80 Unavailable = "unavailable",
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, Hash)]
87pub struct RecipeMember {
88 spelling: String,
89 name: GeneratedToken,
90 at: SpanHandle,
91}
92
93#[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#[non_exhaustive]
104#[derive(Debug, Clone, PartialEq, Eq, Hash)]
105pub enum RecipeRelationPayload {
106 Unlabeled,
108 Path(GeneratedTree),
110 ExactRust(GeneratedTree),
112 Transition {
114 target: String,
116 target_name: GeneratedToken,
118 effect: RecipeTransitionEffect,
120 },
121}
122
123#[non_exhaustive]
125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
126pub enum RecipeTransitionEffect {
127 Path(GeneratedTree),
129 ExactRust {
131 target_binding: GeneratedToken,
133 body: GeneratedTree,
135 },
136}
137
138named_vocabulary! {
139 #[non_exhaustive]
141 pub enum RecipeRelationPayloadKind {
142 Unlabeled = "unlabeled",
144 Path = "path",
146 ExactRust = "exact-rust",
148 Transition = "transition",
150 }
151}
152
153#[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#[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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub(super) enum RelationLowering {
198 Generic,
200 Transition,
202}
203
204#[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 #[non_exhaustive]
217 pub enum RecipeRole {
218 Companions = "companions",
220 RelationTables = "relation-tables",
222 Dispatch = "dispatch",
224 CompileContract = "compile-contract",
226 DeclarationConformance = "declaration-conformance",
228 Typestate = "typestate",
230 Trials = "trials",
232 Mutation = "mutation",
234 Benchmarks = "benchmarks",
236 Network = "network",
238 Concurrency = "concurrency",
240 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
263pub const PROJECTION_LIMIT: usize = RecipeRole::ALL.len();
265
266pub const PROJECTION_CLAUSE_LIMIT: usize = PROJECTION_ROLES.len();
268
269pub const EVIDENCE_LIMIT: usize = EVIDENCE_ROLES.len();
271
272#[derive(Debug, Clone, Copy, PartialEq, Eq)]
274pub(super) enum RecipeRoleEntrance {
275 Projection,
277 Evidence,
279}
280
281#[derive(Debug, Clone, Copy, PartialEq, Eq)]
283pub(super) enum RecipeRoleAvailability {
284 Always,
286 Harness,
288}
289
290#[derive(Debug, Clone, Copy, PartialEq, Eq)]
292pub(super) enum RecipeRolePlacement {
293 DeclarationRoot,
295 BakedModule,
297 SupportCarrier,
299}
300
301#[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#[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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
322pub struct EvidenceTarget {
323 vocabulary: String,
324}
325
326#[derive(Debug, Clone, PartialEq, Eq, Hash)]
328pub struct RecipeEvidence {
329 role: RecipeRole,
330 target: Option<EvidenceTarget>,
331 body: CapturedInput,
332 at: SpanHandle,
333}
334
335pub(crate) struct PreparedEvidence {
337 pub(super) trees: [Option<GeneratedTree>; EVIDENCE_LIMIT],
338}
339
340pub(crate) trait EvidenceCompiler {
342 fn prepared(
344 capture: &CapturedInput,
345 recipe: &Recipe,
346 door: &Door,
347 replaced: &[RecipeRole],
348 ) -> Result<PreparedEvidence, Diagnostic>;
349}
350
351pub(crate) struct ConfiguredEvidence;
353
354named_vocabulary! {
355 #[non_exhaustive]
357 pub enum LoweringSource {
358 Preset = "preset",
360 Configuration = "configuration",
362 ExactRust = "exact-rust",
364 }
365}
366
367#[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#[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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
396pub(super) enum ProjectionStanding {
397 Generated(EffectiveProjection),
399 NotRequested,
401 FeatureUnavailable,
403 TargetUnavailable,
405}
406
407named_vocabulary! {
408 pub enum ProjectionDisposition {
410 Generated = "generated",
412 NotRequested = "not-requested",
414 FeatureUnavailable = "feature-unavailable",
416 TargetUnavailable = "target-unavailable",
418 }
419}
420
421#[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
439pub(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
456pub(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
464pub(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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
479pub struct RecipeProjection;
480
481#[derive(Clone, Copy)]
483pub struct RecipeView<'recipe> {
484 recipe: &'recipe Recipe,
485}
486
487#[derive(Clone, Copy)]
489pub struct ProjectionRequest<'recipe> {
490 effective: &'recipe EffectiveProjection,
491}
492
493pub struct ProjectionSink<'output, 'plan> {
495 output: &'output mut Output<'plan, RecipeProjection>,
496 role: RecipeRole,
497}
498
499#[must_use = "a successful offer is evidence that the selected projection seat was filled"]
501pub struct ProjectionOffered {
502 _private: (),
503}
504
505pub trait RecipeProjector {
507 fn project(
513 &self,
514 view: RecipeView<'_>,
515 request: ProjectionRequest<'_>,
516 sink: ProjectionSink<'_, '_>,
517 ) -> Result<ProjectionOffered, ProjectionError>;
518}
519
520#[derive(Clone, Copy)]
522pub struct ProjectorReplacement<'projector> {
523 role: RecipeRole,
524 projector: &'projector dyn RecipeProjector,
525}
526
527pub(super) struct StandardProjector<'evidence> {
529 pub(super) evidence: &'evidence PreparedEvidence,
530}
531
532#[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 Tokens(crate::bounded::Overflow),
539 Render(crate::render::RenderError),
541}
542
543#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
552pub(super) struct RecipeShell;
553
554#[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}