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 jump_offset = if let Some(jump_offset) = jump_offset {
let index = index as isize; 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}") format!("{index} -> {jump_index}")
} else { } else {

View File

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

View File

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

View File

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