From 182ef66f237961d1f88e4bef23b9fa81ee77436e Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 23 Sep 2024 11:15:49 -0400 Subject: [PATCH] Refactor register incrementing/decrementing --- dust-lang/src/instruction.rs | 2 +- dust-lang/src/parser/mod.rs | 83 ++++++++++------------------------- dust-lang/src/parser/tests.rs | 27 ++++-------- 3 files changed, 32 insertions(+), 80 deletions(-) diff --git a/dust-lang/src/instruction.rs b/dust-lang/src/instruction.rs index 745e31e..c15fc0a 100644 --- a/dust-lang/src/instruction.rs +++ b/dust-lang/src/instruction.rs @@ -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) } diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index 082684c..e0b1cd5 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -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); + if let Operation::LoadBoolean = right_instruction.operation() { + right_instruction.set_second_argument_to_boolean(true); } + 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, - ); - } + self.emit_instruction(right_instruction, right_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 diff --git a/dust-lang/src/parser/tests.rs b/dust-lang/src/parser/tests.rs index 87c4092..e39fa00 100644 --- a/dust-lang/src/parser/tests.rs +++ b/dust-lang/src/parser/tests.rs @@ -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![