Skip to main content

macroonz_compiler/token/generation/
items.rs

1//! Conventional namespace and data items assembled from exact generated-token runs.
2//!
3//! These operations own Rust punctuation and item order only.
4//! The caller owns every name, visibility, attribute, type, bound, predicate, field, variant, value, and semantic meaning.
5
6use super::compose::{comma_many, group};
7use super::{GeneratedDelimiter, GeneratedToken};
8use crate::bounded::Overflow;
9
10/// Prefix one item with its declared attributes and visibility.
11#[must_use]
12pub fn decorated(
13    attributes: Vec<Vec<GeneratedToken>>,
14    visibility: Vec<GeneratedToken>,
15    item: Vec<GeneratedToken>,
16) -> Vec<GeneratedToken> {
17    let mut tokens = attributes.into_iter().flatten().collect::<Vec<_>>();
18    tokens.extend(visibility);
19    tokens.extend(item);
20    tokens
21}
22
23/// One inline module `mod name { items }`.
24///
25/// # Errors
26///
27/// Returns [`Overflow`] where the item body outgrows the declared generated-token magnitude.
28pub fn inline_module(
29    name: GeneratedToken,
30    items: Vec<GeneratedToken>,
31) -> Result<Vec<GeneratedToken>, Overflow> {
32    Ok(vec![
33        GeneratedToken::word("mod"),
34        name,
35        group(GeneratedDelimiter::Brace, items)?,
36    ])
37}
38
39/// One import `use path [as alias];`.
40#[must_use]
41pub fn use_item(path: Vec<GeneratedToken>, alias: Option<GeneratedToken>) -> Vec<GeneratedToken> {
42    let mut tokens = vec![GeneratedToken::word("use")];
43    tokens.extend(path);
44    if let Some(alias) = alias {
45        tokens.extend([GeneratedToken::word("as"), alias]);
46    }
47    tokens.push(GeneratedToken::alone(';'));
48    tokens
49}
50
51/// One generic-parameter list `<parameters>`, or nothing when the roster is empty.
52#[must_use]
53pub fn generic_parameters(parameters: Vec<Vec<GeneratedToken>>) -> Vec<GeneratedToken> {
54    if parameters.is_empty() {
55        Vec::new()
56    } else {
57        let mut tokens = vec![GeneratedToken::alone('<')];
58        tokens.extend(comma_many(parameters));
59        tokens.push(GeneratedToken::alone('>'));
60        tokens
61    }
62}
63
64/// One `where` clause over exact caller-owned predicates, or nothing when the roster is empty.
65#[must_use]
66pub fn where_clause(predicates: Vec<Vec<GeneratedToken>>) -> Vec<GeneratedToken> {
67    if predicates.is_empty() {
68        Vec::new()
69    } else {
70        let mut tokens = vec![GeneratedToken::word("where")];
71        tokens.extend(comma_many(predicates));
72        tokens
73    }
74}
75
76/// One type alias `type Name<...> = value where ...;`.
77#[must_use]
78pub fn type_alias(
79    name: GeneratedToken,
80    parameters: Vec<Vec<GeneratedToken>>,
81    value: Vec<GeneratedToken>,
82    predicates: Vec<Vec<GeneratedToken>>,
83) -> Vec<GeneratedToken> {
84    let mut tokens = vec![GeneratedToken::word("type"), name];
85    tokens.extend(generic_parameters(parameters));
86    tokens.push(GeneratedToken::alone('='));
87    tokens.extend(value);
88    tokens.extend(where_clause(predicates));
89    tokens.push(GeneratedToken::alone(';'));
90    tokens
91}
92
93/// One unit struct `struct Name<...> where ...;`.
94#[must_use]
95pub fn unit_struct(
96    name: GeneratedToken,
97    parameters: Vec<Vec<GeneratedToken>>,
98    predicates: Vec<Vec<GeneratedToken>>,
99) -> Vec<GeneratedToken> {
100    let mut tokens = item_head("struct", name, parameters);
101    tokens.extend(where_clause(predicates));
102    tokens.push(GeneratedToken::alone(';'));
103    tokens
104}
105
106/// One tuple struct `struct Name<...>(fields) where ...;`.
107///
108/// A single field is a newtype, and a `PhantomData<T>` field is an ordinary caller-owned type fragment rather than another projector concept.
109///
110/// # Errors
111///
112/// Returns [`Overflow`] where the field group outgrows the declared generated-token magnitude.
113pub fn tuple_struct(
114    name: GeneratedToken,
115    parameters: Vec<Vec<GeneratedToken>>,
116    fields: Vec<Vec<GeneratedToken>>,
117    predicates: Vec<Vec<GeneratedToken>>,
118) -> Result<Vec<GeneratedToken>, Overflow> {
119    let mut tokens = item_head("struct", name, parameters);
120    tokens.push(group(GeneratedDelimiter::Parenthesis, comma_many(fields))?);
121    tokens.extend(where_clause(predicates));
122    tokens.push(GeneratedToken::alone(';'));
123    Ok(tokens)
124}
125
126/// One named struct `struct Name<...> where ... { fields }`.
127///
128/// # Errors
129///
130/// Returns [`Overflow`] where the field group outgrows the declared generated-token magnitude.
131pub fn named_struct(
132    name: GeneratedToken,
133    parameters: Vec<Vec<GeneratedToken>>,
134    predicates: Vec<Vec<GeneratedToken>>,
135    fields: Vec<Vec<GeneratedToken>>,
136) -> Result<Vec<GeneratedToken>, Overflow> {
137    let mut tokens = item_head("struct", name, parameters);
138    tokens.extend(where_clause(predicates));
139    tokens.push(group(GeneratedDelimiter::Brace, comma_many(fields))?);
140    Ok(tokens)
141}
142
143/// One named field `name: kind`.
144#[must_use]
145pub fn named_field(name: GeneratedToken, kind: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
146    let mut tokens = vec![name, GeneratedToken::alone(':')];
147    tokens.extend(kind);
148    tokens
149}
150
151/// One enum `enum Name<...> where ... { variants }`.
152///
153/// # Errors
154///
155/// Returns [`Overflow`] where the variant group outgrows the declared generated-token magnitude.
156pub fn enumeration(
157    name: GeneratedToken,
158    parameters: Vec<Vec<GeneratedToken>>,
159    predicates: Vec<Vec<GeneratedToken>>,
160    variants: Vec<Vec<GeneratedToken>>,
161) -> Result<Vec<GeneratedToken>, Overflow> {
162    let mut tokens = item_head("enum", name, parameters);
163    tokens.extend(where_clause(predicates));
164    tokens.push(group(GeneratedDelimiter::Brace, comma_many(variants))?);
165    Ok(tokens)
166}
167
168/// One unit variant.
169#[must_use]
170pub fn unit_variant(name: GeneratedToken) -> Vec<GeneratedToken> {
171    vec![name]
172}
173
174/// One tuple variant.
175///
176/// # Errors
177///
178/// Returns [`Overflow`] where the field group outgrows the declared generated-token magnitude.
179pub fn tuple_variant(
180    name: GeneratedToken,
181    fields: Vec<Vec<GeneratedToken>>,
182) -> Result<Vec<GeneratedToken>, Overflow> {
183    Ok(vec![
184        name,
185        group(GeneratedDelimiter::Parenthesis, comma_many(fields))?,
186    ])
187}
188
189/// One named variant.
190///
191/// # Errors
192///
193/// Returns [`Overflow`] where the field group outgrows the declared generated-token magnitude.
194pub fn named_variant(
195    name: GeneratedToken,
196    fields: Vec<Vec<GeneratedToken>>,
197) -> Result<Vec<GeneratedToken>, Overflow> {
198    Ok(vec![
199        name,
200        group(GeneratedDelimiter::Brace, comma_many(fields))?,
201    ])
202}
203
204/// One item keyword, name, and exact generic-parameter roster.
205fn item_head(
206    keyword: &str,
207    name: GeneratedToken,
208    parameters: Vec<Vec<GeneratedToken>>,
209) -> Vec<GeneratedToken> {
210    let mut tokens = vec![GeneratedToken::word(keyword), name];
211    tokens.extend(generic_parameters(parameters));
212    tokens
213}