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, StreamBuffer, StreamMemory},
        OutputReference, StreamReference,
    },
};
use std::fmt::Write;

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

pub(super) struct CloseFunction(pub(super) OutputReference);

impl FunctionDefinition for CloseFunction {
    fn header(&self, f: &SolidityFormatter) -> String {
        let parameter = f
            .stream_parameter(StreamReference::Out(self.0))
            .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(StreamReference::Out(self.0));
        let res = match self.0 {
            OutputReference::Unparameterized(_) => format!("{name}_spawned = false;"),
            OutputReference::Parameterized(_) => {
                let param_access = f.param_access(StreamReference::Out(self.0));

                let mut res = String::new();
                writeln!(res, "{name}_buffer{param_access}.{name}_spawned = false;").unwrap();
                if f.streams_with_iteration.contains(&self.0) {
                    writeln!(res, "for (uint i = 0; i < {name}_params.length; i++) {{").unwrap();
                    let condition = f
                        .stream_parameter(StreamReference::Out(self.0))
                        .unwrap()
                        .iter()
                        .map(|Parameter { name: pname, .. }| {
                            format!("{name}_params[i].{pname} == {pname}")
                        })
                        .join(" && ");
                    writeln!(res, "if ({condition}) {{").unwrap();
                    writeln!(res, "delete {name}_params[i];",).unwrap();
                    writeln!(res, "return;",).unwrap();
                    writeln!(res, "}}").unwrap();
                    writeln!(res, "}}").unwrap();
                }
                res
            }
        };
        format!("{}{res}", f.close_buffer(self.0.sr()))
    }

    fn key(&self) -> RequirementKey {
        RequirementKey::CloseFunction(StreamReference::Out(self.0))
    }

    fn name(&self, f: &SolidityFormatter) -> String {
        format!("close_{}", f.name(StreamReference::Out(self.0)))
    }
}

impl SolidityFormatter {
    fn close_buffer(&self, sr: StreamReference) -> String {
        match self.stream_memory(sr) {
            StreamMemory::NoMemory | StreamMemory::Static(_) => unreachable!(),
            StreamMemory::Dynamic {
                buffer,
                has_spawn: _,
                has_close: _,
            } => match buffer {
                StreamBuffer::SingleValue => format!("{}_valid = false;", self.name(sr)),
                StreamBuffer::Bounded(b) => {
                    format!(
                        "for (uint i = 0; i < {b}; i++) {{ {}_valid[i] = false; }}",
                        self.name(sr)
                    )
                }
                StreamBuffer::UnBounded => unimplemented!(),
            },
            StreamMemory::Instances { buffer, .. } => match buffer {
                StreamBuffer::SingleValue => format!(
                    "{name}_buffer{params}.{name}_valid = false; }}",
                    name = self.name(sr),
                    params = self.param_access(sr)
                ),
                StreamBuffer::Bounded(b) => {
                    format!(
                        "for (uint i = 0; i < {b}; i++) {{ {name}_buffer{params}.{name}_valid[i] = false; }}",
                        name=self.name(sr),
                        params=self.param_access(sr)
                    )
                }
                StreamBuffer::UnBounded => unimplemented!(),
            },
        }
    }
}