hexput_ast_api/
optimizer.rs

1use crate::ast_structs::{Block, Expression, Program, Property, Statement};
2use crate::parallel;
3use tokio::runtime::Runtime;
4
5const PARALLELISM_THRESHOLD: usize = 2; 
6
7pub fn optimize_ast(program: Program, runtime: &Runtime) -> Program {
8    
9    let optimized_statements = if program.statements.len() > PARALLELISM_THRESHOLD {
10        parallel::process_items_sync(runtime, program.statements, |stmt, rt| {
11            optimize_statement(stmt, rt)
12        })
13            .into_iter()
14            .filter_map(|s| s)
15            .collect()
16    } else {
17        optimize_statements(program.statements, runtime)
18    };
19    
20    
21    let optimized = Program::new(optimized_statements, program.location);
22  
23    optimized
24}
25
26fn optimize_statements(statements: Vec<Statement>, runtime: &Runtime) -> Vec<Statement> {
27    let mut optimized = Vec::new();
28    
29    for statement in statements {
30        match optimize_statement(statement, runtime) {
31            Some(stmt) => optimized.push(stmt),
32            None => {} 
33        }
34    }
35    
36    optimized
37}
38
39fn optimize_statement(statement: Statement, runtime: &Runtime) -> Option<Statement> {
40    match statement {
41        Statement::Block { block, location } => {
42            
43            let optimized_block = optimize_block(block, runtime);
44            
45            
46            if optimized_block.statements.is_empty() {
47                return None;
48            }
49            
50            
51            
52            if optimized_block.statements.len() == 1 {
53                match &optimized_block.statements[0] {
54                    Statement::Block { .. } => {},
55                    _ => return Some(optimized_block.statements.into_iter().next().unwrap())
56                }
57            }
58            
59            Some(Statement::Block { block: optimized_block, location })
60        },
61        Statement::IfStatement { condition, body, else_body, location } => {
62            
63            let optimized_condition = optimize_expression(condition, runtime);
64            
65            
66            let optimized_body = optimize_block(body, runtime);
67            
68            
69            let optimized_else_body = else_body.map(|body| optimize_block(body, runtime));
70            
71            
72            if optimized_body.statements.is_empty() && 
73               optimized_else_body.as_ref().map_or(true, |b| b.statements.is_empty()) {
74                return None;
75            }
76            
77            Some(Statement::IfStatement { 
78                condition: optimized_condition, 
79                body: optimized_body,
80                else_body: optimized_else_body,
81                location
82            })
83        },
84        Statement::ExpressionStatement { expression, location } => {
85            let optimized_expr = optimize_expression(expression, runtime);
86            
87            Some(Statement::ExpressionStatement { expression: optimized_expr, location })
88        },
89        Statement::CallbackDeclaration { name, params, body, location } => {
90            
91            let optimized_body = optimize_block(body, runtime);
92            
93            Some(Statement::CallbackDeclaration {
94                name,
95                params,
96                body: optimized_body,
97                location,
98            })
99        },
100        Statement::ReturnStatement { value, location } => {
101            
102            let optimized_value = optimize_expression(value, runtime);
103            
104            
105            Some(Statement::ReturnStatement { value: optimized_value, location })
106        },
107        Statement::LoopStatement { variable, iterable, body, location } => {
108            
109            let optimized_iterable = optimize_expression(iterable, runtime);
110            
111            
112            let optimized_body = optimize_block(body, runtime);
113            
114            
115            if optimized_body.statements.is_empty() {
116                return None;
117            }
118            
119            Some(Statement::LoopStatement {
120                variable,
121                iterable: optimized_iterable,
122                body: optimized_body,
123                location,
124            })
125        },
126        
127        Statement::EndStatement { location } => Some(Statement::EndStatement { location }),
128        Statement::ContinueStatement { location } => Some(Statement::ContinueStatement { location }),
129        
130        
131        Statement::VariableDeclaration { name, value, location } => {
132            let optimized_value = optimize_expression(value, runtime);
133            Some(Statement::VariableDeclaration { name, value: optimized_value, location })
134        }
135    }
136}
137
138fn optimize_block(block: Block, runtime: &Runtime) -> Block {
139    
140    let statements = if block.statements.len() > PARALLELISM_THRESHOLD {
141        parallel::process_items_sync(runtime, block.statements, |stmt, rt| optimize_statement(stmt, rt))
142            .into_iter()
143            .filter_map(|s| s)
144            .collect()
145    } else {
146        optimize_statements(block.statements, runtime)
147    };
148    
149    
150    let mut flattened = Vec::new();
151    for stmt in statements {
152        match stmt {
153            
154            Statement::Block { block: inner_block, .. } => {
155                flattened.extend(inner_block.statements);
156            },
157            _ => flattened.push(stmt)
158        }
159    }
160    
161    Block::new(flattened, block.location)
162}
163
164
165fn optimize_expression(expr: Expression, runtime: &Runtime) -> Expression {
166    match expr {
167        Expression::BinaryExpression { left, operator, right, location } => {
168            
169            let optimized_left = optimize_expression(*left, runtime);
170            let optimized_right = optimize_expression(*right, runtime);
171            let result = Expression::BinaryExpression {
172                left: Box::new(optimized_left),
173                operator,
174                right: Box::new(optimized_right),
175                location,
176            };
177            result
178        },
179        Expression::AssignmentExpression { target, value, location } => {
180            let optimized_value = Box::new(optimize_expression(*value, runtime));
181            let result = Expression::AssignmentExpression { target, value: optimized_value, location };
182            result
183        },
184        Expression::MemberAssignmentExpression { object, property, property_expr, computed, value, location } => {
185            
186            let optimized_object = Box::new(optimize_expression(*object, runtime));
187            
188            
189            let optimized_prop_expr = match property_expr {
190                Some(expr) => Some(Box::new(optimize_expression(*expr, runtime))),
191                None => None,
192            };
193            
194            let optimized_value = Box::new(optimize_expression(*value, runtime));
195            let result = Expression::MemberAssignmentExpression {
196                object: optimized_object,
197                property,
198                property_expr: optimized_prop_expr,
199                computed,
200                value: optimized_value,
201                location,
202            };
203            result
204        },
205        Expression::CallExpression { callee, arguments, location } => {
206            
207            let optimized_args = if arguments.len() > PARALLELISM_THRESHOLD {
208                parallel::process_items_sync(runtime, arguments, |arg, rt| optimize_expression(arg, rt))
209            } else {
210                arguments.into_iter().map(|arg| optimize_expression(arg, runtime)).collect()
211            };
212            let result = Expression::CallExpression { callee, arguments: optimized_args, location };
213            result
214        },
215        Expression::ArrayExpression { elements, location } => {
216            
217            let optimized_elements = if elements.len() > PARALLELISM_THRESHOLD {
218                parallel::process_items_sync(runtime, elements, |elem, rt| optimize_expression(elem, rt))
219            } else {
220                elements.into_iter().map(|elem| optimize_expression(elem, runtime)).collect()
221            };
222            let result = Expression::ArrayExpression { elements: optimized_elements, location };
223            result
224        },
225        Expression::ObjectExpression { properties, location } => {
226            
227            let optimized_properties = if properties.len() > PARALLELISM_THRESHOLD {
228                parallel::process_items_sync(
229                    runtime,
230                    properties,
231                    |prop, rt| Property::new(prop.key, optimize_expression(prop.value, rt), prop.location)
232                )
233            } else {
234                properties.into_iter()
235                    .map(|prop| Property::new(prop.key, optimize_expression(prop.value, runtime), prop.location))
236                    .collect()
237            };
238            let result = Expression::ObjectExpression { properties: optimized_properties, location };
239            result
240        },
241        Expression::MemberExpression { object, property, property_expr, computed, location } => {
242            
243            let optimized_object = Box::new(optimize_expression(*object, runtime));
244            
245            
246            let optimized_prop_expr = match property_expr {
247                Some(expr) => Some(Box::new(optimize_expression(*expr, runtime))),
248                None => None,
249            };
250            let result = Expression::MemberExpression {
251                object: optimized_object,
252                property,
253                property_expr: optimized_prop_expr,
254                computed,
255                location,
256            };
257            result
258        },
259        Expression::KeysOfExpression { object, location } => {
260            let optimized_object = Box::new(optimize_expression(*object, runtime));
261            let result = Expression::KeysOfExpression { object: optimized_object, location };
262            result
263        },
264        Expression::MemberCallExpression { object, property, property_expr, computed, arguments, location } => {
265            
266            let optimized_object = Box::new(optimize_expression(*object, runtime));
267            
268            
269            let optimized_prop_expr = match property_expr {
270                Some(expr) => Some(Box::new(optimize_expression(*expr, runtime))),
271                None => None,
272            };
273            
274            
275            let optimized_args = if arguments.len() > PARALLELISM_THRESHOLD {
276                parallel::process_items_sync(runtime, arguments, |arg, rt| optimize_expression(arg, rt))
277            } else {
278                arguments.into_iter().map(|arg| optimize_expression(arg, runtime)).collect()
279            };
280            
281            Expression::MemberCallExpression {
282                object: optimized_object,
283                property,
284                property_expr: optimized_prop_expr,
285                computed,
286                arguments: optimized_args,
287                location,
288            }
289        },
290        Expression::InlineCallbackExpression { name, params, body, location } => {
291            let optimized_body = optimize_block(body, runtime);
292            
293            Expression::InlineCallbackExpression {
294                name,
295                params,
296                body: optimized_body,
297                location,
298            }
299        },
300        Expression::UnaryExpression { operator, operand, location } => {
301            let optimized_operand = Box::new(optimize_expression(*operand, runtime));
302            Expression::UnaryExpression { 
303                operator,
304                operand: optimized_operand,
305                location,
306            }
307        },
308        Expression::StringLiteral { .. } |
309        Expression::NumberLiteral { .. } |
310        Expression::Identifier { .. } |
311        Expression::BooleanLiteral { .. } |
312        Expression::NullLiteral { .. } => {
313            expr
314        },
315    }
316}