1use super::{Alternative, Permission, Policy, Site, Surface};
13use crate::bounded::Overflow;
14use crate::descriptor::vocabulary::{self, HarnessName};
15use crate::descriptor::{Name, TypeName};
16use crate::stamp::{Visibility, declared_reach_tokens};
17use crate::token::{
18 GeneratedDelimiter, GeneratedToken, and_all, bound_local, call, comma_many, constant, equality,
19 function, group, method_call, method_chain, result_type, roster, text_pair,
20};
21
22const NAME_ARM: &str = "Name";
24
25const PERMISSION_ARM: &str = "Permission";
27
28const POLICY_ARM: &str = "Policy";
30
31const DISCOVERY_ARM: &str = "Discovery";
33
34const LOWERING_ARM: &str = "Lowering";
36
37const UNRESOLVED_ARM: &str = "OperatorFamilyNotFound";
39
40const LOWERING: &str = "lowering";
42
43const PRODUCTION: &str = "production";
45
46const EVALUATION: &str = "evaluation";
48
49const CANDIDATES: &str = "candidate_orders";
51
52const FAMILY_LOCAL: &str = "family";
54
55const POLICY_LOCAL: &str = "policy";
57
58const POINT_LOCAL: &str = "point";
60
61const ACTIVATION_LOCAL: &str = "activation";
63
64const OWNER_CLAIM_LOCAL: &str = "owner_claim";
66
67const SITE_LOCAL: &str = "site";
69
70const RESOLVED_LOCAL: &str = "resolved";
72
73const INPUT_PARAMETER: &str = "_input";
75
76const SURFACE_LIFETIME: &str = "surface";
78
79const ALTERNATIVE_STEM: &str = "ALTERNATIVE";
81
82pub fn generated_module(surface: &Surface) -> Result<Vec<GeneratedToken>, Overflow> {
88 let refusal = &surface.address().refusal;
89 let site = surface.site();
90 let mut body = refusal_type(refusal)?;
91 body.extend(alternative_constants(site));
92 body.extend(candidate_orders(site)?);
93 body.extend(lowering(surface)?);
94 body.extend(production(site)?);
95 body.extend(evaluation(site)?);
96 let mut tokens = declared_reach_tokens(Visibility::Crate)?;
97 tokens.push(GeneratedToken::word("mod"));
98 tokens.push(GeneratedToken::word(surface.address().module.spelling()));
99 tokens.push(group(GeneratedDelimiter::Brace, body)?);
100 Ok(tokens)
101}
102
103fn refusal_type(refusal: &TypeName) -> Result<Vec<GeneratedToken>, Overflow> {
105 let carried = [
106 (NAME_ARM, HarnessName::Descriptor, HarnessName::NameRefusal),
107 (
108 PERMISSION_ARM,
109 HarnessName::Muterprater,
110 HarnessName::PermissionRefusal,
111 ),
112 (
113 POLICY_ARM,
114 HarnessName::Muterprater,
115 HarnessName::PolicyRefusal,
116 ),
117 (
118 DISCOVERY_ARM,
119 HarnessName::Muterprater,
120 HarnessName::DiscoveryRefusal,
121 ),
122 (
123 LOWERING_ARM,
124 HarnessName::Muterprater,
125 HarnessName::DiscoveryLoweringRefusal,
126 ),
127 ];
128 let mut arms: Vec<GeneratedToken> = Vec::new();
129 for (arm, module, kind) in carried {
130 arms.push(GeneratedToken::word(arm));
131 arms.push(group(
132 GeneratedDelimiter::Parenthesis,
133 vocabulary::path(&[module, kind]),
134 )?);
135 arms.push(GeneratedToken::alone(','));
136 }
137 arms.push(GeneratedToken::word(UNRESOLVED_ARM));
138 arms.push(GeneratedToken::alone(','));
139
140 let mut tokens = vec![
141 GeneratedToken::alone('#'),
142 group(
143 GeneratedDelimiter::Bracket,
144 vec![
145 GeneratedToken::word("derive"),
146 group(
147 GeneratedDelimiter::Parenthesis,
148 vec![GeneratedToken::word("Debug")],
149 )?,
150 ],
151 )?,
152 ];
153 tokens.extend(declared_reach_tokens(Visibility::Crate)?);
154 tokens.push(GeneratedToken::word("enum"));
155 tokens.push(GeneratedToken::word(refusal.spelling()));
156 tokens.push(group(GeneratedDelimiter::Brace, arms)?);
157 Ok(tokens)
158}
159
160fn alternative_name(position: usize) -> String {
162 format!("{ALTERNATIVE_STEM}_{position}")
163}
164
165fn alternative_constants(site: &Site) -> Vec<GeneratedToken> {
167 let mut tokens: Vec<GeneratedToken> = Vec::new();
168 for (position, alternative) in site.alternatives().iter().enumerate() {
169 tokens.extend(constant(
170 &alternative_name(position),
171 site.order().to_vec(),
172 alternative.meaning().to_vec(),
173 ));
174 }
175 tokens
176}
177
178fn candidate_orders(site: &Site) -> Result<Vec<GeneratedToken>, Overflow> {
180 let mut values: Vec<GeneratedToken> = Vec::new();
181 for position in 0..site.alternatives().len() {
182 values.push(GeneratedToken::word(&alternative_name(position)));
183 values.push(GeneratedToken::alone(','));
184 }
185 let mut result = site.order().to_vec();
186 result.push(GeneratedToken::alone(';'));
187 result.push(GeneratedToken::number(
188 u64::try_from(site.alternatives().len()).unwrap_or(u64::MAX),
189 ));
190 let mut tokens = declared_reach_tokens(Visibility::Crate)?;
191 tokens.extend(function(
192 CANDIDATES,
193 Vec::new(),
194 vec![group(GeneratedDelimiter::Bracket, result)?],
195 vec![group(GeneratedDelimiter::Bracket, values)?],
196 )?);
197 Ok(tokens)
198}
199
200fn mapped(
202 expression: Vec<GeneratedToken>,
203 refusal: &TypeName,
204 arm: &str,
205) -> Result<Vec<GeneratedToken>, Overflow> {
206 let mut tokens = method_call(expression, "map_err", arm_path(refusal, arm))?;
207 tokens.push(GeneratedToken::alone('?'));
208 Ok(tokens)
209}
210
211fn or_refused(
213 expression: Vec<GeneratedToken>,
214 refusal: &TypeName,
215 arm: &str,
216) -> Result<Vec<GeneratedToken>, Overflow> {
217 let mut tokens = method_call(expression, "ok_or", arm_path(refusal, arm))?;
218 tokens.push(GeneratedToken::alone('?'));
219 Ok(tokens)
220}
221
222fn arm_path(refusal: &TypeName, arm: &str) -> Vec<GeneratedToken> {
224 vec![
225 GeneratedToken::word(refusal.spelling()),
226 GeneratedToken::joint(':'),
227 GeneratedToken::alone(':'),
228 GeneratedToken::word(arm),
229 ]
230}
231
232fn name_arguments(name: &Name) -> Vec<GeneratedToken> {
234 text_pair(name.namespace(), name.stem())
235}
236
237fn owned_bytes(material: &[u8]) -> Result<Vec<GeneratedToken>, Overflow> {
239 method_chain(vec![GeneratedToken::byte_text(material)], &["to_vec"])
240}
241
242fn policy_locals(policy: &Policy, refusal: &TypeName) -> Result<Vec<GeneratedToken>, Overflow> {
244 let mut body = bound_local(
245 FAMILY_LOCAL,
246 mapped(
247 vocabulary::road(
248 &[
249 HarnessName::Muterprater,
250 HarnessName::EvaluationFamilyRef,
251 HarnessName::Named,
252 ],
253 name_arguments(policy.family()),
254 )?,
255 refusal,
256 NAME_ARM,
257 )?,
258 );
259 for (position, permission) in policy.permissions().iter().enumerate() {
260 body.extend(permission_locals(permission, position, refusal)?);
261 }
262 let mut named: Vec<GeneratedToken> = Vec::new();
263 for position in 0..policy.permissions().len() {
264 named.push(GeneratedToken::word(&format!("permission_{position}")));
265 named.push(GeneratedToken::alone(','));
266 }
267 body.extend(bound_local(
268 POLICY_LOCAL,
269 mapped(
270 vocabulary::road(
271 &[
272 HarnessName::Muterprater,
273 HarnessName::MutationPolicy,
274 HarnessName::Declared,
275 ],
276 comma_many(vec![
277 vec![GeneratedToken::word(FAMILY_LOCAL)],
278 roster(named)?,
279 ]),
280 )?,
281 refusal,
282 POLICY_ARM,
283 )?,
284 ));
285 Ok(body)
286}
287
288fn permission_locals(
290 permission: &Permission,
291 position: usize,
292 refusal: &TypeName,
293) -> Result<Vec<GeneratedToken>, Overflow> {
294 let claim = format!("permission_claim_{position}");
295 let mut body = bound_local(
296 &claim,
297 mapped(
298 vocabulary::road(
299 &[
300 HarnessName::Descriptor,
301 HarnessName::ClaimRef,
302 HarnessName::Named,
303 ],
304 name_arguments(permission.claim()),
305 )?,
306 refusal,
307 NAME_ARM,
308 )?,
309 );
310 let mut named: Vec<GeneratedToken> = Vec::new();
311 for (seat, family) in permission.families().iter().enumerate() {
312 let local = format!("permission_family_{position}_{seat}");
313 body.extend(bound_local(
314 &local,
315 or_refused(family_reference(family.slug())?, refusal, UNRESOLVED_ARM)?,
316 ));
317 named.push(GeneratedToken::word(&local));
318 named.push(GeneratedToken::alone(','));
319 }
320 body.extend(bound_local(
321 &format!("permission_{position}"),
322 mapped(
323 vocabulary::road(
324 &[
325 HarnessName::Muterprater,
326 HarnessName::MutationPermission,
327 HarnessName::Declared,
328 ],
329 comma_many(vec![vec![GeneratedToken::word(&claim)], roster(named)?]),
330 )?,
331 refusal,
332 PERMISSION_ARM,
333 )?,
334 ));
335 Ok(body)
336}
337
338fn family_reference(slug: &str) -> Result<Vec<GeneratedToken>, Overflow> {
340 vocabulary::road(
341 &[
342 HarnessName::Muterprater,
343 HarnessName::OperatorFamilyRef,
344 HarnessName::OfSlug,
345 ],
346 vec![GeneratedToken::text(slug)],
347 )
348}
349
350fn site_locals(
352 site: &Site,
353 policy: &Policy,
354 refusal: &TypeName,
355) -> Result<Vec<GeneratedToken>, Overflow> {
356 let mut body = bound_local(
357 POINT_LOCAL,
358 mapped(
359 vocabulary::road(
360 &[
361 HarnessName::Descriptor,
362 HarnessName::MutationPointRef,
363 HarnessName::Named,
364 ],
365 name_arguments(site.point()),
366 )?,
367 refusal,
368 NAME_ARM,
369 )?,
370 );
371 body.extend(bound_local(
372 ACTIVATION_LOCAL,
373 mapped(
374 vocabulary::road(
375 &[
376 HarnessName::Muterprater,
377 HarnessName::ActivationSite,
378 HarnessName::Named,
379 ],
380 name_arguments(site.point()),
381 )?,
382 refusal,
383 NAME_ARM,
384 )?,
385 ));
386 let mapping = match policy.claim_for(site.fact()) {
387 Some(claim) => {
388 body.extend(bound_local(
389 OWNER_CLAIM_LOCAL,
390 mapped(
391 vocabulary::road(
392 &[
393 HarnessName::Descriptor,
394 HarnessName::ClaimRef,
395 HarnessName::Named,
396 ],
397 name_arguments(claim),
398 )?,
399 refusal,
400 NAME_ARM,
401 )?,
402 ));
403 call(
404 vocabulary::path(&[
405 HarnessName::Muterprater,
406 HarnessName::OwnerClaimMapping,
407 HarnessName::Mapped,
408 ]),
409 vec![GeneratedToken::word(OWNER_CLAIM_LOCAL)],
410 )?
411 }
412 None => vocabulary::path(&[
413 HarnessName::Muterprater,
414 HarnessName::OwnerClaimMapping,
415 HarnessName::OwnerUnmapped,
416 ]),
417 };
418 body.extend(bound_local(
419 SITE_LOCAL,
420 mapped(discovered(site, mapping, refusal)?, refusal, DISCOVERY_ARM)?,
421 ));
422 Ok(body)
423}
424
425fn discovered(
427 site: &Site,
428 mapping: Vec<GeneratedToken>,
429 refusal: &TypeName,
430) -> Result<Vec<GeneratedToken>, Overflow> {
431 let mut candidates: Vec<GeneratedToken> = Vec::new();
432 for alternative in site.alternatives() {
433 candidates.extend(stated(alternative, refusal)?);
434 candidates.push(GeneratedToken::alone(','));
435 }
436 vocabulary::road(
437 &[
438 HarnessName::Muterprater,
439 HarnessName::DiscoveredMutationSite,
440 HarnessName::Discovered,
441 ],
442 comma_many(vec![
443 vec![GeneratedToken::word(POINT_LOCAL)],
444 mapping,
445 owned_bytes(site.unchanged())?,
446 roster(candidates)?,
447 vec![GeneratedToken::word(ACTIVATION_LOCAL)],
448 ]),
449 )
450}
451
452fn stated(alternative: &Alternative, refusal: &TypeName) -> Result<Vec<GeneratedToken>, Overflow> {
454 let family = or_refused(
455 family_reference(alternative.family().slug())?,
456 refusal,
457 UNRESOLVED_ARM,
458 )?;
459 vocabulary::road(
460 &[
461 HarnessName::Muterprater,
462 HarnessName::AlternativeDeclaration,
463 HarnessName::Stated,
464 ],
465 comma_many(vec![family, owned_bytes(alternative.operation())?]),
466 )
467}
468
469fn lowering(surface: &Surface) -> Result<Vec<GeneratedToken>, Overflow> {
471 let refusal = &surface.address().refusal;
472 let policy = surface.policy();
473 let mut body = policy_locals(policy, refusal)?;
474 body.extend(site_locals(surface.site(), policy, refusal)?);
475 let lowered = vocabulary::road(
476 &[
477 HarnessName::Muterprater,
478 HarnessName::Discover,
479 HarnessName::LowerDiscoveries,
480 ],
481 comma_many(vec![
482 vec![
483 GeneratedToken::alone('&'),
484 GeneratedToken::word(POLICY_LOCAL),
485 ],
486 roster(vec![
487 GeneratedToken::word(SITE_LOCAL),
488 GeneratedToken::alone(','),
489 ])?,
490 ]),
491 )?;
492 body.extend(method_call(
493 lowered,
494 "map_err",
495 arm_path(refusal, LOWERING_ARM),
496 )?);
497 let mut tokens = declared_reach_tokens(Visibility::Crate)?;
498 tokens.extend(function(
499 LOWERING,
500 Vec::new(),
501 result_type(
502 vocabulary::path(&[
503 HarnessName::Muterprater,
504 HarnessName::MutationSurfaceLowering,
505 ]),
506 vec![GeneratedToken::word(refusal.spelling())],
507 ),
508 body,
509 )?);
510 Ok(tokens)
511}
512
513fn production(site: &Site) -> Result<Vec<GeneratedToken>, Overflow> {
515 let mut tokens = declared_reach_tokens(Visibility::Crate)?;
516 tokens.extend(function(
517 PRODUCTION,
518 input_parameter()?,
519 site.order().to_vec(),
520 site.production().to_vec(),
521 )?);
522 Ok(tokens)
523}
524
525fn input_parameter() -> Result<Vec<GeneratedToken>, Overflow> {
527 Ok(vec![
528 GeneratedToken::word(INPUT_PARAMETER),
529 GeneratedToken::alone(':'),
530 GeneratedToken::alone('&'),
531 group(GeneratedDelimiter::Parenthesis, Vec::new())?,
532 ])
533}
534
535fn evaluation(site: &Site) -> Result<Vec<GeneratedToken>, Overflow> {
537 let observation = observation_type(site);
538 let mut body = unselected()?;
539 for (position, alternative) in site.alternatives().iter().enumerate() {
540 body.push(GeneratedToken::word("if"));
541 body.extend(active_condition(site, alternative)?);
542 body.push(group(
543 GeneratedDelimiter::Brace,
544 observed(vec![GeneratedToken::word(&alternative_name(position))], 1)?,
545 )?);
546 }
547 body.extend(call(
548 vec![GeneratedToken::word("Err")],
549 call(
550 vocabulary::path(&[
551 HarnessName::Muterprater,
552 HarnessName::EvaluationCallRefusal,
553 HarnessName::ActiveSelectionNotImplemented,
554 ]),
555 method_chain(
556 vec![GeneratedToken::word(RESOLVED_LOCAL)],
557 &[HarnessName::Selection.spelling()],
558 )?,
559 )?,
560 )?);
561
562 let mut tokens = declared_reach_tokens(Visibility::Crate)?;
563 tokens.push(GeneratedToken::word("fn"));
564 tokens.push(GeneratedToken::word(EVALUATION));
565 tokens.extend(surface_lifetime());
566 tokens.push(group(
567 GeneratedDelimiter::Parenthesis,
568 directive_parameters()?,
569 )?);
570 tokens.push(GeneratedToken::joint('-'));
571 tokens.push(GeneratedToken::alone('>'));
572 tokens.extend(result_type(
573 observation,
574 vocabulary::path(&[HarnessName::Muterprater, HarnessName::EvaluationCallRefusal]),
575 ));
576 tokens.push(group(GeneratedDelimiter::Brace, body)?);
577 Ok(tokens)
578}
579
580fn surface_lifetime() -> Vec<GeneratedToken> {
582 vec![
583 GeneratedToken::alone('<'),
584 GeneratedToken::joint('\''),
585 GeneratedToken::word(SURFACE_LIFETIME),
586 GeneratedToken::alone('>'),
587 ]
588}
589
590fn directive_parameters() -> Result<Vec<GeneratedToken>, Overflow> {
592 let mut tokens = input_parameter()?;
593 tokens.push(GeneratedToken::alone(','));
594 tokens.push(GeneratedToken::word("directive"));
595 tokens.push(GeneratedToken::alone(':'));
596 tokens.extend(vocabulary::path(&[
597 HarnessName::Muterprater,
598 HarnessName::EvaluationDirective,
599 ]));
600 tokens.extend(surface_lifetime());
601 Ok(tokens)
602}
603
604fn observation_type(site: &Site) -> Vec<GeneratedToken> {
606 let mut tokens =
607 vocabulary::path(&[HarnessName::Muterprater, HarnessName::EvaluationObservation]);
608 tokens.push(GeneratedToken::alone('<'));
609 tokens.extend(site.order().to_vec());
610 tokens.push(GeneratedToken::alone('>'));
611 tokens
612}
613
614fn unselected() -> Result<Vec<GeneratedToken>, Overflow> {
616 let resolved = method_chain(
617 vec![GeneratedToken::word("directive")],
618 &[HarnessName::Resolved.spelling()],
619 )?;
620 let mut tokens = vec![
621 GeneratedToken::word("let"),
622 GeneratedToken::word("Some"),
623 group(
624 GeneratedDelimiter::Parenthesis,
625 vec![GeneratedToken::word(RESOLVED_LOCAL)],
626 )?,
627 GeneratedToken::alone('='),
628 ];
629 tokens.extend(resolved);
630 tokens.push(GeneratedToken::word("else"));
631 tokens.push(group(
632 GeneratedDelimiter::Brace,
633 observed(
634 call(
635 vec![GeneratedToken::word(PRODUCTION)],
636 vec![GeneratedToken::word(INPUT_PARAMETER)],
637 )?,
638 0,
639 )?,
640 )?);
641 tokens.push(GeneratedToken::alone(';'));
642 Ok(tokens)
643}
644
645fn observed(meaning: Vec<GeneratedToken>, firings: u64) -> Result<Vec<GeneratedToken>, Overflow> {
647 let taken = vocabulary::road(
648 &[
649 HarnessName::Muterprater,
650 HarnessName::EvaluationObservation,
651 HarnessName::Observed,
652 ],
653 comma_many(vec![meaning, vec![GeneratedToken::number(firings)]]),
654 )?;
655 let mut tokens = vec![GeneratedToken::word("return")];
656 tokens.extend(call(vec![GeneratedToken::word("Ok")], taken)?);
657 tokens.push(GeneratedToken::alone(';'));
658 Ok(tokens)
659}
660
661fn active_condition(
663 site: &Site,
664 alternative: &Alternative,
665) -> Result<Vec<GeneratedToken>, Overflow> {
666 let point = site.point();
667 let comparisons = vec![
668 equality(
669 selected_point(&[HarnessName::NamespaceRoad, HarnessName::Written])?,
670 vec![GeneratedToken::text(point.namespace())],
671 ),
672 equality(
673 selected_point(&[HarnessName::StemRoad, HarnessName::Written])?,
674 vec![GeneratedToken::text(point.stem())],
675 ),
676 equality(
677 method_chain(
678 vec![GeneratedToken::word(RESOLVED_LOCAL)],
679 &[
680 HarnessName::Alternative.spelling(),
681 HarnessName::Family.spelling(),
682 HarnessName::Slug.spelling(),
683 ],
684 )?,
685 vec![GeneratedToken::text(alternative.family().slug())],
686 ),
687 equality(
688 method_chain(
689 vec![GeneratedToken::word(RESOLVED_LOCAL)],
690 &[
691 HarnessName::Alternative.spelling(),
692 HarnessName::Operation.spelling(),
693 ],
694 )?,
695 vec![GeneratedToken::byte_text(alternative.operation())],
696 ),
697 ];
698 Ok(and_all(comparisons))
699}
700
701fn selected_point(part: &[HarnessName]) -> Result<Vec<GeneratedToken>, Overflow> {
703 let mut roads = vec![
704 HarnessName::Point.spelling(),
705 HarnessName::Identity.spelling(),
706 HarnessName::NameRoad.spelling(),
707 ];
708 roads.extend(part.iter().map(|road| road.spelling()));
709 method_chain(vec![GeneratedToken::word(RESOLVED_LOCAL)], &roads)
710}