1
0

Pass all tests

This commit is contained in:
Jeff 2024-10-05 02:07:26 -04:00
parent 9d0aa13e8a
commit d857f42434
4 changed files with 81 additions and 39 deletions

View File

@ -437,7 +437,13 @@ impl<'a> ChunkDisassembler<'a> {
};
let jump_offset = if let Some(jump_offset) = jump_offset {
let index = index as isize;
let jump_index = index + jump_offset + 1;
let jump_index = {
if jump_offset > 0 {
index + (jump_offset + 1)
} else {
index + jump_offset
}
};
format!("{index} -> {jump_index}")
} else {

View File

@ -345,11 +345,13 @@ impl<'src> Parser<'src> {
fn handle_binary_argument(
&mut self,
instruction: &Instruction,
) -> Result<(bool, bool, u8), ParseError> {
) -> Result<(bool, bool, bool, u8), ParseError> {
let mut push_back = false;
let mut is_constant = false;
let mut is_local = false;
let argument = match instruction.operation() {
Operation::GetLocal => {
is_local = true;
let local_index = instruction.b();
let local = self.chunk.get_local(local_index, self.current_position)?;
@ -378,13 +380,13 @@ impl<'src> Parser<'src> {
}
};
Ok((push_back, is_constant, argument))
Ok((push_back, is_constant, is_local, argument))
}
fn parse_math_binary(&mut self) -> Result<(), ParseError> {
let (left_instruction, left_position) =
self.chunk.pop_instruction(self.current_position)?;
let (push_back_left, left_is_constant, left) =
let (push_back_left, left_is_constant, left_is_local, left) =
self.handle_binary_argument(&left_instruction)?;
let operator = self.current_token;
@ -394,12 +396,21 @@ impl<'src> Parser<'src> {
self.advance()?;
self.parse(rule.precedence.increment())?;
let register = if left_is_local {
left
} else {
let current = self.current_register;
self.increment_register()?;
current
};
let mut new_instruction = match operator.kind() {
TokenKind::Plus => Instruction::add(self.current_register, left, 0),
TokenKind::Minus => Instruction::subtract(self.current_register, left, 0),
TokenKind::Star => Instruction::multiply(self.current_register, left, 0),
TokenKind::Slash => Instruction::divide(self.current_register, left, 0),
TokenKind::Percent => Instruction::modulo(self.current_register, left, 0),
TokenKind::Plus => Instruction::add(register, left, 0),
TokenKind::Minus => Instruction::subtract(register, left, 0),
TokenKind::Star => Instruction::multiply(register, left, 0),
TokenKind::Slash => Instruction::divide(register, left, 0),
TokenKind::Percent => Instruction::modulo(register, left, 0),
_ => {
return Err(ParseError::ExpectedTokenMultiple {
expected: &[
@ -415,11 +426,9 @@ impl<'src> Parser<'src> {
}
};
self.increment_register()?;
let (right_instruction, right_position) =
self.chunk.pop_instruction(self.current_position)?;
let (push_back_right, right_is_constant, right) =
let (push_back_right, right_is_constant, right_is_local, right) =
self.handle_binary_argument(&right_instruction)?;
new_instruction.set_c(right);
@ -476,7 +485,7 @@ impl<'src> Parser<'src> {
fn parse_comparison_binary(&mut self) -> Result<(), ParseError> {
let (left_instruction, left_position) =
self.chunk.pop_instruction(self.current_position)?;
let (push_back_left, left_is_constant, left) =
let (push_back_left, left_is_constant, _, left) =
self.handle_binary_argument(&left_instruction)?;
let operator = self.current_token;
@ -510,7 +519,7 @@ impl<'src> Parser<'src> {
let (right_instruction, right_position) =
self.chunk.pop_instruction(self.current_position)?;
let (push_back_right, right_is_constant, right) =
let (push_back_right, right_is_constant, _, right) =
self.handle_binary_argument(&right_instruction)?;
instruction.set_c(right);
@ -771,14 +780,14 @@ impl<'src> Parser<'src> {
self.parse_block(allow_assignment, allow_return)?;
let jump_end = self.chunk.len();
let jump_distance = jump_end.saturating_sub(jump_start) as u8;
let jump_distance = jump_end.abs_diff(jump_start) as u8;
let jump_back = Instruction::jump(jump_distance, false);
let jump_over_index = self.chunk.find_last_instruction(Operation::Jump);
if let Some(index) = jump_over_index {
let (mut jump_over, jump_over_position) = self.chunk.remove_instruction(index);
let (_, jump_over_position) = self.chunk.remove_instruction(index);
let jump_over = Instruction::jump(jump_distance - 1, true);
jump_over.set_b(jump_distance);
self.chunk
.insert_instruction(index, jump_over, jump_over_position);
}

View File

@ -356,7 +356,7 @@ impl Vm {
let new_ip = if is_positive {
self.ip + offset as usize
} else {
self.ip - offset as usize
self.ip - (offset + 1) as usize
};
self.ip = new_ip;

View File

@ -332,7 +332,33 @@ fn if_else_expression() {
}
#[test]
fn if_expression() {
fn if_expression_false() {
let source = "if 1 == 2 { 2 }";
assert_eq!(
parse(source),
Ok(Chunk::with_data(
vec![
(
*Instruction::equal(true, 0, 1)
.set_b_is_constant()
.set_c_is_constant(),
Span(5, 7)
),
(Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2, false), Span(12, 13)),
(Instruction::r#return(), Span(15, 15)),
],
vec![Value::integer(1), Value::integer(2), Value::integer(2)],
vec![]
)),
);
assert_eq!(run(source), Ok(None));
}
#[test]
fn if_expression_true() {
let source = "if 1 == 1 { 2 }";
assert_eq!(
@ -730,12 +756,15 @@ fn subtract() {
assert_eq!(
parse(source),
Ok(Chunk::with_data(
vec![(
vec![
(
*Instruction::subtract(0, 0, 1)
.set_b_is_constant()
.set_c_is_constant(),
Span(2, 3)
),],
),
(Instruction::r#return(), Span(5, 5)),
],
vec![Value::integer(1), Value::integer(2)],
vec![]
))
@ -759,6 +788,7 @@ fn variable_and() {
(Instruction::test(2, false), Span(31, 33)),
(Instruction::jump(1, true), Span(31, 33)),
(Instruction::get_local(3, 1), Span(34, 35)),
(Instruction::r#return(), Span(35, 35)),
],
vec![],
vec![
@ -779,23 +809,20 @@ fn r#while() {
parse(source),
Ok(Chunk::with_data(
vec![
(Instruction::load_constant(0, 0, false), Span(0, 1)),
(Instruction::define_local(0, 0, true), Span(0, 0)),
(Instruction::load_constant(0, 0, false), Span(12, 13)),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
*Instruction::less(false, 0, 1)
.set_b_is_constant()
.set_c_is_constant(),
Span(0, 1)
*Instruction::less(true, 0, 1).set_c_is_constant(),
Span(23, 24)
),
(Instruction::jump(1, true), Span(0, 1)),
(Instruction::load_boolean(1, true, true), Span(0, 1)),
(Instruction::load_boolean(1, false, false), Span(0, 1)),
(Instruction::add(0, 0, 2), Span(0, 1)),
(Instruction::jump(0, false), Span(0, 1)),
(Instruction::get_local(3, 0), Span(0, 1)),
(Instruction::jump(2, true), Span(23, 24)),
(*Instruction::add(0, 0, 2).set_c_is_constant(), Span(39, 40)),
(Instruction::jump(3, false), Span(41, 42)),
(Instruction::get_local(1, 0), Span(41, 42)),
(Instruction::r#return(), Span(42, 42)),
],
vec![],
vec![]
vec![Value::integer(0), Value::integer(5), Value::integer(1),],
vec![Local::new(Identifier::new("x"), true, 0, Some(0)),]
)),
);