use rtlola_reporting::{Diagnostic, RtLolaError};
use super::{builder::Builder, ChangeSet, SynSugar};
use crate::ast::{EvalSpec, Mirror as AstMirror, Output, OutputKind, RtLolaAst};
#[derive(Debug, Clone)]
pub(crate) struct Mirror {}
impl Mirror {
fn apply<'a>(
&self,
stream: &'a AstMirror,
ast: &'a RtLolaAst,
) -> Result<ChangeSet, RtLolaError> {
let AstMirror {
name,
target,
filter,
span: _,
id: mirror_id,
} = stream.clone();
let Some(target) = ast
.outputs
.iter()
.find(|o| o.name().is_some_and(|name| name.name == target.name))
else {
return Err(Diagnostic::error(
"Mirror stream refers to a stream name that does not exist.",
)
.add_span_with_label(
target.span,
Some("Found non-existing stream name here."),
true,
)
.into());
};
let Output {
kind: _,
annotated_type,
params,
spawn,
eval,
close,
tags,
id,
span,
} = target.next_id(ast);
let eval = eval
.into_iter()
.map(|e| {
let EvalSpec {
annotated_pacing,
condition,
eval_expression,
id: _,
span,
} = e;
let builder = Builder::new(span, ast);
let condition = match condition {
Some(condition) => builder.and(condition, filter.next_id(ast)),
None => filter.next_id(ast),
};
builder.eval_spec(Some(condition), annotated_pacing, eval_expression)
})
.collect();
let output = Output {
kind: OutputKind::NamedOutput(name),
eval,
id,
span,
annotated_type,
params,
spawn,
close,
tags,
};
Ok(ChangeSet::replace_stream(mirror_id, output))
}
}
impl SynSugar for Mirror {
fn desugarize_stream_mirror<'a>(
&self,
stream: &'a AstMirror,
ast: &'a RtLolaAst,
) -> Result<ChangeSet, RtLolaError> {
self.apply(stream, ast)
}
}