palladium/optimizer/
simplify.rs1use crate::ast::*;
7use crate::errors::{CompileError, Span};
8use crate::optimizer::OptimizationPass;
9
10pub struct SimplificationPass {
11 changes_made: usize,
12}
13
14impl Default for SimplificationPass {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl SimplificationPass {
21 pub fn new() -> Self {
22 Self { changes_made: 0 }
23 }
24}
25
26impl OptimizationPass for SimplificationPass {
27 fn name(&self) -> &str {
28 "Expression Simplification"
29 }
30
31 fn optimize_program(&mut self, program: &mut Program) -> Result<bool, CompileError> {
32 self.changes_made = 0;
33
34 for item in &mut program.items {
35 if let Item::Function(func) = item {
36 self.optimize_function(func)?;
37 }
38 }
39
40 Ok(self.changes_made > 0)
41 }
42
43 fn optimize_statement(&mut self, stmt: &mut Stmt) -> Result<bool, CompileError> {
44 match stmt {
45 Stmt::Let { value, .. } => {
46 self.optimize_expression(value)?;
47 }
48 Stmt::Expr(expr) => {
49 self.optimize_expression(expr)?;
50 }
51 Stmt::If {
52 condition,
53 then_branch,
54 else_branch,
55 ..
56 } => {
57 self.optimize_expression(condition)?;
58
59 for stmt in then_branch {
60 self.optimize_statement(stmt)?;
61 }
62
63 if let Some(else_branch) = else_branch {
64 for stmt in else_branch {
65 self.optimize_statement(stmt)?;
66 }
67 }
68 }
69 Stmt::While {
70 condition, body, ..
71 } => {
72 self.optimize_expression(condition)?;
73
74 for stmt in body {
75 self.optimize_statement(stmt)?;
76 }
77 }
78 Stmt::Return(Some(expr)) => {
79 self.optimize_expression(expr)?;
80 }
81 Stmt::Return(None) => {}
82 Stmt::Assign { value, .. } => {
83 self.optimize_expression(value)?;
84 }
85 _ => {}
86 }
87
88 Ok(false)
89 }
90
91 fn optimize_expression(&mut self, expr: &mut Expr) -> Result<bool, CompileError> {
92 match expr {
93 Expr::Binary {
94 left, op, right, ..
95 } => {
96 self.optimize_expression(left)?;
98 self.optimize_expression(right)?;
99
100 match (left.as_ref(), *op, right.as_ref()) {
102 (_, BinOp::Eq, Expr::Bool(true)) => {
104 *expr = left.as_ref().clone();
105 self.changes_made += 1;
106 return Ok(true);
107 }
108 (Expr::Bool(true), BinOp::Eq, _) => {
110 *expr = right.as_ref().clone();
111 self.changes_made += 1;
112 return Ok(true);
113 }
114 (_, BinOp::Eq, Expr::Bool(false)) => {
116 *expr = Expr::Unary {
117 op: UnaryOp::Not,
118 operand: left.clone(),
119 span: Span::dummy(),
120 };
121 self.changes_made += 1;
122 return Ok(true);
123 }
124 (Expr::Bool(false), BinOp::Eq, _) => {
126 *expr = Expr::Unary {
127 op: UnaryOp::Not,
128 operand: right.clone(),
129 span: Span::dummy(),
130 };
131 self.changes_made += 1;
132 return Ok(true);
133 }
134 (_, BinOp::Ne, Expr::Bool(false)) => {
136 *expr = left.as_ref().clone();
137 self.changes_made += 1;
138 return Ok(true);
139 }
140 (Expr::Bool(false), BinOp::Ne, _) => {
142 *expr = right.as_ref().clone();
143 self.changes_made += 1;
144 return Ok(true);
145 }
146 (_, BinOp::Ne, Expr::Bool(true)) => {
148 *expr = Expr::Unary {
149 op: UnaryOp::Not,
150 operand: left.clone(),
151 span: Span::dummy(),
152 };
153 self.changes_made += 1;
154 return Ok(true);
155 }
156 (Expr::Bool(true), BinOp::Ne, _) => {
158 *expr = Expr::Unary {
159 op: UnaryOp::Not,
160 operand: right.clone(),
161 span: Span::dummy(),
162 };
163 self.changes_made += 1;
164 return Ok(true);
165 }
166 _ => {}
167 }
168
169 match (left.as_ref(), *op, right.as_ref()) {
171 (
173 Expr::Unary {
174 op: UnaryOp::Not,
175 operand,
176 ..
177 },
178 BinOp::Eq,
179 _,
180 ) => {
181 if let Expr::Binary {
182 left: l,
183 op: BinOp::Eq,
184 right: r,
185 ..
186 } = operand.as_ref()
187 {
188 *expr = Expr::Binary {
189 left: l.clone(),
190 op: BinOp::Ne,
191 right: r.clone(),
192 span: Span::dummy(),
193 };
194 self.changes_made += 1;
195 return Ok(true);
196 }
197 }
198 _ => {}
199 }
200 }
201 Expr::Unary { op, operand, .. } => {
202 self.optimize_expression(operand)?;
203
204 if let UnaryOp::Not = op {
206 if let Expr::Unary {
207 op: UnaryOp::Not,
208 operand: inner,
209 ..
210 } = operand.as_ref()
211 {
212 *expr = inner.as_ref().clone();
213 self.changes_made += 1;
214 return Ok(true);
215 }
216 }
217 }
218 Expr::Call { args, .. } => {
219 for arg in args {
220 self.optimize_expression(arg)?;
221 }
222 }
223 Expr::Index { array, index, .. } => {
224 self.optimize_expression(array)?;
225 self.optimize_expression(index)?;
226 }
227 Expr::FieldAccess { object, .. } => {
228 self.optimize_expression(object)?;
229 }
230 Expr::ArrayLiteral { elements, .. } => {
231 for elem in elements {
232 self.optimize_expression(elem)?;
233 }
234 }
235 _ => {}
236 }
237
238 Ok(false)
239 }
240}