use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_macro_input, spanned::Spanned};
use crate::{tokens::PipeStatement, utils::ConstIdent};
pub const PIPELINE_IDENT: ConstIdent = ConstIdent("__");
pub fn pipe(input: TokenStream) -> TokenStream {
let pipes = parse_macro_input!(input as PipeStatement);
let mut lines = vec![];
for (i, line) in pipes.lines.iter().enumerate() {
let mut expressions = vec![];
for (j, expression) in line.expressions.iter().enumerate() {
let expr = expression.clone();
if i == 0 && j == 0 {
if PIPELINE_IDENT.to_ident(Some(expr.span()))
!= expr.to_string()
{
expressions.push(quote! {
let #PIPELINE_IDENT = #expr;
});
}
}
else if i > 0 && j == 0 {
}
else if i == pipes.lines.len() - 1
&& j == line.expressions.len() - 1
{
expressions.push(quote! {
#expr
});
}
else if i < pipes.lines.len() - 1
&& j == line.expressions.len() - 1
{
let next = pipes
.lines
.get(i + 1)
.expect("a pipeline is missing") .expressions
.get(0)
.expect("a pipeline has no expressions");
expressions.push(quote! {
let #next = #expr;
});
} else {
expressions.push(quote! {
let #PIPELINE_IDENT = #expr;
});
}
}
lines.push(TokenStream2::from_iter(expressions));
}
quote! {
{
#(#lines)*
}
}
.into()
}