rtlola_streamir/
lib.rs

1//! A common library for bringing the RTLolaMir, the output of the Frontend, into the StreamIR representation.
2//! It offers functionality for optimizing the StreamIR through rewriting rules and a framework for formatting the StreamIR in a target language.
3
4#![forbid(unused_must_use)]
5#![warn(
6    missing_docs,
7    missing_debug_implementations,
8    missing_copy_implementations,
9    trivial_casts,
10    trivial_numeric_casts,
11    unsafe_code,
12    unstable_features,
13    unused_import_braces,
14    unused_qualifications
15)]
16
17use formatter::StreamIrFormatter;
18use ir::{LoweringError, StreamIr};
19use rewrite_rules::{
20    CombineIf, CombineIterate, CombineNestedIf, CombineSeq, FastGuards, ImpliedGuards,
21    IterateAssign, MemoryOptimizations, MoveIfOutside, RemoveClose, RemoveIfs, RemoveShift,
22    RemoveSkip, RewriteError, RewriteRule, Rewriter, SimplifyGuard,
23};
24use rewrite_rules::{MoveCommonGuardsOutside, RemoveSpawn};
25use rtlola_frontend::RtLolaError;
26pub use rtlola_frontend::{FrontendConfig, MemoryBoundMode, ParserConfigExt};
27pub use rtlola_frontend::{Handler, ParserConfig};
28use thiserror::Error;
29
30pub mod formatter;
31pub mod ir;
32pub mod rewrite_rules;
33
34#[derive(Clone, Debug, Error)]
35/// An error that can happen when parsing a specification into the StreamIR
36pub enum ParseError {
37    #[error("Parser error: {0}")]
38    /// The error happened when parsing the specification into the MIR
39    FrontendError(#[from] RtLolaError),
40    #[error("Lowering error: {0}")]
41    /// The error happened when lowering the MIR into the StreamIR
42    LoweringError(#[from] LoweringError),
43}
44
45/// Parse a specification directly into the StreamIR representation.
46///
47/// See the RTLola Frontend on more details about the `config` argument.
48/// The resulting StreamIR does not have any optimizations applied.
49pub fn parse<'a>(config: impl Into<FrontendConfig<'a>>) -> Result<StreamIr, ParseError> {
50    let mir = rtlola_frontend::parse(config)?;
51    let streamir: StreamIr = mir.try_into()?;
52    Ok(optimize(streamir, vec![Box::new(RemoveSkip)]).unwrap())
53}
54
55/// Applies all general optimizations to the given StreamIR.
56pub fn optimize_all(ir: StreamIr) -> Result<StreamIr, RewriteError> {
57    let ir = optimize(
58        ir,
59        vec![
60            Box::new(CombineIf),
61            Box::new(SimplifyGuard),
62            Box::new(MoveCommonGuardsOutside),
63            Box::new(ImpliedGuards),
64            Box::new(SimplifyGuard),
65            Box::new(RemoveIfs),
66            Box::new(CombineSeq),
67            Box::new(MoveIfOutside),
68            Box::new(IterateAssign),
69            Box::new(CombineNestedIf),
70            Box::new(CombineIterate),
71            Box::new(RemoveIfs),
72            Box::new(RemoveShift),
73            Box::new(MemoryOptimizations),
74            Box::new(RemoveSpawn),
75            Box::new(RemoveClose),
76        ],
77    )?;
78    optimize(ir, vec![Box::new(FastGuards)])
79}
80
81/// Applies a given list of rewriting rules to the StreamIR.
82pub fn optimize(ir: StreamIr, rules: Vec<Box<dyn RewriteRule>>) -> Result<StreamIr, RewriteError> {
83    let rewriter = Rewriter::new(rules);
84    rewriter.run(ir)
85}
86
87/// Uses the given formatter for translating the StreamIR to the target language.
88pub fn translate<F: StreamIrFormatter>(ir: StreamIr, f: F) -> F::Return {
89    f.format(ir)
90}