use std::fmt;
use self::stage::Stage;
use crate::{
common::{Span, Spanned},
pretty::{indent, Pretty},
schema::definable,
token,
};
pub mod stage;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Preamble {
pub span: Option<Span>,
pub function: definable::Function,
}
impl Preamble {
pub(crate) fn new(span: Option<Span>, function: definable::Function) -> Self {
Self { span, function }
}
}
impl Pretty for Preamble {
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
indent(indent_level, f)?;
writeln!(f, "{}", token::Clause::With)?;
Pretty::fmt(&self.function, indent_level + 1, f)?;
Ok(())
}
}
impl fmt::Display for Preamble {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}", token::Clause::With, &self.function)
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Pipeline {
pub span: Option<Span>,
pub preambles: Vec<Preamble>,
pub stages: Vec<Stage>,
}
impl Pipeline {
pub fn new(span: Option<Span>, preambles: Vec<Preamble>, stages: Vec<Stage>) -> Self {
Self { span, preambles, stages }
}
pub fn build() -> Self {
Self::new(None, Vec::new(), Vec::new())
}
pub fn then(mut self, stage: Stage) -> Self {
self.stages.push(stage);
self
}
}
impl Spanned for Pipeline {
fn span(&self) -> Option<Span> {
self.span
}
}
impl Pretty for Pipeline {
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for preamble in &self.preambles {
Pretty::fmt(preamble, indent_level, f)?;
writeln!(f)?;
}
if let Some((last, rest)) = self.stages.split_last() {
for stage in rest {
Pretty::fmt(stage, indent_level, f)?;
writeln!(f)?;
}
Pretty::fmt(last, indent_level, f)?;
}
Ok(())
}
}
impl fmt::Display for Pipeline {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
Pretty::fmt(self, 0, f)
} else {
for preamble in &self.preambles {
write!(f, "{} ", preamble)?;
}
if let Some((last, rest)) = self.stages.split_last() {
for stage in rest {
write!(f, "{} ", stage)?;
}
write!(f, "{}", last)?;
}
Ok(())
}
}
}