Fix improvements not being applied to all IR.

This commit is contained in:
James Harton 2019-04-03 21:40:06 +13:00
parent 396a6d020b
commit 87f4b970f6
8 changed files with 41 additions and 40 deletions

View file

@ -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"

View file

@ -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);
}
}

View file

@ -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());
}

View file

@ -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());
}

View file

@ -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);

View file

@ -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());

View file

@ -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,

View file

@ -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);
});