macroonz_compiler/token/generation/
compose.rs1use super::{GeneratedDelimiter, GeneratedToken};
10use crate::bounded::Overflow;
11
12pub fn group(
18 delimiter: GeneratedDelimiter,
19 tokens: Vec<GeneratedToken>,
20) -> Result<GeneratedToken, Overflow> {
21 GeneratedToken::group(delimiter, tokens)
22}
23
24#[must_use]
28pub fn metavariable(name: &str) -> Vec<GeneratedToken> {
29 vec![GeneratedToken::joint('$'), GeneratedToken::word(name)]
30}
31
32#[must_use]
34pub fn absolute_path(segments: &[&str]) -> Vec<GeneratedToken> {
35 let mut tokens = Vec::new();
36 extend_path(&mut tokens, segments);
37 tokens
38}
39
40#[must_use]
44pub fn bound_path(root: &str, segments: &[&str]) -> Vec<GeneratedToken> {
45 let mut tokens = vec![GeneratedToken::word(root)];
46 extend_path(&mut tokens, segments);
47 tokens
48}
49
50#[must_use]
52pub fn twin_path(binding: &str, segments: &[&str]) -> Vec<GeneratedToken> {
53 let mut tokens = metavariable(binding);
54 extend_path(&mut tokens, segments);
55 tokens
56}
57
58#[must_use]
62pub(crate) fn segmented_twin_path(
63 root_binding: &str,
64 segment_binding: &str,
65 segments: &[&str],
66) -> Vec<GeneratedToken> {
67 let mut tokens = metavariable(root_binding);
68 tokens.push(GeneratedToken::joint('$'));
69 tokens.push(GeneratedToken::fixed_group(
70 GeneratedDelimiter::Parenthesis,
71 [
72 GeneratedToken::joint(':'),
73 GeneratedToken::alone(':'),
74 GeneratedToken::joint('$'),
75 GeneratedToken::word(segment_binding),
76 ],
77 ));
78 tokens.push(GeneratedToken::alone('*'));
79 extend_path(&mut tokens, segments);
80 tokens
81}
82
83fn extend_path(tokens: &mut Vec<GeneratedToken>, segments: &[&str]) {
85 for segment in segments {
86 tokens.push(GeneratedToken::joint(':'));
87 tokens.push(GeneratedToken::alone(':'));
88 tokens.push(GeneratedToken::word(segment));
89 }
90}
91
92pub fn call(
98 mut path: Vec<GeneratedToken>,
99 arguments: Vec<GeneratedToken>,
100) -> Result<Vec<GeneratedToken>, Overflow> {
101 path.push(group(GeneratedDelimiter::Parenthesis, arguments)?);
102 Ok(path)
103}
104
105pub fn method_call(
111 mut receiver: Vec<GeneratedToken>,
112 method: &str,
113 arguments: Vec<GeneratedToken>,
114) -> Result<Vec<GeneratedToken>, Overflow> {
115 receiver.push(GeneratedToken::alone('.'));
116 receiver.push(GeneratedToken::word(method));
117 call(receiver, arguments)
118}
119
120pub fn method_chain(
126 mut receiver: Vec<GeneratedToken>,
127 methods: &[&str],
128) -> Result<Vec<GeneratedToken>, Overflow> {
129 for method in methods {
130 receiver = method_call(receiver, method, Vec::new())?;
131 }
132 Ok(receiver)
133}
134
135#[must_use]
139pub fn bound_local(name: &str, expression: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
140 let mut tokens = vec![
141 GeneratedToken::word("let"),
142 GeneratedToken::word(name),
143 GeneratedToken::alone('='),
144 ];
145 tokens.extend(expression);
146 tokens.push(GeneratedToken::alone(';'));
147 tokens
148}
149
150#[must_use]
152pub fn result_type(ok: Vec<GeneratedToken>, error: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
153 let mut tokens = absolute_path(&["core", "result", "Result"]);
154 tokens.push(GeneratedToken::alone('<'));
155 tokens.extend(ok);
156 tokens.push(GeneratedToken::alone(','));
157 tokens.extend(error);
158 tokens.push(GeneratedToken::alone('>'));
159 tokens
160}
161
162#[must_use]
166pub fn constant(
167 name: &str,
168 kind: Vec<GeneratedToken>,
169 value: Vec<GeneratedToken>,
170) -> Vec<GeneratedToken> {
171 let mut tokens = vec![GeneratedToken::word("const"), GeneratedToken::word(name)];
172 tokens.push(GeneratedToken::alone(':'));
173 tokens.extend(kind);
174 tokens.push(GeneratedToken::alone('='));
175 tokens.extend(value);
176 tokens.push(GeneratedToken::alone(';'));
177 tokens
178}
179
180#[must_use]
182pub fn equality(mut left: Vec<GeneratedToken>, right: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
183 left.push(GeneratedToken::joint('='));
184 left.push(GeneratedToken::alone('='));
185 left.extend(right);
186 left
187}
188
189#[must_use]
191pub fn and_all(comparisons: Vec<Vec<GeneratedToken>>) -> Vec<GeneratedToken> {
192 let mut tokens = Vec::new();
193 for (position, comparison) in comparisons.into_iter().enumerate() {
194 if position > 0 {
195 tokens.push(GeneratedToken::joint('&'));
196 tokens.push(GeneratedToken::alone('&'));
197 }
198 tokens.extend(comparison);
199 }
200 tokens
201}
202
203#[must_use]
205pub fn comma(mut left: Vec<GeneratedToken>, right: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
206 left.push(GeneratedToken::alone(','));
207 left.extend(right);
208 left
209}
210
211#[must_use]
213pub fn comma_many(parts: Vec<Vec<GeneratedToken>>) -> Vec<GeneratedToken> {
214 let mut tokens = Vec::new();
215 for (position, part) in parts.into_iter().enumerate() {
216 if position > 0 {
217 tokens.push(GeneratedToken::alone(','));
218 }
219 tokens.extend(part);
220 }
221 tokens
222}
223
224#[must_use]
226pub fn text_pair(first: &str, second: &str) -> Vec<GeneratedToken> {
227 vec![
228 GeneratedToken::text(first),
229 GeneratedToken::alone(','),
230 GeneratedToken::text(second),
231 ]
232}
233
234pub fn attribute(body: Vec<GeneratedToken>) -> Result<Vec<GeneratedToken>, Overflow> {
240 Ok(vec![
241 GeneratedToken::alone('#'),
242 group(GeneratedDelimiter::Bracket, body)?,
243 ])
244}
245
246pub fn documentation(sentence: &str) -> Result<Vec<GeneratedToken>, Overflow> {
252 attribute(vec![
253 GeneratedToken::word("doc"),
254 GeneratedToken::alone('='),
255 GeneratedToken::text(sentence),
256 ])
257}
258
259pub fn roster(items: Vec<GeneratedToken>) -> Result<Vec<GeneratedToken>, Overflow> {
265 let mut tokens = absolute_path(&["std", "vec"]);
266 tokens.push(GeneratedToken::alone('!'));
267 tokens.push(group(GeneratedDelimiter::Bracket, items)?);
268 Ok(tokens)
269}
270
271pub(crate) fn vector(members: Vec<Vec<GeneratedToken>>) -> Result<Vec<GeneratedToken>, Overflow> {
277 if members.is_empty() {
278 return call(absolute_path(&["std", "vec", "Vec", "new"]), Vec::new());
279 }
280 let array = group(GeneratedDelimiter::Bracket, comma_many(members))?;
281 call(absolute_path(&["std", "vec", "Vec", "from"]), vec![array])
282}