Implement logical and/or operators
This commit is contained in:
parent
c5c2fe95ae
commit
2c485cf046
@ -547,7 +547,68 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_logical_binary(&mut self) -> Result<(), ParseError> {
|
fn parse_logical_binary(&mut self) -> Result<(), ParseError> {
|
||||||
todo!()
|
let (left_instruction, left_position) =
|
||||||
|
self.chunk.pop_instruction(self.current_position)?;
|
||||||
|
let (push_back_left, left_is_constant, _) =
|
||||||
|
self.handle_binary_argument(&left_instruction)?;
|
||||||
|
|
||||||
|
let operator = self.current_token;
|
||||||
|
let operator_position = self.current_position;
|
||||||
|
let rule = ParseRule::from(&operator.kind());
|
||||||
|
|
||||||
|
let mut instruction = match operator.kind() {
|
||||||
|
TokenKind::DoubleAmpersand => Instruction::test(self.current_register, true),
|
||||||
|
TokenKind::DoublePipe => Instruction::test(self.current_register, false),
|
||||||
|
_ => {
|
||||||
|
return Err(ParseError::ExpectedTokenMultiple {
|
||||||
|
expected: &[TokenKind::DoubleAmpersand, TokenKind::DoublePipe],
|
||||||
|
found: operator.to_owned(),
|
||||||
|
position: operator_position,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Operation::LoadBoolean = left_instruction.operation() {
|
||||||
|
self.increment_register()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.advance()?;
|
||||||
|
self.parse(rule.precedence.increment())?;
|
||||||
|
|
||||||
|
let (mut right_instruction, right_position) =
|
||||||
|
self.chunk.pop_instruction(self.current_position)?;
|
||||||
|
let (push_back_right, right_is_constant, _) =
|
||||||
|
self.handle_binary_argument(&right_instruction)?;
|
||||||
|
|
||||||
|
if left_is_constant {
|
||||||
|
instruction.set_first_argument_to_constant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if right_is_constant {
|
||||||
|
if let Operation::LoadBoolean = right_instruction.operation() {
|
||||||
|
right_instruction.set_second_argument_to_boolean(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction.set_second_argument_to_constant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if push_back_left {
|
||||||
|
self.emit_instruction(left_instruction, left_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.emit_instruction(instruction, operator_position);
|
||||||
|
self.emit_instruction(Instruction::jump(1, true), operator_position);
|
||||||
|
|
||||||
|
if push_back_right {
|
||||||
|
self.emit_instruction(right_instruction, right_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.emit_instruction(
|
||||||
|
Instruction::r#move(self.current_register, self.current_register - 1),
|
||||||
|
operator_position,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_variable(
|
fn parse_variable(
|
||||||
|
@ -457,6 +457,7 @@ fn or() {
|
|||||||
parse("true || false"),
|
parse("true || false"),
|
||||||
Ok(Chunk::with_data(
|
Ok(Chunk::with_data(
|
||||||
vec![
|
vec![
|
||||||
|
(Instruction::load_boolean(0, true, false), Span(0, 4)),
|
||||||
(
|
(
|
||||||
*Instruction::test(0, false)
|
*Instruction::test(0, false)
|
||||||
.set_second_argument_to_constant()
|
.set_second_argument_to_constant()
|
||||||
@ -464,8 +465,8 @@ fn or() {
|
|||||||
Span(5, 7)
|
Span(5, 7)
|
||||||
),
|
),
|
||||||
(Instruction::jump(1, true), Span(5, 7)),
|
(Instruction::jump(1, true), Span(5, 7)),
|
||||||
(Instruction::load_boolean(0, true, false), Span(0, 4)),
|
(Instruction::load_boolean(1, false, true), Span(8, 13)),
|
||||||
(Instruction::load_boolean(1, false, false), Span(8, 13)),
|
(Instruction::r#move(1, 0), Span(5, 7)),
|
||||||
],
|
],
|
||||||
vec![],
|
vec![],
|
||||||
vec![]
|
vec![]
|
||||||
@ -479,6 +480,7 @@ fn and() {
|
|||||||
parse("true && false"),
|
parse("true && false"),
|
||||||
Ok(Chunk::with_data(
|
Ok(Chunk::with_data(
|
||||||
vec![
|
vec![
|
||||||
|
(Instruction::load_boolean(0, true, false), Span(0, 4)),
|
||||||
(
|
(
|
||||||
*Instruction::test(0, true)
|
*Instruction::test(0, true)
|
||||||
.set_second_argument_to_constant()
|
.set_second_argument_to_constant()
|
||||||
@ -486,8 +488,8 @@ fn and() {
|
|||||||
Span(5, 7)
|
Span(5, 7)
|
||||||
),
|
),
|
||||||
(Instruction::jump(1, true), Span(5, 7)),
|
(Instruction::jump(1, true), Span(5, 7)),
|
||||||
(Instruction::load_boolean(0, true, false), Span(0, 4)),
|
(Instruction::load_boolean(1, false, true), Span(8, 13)),
|
||||||
(Instruction::load_boolean(1, false, false), Span(8, 13)),
|
(Instruction::r#move(1, 0), Span(5, 7)),
|
||||||
],
|
],
|
||||||
vec![],
|
vec![],
|
||||||
vec![]
|
vec![]
|
||||||
|
@ -86,7 +86,7 @@ impl Vm {
|
|||||||
|
|
||||||
self.insert(value, to_register, position)?;
|
self.insert(value, to_register, position)?;
|
||||||
|
|
||||||
if boolean && skip {
|
if skip {
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user