Write tests
This commit is contained in:
parent
5441938725
commit
1d03876b89
@ -162,44 +162,8 @@ impl<'src> Parser<'src> {
|
||||
|
||||
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(
|
||||
Instruction::load_boolean(self.current_register, boolean, skip),
|
||||
Instruction::load_boolean(self.current_register, boolean, false),
|
||||
position,
|
||||
);
|
||||
|
||||
@ -745,21 +709,12 @@ impl<'src> Parser<'src> {
|
||||
}
|
||||
|
||||
fn parse_if(&mut self, allow_assignment: bool, allow_return: bool) -> Result<(), ParseError> {
|
||||
let position = self.current_position;
|
||||
|
||||
self.advance()?;
|
||||
self.parse_expression()?;
|
||||
|
||||
let (mut condition, condition_position) =
|
||||
self.chunk.pop_instruction(self.current_position)?;
|
||||
|
||||
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);
|
||||
if self.allow(TokenKind::LeftCurlyBrace)? {
|
||||
self.parse_block(allow_assignment, allow_return)?;
|
||||
}
|
||||
|
||||
let jump_position = self.current_position;
|
||||
let jump_start = self.current_register;
|
||||
@ -773,32 +728,16 @@ impl<'src> Parser<'src> {
|
||||
if self.allow(TokenKind::LeftCurlyBrace)? {
|
||||
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)] =
|
||||
self.chunk.get_last_n_operations()
|
||||
{
|
||||
// Do not emit a jump if the last two instructions were LoadBoolean operations. However,
|
||||
// we need to set them to the same destination register and decrement the register count.
|
||||
|
||||
let (mut second_load_boolean, second_position) =
|
||||
self.chunk.pop_instruction(self.current_position)?;
|
||||
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);
|
||||
// Do not emit a jump if the last two instructions were LoadBoolean operations.
|
||||
} else if let [Some(Operation::LoadConstant), Some(Operation::LoadConstant)] =
|
||||
self.chunk.get_last_n_operations()
|
||||
{
|
||||
// Do not emit a jump if the last two instructions were LoadConstant operations.
|
||||
} else {
|
||||
let jump_end = self.current_register;
|
||||
let jump_distance = (jump_end - jump_start).max(1);
|
||||
|
@ -195,8 +195,8 @@ fn equality_assignment_long() {
|
||||
Span(13, 15)
|
||||
),
|
||||
(Instruction::jump(1, true), Span(13, 15)),
|
||||
(Instruction::load_boolean(0, true, true), Span(20, 24)),
|
||||
(Instruction::load_boolean(0, false, false), Span(34, 39)),
|
||||
(Instruction::load_boolean(0, true, true), Span(13, 15)),
|
||||
(Instruction::load_boolean(0, false, false), Span(13, 15)),
|
||||
(Instruction::define_local(0, 0, false), Span(4, 5)),
|
||||
],
|
||||
vec![Value::integer(4), Value::integer(4)],
|
||||
@ -245,10 +245,10 @@ fn if_expression() {
|
||||
Span(5, 7)
|
||||
),
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_constant(0, 2), Span(12, 13)),
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_boolean(0, true, 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![]
|
||||
)),
|
||||
);
|
||||
@ -269,16 +269,10 @@ fn if_else_expression() {
|
||||
Span(5, 7)
|
||||
),
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_constant(0, 2), Span(12, 13)),
|
||||
(Instruction::jump(1, true), Span(5, 7)),
|
||||
(Instruction::load_constant(0, 3), Span(23, 24)),
|
||||
],
|
||||
vec![
|
||||
Value::integer(1),
|
||||
Value::integer(1),
|
||||
Value::integer(2),
|
||||
Value::integer(3)
|
||||
(Instruction::load_boolean(0, true, true), Span(5, 7)),
|
||||
(Instruction::load_boolean(0, false, false), Span(5, 7)),
|
||||
],
|
||||
vec![Value::integer(1), Value::integer(1)],
|
||||
vec![]
|
||||
)),
|
||||
);
|
||||
|
@ -3,7 +3,10 @@ use dust_lang::*;
|
||||
#[test]
|
||||
fn if_expression() {
|
||||
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]
|
||||
|
Loading…
Reference in New Issue
Block a user