1
0

Write tests

This commit is contained in:
Jeff 2024-09-24 01:30:21 -04:00
parent 5441938725
commit 1d03876b89
3 changed files with 20 additions and 84 deletions

View File

@ -162,44 +162,8 @@ impl<'src> Parser<'src> {
self.advance()?; self.advance()?;
let previous_operations = self.chunk.get_last_n_operations::<2>();
if let [Some(Operation::LoadBoolean), Some(Operation::LoadBoolean)] = previous_operations {
let (second_boolean, second_position) =
self.chunk.pop_instruction(self.current_position)?;
let (first_boolean, first_position) =
self.chunk.pop_instruction(self.current_position)?;
if first_boolean.first_argument_as_boolean() == boolean {
let skip = first_boolean.second_argument_as_boolean();
self.emit_instruction(
Instruction::load_boolean(self.current_register, boolean, skip),
position,
);
return Ok(());
}
if second_boolean.first_argument_as_boolean() == boolean {
let skip = second_boolean.second_argument_as_boolean();
self.emit_instruction(
Instruction::load_boolean(self.current_register, boolean, skip),
position,
);
return Ok(());
}
self.emit_instruction(first_boolean, first_position);
self.emit_instruction(second_boolean, second_position);
}
let skip = previous_operations[0] == Some(Operation::Jump);
self.emit_instruction( self.emit_instruction(
Instruction::load_boolean(self.current_register, boolean, skip), Instruction::load_boolean(self.current_register, boolean, false),
position, position,
); );
@ -745,22 +709,13 @@ impl<'src> Parser<'src> {
} }
fn parse_if(&mut self, allow_assignment: bool, allow_return: bool) -> Result<(), ParseError> { fn parse_if(&mut self, allow_assignment: bool, allow_return: bool) -> Result<(), ParseError> {
let position = self.current_position;
self.advance()?; self.advance()?;
self.parse_expression()?; self.parse_expression()?;
let (mut condition, condition_position) = if self.allow(TokenKind::LeftCurlyBrace)? {
self.chunk.pop_instruction(self.current_position)?; self.parse_block(allow_assignment, allow_return)?;
if let Operation::LoadBoolean = condition.operation() {
condition.set_second_argument_to_boolean(true);
} }
self.emit_instruction(condition, condition_position);
self.emit_instruction(Instruction::jump(1, true), condition_position);
self.parse_block(allow_assignment, allow_return)?;
let jump_position = self.current_position; let jump_position = self.current_position;
let jump_start = self.current_register; let jump_start = self.current_register;
let jump_index = self.chunk.len(); let jump_index = self.chunk.len();
@ -773,32 +728,16 @@ impl<'src> Parser<'src> {
if self.allow(TokenKind::LeftCurlyBrace)? { if self.allow(TokenKind::LeftCurlyBrace)? {
self.parse_block(allow_assignment, allow_return)?; self.parse_block(allow_assignment, allow_return)?;
} }
return Err(ParseError::ExpectedTokenMultiple {
expected: &[TokenKind::If, TokenKind::LeftCurlyBrace],
found: self.current_token.to_owned(),
position: self.current_position,
});
} }
if let [Some(Operation::LoadBoolean), Some(Operation::LoadBoolean)] = if let [Some(Operation::LoadBoolean), Some(Operation::LoadBoolean)] =
self.chunk.get_last_n_operations() self.chunk.get_last_n_operations()
{ {
// Do not emit a jump if the last two instructions were LoadBoolean operations. However, // Do not emit a jump if the last two instructions were LoadBoolean operations.
// we need to set them to the same destination register and decrement the register count. } else if let [Some(Operation::LoadConstant), Some(Operation::LoadConstant)] =
self.chunk.get_last_n_operations()
let (mut second_load_boolean, second_position) = {
self.chunk.pop_instruction(self.current_position)?; // Do not emit a jump if the last two instructions were LoadConstant operations.
let (first_load_boolean, _) = self.chunk.get_previous().unwrap();
second_load_boolean.set_destination(first_load_boolean.destination());
self.emit_instruction(second_load_boolean, second_position);
} else if let Some(Operation::LoadBoolean) = self.chunk.get_last_operation() {
let (mut load_boolean, position) = self.chunk.pop_instruction(self.current_position)?;
load_boolean.set_second_argument_to_boolean(true);
self.emit_instruction(load_boolean, position);
} else { } else {
let jump_end = self.current_register; let jump_end = self.current_register;
let jump_distance = (jump_end - jump_start).max(1); let jump_distance = (jump_end - jump_start).max(1);

View File

@ -195,8 +195,8 @@ fn equality_assignment_long() {
Span(13, 15) Span(13, 15)
), ),
(Instruction::jump(1, true), Span(13, 15)), (Instruction::jump(1, true), Span(13, 15)),
(Instruction::load_boolean(0, true, true), Span(20, 24)), (Instruction::load_boolean(0, true, true), Span(13, 15)),
(Instruction::load_boolean(0, false, false), Span(34, 39)), (Instruction::load_boolean(0, false, false), Span(13, 15)),
(Instruction::define_local(0, 0, false), Span(4, 5)), (Instruction::define_local(0, 0, false), Span(4, 5)),
], ],
vec![Value::integer(4), Value::integer(4)], vec![Value::integer(4), Value::integer(4)],
@ -245,10 +245,10 @@ fn if_expression() {
Span(5, 7) Span(5, 7)
), ),
(Instruction::jump(1, true), Span(5, 7)), (Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2), Span(12, 13)), (Instruction::load_boolean(0, true, true), Span(5, 7)),
(Instruction::jump(1, true), Span(5, 7)), (Instruction::load_boolean(0, false, false), Span(5, 7)),
], ],
vec![Value::integer(1), Value::integer(1), Value::integer(2)], vec![Value::integer(1), Value::integer(1)],
vec![] vec![]
)), )),
); );
@ -269,16 +269,10 @@ fn if_else_expression() {
Span(5, 7) Span(5, 7)
), ),
(Instruction::jump(1, true), Span(5, 7)), (Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2), Span(12, 13)), (Instruction::load_boolean(0, true, true), Span(5, 7)),
(Instruction::jump(1, true), Span(5, 7)), (Instruction::load_boolean(0, false, false), Span(5, 7)),
(Instruction::load_constant(0, 3), Span(23, 24)),
],
vec![
Value::integer(1),
Value::integer(1),
Value::integer(2),
Value::integer(3)
], ],
vec![Value::integer(1), Value::integer(1)],
vec![] vec![]
)), )),
); );

View File

@ -3,7 +3,10 @@ use dust_lang::*;
#[test] #[test]
fn if_expression() { fn if_expression() {
assert_eq!(run("if true { 1 }"), Ok(Some(Value::integer(1)))); assert_eq!(run("if true { 1 }"), Ok(Some(Value::integer(1))));
assert_eq!(run("if false { 1 }"), Ok(None)); assert_eq!(
run("if 42 == 42 { 1 } else { 2 }"),
Ok(Some(Value::integer(2)))
);
} }
#[test] #[test]