-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathast_optimizer.rs
91 lines (81 loc) · 3.72 KB
/
ast_optimizer.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use crate::frontend::ast::{Block, BlockItem, Class, ClassItem, Expression, ExpressionKind, Function, FunctionItem, Reference, ReferenceKind, Statement, StatementKind};
use crate::frontend::error::{FrontendError, FrontendErrorKind};
use crate::meta::{LocationMeta, Meta};
use crate::util::mapper::AstMapper;
pub struct AstOptimizer;
type OptimizationResult<T> = Result<T, Vec<FrontendError<LocationMeta>>>;
impl AstMapper<LocationMeta, LocationMeta, FrontendError<LocationMeta>> for AstOptimizer {
fn map_var_reference(&mut self, r: &Reference<LocationMeta>) -> OptimizationResult<Reference<LocationMeta>> {
Ok(r.clone())
}
fn map_func_reference(&mut self, r: &Reference<LocationMeta>) -> OptimizationResult<Reference<LocationMeta>> {
Ok(r.clone())
}
fn map_block(&mut self, block: &Block<LocationMeta>) -> OptimizationResult<Block<LocationMeta>> {
let mapped_stmts: Vec<_> = block.item.stmts.iter()
.map(|stmt| self.map_statement(stmt))
.filter_map(Result::ok) // no error is possible at this point
.filter(|stmt| stmt.item != StatementKind::Empty)
.map(Box::new)
.collect();
let mapped_block = Block::new(
BlockItem { stmts: mapped_stmts },
block.get_meta().clone(),
);
Ok(mapped_block)
}
fn map_expression(&mut self, expr: &Expression<LocationMeta>) -> OptimizationResult<Expression<LocationMeta>> {
Ok(expr.clone()) // TODO: More optimization is possible, we can recursively check if there are constants
}
fn map_statement(&mut self, stmt: &Statement<LocationMeta>) -> OptimizationResult<Statement<LocationMeta>> {
match &stmt.item {
StatementKind::Block { block } => {
let mapped_block = self.map_block(block)?;
let mapped_stmt = Statement::new(
StatementKind::Block { block: mapped_block },
stmt.get_meta().clone(),
);
Ok(mapped_stmt)
}
StatementKind::Cond { expr, stmt: cond_stmt } => {
match &expr.item {
ExpressionKind::LitBool { val: true } => {
Ok(*cond_stmt.clone())
}
ExpressionKind::LitBool { val: false } => {
let empty = Statement::new(
StatementKind::Empty,
cond_stmt.get_meta().clone(),
);
Ok(empty)
}
_ => Ok(stmt.clone())
}
}
StatementKind::CondElse { expr, stmt_true, stmt_false } => {
match &expr.item {
ExpressionKind::LitBool { val: true } => {
Ok(*stmt_true.clone())
}
ExpressionKind::LitBool { val: false } => {
Ok(*stmt_false.clone())
}
_ => Ok(stmt.clone())
}
}
_ => Ok(stmt.clone())
}
}
fn map_class(&mut self, class: &Class<LocationMeta>) -> OptimizationResult<Class<LocationMeta>> {
let mut mapped_class = class.clone();
mapped_class.item.methods = class.item.methods.iter()
.map(|(k, v)| (k.clone(), self.map_function(v).unwrap())).collect();
Ok(mapped_class)
}
fn map_function(&mut self, function: &Function<LocationMeta>) -> OptimizationResult<Function<LocationMeta>> {
let mapped_block = self.map_block(&function.item.block)?;
let mut mapped_function = function.clone();
mapped_function.item.block = mapped_block;
Ok(mapped_function)
}
}