Fix and pass tests
This commit is contained in:
parent
9fe3e440ac
commit
c31991cc24
@ -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() {
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user