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