use crate::canonical::*;
pub fn eliminate_dead_branches_in_stages(stages: Vec<Stage>) -> Vec<Stage> {
stages.into_iter().map(eliminate_in_stage).collect()
}
fn eliminate_in_stage(stage: Stage) -> Stage {
match stage {
Stage::FnDecl(fd) => Stage::FnDecl(FnDecl {
body: fold(fd.body),
..fd
}),
other => other,
}
}
pub fn fold(e: CExpr) -> CExpr {
let folded = match e {
CExpr::Match { scrutinee, arms } => {
let s = fold(*scrutinee);
let arms: Vec<Arm> = arms.into_iter()
.map(|a| Arm { pattern: a.pattern, body: fold(a.body) })
.collect();
CExpr::Match { scrutinee: Box::new(s), arms }
}
CExpr::Call { callee, args } => CExpr::Call {
callee: Box::new(fold(*callee)),
args: args.into_iter().map(fold).collect(),
},
CExpr::Let { name, ty, value, body } => CExpr::Let {
name, ty,
value: Box::new(fold(*value)),
body: Box::new(fold(*body)),
},
CExpr::Block { statements, result } => CExpr::Block {
statements: statements.into_iter().map(fold).collect(),
result: Box::new(fold(*result)),
},
CExpr::Constructor { name, args } => CExpr::Constructor {
name,
args: args.into_iter().map(fold).collect(),
},
CExpr::RecordLit { fields } => CExpr::RecordLit {
fields: fields.into_iter().map(|f| RecordField {
name: f.name,
value: fold(f.value),
}).collect(),
},
CExpr::TupleLit { items } => CExpr::TupleLit {
items: items.into_iter().map(fold).collect(),
},
CExpr::ListLit { items } => CExpr::ListLit {
items: items.into_iter().map(fold).collect(),
},
CExpr::FieldAccess { value, field } => CExpr::FieldAccess {
value: Box::new(fold(*value)),
field,
},
CExpr::Lambda { params, return_type, effects, effect_row_var, body } => CExpr::Lambda {
params, return_type, effects, effect_row_var,
body: Box::new(fold(*body)),
},
CExpr::BinOp { op, lhs, rhs } => CExpr::BinOp {
op,
lhs: Box::new(fold(*lhs)),
rhs: Box::new(fold(*rhs)),
},
CExpr::UnaryOp { op, expr } => CExpr::UnaryOp {
op,
expr: Box::new(fold(*expr)),
},
CExpr::Return { value } => CExpr::Return {
value: Box::new(fold(*value)),
},
leaf => leaf,
};
if let CExpr::Match { scrutinee, arms } = &folded {
if let CExpr::Literal { value: lit } = scrutinee.as_ref() {
for arm in arms {
if pattern_matches_literal(&arm.pattern, lit) {
return arm.body.clone();
}
}
}
}
folded
}
fn pattern_matches_literal(pat: &Pattern, lit: &CLit) -> bool {
match pat {
Pattern::PLiteral { value } => value == lit,
Pattern::PWild => true,
_ => false,
}
}