macroonz_compiler/support/carrier/
render.rs1use super::super::cargo::{AxisCargo, DeclaredCargo};
21use super::super::types::{BoundPath, CrateFacing, DeliveryForm, SchemaId, SupportName};
22use super::ShellName;
23use crate::bounded::Overflow;
24use crate::request::Door;
25use crate::token::{
26 GeneratedDelimiter, GeneratedToken, attribute, documentation, group, metavariable,
27 segmented_twin_path,
28};
29
30pub const GATE_MACRO: &str = "generated_support";
32
33pub const EXPECTED_CLAUSE: &str = "expected";
35
36const PATH_SEGMENT_SUFFIX: &str = "_segment";
38
39fn segment_binding(facing: CrateFacing) -> String {
41 format!("{}{PATH_SEGMENT_SUFFIX}", facing.name())
42}
43
44#[must_use]
46pub(crate) fn rooted_path(facing: CrateFacing, segments: &[&str]) -> Vec<GeneratedToken> {
47 segmented_twin_path(facing.name(), &segment_binding(facing), segments)
48}
49
50#[must_use]
52pub fn rendered_path(path: &BoundPath) -> Vec<GeneratedToken> {
53 let segments: Vec<&str> = path.segments().iter().map(String::as_str).collect();
54 rooted_path(path.facing(), &segments)
55}
56
57pub fn expectation_roster(expectation: SchemaId) -> Result<GeneratedToken, Overflow> {
63 let mut bytes: Vec<GeneratedToken> = Vec::new();
64 for byte in expectation.as_bytes() {
65 bytes.push(GeneratedToken::number(u64::from(*byte)));
66 bytes.push(GeneratedToken::alone(','));
67 }
68 group(GeneratedDelimiter::Bracket, bytes)
69}
70
71#[must_use]
73pub fn matched_clause(name: &str, fragment: &str) -> Vec<GeneratedToken> {
74 let mut tokens = vec![GeneratedToken::word(name), GeneratedToken::alone(':')];
75 tokens.extend(metavariable(name));
76 tokens.push(GeneratedToken::alone(':'));
77 tokens.push(GeneratedToken::word(fragment));
78 tokens.push(GeneratedToken::alone(','));
79 tokens
80}
81
82#[must_use]
87pub fn matcher(declared: &AxisCargo<DeclaredCargo>) -> Vec<GeneratedToken> {
88 let facing = CrateFacing::Harness;
89 let binding = facing.name();
90 let segment = segment_binding(facing);
91 let mut tokens = vec![GeneratedToken::word(binding), GeneratedToken::alone(':')];
92 tokens.extend(metavariable(binding));
93 tokens.push(GeneratedToken::alone(':'));
94 tokens.push(GeneratedToken::word("ident"));
95 tokens.push(GeneratedToken::joint('$'));
96 tokens.push(GeneratedToken::fixed_group(
97 GeneratedDelimiter::Parenthesis,
98 [
99 GeneratedToken::joint(':'),
100 GeneratedToken::alone(':'),
101 GeneratedToken::joint('$'),
102 GeneratedToken::word(&segment),
103 GeneratedToken::alone(':'),
104 GeneratedToken::word("ident"),
105 ],
106 ));
107 tokens.push(GeneratedToken::alone('*'));
108 tokens.push(GeneratedToken::alone(','));
109 if let AxisCargo::Carried(cargo) = declared {
110 tokens.extend(cargo.matched().tokens().iter().cloned());
111 }
112 tokens
113}
114
115pub fn gate_invocation(
127 form: DeliveryForm,
128 expectation: GeneratedToken,
129 stamped: Vec<GeneratedToken>,
130 opaque: Vec<GeneratedToken>,
131) -> Result<Vec<GeneratedToken>, Overflow> {
132 let facing = CrateFacing::Harness;
133 let binding = facing.name();
134 let mut clauses = vec![
135 GeneratedToken::word(EXPECTED_CLAUSE),
136 GeneratedToken::alone(':'),
137 expectation,
138 GeneratedToken::alone(','),
139 GeneratedToken::word(binding),
140 GeneratedToken::alone(':'),
141 ];
142 clauses.extend(rooted_path(facing, &[]));
143 clauses.push(GeneratedToken::alone(','));
144 clauses.push(GeneratedToken::word(form.name()));
145 clauses.push(GeneratedToken::alone(':'));
146 clauses.push(group(GeneratedDelimiter::Brace, stamped)?);
147 clauses.push(GeneratedToken::alone(','));
148 clauses.push(GeneratedToken::word(form.opaque()));
149 clauses.push(GeneratedToken::alone(':'));
150 clauses.push(group(GeneratedDelimiter::Brace, opaque)?);
151 clauses.push(GeneratedToken::alone(','));
152 let mut tokens = rooted_path(facing, &[GATE_MACRO]);
153 tokens.push(GeneratedToken::alone('!'));
154 tokens.push(group(GeneratedDelimiter::Brace, clauses)?);
155 Ok(tokens)
156}
157
158pub fn exported_shell(
164 name: &ShellName,
165 sentence: &str,
166 matched: Vec<GeneratedToken>,
167 body: Vec<GeneratedToken>,
168) -> Result<Vec<GeneratedToken>, Overflow> {
169 let mut tokens = documentation(sentence)?;
170 tokens.extend(attribute(vec![
171 GeneratedToken::word("doc"),
172 group(
173 GeneratedDelimiter::Parenthesis,
174 vec![GeneratedToken::word("hidden")],
175 )?,
176 ])?);
177 tokens.extend(attribute(vec![GeneratedToken::word("macro_export")])?);
178 tokens.push(GeneratedToken::word("macro_rules"));
179 tokens.push(GeneratedToken::alone('!'));
180 tokens.push(GeneratedToken::word(name.spelling()));
181 let mut rule = vec![group(GeneratedDelimiter::Parenthesis, matched)?];
182 rule.push(GeneratedToken::joint('='));
183 rule.push(GeneratedToken::alone('>'));
184 rule.push(group(GeneratedDelimiter::Brace, body)?);
185 rule.push(GeneratedToken::alone(';'));
186 tokens.push(group(GeneratedDelimiter::Brace, rule)?);
187 Ok(tokens)
188}
189
190pub fn public_alias(
207 name: &ShellName,
208 address: &SupportName,
209 sentence: &str,
210) -> Result<Vec<GeneratedToken>, Overflow> {
211 let mut tokens = documentation(sentence)?;
212 tokens.extend(attribute(vec![GeneratedToken::word("macro_export")])?);
213 tokens.push(GeneratedToken::word("macro_rules"));
214 tokens.push(GeneratedToken::alone('!'));
215 tokens.push(GeneratedToken::word(address.spelling()));
216
217 let mut taken = metavariable("input");
218 taken.push(GeneratedToken::alone(':'));
219 taken.push(GeneratedToken::word("tt"));
220 let mut repeated = vec![GeneratedToken::joint('$')];
221 repeated.push(group(GeneratedDelimiter::Parenthesis, taken)?);
222 repeated.push(GeneratedToken::alone('*'));
223
224 let mut forwarded = metavariable("crate");
225 forwarded.push(GeneratedToken::joint(':'));
226 forwarded.push(GeneratedToken::alone(':'));
227 forwarded.push(GeneratedToken::word(name.spelling()));
228 forwarded.push(GeneratedToken::alone('!'));
229 let mut passed = vec![GeneratedToken::joint('$')];
230 passed.push(group(
231 GeneratedDelimiter::Parenthesis,
232 metavariable("input"),
233 )?);
234 passed.push(GeneratedToken::alone('*'));
235 forwarded.push(group(GeneratedDelimiter::Brace, passed)?);
236
237 let mut rule = vec![group(GeneratedDelimiter::Parenthesis, repeated)?];
238 rule.push(GeneratedToken::joint('='));
239 rule.push(GeneratedToken::alone('>'));
240 rule.push(group(GeneratedDelimiter::Brace, forwarded)?);
241 rule.push(GeneratedToken::alone(';'));
242 tokens.push(group(GeneratedDelimiter::Brace, rule)?);
243 Ok(tokens)
244}
245
246pub(super) fn shell_sentence(door: &Door) -> String {
250 let producer = door.producer();
251 let namespace = producer.namespace;
252 let name = producer.name;
253 format!(
254 "Generated support carrier from {namespace}/{name}: deferred tokens a consumption \
255 target invokes. Hidden and mangled because it is machinery. Its body is one gate \
256 invocation, and the gate compares this producer's expected schema identity against \
257 the published one before any constructor reaches type checking."
258 )
259}
260
261pub(super) fn alias_sentence(door: &Door) -> String {
266 let producer = door.producer();
267 let namespace = producer.namespace;
268 let name = producer.name;
269 format!(
270 "Generated support from {namespace}/{name}: invoke this from a consumption target to \
271 receive what this declaration states. It forwards every token to the hidden plan-keyed \
272 carrier, whose matcher is the grammar and whose gate compares the producer's expected \
273 schema identity against the published one."
274 )
275}