Skip to main content

elo_rust/codegen/
operators.rs

1//! Binary and unary operator code generation
2
3use proc_macro2::TokenStream;
4use quote::quote;
5
6/// Represents a binary operator
7///
8/// Supports all common comparison, arithmetic, and logical operators.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum BinaryOp {
11    /// Equality (==)
12    Equal,
13    /// Inequality (!=)
14    NotEqual,
15    /// Less than (<)
16    Less,
17    /// Less than or equal (<=)
18    LessEqual,
19    /// Greater than (>)
20    Greater,
21    /// Greater than or equal (>=)
22    GreaterEqual,
23    /// Logical AND (&&)
24    And,
25    /// Logical OR (||)
26    Or,
27    /// Addition (+)
28    Add,
29    /// Subtraction (-)
30    Subtract,
31    /// Multiplication (*)
32    Multiply,
33    /// Division (/)
34    Divide,
35    /// Modulo (%)
36    Modulo,
37}
38
39/// Represents a unary operator
40///
41/// Supports logical negation and numeric negation.
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub enum UnaryOp {
44    /// Logical NOT (!)
45    Not,
46    /// Negation (-)
47    Negate,
48}
49
50/// Generates code for operators
51///
52/// Provides methods for generating Rust code for binary and unary operations.
53#[derive(Debug, Clone)]
54pub struct OperatorGenerator;
55
56impl OperatorGenerator {
57    /// Create a new operator generator
58    pub fn new() -> Self {
59        Self
60    }
61
62    /// Generate code for a binary operation
63    ///
64    /// # Arguments
65    ///
66    /// * `op` - The operator to apply
67    /// * `left` - The left operand as a TokenStream
68    /// * `right` - The right operand as a TokenStream
69    ///
70    /// # Returns
71    ///
72    /// A `TokenStream` representing the binary operation
73    pub fn binary(&self, op: BinaryOp, left: TokenStream, right: TokenStream) -> TokenStream {
74        match op {
75            BinaryOp::Equal => quote! { #left == #right },
76            BinaryOp::NotEqual => quote! { #left != #right },
77            BinaryOp::Less => quote! { #left < #right },
78            BinaryOp::LessEqual => quote! { #left <= #right },
79            BinaryOp::Greater => quote! { #left > #right },
80            BinaryOp::GreaterEqual => quote! { #left >= #right },
81            BinaryOp::Add => quote! { #left + #right },
82            BinaryOp::Subtract => quote! { #left - #right },
83            BinaryOp::Multiply => quote! { #left * #right },
84            BinaryOp::Divide => quote! { #left / #right },
85            BinaryOp::Modulo => quote! { #left % #right },
86            BinaryOp::And => quote! { #left && #right },
87            BinaryOp::Or => quote! { #left || #right },
88        }
89    }
90
91    /// Generate code for a unary operation
92    ///
93    /// # Arguments
94    ///
95    /// * `op` - The unary operator to apply
96    /// * `operand` - The operand as a TokenStream
97    ///
98    /// # Returns
99    ///
100    /// A `TokenStream` representing the unary operation
101    pub fn unary(&self, op: UnaryOp, operand: TokenStream) -> TokenStream {
102        match op {
103            UnaryOp::Not => quote! { !#operand },
104            UnaryOp::Negate => quote! { -#operand },
105        }
106    }
107}
108
109impl Default for OperatorGenerator {
110    fn default() -> Self {
111        Self::new()
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_binary_op_equality() {
121        assert_eq!(BinaryOp::Equal, BinaryOp::Equal);
122        assert_ne!(BinaryOp::Equal, BinaryOp::NotEqual);
123    }
124
125    #[test]
126    fn test_binary_op_comparison() {
127        assert_ne!(BinaryOp::Less, BinaryOp::Greater);
128        assert_eq!(BinaryOp::LessEqual, BinaryOp::LessEqual);
129    }
130
131    #[test]
132    fn test_binary_op_logical() {
133        assert_eq!(BinaryOp::And, BinaryOp::And);
134        assert_ne!(BinaryOp::And, BinaryOp::Or);
135    }
136
137    #[test]
138    fn test_unary_op_not() {
139        assert_eq!(UnaryOp::Not, UnaryOp::Not);
140        assert_ne!(UnaryOp::Not, UnaryOp::Negate);
141    }
142
143    #[test]
144    fn test_operator_generator_creation() {
145        let _gen = OperatorGenerator::new();
146    }
147}