|
@@ -37,55 +37,52 @@ impl<'a> Compiler<'a> {
|
|
|
&mut self,
|
|
|
expr: &'a Expr,
|
|
|
exit_label: Addr,
|
|
|
- ) -> Result<(Vec<OpCode>, Register), Error> {
|
|
|
- let mut return_value = self.next_register();
|
|
|
+ return_to: Register,
|
|
|
+ ) -> Result<Vec<OpCode>, Error> {
|
|
|
Ok(match expr {
|
|
|
- Expr::Variable(name) => (
|
|
|
- vec![OpCode::LOAD_EXTERNAL(return_value, name.clone())],
|
|
|
- return_value,
|
|
|
- ),
|
|
|
- Expr::Bool(value) => (
|
|
|
- vec![OpCode::LOAD(return_value, Value::Bool(*value))],
|
|
|
- return_value,
|
|
|
- ),
|
|
|
- Expr::String(string) => (
|
|
|
- vec![OpCode::LOAD(return_value, Value::String(string.clone()))],
|
|
|
- return_value,
|
|
|
- ),
|
|
|
- Expr::Number(number) => (
|
|
|
- vec![OpCode::LOAD(return_value, Value::Number(*number))],
|
|
|
- return_value,
|
|
|
- ),
|
|
|
+ Expr::Variable(name) => vec![OpCode::LOAD_EXTERNAL(return_to, name.clone())],
|
|
|
+ Expr::Bool(value) => vec![OpCode::LOAD(return_to, Value::Bool(*value))],
|
|
|
+ Expr::String(string) => vec![OpCode::LOAD(return_to, Value::String(string.clone()))],
|
|
|
+ Expr::Number(number) => vec![OpCode::LOAD(return_to, Value::Number(*number))],
|
|
|
Expr::Op { op, terms } => {
|
|
|
let mut opcodes = vec![];
|
|
|
let current_exit_label = self.next_label();
|
|
|
|
|
|
- let mut compiled_terms = terms
|
|
|
- .iter()
|
|
|
- .map(|term| self.compile_expr(term, current_exit_label))
|
|
|
- .collect::<Result<Vec<_>, _>>()?;
|
|
|
-
|
|
|
match op {
|
|
|
ExprOp::Not => {
|
|
|
- let (mut opcodes, term_return_value) =
|
|
|
- compiled_terms.pop().ok_or(Error::UnexpectedExprState)?;
|
|
|
- if !compiled_terms.is_empty() {
|
|
|
+ if terms.len() != 1 {
|
|
|
return Err(Error::UnexpectedExprState);
|
|
|
}
|
|
|
- opcodes.push(OpCode::NOT(return_value, return_value));
|
|
|
- return_value = term_return_value;
|
|
|
+ let mut opcodes = terms
|
|
|
+ .first()
|
|
|
+ .map(|expr| self.compile_expr(expr, exit_label, return_to))
|
|
|
+ .ok_or(Error::UnexpectedExprState)??;
|
|
|
+ opcodes.push(OpCode::NOT(return_to, return_to));
|
|
|
}
|
|
|
ExprOp::Eq => {
|
|
|
- let mut iter = compiled_terms.into_iter();
|
|
|
- let (mut term_opcodes, last_value) =
|
|
|
- iter.next().ok_or(Error::MissingNextRule)?;
|
|
|
-
|
|
|
+ let first = self.next_register();
|
|
|
+ let other = self.next_register();
|
|
|
+
|
|
|
+ let terms = terms
|
|
|
+ .iter()
|
|
|
+ .enumerate()
|
|
|
+ .map(|(idx, term)| {
|
|
|
+ self.compile_expr(
|
|
|
+ term,
|
|
|
+ current_exit_label,
|
|
|
+ if idx == 0 { first } else { other },
|
|
|
+ )
|
|
|
+ })
|
|
|
+ .collect::<Result<Vec<_>, _>>()?;
|
|
|
+ let mut iter = terms.into_iter();
|
|
|
+ let mut term_opcodes = iter.next().ok_or(Error::MissingNextRule)?;
|
|
|
opcodes.append(&mut term_opcodes);
|
|
|
+
|
|
|
if iter
|
|
|
- .map(|(mut term_codes, term_return)| {
|
|
|
+ .map(|mut term_codes| {
|
|
|
opcodes.append(&mut term_codes);
|
|
|
- opcodes.push(OpCode::EQ(return_value, last_value, term_return));
|
|
|
- opcodes.push(OpCode::JNE(return_value, exit_label));
|
|
|
+ opcodes.push(OpCode::EQ(return_to, first, other));
|
|
|
+ opcodes.push(OpCode::JNE(return_to, exit_label));
|
|
|
1
|
|
|
})
|
|
|
.sum::<usize>()
|
|
@@ -97,32 +94,51 @@ impl<'a> Compiler<'a> {
|
|
|
let _ = opcodes.pop();
|
|
|
}
|
|
|
ExprOp::Add | ExprOp::Mul | ExprOp::Div | ExprOp::Sub => {
|
|
|
- let mut iter = compiled_terms.into_iter();
|
|
|
- let (mut term_opcodes, return_value) =
|
|
|
- iter.next().ok_or(Error::MissingNextRule)?;
|
|
|
+ let term_return = self.next_register();
|
|
|
+ let terms = terms
|
|
|
+ .iter()
|
|
|
+ .enumerate()
|
|
|
+ .map(|(idx, term)| {
|
|
|
+ self.compile_expr(term, current_exit_label, term_return)
|
|
|
+ })
|
|
|
+ .collect::<Result<Vec<_>, _>>()?;
|
|
|
+
|
|
|
+ let mut iter = terms.into_iter();
|
|
|
+ let mut term_opcodes = iter.next().ok_or(Error::MissingNextRule)?;
|
|
|
opcodes.append(&mut term_opcodes);
|
|
|
+ opcodes.push(OpCode::MOV(return_to, term_return));
|
|
|
|
|
|
- for (mut term_opcodes, term_return) in iter {
|
|
|
+ for mut term_opcodes in iter {
|
|
|
opcodes.append(&mut term_opcodes);
|
|
|
opcodes.push(match op {
|
|
|
- ExprOp::Add => OpCode::ADD(return_value, return_value, term_return),
|
|
|
- ExprOp::Mul => OpCode::MUL(return_value, return_value, term_return),
|
|
|
- ExprOp::Div => OpCode::DIV(return_value, return_value, term_return),
|
|
|
- ExprOp::Sub => OpCode::SUB(return_value, return_value, term_return),
|
|
|
+ ExprOp::Add => OpCode::ADD(return_to, return_to, term_return),
|
|
|
+ ExprOp::Mul => OpCode::MUL(return_to, return_to, term_return),
|
|
|
+ ExprOp::Div => OpCode::DIV(return_to, return_to, term_return),
|
|
|
+ ExprOp::Sub => OpCode::SUB(return_to, return_to, term_return),
|
|
|
_ => unreachable!(),
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- return Ok((opcodes, return_value));
|
|
|
+ return Ok(opcodes);
|
|
|
}
|
|
|
ExprOp::Or | ExprOp::And => {
|
|
|
- opcodes = vec![OpCode::LOAD(return_value, Value::Bool(false))];
|
|
|
- for (mut term_opcodes, term_return_value) in compiled_terms.into_iter() {
|
|
|
+ opcodes = vec![OpCode::LOAD(return_to, Value::Bool(false))];
|
|
|
+
|
|
|
+ let terms = terms
|
|
|
+ .iter()
|
|
|
+ .enumerate()
|
|
|
+ .map(|(idx, term)| {
|
|
|
+ self.compile_expr(term, current_exit_label, return_to)
|
|
|
+ })
|
|
|
+ .collect::<Result<Vec<_>, _>>()?;
|
|
|
+
|
|
|
+ let mut iter = terms.into_iter();
|
|
|
+
|
|
|
+ for mut term_opcodes in iter.into_iter() {
|
|
|
opcodes.append(&mut term_opcodes);
|
|
|
- opcodes.push(OpCode::MOV(return_value, term_return_value));
|
|
|
match op {
|
|
|
- ExprOp::Or => opcodes.push(OpCode::JEQ(return_value, exit_label)),
|
|
|
- ExprOp::And => opcodes.push(OpCode::JNE(return_value, exit_label)),
|
|
|
+ ExprOp::Or => opcodes.push(OpCode::JEQ(return_to, exit_label)),
|
|
|
+ ExprOp::And => opcodes.push(OpCode::JNE(return_to, exit_label)),
|
|
|
_ => unreachable!(),
|
|
|
};
|
|
|
}
|
|
@@ -131,20 +147,20 @@ impl<'a> Compiler<'a> {
|
|
|
}
|
|
|
|
|
|
opcodes.push(OpCode::LABEL(current_exit_label));
|
|
|
- (opcodes, return_value)
|
|
|
+ opcodes
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
pub fn optimize(opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
|
|
|
vec![
|
|
|
- optimizations::assign_unique_register_addresses,
|
|
|
+ //optimizations::assign_unique_register_addresses,
|
|
|
optimizations::remove_redundant_load_and_mov,
|
|
|
optimizations::remove_unused_values,
|
|
|
optimizations::calculate_static_values,
|
|
|
optimizations::remove_useless_jumps,
|
|
|
optimizations::remove_dead_code,
|
|
|
- optimizations::move_load_top,
|
|
|
+ //optimizations::move_load_top,
|
|
|
]
|
|
|
.into_iter()
|
|
|
.fold((opcodes, false), |(opcodes, has_optimized), f| {
|
|
@@ -211,9 +227,10 @@ impl<'a> Compiler<'a> {
|
|
|
|
|
|
pub fn compile(mut self) -> Result<Vec<OpCode>, Error> {
|
|
|
let program_exit = self.next_label();
|
|
|
- let (mut opcodes, return_value) = self.compile_expr(self.expr, program_exit)?;
|
|
|
+ let return_to = self.next_register();
|
|
|
+ let mut opcodes = self.compile_expr(self.expr, program_exit, return_to)?;
|
|
|
opcodes.push(OpCode::LABEL(program_exit));
|
|
|
- opcodes.push(OpCode::HLT(return_value));
|
|
|
+ opcodes.push(OpCode::HLT(return_to));
|
|
|
Ok(opcodes)
|
|
|
}
|
|
|
}
|