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}