rtlola2solidity 0.1.0

A compiler from RTLola to Solidity through StreamIR
Documentation
use itertools::Itertools;
use rtlola_streamir::{
    formatter::types::TypeFormatter,
    ir::{memory::Parameter, OutputReference},
};
use std::fmt::Write;

use crate::{functions::FunctionDefinition, RequirementKey, SolidityFormatter};

pub(super) struct SpawnFunction {
    pub(super) sr: OutputReference,
}

impl FunctionDefinition for SpawnFunction {
    fn header(&self, f: &SolidityFormatter) -> String {
        let parameter = f
            .stream_parameter(rtlola_streamir::ir::StreamReference::Out(self.sr))
            .map(|p| {
                p.iter()
                    .map(|Parameter { name, ty }| format!("{} {name}", f.ty(ty.clone())))
                    .join(",")
            })
            .unwrap_or_default();
        format!("{}({parameter})", self.name(f))
    }

    fn body(self, f: &SolidityFormatter) -> String {
        let name = f.name(rtlola_streamir::ir::StreamReference::Out(self.sr));
        match self.sr {
            OutputReference::Unparameterized(_) => format!("{name}_spawned = true;"),
            OutputReference::Parameterized(_) => {
                let param_access =
                    f.param_access(rtlola_streamir::ir::StreamReference::Out(self.sr));

                let mut res = String::new();
                if f.streams_with_iteration.contains(&self.sr) {
                    writeln!(res, "if (!{name}_buffer{param_access}.{name}_spawned) {{").unwrap();
                    let p = &format!(
                        "{name}Param({{ {} }})",
                        f.stream_parameter(rtlola_streamir::ir::StreamReference::Out(self.sr))
                            .unwrap()
                            .iter()
                            .map(|Parameter { name, .. }| format!("{name}: {name}"))
                            .join(",")
                    );
                    writeln!(res, "{name}_params.push({p});",).unwrap();
                    writeln!(res, "}}").unwrap();
                }
                writeln!(res, "{name}_buffer{param_access}.{name}_spawned = true;").unwrap();
                res
            }
        }
    }

    fn key(&self) -> RequirementKey {
        RequirementKey::SpawnFunction(rtlola_streamir::ir::StreamReference::Out(self.sr))
    }

    fn name(&self, f: &SolidityFormatter) -> String {
        format!(
            "spawn_{}",
            f.name(rtlola_streamir::ir::StreamReference::Out(self.sr))
        )
    }
}