Refactor register incrementing/decrementing
This commit is contained in:
parent
d68c789ea8
commit
182ef66f23
@ -365,7 +365,7 @@ impl Instruction {
|
||||
Operation::LoadList => {
|
||||
let destination = self.destination();
|
||||
let first_index = self.first_argument();
|
||||
let last_index = destination - 1;
|
||||
let last_index = destination.saturating_sub(1);
|
||||
|
||||
format!("R{} = [R{}..=R{}]", destination, first_index, last_index)
|
||||
}
|
||||
|
@ -138,7 +138,6 @@ impl<'src> Parser<'src> {
|
||||
Instruction::load_constant(self.current_register, constant_index),
|
||||
position,
|
||||
);
|
||||
self.increment_register()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -203,7 +202,6 @@ impl<'src> Parser<'src> {
|
||||
Instruction::load_boolean(self.current_register, boolean, skip),
|
||||
position,
|
||||
);
|
||||
self.increment_register()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -332,11 +330,7 @@ impl<'src> Parser<'src> {
|
||||
let (push_back, is_constant, argument) = {
|
||||
match previous_instruction.operation() {
|
||||
Operation::GetLocal => (false, false, previous_instruction.destination()),
|
||||
Operation::LoadConstant => {
|
||||
self.decrement_register()?;
|
||||
|
||||
(false, true, previous_instruction.first_argument())
|
||||
}
|
||||
Operation::LoadConstant => (false, true, previous_instruction.first_argument()),
|
||||
Operation::LoadBoolean => (true, false, previous_instruction.destination()),
|
||||
Operation::Close => {
|
||||
return Err(ParseError::ExpectedExpression {
|
||||
@ -348,6 +342,10 @@ impl<'src> Parser<'src> {
|
||||
}
|
||||
};
|
||||
|
||||
if push_back {
|
||||
self.increment_register()?;
|
||||
}
|
||||
|
||||
let mut instruction = match operator.kind() {
|
||||
TokenKind::Bang => Instruction::not(self.current_register, argument),
|
||||
TokenKind::Minus => Instruction::negate(self.current_register, argument),
|
||||
@ -380,21 +378,16 @@ impl<'src> Parser<'src> {
|
||||
let mut push_back = false;
|
||||
let mut is_constant = false;
|
||||
let argument = match instruction.operation() {
|
||||
Operation::GetLocal => {
|
||||
self.decrement_register()?;
|
||||
instruction.destination()
|
||||
}
|
||||
Operation::GetLocal => instruction.destination(),
|
||||
Operation::LoadConstant => {
|
||||
is_constant = true;
|
||||
|
||||
self.decrement_register()?;
|
||||
instruction.first_argument()
|
||||
}
|
||||
Operation::LoadBoolean => {
|
||||
is_constant = true;
|
||||
push_back = true;
|
||||
|
||||
self.decrement_register()?;
|
||||
instruction.destination()
|
||||
}
|
||||
Operation::Close => {
|
||||
@ -480,8 +473,6 @@ impl<'src> Parser<'src> {
|
||||
let (previous_booleans, equal_argument) = if let [Some(Operation::LoadBoolean), Some(Operation::LoadBoolean), Some(Operation::Jump), Some(Operation::Equal)] =
|
||||
self.chunk.get_last_n_operations()
|
||||
{
|
||||
self.increment_register()?;
|
||||
|
||||
let load_booleans = (
|
||||
self.chunk.pop_instruction(self.current_position)?,
|
||||
self.chunk.pop_instruction(self.current_position)?,
|
||||
@ -557,10 +548,12 @@ impl<'src> Parser<'src> {
|
||||
|
||||
if push_back_left {
|
||||
self.emit_instruction(left_instruction, left_position);
|
||||
self.increment_register()?;
|
||||
}
|
||||
|
||||
if push_back_right {
|
||||
self.emit_instruction(right_instruction, right_position);
|
||||
self.increment_register()?;
|
||||
}
|
||||
|
||||
self.emit_instruction(instruction, operator_position);
|
||||
@ -588,19 +581,13 @@ impl<'src> Parser<'src> {
|
||||
fn parse_logical_binary(&mut self) -> Result<(), ParseError> {
|
||||
let (left_instruction, left_position) =
|
||||
self.chunk.pop_instruction(self.current_position)?;
|
||||
let (push_back_left, left_is_constant, _) =
|
||||
self.handle_binary_argument(&left_instruction)?;
|
||||
|
||||
if let Operation::LoadBoolean = left_instruction.operation() {
|
||||
self.increment_register()?;
|
||||
}
|
||||
|
||||
let operator = self.current_token;
|
||||
let operator_position = self.current_position;
|
||||
let rule = ParseRule::from(&operator.kind());
|
||||
|
||||
let test_register = self.current_register.saturating_sub(1);
|
||||
let mut instruction = match operator.kind() {
|
||||
let test_register = left_instruction.destination();
|
||||
let instruction = match operator.kind() {
|
||||
TokenKind::DoubleAmpersand => Instruction::test(test_register, true),
|
||||
TokenKind::DoublePipe => Instruction::test(test_register, false),
|
||||
_ => {
|
||||
@ -612,49 +599,21 @@ impl<'src> Parser<'src> {
|
||||
}
|
||||
};
|
||||
|
||||
self.increment_register()?;
|
||||
self.advance()?;
|
||||
self.parse(rule.precedence.increment())?;
|
||||
|
||||
let (mut right_instruction, right_position) =
|
||||
self.chunk.pop_instruction(self.current_position)?;
|
||||
let (push_back_right, right_is_constant, _) =
|
||||
self.handle_binary_argument(&right_instruction)?;
|
||||
|
||||
let emit_move_to = if self.current_register != test_register {
|
||||
Some(self.current_register)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if left_is_constant {
|
||||
instruction.set_first_argument_to_constant();
|
||||
}
|
||||
|
||||
if right_is_constant {
|
||||
if let Operation::LoadBoolean = right_instruction.operation() {
|
||||
right_instruction.set_second_argument_to_boolean(true);
|
||||
}
|
||||
|
||||
instruction.set_second_argument_to_constant();
|
||||
}
|
||||
|
||||
if push_back_left {
|
||||
self.emit_instruction(left_instruction, left_position);
|
||||
}
|
||||
|
||||
self.emit_instruction(instruction, operator_position);
|
||||
self.emit_instruction(Instruction::jump(1, true), operator_position);
|
||||
|
||||
if push_back_right {
|
||||
self.emit_instruction(right_instruction, right_position);
|
||||
}
|
||||
|
||||
if let Some(register) = emit_move_to {
|
||||
self.emit_instruction(
|
||||
Instruction::r#move(register, test_register),
|
||||
operator_position,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -704,7 +663,7 @@ impl<'src> Parser<'src> {
|
||||
|
||||
self.emit_instruction(previous_instruction, previous_position);
|
||||
self.emit_instruction(
|
||||
Instruction::set_local(self.current_register - 1, local_index),
|
||||
Instruction::set_local(self.current_register, local_index),
|
||||
start_position,
|
||||
);
|
||||
} else {
|
||||
@ -712,7 +671,6 @@ impl<'src> Parser<'src> {
|
||||
Instruction::get_local(self.current_register, local_index),
|
||||
self.previous_position,
|
||||
);
|
||||
self.increment_register()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -773,9 +731,13 @@ impl<'src> Parser<'src> {
|
||||
|
||||
self.parse(Precedence::Assignment)?; // Do not allow assignment
|
||||
|
||||
if next_register != self.current_register - 1 {
|
||||
if let Some(Operation::LoadConstant) = self.chunk.get_last_operation() {
|
||||
self.increment_register()?;
|
||||
}
|
||||
|
||||
if next_register != self.current_register.saturating_sub(1) {
|
||||
self.emit_instruction(
|
||||
Instruction::close(next_register, self.current_register - 1),
|
||||
Instruction::close(next_register, self.current_register.saturating_sub(1)),
|
||||
self.current_position,
|
||||
);
|
||||
}
|
||||
@ -919,6 +881,7 @@ impl<'src> Parser<'src> {
|
||||
|
||||
self.expect(TokenKind::Equal)?;
|
||||
self.parse_expression()?;
|
||||
self.increment_register()?;
|
||||
|
||||
let (previous_instruction, previous_position) =
|
||||
*self
|
||||
|
@ -3,8 +3,8 @@ use crate::Local;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn equality_chain() {
|
||||
let source = "1 == 2 == 3;";
|
||||
fn comparison_chain() {
|
||||
let source = "1 == 2 > 3 < 4 != 5;";
|
||||
|
||||
assert_eq!(
|
||||
parse(source),
|
||||
@ -278,7 +278,7 @@ fn if_else_expression() {
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_constant(0, 2), Span(12, 13)),
|
||||
(Instruction::jump(1, true), Span(26, 26)),
|
||||
(Instruction::load_constant(1, 3), Span(23, 24)),
|
||||
(Instruction::load_constant(0, 3), Span(23, 24)),
|
||||
],
|
||||
vec![
|
||||
Value::integer(1),
|
||||
@ -489,15 +489,9 @@ fn or() {
|
||||
Ok(Chunk::with_data(
|
||||
vec![
|
||||
(Instruction::load_boolean(0, true, false), Span(0, 4)),
|
||||
(
|
||||
*Instruction::test(0, false)
|
||||
.set_second_argument_to_constant()
|
||||
.set_first_argument_to_constant(),
|
||||
Span(5, 7)
|
||||
),
|
||||
(Instruction::test(0, false), Span(5, 7)),
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_boolean(1, false, true), Span(8, 13)),
|
||||
(Instruction::r#move(1, 0), Span(5, 7)),
|
||||
],
|
||||
vec![],
|
||||
vec![]
|
||||
@ -512,15 +506,9 @@ fn and() {
|
||||
Ok(Chunk::with_data(
|
||||
vec![
|
||||
(Instruction::load_boolean(0, true, false), Span(0, 4)),
|
||||
(
|
||||
*Instruction::test(0, true)
|
||||
.set_second_argument_to_constant()
|
||||
.set_first_argument_to_constant(),
|
||||
Span(5, 7)
|
||||
),
|
||||
(Instruction::test(0, true), Span(5, 7)),
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_boolean(1, false, true), Span(8, 13)),
|
||||
(Instruction::r#move(1, 0), Span(5, 7)),
|
||||
],
|
||||
vec![],
|
||||
vec![]
|
||||
@ -538,9 +526,10 @@ fn variable_and() {
|
||||
(Instruction::define_local(0, 0, false), Span(4, 5)),
|
||||
(Instruction::load_boolean(1, false, false), Span(22, 27)),
|
||||
(Instruction::define_local(1, 1, false), Span(18, 19)),
|
||||
(Instruction::test(1, true), Span(31, 33)),
|
||||
(Instruction::get_local(2, 0), Span(29, 30)),
|
||||
(Instruction::test(2, true), Span(31, 33)),
|
||||
(Instruction::jump(1, true), Span(31, 33)),
|
||||
(Instruction::r#move(2, 1), Span(31, 33)),
|
||||
(Instruction::get_local(3, 1), Span(34, 35)),
|
||||
],
|
||||
vec![],
|
||||
vec![
|
||||
|
Loading…
Reference in New Issue
Block a user