use super::{GeneratedDelimiter, GeneratedToken};
use crate::bounded::Overflow;
pub fn group(
delimiter: GeneratedDelimiter,
tokens: Vec<GeneratedToken>,
) -> Result<GeneratedToken, Overflow> {
GeneratedToken::group(delimiter, tokens)
}
#[must_use]
pub fn metavariable(name: &str) -> Vec<GeneratedToken> {
vec![GeneratedToken::joint('$'), GeneratedToken::word(name)]
}
#[must_use]
pub fn absolute_path(segments: &[&str]) -> Vec<GeneratedToken> {
let mut tokens = Vec::new();
extend_path(&mut tokens, segments);
tokens
}
#[must_use]
pub fn bound_path(root: &str, segments: &[&str]) -> Vec<GeneratedToken> {
let mut tokens = vec![GeneratedToken::word(root)];
extend_path(&mut tokens, segments);
tokens
}
#[must_use]
pub fn twin_path(binding: &str, segments: &[&str]) -> Vec<GeneratedToken> {
let mut tokens = metavariable(binding);
extend_path(&mut tokens, segments);
tokens
}
#[must_use]
pub(crate) fn segmented_twin_path(
root_binding: &str,
segment_binding: &str,
segments: &[&str],
) -> Vec<GeneratedToken> {
let mut tokens = metavariable(root_binding);
tokens.push(GeneratedToken::joint('$'));
tokens.push(GeneratedToken::fixed_group(
GeneratedDelimiter::Parenthesis,
[
GeneratedToken::joint(':'),
GeneratedToken::alone(':'),
GeneratedToken::joint('$'),
GeneratedToken::word(segment_binding),
],
));
tokens.push(GeneratedToken::alone('*'));
extend_path(&mut tokens, segments);
tokens
}
fn extend_path(tokens: &mut Vec<GeneratedToken>, segments: &[&str]) {
for segment in segments {
tokens.push(GeneratedToken::joint(':'));
tokens.push(GeneratedToken::alone(':'));
tokens.push(GeneratedToken::word(segment));
}
}
pub fn call(
mut path: Vec<GeneratedToken>,
arguments: Vec<GeneratedToken>,
) -> Result<Vec<GeneratedToken>, Overflow> {
path.push(group(GeneratedDelimiter::Parenthesis, arguments)?);
Ok(path)
}
pub fn method_call(
mut receiver: Vec<GeneratedToken>,
method: &str,
arguments: Vec<GeneratedToken>,
) -> Result<Vec<GeneratedToken>, Overflow> {
receiver.push(GeneratedToken::alone('.'));
receiver.push(GeneratedToken::word(method));
call(receiver, arguments)
}
pub fn method_chain(
mut receiver: Vec<GeneratedToken>,
methods: &[&str],
) -> Result<Vec<GeneratedToken>, Overflow> {
for method in methods {
receiver = method_call(receiver, method, Vec::new())?;
}
Ok(receiver)
}
#[must_use]
pub fn bound_local(name: &str, expression: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
let mut tokens = vec![
GeneratedToken::word("let"),
GeneratedToken::word(name),
GeneratedToken::alone('='),
];
tokens.extend(expression);
tokens.push(GeneratedToken::alone(';'));
tokens
}
#[must_use]
pub fn result_type(ok: Vec<GeneratedToken>, error: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
let mut tokens = absolute_path(&["core", "result", "Result"]);
tokens.push(GeneratedToken::alone('<'));
tokens.extend(ok);
tokens.push(GeneratedToken::alone(','));
tokens.extend(error);
tokens.push(GeneratedToken::alone('>'));
tokens
}
#[must_use]
pub fn constant(
name: &str,
kind: Vec<GeneratedToken>,
value: Vec<GeneratedToken>,
) -> Vec<GeneratedToken> {
let mut tokens = vec![GeneratedToken::word("const"), GeneratedToken::word(name)];
tokens.push(GeneratedToken::alone(':'));
tokens.extend(kind);
tokens.push(GeneratedToken::alone('='));
tokens.extend(value);
tokens.push(GeneratedToken::alone(';'));
tokens
}
#[must_use]
pub fn equality(mut left: Vec<GeneratedToken>, right: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
left.push(GeneratedToken::joint('='));
left.push(GeneratedToken::alone('='));
left.extend(right);
left
}
#[must_use]
pub fn and_all(comparisons: Vec<Vec<GeneratedToken>>) -> Vec<GeneratedToken> {
let mut tokens = Vec::new();
for (position, comparison) in comparisons.into_iter().enumerate() {
if position > 0 {
tokens.push(GeneratedToken::joint('&'));
tokens.push(GeneratedToken::alone('&'));
}
tokens.extend(comparison);
}
tokens
}
#[must_use]
pub fn comma(mut left: Vec<GeneratedToken>, right: Vec<GeneratedToken>) -> Vec<GeneratedToken> {
left.push(GeneratedToken::alone(','));
left.extend(right);
left
}
#[must_use]
pub fn comma_many(parts: Vec<Vec<GeneratedToken>>) -> Vec<GeneratedToken> {
let mut tokens = Vec::new();
for (position, part) in parts.into_iter().enumerate() {
if position > 0 {
tokens.push(GeneratedToken::alone(','));
}
tokens.extend(part);
}
tokens
}
#[must_use]
pub fn text_pair(first: &str, second: &str) -> Vec<GeneratedToken> {
vec![
GeneratedToken::text(first),
GeneratedToken::alone(','),
GeneratedToken::text(second),
]
}
pub fn attribute(body: Vec<GeneratedToken>) -> Result<Vec<GeneratedToken>, Overflow> {
Ok(vec![
GeneratedToken::alone('#'),
group(GeneratedDelimiter::Bracket, body)?,
])
}
pub fn documentation(sentence: &str) -> Result<Vec<GeneratedToken>, Overflow> {
attribute(vec![
GeneratedToken::word("doc"),
GeneratedToken::alone('='),
GeneratedToken::text(sentence),
])
}
pub fn roster(items: Vec<GeneratedToken>) -> Result<Vec<GeneratedToken>, Overflow> {
let mut tokens = absolute_path(&["std", "vec"]);
tokens.push(GeneratedToken::alone('!'));
tokens.push(group(GeneratedDelimiter::Bracket, items)?);
Ok(tokens)
}
pub(crate) fn vector(members: Vec<Vec<GeneratedToken>>) -> Result<Vec<GeneratedToken>, Overflow> {
if members.is_empty() {
return call(absolute_path(&["std", "vec", "Vec", "new"]), Vec::new());
}
let array = group(GeneratedDelimiter::Bracket, comma_many(members))?;
call(absolute_path(&["std", "vec", "Vec", "from"]), vec![array])
}