Skip to main content

vexil_lang/
codegen.rs

1//! # Stability: Tier 1
2//!
3//! Codegen backend trait and shared error type. Implement [`CodegenBackend`]
4//! to add a new code-generation target to `vexilc`.
5
6/// Typed, target-independent projection of portable trait-function bodies.
7pub mod portable;
8
9use std::collections::BTreeMap;
10use std::path::PathBuf;
11
12use crate::ir::CompiledSchema;
13use crate::project::ProjectResult;
14
15/// A pluggable code-generation backend.
16///
17/// Each backend translates compiled Vexil schemas into source code for a
18/// specific target language.  Implement this trait to add support for a new
19/// language.
20///
21/// Backends are used in two modes:
22/// - **Single-file** via [`generate`](CodegenBackend::generate) — for REPL,
23///   quick checks, or single-schema compilation.
24/// - **Project-level** via [`generate_project`](CodegenBackend::generate_project)
25///   — for multi-file projects.  The backend owns cross-file import strategy
26///   and output file layout.
27pub trait CodegenBackend {
28    /// Backend identifier, e.g. `"rust"`, `"typescript"`.
29    fn name(&self) -> &str;
30
31    /// File extension for generated files, e.g. `"rs"`, `"ts"`.
32    fn file_extension(&self) -> &str;
33
34    /// Generate code for a single compiled schema.
35    fn generate(&self, compiled: &CompiledSchema) -> Result<String, CodegenError>;
36
37    /// Generate all files for a multi-file project.
38    ///
39    /// Returns a map from relative output path to file content.
40    /// The backend is responsible for cross-file import statements and
41    /// module-scaffolding files (e.g. `mod.rs`, `index.ts`).
42    fn generate_project(
43        &self,
44        result: &ProjectResult,
45    ) -> Result<BTreeMap<PathBuf, String>, CodegenError>;
46}
47
48/// Errors that can occur during code generation.
49#[derive(Debug, thiserror::Error)]
50pub enum CodegenError {
51    /// The backend does not support a type used in the schema.
52    #[error("unsupported type `{type_name}` in {backend} backend")]
53    UnsupportedType {
54        /// Name of the unsupported type.
55        type_name: String,
56        /// Backend that encountered the error.
57        backend: String,
58    },
59
60    /// A required annotation is missing from the schema.
61    #[error("missing required annotation `{annotation}` ({context})")]
62    MissingAnnotation {
63        /// The annotation that was expected.
64        annotation: String,
65        /// Where it was expected.
66        context: String,
67    },
68
69    /// An I/O error occurred during code generation.
70    #[error("I/O error: {0}")]
71    Io(#[from] std::io::Error),
72
73    /// A backend-specific error not covered by the common variants.
74    #[error("backend error: {0}")]
75    BackendSpecific(Box<dyn std::error::Error + Send + Sync>),
76}