1
0

Refactor register incrementing/decrementing

This commit is contained in:
Jeff 2024-09-23 11:15:49 -04:00
parent d68c789ea8
commit 182ef66f23
3 changed files with 32 additions and 80 deletions

View File

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

View File

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

View File

@ -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![