Skip to main content

elo_rust/codegen/
mod.rs

1//! Code generation module for compiling ELO expressions to Rust
2//!
3//! This module provides the core code generation engine that transforms ELO AST
4//! into idiomatic Rust code via the `quote!` macro.
5
6pub mod ast_to_code;
7pub mod errors;
8pub mod expressions;
9pub mod functions;
10pub mod operators;
11pub mod optimization;
12pub mod temporal;
13pub mod type_inference;
14pub mod types;
15
16pub use errors::CodeGenError;
17pub use operators::{BinaryOp, OperatorGenerator, UnaryOp};
18
19use crate::ast::visitor::Visitor;
20use proc_macro2::TokenStream;
21use quote::quote;
22
23pub use types::TypeContext;
24
25/// Main code generator for transforming ELO AST to Rust code
26///
27/// Provides methods for generating Rust code from ELO expressions,
28/// including literal values, field access, operators, and more.
29///
30/// # Example
31///
32/// ```no_run
33/// use elo_rust::RustCodeGenerator;
34///
35/// let generator = RustCodeGenerator::new();
36/// let int_literal = generator.generate_literal_integer(42).unwrap();
37/// ```
38#[derive(Debug, Clone)]
39pub struct RustCodeGenerator {
40    /// Type context for resolving custom types
41    type_context: TypeContext,
42}
43
44impl RustCodeGenerator {
45    /// Create a new code generator instance with empty type context
46    pub fn new() -> Self {
47        Self {
48            type_context: TypeContext::new(),
49        }
50    }
51
52    /// Create a new code generator with a populated type context
53    ///
54    /// # Arguments
55    ///
56    /// * `type_context` - Pre-configured type context with custom types
57    pub fn with_context(type_context: TypeContext) -> Self {
58        Self { type_context }
59    }
60
61    /// Check if the generator is in a valid state
62    pub fn is_valid(&self) -> bool {
63        true
64    }
65
66    /// Check if a type is registered in the context
67    pub fn has_type(&self, type_name: &str) -> bool {
68        self.type_context
69            .list_all_type_names()
70            .iter()
71            .any(|n| n == type_name)
72    }
73
74    /// Get the type of a field in a registered type
75    pub fn get_field_type(&self, type_name: &str, field_name: &str) -> Option<&types::RustType> {
76        self.type_context.get_field_type(type_name, field_name)
77    }
78
79    /// Generate function signature for a validator
80    ///
81    /// # Arguments
82    ///
83    /// * `name` - The name of the validation function
84    /// * `input_type` - The type being validated
85    ///
86    /// # Returns
87    ///
88    /// A `TokenStream` representing the function signature
89    pub fn generate_function_signature(
90        &self,
91        name: &str,
92        input_type: &str,
93    ) -> Result<TokenStream, String> {
94        let fn_name = quote::format_ident!("{}", name);
95        let input_ident = quote::format_ident!("{}", input_type);
96
97        Ok(quote! {
98            pub fn #fn_name(input: &#input_ident) -> Result<(), Vec<String>>
99        })
100    }
101
102    /// Generate code for an integer literal
103    pub fn generate_literal_integer(&self, value: i64) -> Result<TokenStream, String> {
104        Ok(quote! {
105            #value
106        })
107    }
108
109    /// Generate code for a string literal
110    pub fn generate_literal_string(&self, value: &str) -> Result<TokenStream, String> {
111        Ok(quote! {
112            #value
113        })
114    }
115
116    /// Generate code for a boolean literal
117    pub fn generate_literal_bool(&self, value: bool) -> Result<TokenStream, String> {
118        Ok(quote! {
119            #value
120        })
121    }
122
123    /// Generate code for field access (e.g., user.age)
124    ///
125    /// This generates the Rust code for accessing a field on a value.
126    /// The receiver should be a valid Rust identifier (e.g., "user", "input").
127    ///
128    /// # Arguments
129    ///
130    /// * `receiver` - The expression being accessed (e.g., "user")
131    /// * `field` - The field name (e.g., "age")
132    ///
133    /// # Returns
134    ///
135    /// A `TokenStream` representing `receiver.field`
136    ///
137    /// # Example
138    ///
139    /// ```ignore
140    /// let gen = RustCodeGenerator::new();
141    /// let tokens = gen.generate_field_access("user", "age")?;
142    /// // Generates: user.age
143    /// ```
144    pub fn generate_field_access(
145        &self,
146        receiver: &str,
147        field: &str,
148    ) -> Result<TokenStream, String> {
149        let receiver_ident = quote::format_ident!("{}", receiver);
150        let field_ident = quote::format_ident!("{}", field);
151
152        Ok(quote! {
153            #receiver_ident.#field_ident
154        })
155    }
156
157    /// Generate a single-line comment
158    ///
159    /// Note: Comments are handled at the token manipulation level, not in token streams.
160    /// This method is provided for future extensibility.
161    pub fn generate_comment(&self, _text: &str) -> Result<TokenStream, String> {
162        // Comments are handled at the token level
163        // For now, just return empty - comments will be added via token manipulation
164        Ok(quote! {})
165    }
166
167    /// Generate a documentation comment
168    ///
169    /// Note: Doc comments are handled at the token manipulation level, not in token streams.
170    /// This method is provided for future extensibility.
171    pub fn generate_doc_comment(&self, _text: &str) -> Result<TokenStream, String> {
172        // Doc comments are handled at the token level
173        // For now, just return empty - doc comments will be added via token manipulation
174        Ok(quote! {})
175    }
176
177    /// Generate a complete validator function from an ELO expression
178    ///
179    /// # Arguments
180    ///
181    /// * `name` - The name of the validator function
182    /// * `elo_expr` - The ELO validation expression
183    /// * `input_type` - The type being validated
184    ///
185    /// # Returns
186    ///
187    /// A `TokenStream` representing the complete validator function
188    pub fn generate_validator(
189        &self,
190        name: &str,
191        elo_expr: &str,
192        input_type: &str,
193    ) -> Result<TokenStream, String> {
194        // Parse the ELO expression
195        let ast =
196            crate::parser::Parser::parse(elo_expr).map_err(|e| format!("Parse error: {}", e))?;
197
198        // Generate code via visitor
199        let mut visitor = ast_to_code::CodegenVisitor::new();
200        let validation_code = visitor.visit_expr(&ast);
201
202        // Wrap in function
203        let fn_name = quote::format_ident!("{}", name);
204        let input_ident = quote::format_ident!("{}", input_type);
205
206        Ok(quote! {
207            pub fn #fn_name(input: &#input_ident) -> Result<(), Vec<String>> {
208                let result = #validation_code;
209                if result {
210                    Ok(())
211                } else {
212                    Err(vec!["Validation failed".to_string()])
213                }
214            }
215        })
216    }
217
218    /// Generate validator implementation for a type
219    ///
220    /// # Arguments
221    ///
222    /// * `struct_name` - The name of the struct implementing the validator
223    /// * `validator_fn_name` - The name of the validation function
224    /// * `input_type` - The type being validated
225    ///
226    /// # Returns
227    ///
228    /// A `TokenStream` representing the impl block
229    pub fn generate_validator_impl(
230        &self,
231        struct_name: &str,
232        validator_fn_name: &str,
233        input_type: &str,
234    ) -> Result<TokenStream, String> {
235        let struct_ident = quote::format_ident!("{}", struct_name);
236        let fn_ident = quote::format_ident!("{}", validator_fn_name);
237        let input_ident = quote::format_ident!("{}", input_type);
238
239        Ok(quote! {
240            impl #struct_ident {
241                pub fn #fn_ident(input: &#input_ident) -> Result<(), Vec<String>> {
242                    Ok(())
243                }
244            }
245        })
246    }
247}
248
249impl Default for RustCodeGenerator {
250    fn default() -> Self {
251        Self::new()
252    }
253}