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"
|
string-interner = "0.7.0"
|
||||||
cranelift = "0.29.0"
|
cranelift = "0.29.0"
|
||||||
cranelift-module = "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 block in blocks.iter_mut() {
|
||||||
for ir in block.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.
|
/// Desugar infix operations into method calls.
|
||||||
pub fn pass(ir: &mut IR, context: &mut Context) {
|
pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||||
if ir.is_infix() {
|
if let Some((op, lhs, rhs)) = ir.get_infix() {
|
||||||
let (op, lhs, rhs) = ir.get_infix().unwrap();
|
|
||||||
let method_name = match op {
|
let method_name = match op {
|
||||||
BinOp::BitwiseAnd => "bitwise_and",
|
BinOp::BitwiseAnd => "bitwise_and",
|
||||||
BinOp::BitwiseOr => "bitwise_or",
|
BinOp::BitwiseOr => "bitwise_or",
|
||||||
BinOp::BitwiseXor => "bitwise_xor",
|
BinOp::BitwiseXor => "bitwise_xor",
|
||||||
BinOp::Divide => "divide",
|
BinOp::Divide => "divide",
|
||||||
BinOp::Equal => "equal",
|
BinOp::Equal => "equal_to",
|
||||||
BinOp::Exponent => "exponent",
|
BinOp::Exponent => "exponent",
|
||||||
BinOp::GreaterThan => "greater_than",
|
BinOp::GreaterThan => "greater_than",
|
||||||
BinOp::GreaterThanOrEqual => "greater_than_or_equal",
|
BinOp::GreaterThanOrEqual => "greater_than_or_equal_to",
|
||||||
BinOp::LessThan => "less_than",
|
BinOp::LessThan => "less_than",
|
||||||
BinOp::LessThanOrEqual => "less_than_or_equal",
|
BinOp::LessThanOrEqual => "less_than_or_equal_to",
|
||||||
BinOp::LogicalAnd => "logical_and",
|
BinOp::LogicalAnd => "logical_and",
|
||||||
BinOp::LogicalOr => "logical_or",
|
BinOp::LogicalOr => "logical_or",
|
||||||
BinOp::Minus => "minus",
|
BinOp::Minus => "minus",
|
||||||
BinOp::Modulus => "modulus",
|
BinOp::Modulus => "modulus",
|
||||||
BinOp::Multiply => "multiply",
|
BinOp::Multiply => "multiply_by",
|
||||||
BinOp::NotEqual => "not_equal",
|
BinOp::NotEqual => "not_equal_to",
|
||||||
BinOp::Plus => "plus",
|
BinOp::Plus => "plus",
|
||||||
BinOp::ShiftLeft => "shift_left",
|
BinOp::ShiftLeft => "shift_left",
|
||||||
BinOp::ShiftRight => "shift_right",
|
BinOp::ShiftRight => "shift_right",
|
||||||
|
@ -61,7 +60,7 @@ mod test {
|
||||||
|
|
||||||
assert!(ir.is_infix());
|
assert!(ir.is_infix());
|
||||||
|
|
||||||
ir.improve(&mut context, pass);
|
ir.improve(&mut context, &pass);
|
||||||
|
|
||||||
assert!(ir.is_method_call());
|
assert!(ir.is_method_call());
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ mod test {
|
||||||
|
|
||||||
assert!(ir.is_unary());
|
assert!(ir.is_unary());
|
||||||
|
|
||||||
ir.improve(&mut context, pass);
|
ir.improve(&mut context, &pass);
|
||||||
|
|
||||||
assert!(ir.is_method_call());
|
assert!(ir.is_method_call());
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ mod test {
|
||||||
|
|
||||||
builder.build(term, &mut context);
|
builder.build(term, &mut context);
|
||||||
let mut ir = builder.pop_ir().unwrap();
|
let mut ir = builder.pop_ir().unwrap();
|
||||||
ir.improve(&mut context, pass);
|
ir.improve(&mut context, &pass);
|
||||||
|
|
||||||
assert!(ir.is_constant());
|
assert!(ir.is_constant());
|
||||||
assert_eq!(ir.get_value().unwrap().integer().unwrap(), 12);
|
assert_eq!(ir.get_value().unwrap().integer().unwrap(), 12);
|
||||||
|
@ -98,7 +98,7 @@ mod test {
|
||||||
|
|
||||||
builder.build(term, &mut context);
|
builder.build(term, &mut context);
|
||||||
let mut ir = builder.pop_ir().unwrap();
|
let mut ir = builder.pop_ir().unwrap();
|
||||||
ir.improve(&mut context, pass);
|
ir.improve(&mut context, &pass);
|
||||||
|
|
||||||
assert!(ir.is_constant());
|
assert!(ir.is_constant());
|
||||||
assert!(ir.get_value().unwrap().float().unwrap() - 1.0 < f64::EPSILON);
|
assert!(ir.get_value().unwrap().float().unwrap() - 1.0 < f64::EPSILON);
|
||||||
|
|
|
@ -67,7 +67,7 @@ mod test {
|
||||||
|
|
||||||
builder.build(term, &mut context);
|
builder.build(term, &mut context);
|
||||||
let mut ir = builder.pop_ir().unwrap();
|
let mut ir = builder.pop_ir().unwrap();
|
||||||
ir.improve(&mut context, pass);
|
ir.improve(&mut context, &pass);
|
||||||
|
|
||||||
assert!(ir.is_constant());
|
assert!(ir.is_constant());
|
||||||
assert!(!ir.get_value().unwrap().boolean().unwrap());
|
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)> {
|
pub fn get_set_local(&self) -> Option<(&StringIdx, &IR)> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IRKind::SetLocal(ref name, ref value) => Some((name, value)),
|
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
|
/// Child nodes are visited *before* the receiving node to ensure that
|
||||||
/// improvements can bubble up.
|
/// 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 self,
|
||||||
mut context: &mut Context,
|
mut context: &mut Context,
|
||||||
improver: F,
|
improver: F,
|
||||||
) {
|
) {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IRKind::Call(ref mut fun, ref mut args) => {
|
IRKind::Call(ref mut fun, ref mut args) => {
|
||||||
improver(fun, &mut context);
|
fun.improve(&mut context, improver);
|
||||||
for mut arg in args.iter_mut() {
|
for arg in args.iter_mut() {
|
||||||
improver(&mut arg, &mut context);
|
arg.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IRKind::Constant(ref mut value) => match value {
|
IRKind::Constant(ref mut value) => match value {
|
||||||
Val::Array(ref mut elements) => {
|
Val::Array(ref mut elements) => {
|
||||||
for mut element in elements.iter_mut() {
|
for element in elements.iter_mut() {
|
||||||
improver(&mut element, &mut context);
|
element.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Val::Map(ref mut elements) => {
|
Val::Map(ref mut elements) => {
|
||||||
for (ref mut key, ref mut value) in elements.iter_mut() {
|
for (ref mut key, ref mut value) in elements.iter_mut() {
|
||||||
improver(key, &mut context);
|
key.improve(&mut context, improver);
|
||||||
improver(value, &mut context);
|
value.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
IRKind::Constructor(ref mut properties) => {
|
IRKind::Constructor(ref mut properties) => {
|
||||||
for (_key, ref mut value) in properties.iter_mut() {
|
for (_key, ref mut value) in properties.iter_mut() {
|
||||||
improver(value, &mut context)
|
value.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IRKind::FunctionRef(..) => (),
|
IRKind::FunctionRef(..) => (),
|
||||||
IRKind::GetLocal(..) => (),
|
IRKind::GetLocal(..) => (),
|
||||||
IRKind::GetProperty(..) => (),
|
IRKind::GetProperty(..) => (),
|
||||||
IRKind::Infix(_, ref mut lhs, ref mut rhs) => {
|
IRKind::Infix(_, ref mut lhs, ref mut rhs) => {
|
||||||
improver(lhs, &mut context);
|
lhs.improve(&mut context, improver);
|
||||||
improver(rhs, &mut context);
|
rhs.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
IRKind::Jump(..) => (),
|
IRKind::Jump(..) => (),
|
||||||
IRKind::JumpIfFalse(ref mut test, ..) => {
|
IRKind::JumpIfFalse(ref mut test, ..) => {
|
||||||
improver(test, &mut context);
|
test.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
IRKind::JumpIfTrue(ref mut test, ..) => {
|
IRKind::JumpIfTrue(ref mut test, ..) => {
|
||||||
improver(test, &mut context);
|
test.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
IRKind::MethodCall(ref mut callee, _, ref mut arguments) => {
|
IRKind::MethodCall(ref mut callee, _, ref mut arguments) => {
|
||||||
improver(callee, &mut context);
|
callee.improve(&mut context, improver);
|
||||||
for argument in arguments {
|
for argument in arguments {
|
||||||
improver(argument, &mut context);
|
argument.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IRKind::Return(ref mut value) => {
|
IRKind::Return(ref mut value) => {
|
||||||
improver(value, &mut context);
|
value.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
IRKind::SetLocal(_, ref mut rhs) => {
|
IRKind::SetLocal(_, ref mut rhs) => {
|
||||||
improver(rhs, &mut context);
|
rhs.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
IRKind::SetProperties(ref mut properties) => {
|
IRKind::SetProperties(ref mut properties) => {
|
||||||
for (_key, ref mut value) in properties.iter_mut() {
|
for (_key, ref mut value) in properties.iter_mut() {
|
||||||
improver(value, &mut context)
|
value.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IRKind::TypeReference(..) => (),
|
IRKind::TypeReference(..) => (),
|
||||||
IRKind::Unary(_, ref mut rhs) => {
|
IRKind::Unary(_, ref mut rhs) => {
|
||||||
improver(rhs, &mut context);
|
rhs.improve(&mut context, improver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
improver(self, &mut context);
|
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 {
|
pub fn is_infix(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IRKind::Infix(..) => true,
|
IRKind::Infix(..) => true,
|
||||||
|
|
|
@ -27,8 +27,8 @@ pub fn compile_file(path: &str) -> Context {
|
||||||
|
|
||||||
context.improve_ir(|mut ir, mut context| {
|
context.improve_ir(|mut ir, mut context| {
|
||||||
improvements::infix_folding::pass(&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::desugar_infix::pass(&mut ir, &mut context);
|
||||||
|
improvements::unary_folding::pass(&mut ir, &mut context);
|
||||||
improvements::desugar_unary::pass(&mut ir, &mut context);
|
improvements::desugar_unary::pass(&mut ir, &mut context);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Reference in a new issue