use etdl_parser::ast::EtlDocument;
use etdl_parser::asyncapi::AsyncApiRegistry;
pub mod codegen;
pub mod fault_tree;
mod typeck;
pub mod validate;
pub use codegen::{CodeGenerator, RustCodeGenerator};
pub use validate::Diagnostic;
pub struct Compiler {
pub rust_codegen: RustCodeGenerator,
}
#[derive(Debug, Clone)]
pub struct CompilationResult {
pub diagnostics: Vec<Diagnostic>,
pub rust_output: Option<String>,
}
impl Compiler {
pub fn new() -> Self {
Compiler {
rust_codegen: RustCodeGenerator::new(),
}
}
pub fn validate(
&self,
doc: &EtlDocument,
asyncapi_registry: &AsyncApiRegistry,
) -> Vec<Diagnostic> {
let mut diagnostics = Vec::new();
validate::validate_document(doc, asyncapi_registry, &mut diagnostics);
if diagnostics.iter().any(|d| d.is_error()) {
return diagnostics;
}
let fault_tree_probs = fault_tree::resolve_fault_trees(doc, &mut diagnostics);
let resolved_probabilities =
validate::resolve_probability_links(doc, &fault_tree_probs, &mut diagnostics);
validate::validate_probability_sums(doc, &resolved_probabilities, &mut diagnostics);
if diagnostics.iter().any(|d| d.is_error()) {
return diagnostics;
}
typeck::type_check_conditions(doc, asyncapi_registry, &mut diagnostics);
diagnostics
}
pub fn compile(
&self,
doc: &EtlDocument,
asyncapi_registry: &AsyncApiRegistry,
) -> CompilationResult {
let mut diagnostics = self.validate(doc, asyncapi_registry);
let has_errors = diagnostics.iter().any(|d| d.is_error());
if has_errors {
return CompilationResult {
diagnostics,
rust_output: None,
};
}
let fault_tree_probs = fault_tree::resolve_fault_trees(doc, &mut Vec::new());
let mut rust_output = String::new();
let gen_result = self
.rust_codegen
.generate_all(doc, &fault_tree_probs, &asyncapi_registry, &mut diagnostics);
if gen_result.is_ok() {
rust_output = gen_result.unwrap();
}
CompilationResult {
diagnostics,
rust_output: if rust_output.is_empty() {
None
} else {
Some(rust_output)
},
}
}
}
impl Default for Compiler {
fn default() -> Self {
Self::new()
}
}