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