Write tests
This commit is contained in:
parent
5441938725
commit
1d03876b89
@ -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);
|
||||||
|
@ -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![]
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user