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}