Fix improvements not being applied to all IR.
This commit is contained in:
parent
396a6d020b
commit
87f4b970f6
8 changed files with 41 additions and 40 deletions
|
@ -9,3 +9,5 @@ huia-parser = { path = "../huia-parser" }
|
|||
string-interner = "0.7.0"
|
||||
cranelift = "0.29.0"
|
||||
cranelift-module = "0.29.0"
|
||||
codespan = "0.2.1"
|
||||
codespan-reporting = "0.2.1"
|
||||
|
|
|
@ -225,7 +225,7 @@ impl Context {
|
|||
|
||||
for block in blocks.iter_mut() {
|
||||
for ir in block.iter_mut() {
|
||||
improver(ir, self)
|
||||
ir.improve(self, &improver);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,25 +7,24 @@ use huia_parser::ast::binary::Operator as BinOp;
|
|||
|
||||
/// Desugar infix operations into method calls.
|
||||
pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||
if ir.is_infix() {
|
||||
let (op, lhs, rhs) = ir.get_infix().unwrap();
|
||||
if let Some((op, lhs, rhs)) = ir.get_infix() {
|
||||
let method_name = match op {
|
||||
BinOp::BitwiseAnd => "bitwise_and",
|
||||
BinOp::BitwiseOr => "bitwise_or",
|
||||
BinOp::BitwiseXor => "bitwise_xor",
|
||||
BinOp::Divide => "divide",
|
||||
BinOp::Equal => "equal",
|
||||
BinOp::Equal => "equal_to",
|
||||
BinOp::Exponent => "exponent",
|
||||
BinOp::GreaterThan => "greater_than",
|
||||
BinOp::GreaterThanOrEqual => "greater_than_or_equal",
|
||||
BinOp::GreaterThanOrEqual => "greater_than_or_equal_to",
|
||||
BinOp::LessThan => "less_than",
|
||||
BinOp::LessThanOrEqual => "less_than_or_equal",
|
||||
BinOp::LessThanOrEqual => "less_than_or_equal_to",
|
||||
BinOp::LogicalAnd => "logical_and",
|
||||
BinOp::LogicalOr => "logical_or",
|
||||
BinOp::Minus => "minus",
|
||||
BinOp::Modulus => "modulus",
|
||||
BinOp::Multiply => "multiply",
|
||||
BinOp::NotEqual => "not_equal",
|
||||
BinOp::Multiply => "multiply_by",
|
||||
BinOp::NotEqual => "not_equal_to",
|
||||
BinOp::Plus => "plus",
|
||||
BinOp::ShiftLeft => "shift_left",
|
||||
BinOp::ShiftRight => "shift_right",
|
||||
|
@ -61,7 +60,7 @@ mod test {
|
|||
|
||||
assert!(ir.is_infix());
|
||||
|
||||
ir.improve(&mut context, pass);
|
||||
ir.improve(&mut context, &pass);
|
||||
|
||||
assert!(ir.is_method_call());
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ mod test {
|
|||
|
||||
assert!(ir.is_unary());
|
||||
|
||||
ir.improve(&mut context, pass);
|
||||
ir.improve(&mut context, &pass);
|
||||
|
||||
assert!(ir.is_method_call());
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ mod test {
|
|||
|
||||
builder.build(term, &mut context);
|
||||
let mut ir = builder.pop_ir().unwrap();
|
||||
ir.improve(&mut context, pass);
|
||||
ir.improve(&mut context, &pass);
|
||||
|
||||
assert!(ir.is_constant());
|
||||
assert_eq!(ir.get_value().unwrap().integer().unwrap(), 12);
|
||||
|
@ -98,7 +98,7 @@ mod test {
|
|||
|
||||
builder.build(term, &mut context);
|
||||
let mut ir = builder.pop_ir().unwrap();
|
||||
ir.improve(&mut context, pass);
|
||||
ir.improve(&mut context, &pass);
|
||||
|
||||
assert!(ir.is_constant());
|
||||
assert!(ir.get_value().unwrap().float().unwrap() - 1.0 < f64::EPSILON);
|
||||
|
|
|
@ -67,7 +67,7 @@ mod test {
|
|||
|
||||
builder.build(term, &mut context);
|
||||
let mut ir = builder.pop_ir().unwrap();
|
||||
ir.improve(&mut context, pass);
|
||||
ir.improve(&mut context, &pass);
|
||||
|
||||
assert!(ir.is_constant());
|
||||
assert!(!ir.get_value().unwrap().boolean().unwrap());
|
||||
|
|
|
@ -103,6 +103,13 @@ impl IR {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_return(&self) -> Option<&IR> {
|
||||
match self.kind {
|
||||
IRKind::Return(ref ir) => Some(ir),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_set_local(&self) -> Option<(&StringIdx, &IR)> {
|
||||
match self.kind {
|
||||
IRKind::SetLocal(ref name, ref value) => Some((name, value)),
|
||||
|
@ -152,71 +159,71 @@ impl IR {
|
|||
///
|
||||
/// Child nodes are visited *before* the receiving node to ensure that
|
||||
/// improvements can bubble up.
|
||||
pub fn improve<F: Fn(&mut IR, &mut Context)>(
|
||||
pub fn improve<F: Fn(&mut IR, &mut Context) + Copy>(
|
||||
&mut self,
|
||||
mut context: &mut Context,
|
||||
improver: F,
|
||||
) {
|
||||
match self.kind {
|
||||
IRKind::Call(ref mut fun, ref mut args) => {
|
||||
improver(fun, &mut context);
|
||||
for mut arg in args.iter_mut() {
|
||||
improver(&mut arg, &mut context);
|
||||
fun.improve(&mut context, improver);
|
||||
for arg in args.iter_mut() {
|
||||
arg.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
IRKind::Constant(ref mut value) => match value {
|
||||
Val::Array(ref mut elements) => {
|
||||
for mut element in elements.iter_mut() {
|
||||
improver(&mut element, &mut context);
|
||||
for element in elements.iter_mut() {
|
||||
element.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
Val::Map(ref mut elements) => {
|
||||
for (ref mut key, ref mut value) in elements.iter_mut() {
|
||||
improver(key, &mut context);
|
||||
improver(value, &mut context);
|
||||
key.improve(&mut context, improver);
|
||||
value.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
IRKind::Constructor(ref mut properties) => {
|
||||
for (_key, ref mut value) in properties.iter_mut() {
|
||||
improver(value, &mut context)
|
||||
value.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
IRKind::FunctionRef(..) => (),
|
||||
IRKind::GetLocal(..) => (),
|
||||
IRKind::GetProperty(..) => (),
|
||||
IRKind::Infix(_, ref mut lhs, ref mut rhs) => {
|
||||
improver(lhs, &mut context);
|
||||
improver(rhs, &mut context);
|
||||
lhs.improve(&mut context, improver);
|
||||
rhs.improve(&mut context, improver);
|
||||
}
|
||||
IRKind::Jump(..) => (),
|
||||
IRKind::JumpIfFalse(ref mut test, ..) => {
|
||||
improver(test, &mut context);
|
||||
test.improve(&mut context, improver);
|
||||
}
|
||||
IRKind::JumpIfTrue(ref mut test, ..) => {
|
||||
improver(test, &mut context);
|
||||
test.improve(&mut context, improver);
|
||||
}
|
||||
IRKind::MethodCall(ref mut callee, _, ref mut arguments) => {
|
||||
improver(callee, &mut context);
|
||||
callee.improve(&mut context, improver);
|
||||
for argument in arguments {
|
||||
improver(argument, &mut context);
|
||||
argument.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
IRKind::Return(ref mut value) => {
|
||||
improver(value, &mut context);
|
||||
value.improve(&mut context, improver);
|
||||
}
|
||||
IRKind::SetLocal(_, ref mut rhs) => {
|
||||
improver(rhs, &mut context);
|
||||
rhs.improve(&mut context, improver);
|
||||
}
|
||||
IRKind::SetProperties(ref mut properties) => {
|
||||
for (_key, ref mut value) in properties.iter_mut() {
|
||||
improver(value, &mut context)
|
||||
value.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
IRKind::TypeReference(..) => (),
|
||||
IRKind::Unary(_, ref mut rhs) => {
|
||||
improver(rhs, &mut context);
|
||||
rhs.improve(&mut context, improver);
|
||||
}
|
||||
}
|
||||
improver(self, &mut context);
|
||||
|
@ -271,13 +278,6 @@ impl IR {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_return(&self) -> Option<&IR> {
|
||||
match self.kind {
|
||||
IRKind::Return(ref ir) => Some(ir),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_infix(&self) -> bool {
|
||||
match self.kind {
|
||||
IRKind::Infix(..) => true,
|
||||
|
|
|
@ -27,8 +27,8 @@ pub fn compile_file(path: &str) -> Context {
|
|||
|
||||
context.improve_ir(|mut ir, mut context| {
|
||||
improvements::infix_folding::pass(&mut ir, &mut context);
|
||||
improvements::unary_folding::pass(&mut ir, &mut context);
|
||||
improvements::desugar_infix::pass(&mut ir, &mut context);
|
||||
improvements::unary_folding::pass(&mut ir, &mut context);
|
||||
improvements::desugar_unary::pass(&mut ir, &mut context);
|
||||
});
|
||||
|
||||
|
|
Reference in a new issue