1
0

Fix and pass tests

This commit is contained in:
Jeff 2024-09-23 23:38:49 -04:00
parent 9fe3e440ac
commit c31991cc24
3 changed files with 35 additions and 53 deletions

View File

@ -467,7 +467,7 @@ impl Instruction {
let (first_argument, second_argument) = format_arguments(); let (first_argument, second_argument) = format_arguments();
format!("if {first_argument} {comparison_symbol} {second_argument} {{ IP += 1 }}",) format!("if {first_argument} {comparison_symbol} {second_argument} IP++",)
} }
Operation::Less => { Operation::Less => {
let comparison_symbol = if self.destination_as_boolean() { let comparison_symbol = if self.destination_as_boolean() {

View File

@ -384,12 +384,7 @@ impl<'src> Parser<'src> {
instruction.first_argument() instruction.first_argument()
} }
Operation::LoadBoolean => { Operation::LoadBoolean => instruction.destination(),
is_constant = true;
push_back = true;
instruction.destination()
}
Operation::Close => { Operation::Close => {
return Err(ParseError::ExpectedExpression { return Err(ParseError::ExpectedExpression {
found: self.previous_token.to_owned(), found: self.previous_token.to_owned(),
@ -470,26 +465,20 @@ impl<'src> Parser<'src> {
} }
fn parse_comparison_binary(&mut self) -> Result<(), ParseError> { fn parse_comparison_binary(&mut self) -> Result<(), ParseError> {
let (previous_booleans, equal_argument) = if let [Some(Operation::LoadBoolean), Some(Operation::LoadBoolean), Some(Operation::Jump), Some(Operation::Equal)] = let is_repetition = matches!(
self.chunk.get_last_n_operations() self.chunk.get_last_n_operations(),
{ [
let load_booleans = ( Some(_),
self.chunk.pop_instruction(self.current_position)?, Some(_),
self.chunk.pop_instruction(self.current_position)?, Some(Operation::Jump),
); Some(Operation::Equal | Operation::Less | Operation::LessEqual)
]
);
let (jump, jump_position) = self.chunk.pop_instruction(self.current_position)?; if is_repetition {
let (equal, equal_position) = self.chunk.pop_instruction(self.current_position)?; self.decrement_register()?;
let equal_argument = equal.second_argument(); self.decrement_register()?;
let is_constant = equal.second_argument_is_constant(); }
self.emit_instruction(equal, equal_position);
self.emit_instruction(jump, jump_position);
(Some(load_booleans), Some((equal_argument, is_constant)))
} else {
(None, None)
};
let (left_instruction, left_position) = let (left_instruction, left_position) =
self.chunk.pop_instruction(self.current_position)?; self.chunk.pop_instruction(self.current_position)?;
@ -532,13 +521,7 @@ impl<'src> Parser<'src> {
instruction.set_second_argument(right); instruction.set_second_argument(right);
if let Some((equal_argument, is_constant)) = equal_argument { if left_is_constant {
instruction.set_first_argument(equal_argument);
if is_constant {
instruction.set_first_argument_to_constant();
}
} else if left_is_constant {
instruction.set_first_argument_to_constant(); instruction.set_first_argument_to_constant();
} }
@ -546,25 +529,24 @@ impl<'src> Parser<'src> {
instruction.set_second_argument_to_constant(); instruction.set_second_argument_to_constant();
} }
if push_back_left { if push_back_left || push_back_right {
self.emit_instruction(left_instruction, left_position); if push_back_left {
self.increment_register()?; self.emit_instruction(left_instruction, left_position);
} }
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);
self.emit_instruction(Instruction::jump(1, true), operator_position); self.emit_instruction(Instruction::jump(1, true), operator_position);
self.emit_instruction(
if let Some(((left_boolean, left_position), (right_boolean, right_position))) = Instruction::r#move(self.current_register, instruction.destination()),
previous_booleans operator_position,
{ );
self.emit_instruction(right_boolean, right_position);
self.emit_instruction(left_boolean, left_position);
} else { } else {
self.emit_instruction(instruction, operator_position);
self.emit_instruction(Instruction::jump(1, true), operator_position);
self.emit_instruction( self.emit_instruction(
Instruction::load_boolean(self.current_register, true, true), Instruction::load_boolean(self.current_register, true, true),
operator_position, operator_position,

View File

@ -37,7 +37,7 @@ impl Vm {
} }
pub fn run(&mut self) -> Result<Option<Value>, VmError> { pub fn run(&mut self) -> Result<Option<Value>, VmError> {
// DRY helper to take constants or clone registers for binary operations // DRY helper to get constant or register values for binary operations
fn get_arguments( fn get_arguments(
vm: &mut Vm, vm: &mut Vm,
instruction: Instruction, instruction: Instruction,
@ -225,7 +225,7 @@ impl Vm {
let compare_to = instruction.destination_as_boolean(); let compare_to = instruction.destination_as_boolean();
if let Some(boolean) = equal.as_boolean() { if let Some(boolean) = equal.as_boolean() {
if boolean == compare_to { if boolean && compare_to {
self.ip += 1; self.ip += 1;
} }
} }
@ -235,7 +235,7 @@ impl Vm {
let less = left let less = left
.less_than(right) .less_than(right)
.map_err(|error| VmError::Value { error, position })?; .map_err(|error| VmError::Value { error, position })?;
let compare_to = instruction.destination() != 0; let compare_to = instruction.destination_as_boolean();
if let Some(boolean) = less.as_boolean() { if let Some(boolean) = less.as_boolean() {
if boolean == compare_to { if boolean == compare_to {
@ -248,7 +248,7 @@ impl Vm {
let less_equal = left let less_equal = left
.less_than_or_equal(right) .less_than_or_equal(right)
.map_err(|error| VmError::Value { error, position })?; .map_err(|error| VmError::Value { error, position })?;
let compare_to = instruction.destination() != 0; let compare_to = instruction.destination_as_boolean();
if let Some(boolean) = less_equal.as_boolean() { if let Some(boolean) = less_equal.as_boolean() {
if boolean == compare_to { if boolean == compare_to {