Skip to main content

etdl_compiler/codegen/
mod.rs

1use etdl_parser::ast::EtlDocument;
2use etdl_parser::asyncapi::AsyncApiRegistry;
3use std::collections::BTreeMap;
4
5use crate::validate::Diagnostic;
6
7mod rust;
8pub use rust::RustCodeGenerator;
9
10/// One file a target generator produces. `relative_path` is relative to the
11/// `--out-dir` the CLI was given — a single-file target (Rust) returns one
12/// entry named from `stem` (e.g. `"order-fulfillment.rs"`); a target whose
13/// ecosystem expects a package/directory layout (Java, Go, ...) returns
14/// several, with `relative_path` encoding that structure (e.g.
15/// `"com/example/OrderFulfillment.java"`). The registry-facing side (the
16/// CLI) never special-cases *how many* files a target produces — it just
17/// writes whatever list comes back, creating parent directories as needed.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct GeneratedFile {
20    pub relative_path: String,
21    pub contents: String,
22}
23
24impl GeneratedFile {
25    pub fn new(relative_path: impl Into<String>, contents: impl Into<String>) -> Self {
26        GeneratedFile {
27            relative_path: relative_path.into(),
28            contents: contents.into(),
29        }
30    }
31}
32
33/// A pluggable code-generation backend (spec-neutral term: "target"). Every
34/// target consumes the *same* validated `EtlDocument` + resolved fault-tree
35/// probabilities + AsyncAPI registry — parsing, semantic validation, and
36/// fault-tree evaluation happen exactly once, upstream of this trait, in
37/// [`crate::Compiler`]; a target implementation only turns that already-
38/// resolved representation into target-language source text. Nothing here
39/// re-parses `.etdl`, re-validates ECEL conditions, or re-evaluates fault
40/// trees — see `docs/architecture/targets.md`.
41pub trait CodeGenerator {
42    /// Short, stable identifier used on the CLI (`--target <name>`) and in
43    /// the target registry (`etdl-cli`'s `TargetRegistry`). Lowercase,
44    /// matches the `--target` value exactly (e.g. `"rust"`, `"java"`).
45    fn target_name(&self) -> &'static str;
46
47    /// Generate this target's output for `doc`. `stem` is the input
48    /// document's filename without extension (what today's Rust target
49    /// already names its single output file after); other targets may use
50    /// it as a package/module root name instead of a literal filename.
51    fn generate_all(
52        &self,
53        doc: &EtlDocument,
54        fault_tree_probs: &BTreeMap<String, f64>,
55        registry: &AsyncApiRegistry,
56        stem: &str,
57        diagnostics: &mut Vec<Diagnostic>,
58    ) -> Result<Vec<GeneratedFile>, String>;
59}