1use etdl_parser::ast::EtlDocument;
37use etdl_parser::asyncapi::AsyncApiRegistry;
38
39pub mod codegen;
40pub mod fault_tree;
41mod typeck;
42pub mod validate;
43
44pub use codegen::{CodeGenerator, RustCodeGenerator};
45pub use validate::Diagnostic;
46
47pub struct Compiler {
48 pub rust_codegen: RustCodeGenerator,
49}
50
51#[derive(Debug, Clone)]
52pub struct CompilationResult {
53 pub diagnostics: Vec<Diagnostic>,
54 pub rust_output: Option<String>,
55}
56
57impl Compiler {
58 pub fn new() -> Self {
59 Compiler {
60 rust_codegen: RustCodeGenerator::new(),
61 }
62 }
63
64 pub fn validate(
68 &self,
69 doc: &EtlDocument,
70 asyncapi_registry: &AsyncApiRegistry,
71 ) -> Vec<Diagnostic> {
72 let mut diagnostics = Vec::new();
73
74 validate::validate_document(doc, asyncapi_registry, &mut diagnostics);
75
76 if diagnostics.iter().any(|d| d.is_error()) {
77 return diagnostics;
78 }
79
80 let fault_tree_probs = fault_tree::resolve_fault_trees(doc, &mut diagnostics);
81 let resolved_probabilities =
82 validate::resolve_probability_links(doc, &fault_tree_probs, &mut diagnostics);
83
84 validate::validate_probability_sums(doc, &resolved_probabilities, &mut diagnostics);
85
86 if diagnostics.iter().any(|d| d.is_error()) {
87 return diagnostics;
88 }
89
90 typeck::type_check_conditions(doc, asyncapi_registry, &mut diagnostics);
91
92 diagnostics
93 }
94
95 pub fn compile(
96 &self,
97 doc: &EtlDocument,
98 asyncapi_registry: &AsyncApiRegistry,
99 ) -> CompilationResult {
100 let mut diagnostics = self.validate(doc, asyncapi_registry);
101
102 let has_errors = diagnostics.iter().any(|d| d.is_error());
103 if has_errors {
104 return CompilationResult {
105 diagnostics,
106 rust_output: None,
107 };
108 }
109
110 let fault_tree_probs = fault_tree::resolve_fault_trees(doc, &mut Vec::new());
111
112 let mut rust_output = String::new();
113 let gen_result = self
114 .rust_codegen
115 .generate_all(doc, &fault_tree_probs, &asyncapi_registry, &mut diagnostics);
116
117 if gen_result.is_ok() {
118 rust_output = gen_result.unwrap();
119 }
120
121 CompilationResult {
122 diagnostics,
123 rust_output: if rust_output.is_empty() {
124 None
125 } else {
126 Some(rust_output)
127 },
128 }
129 }
130}
131
132impl Default for Compiler {
133 fn default() -> Self {
134 Self::new()
135 }
136}