1
0

Implement logical and/or operators

This commit is contained in:
Jeff 2024-09-23 04:01:36 -04:00
parent c5c2fe95ae
commit 2c485cf046
3 changed files with 69 additions and 6 deletions

View File

@ -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(

View File

@ -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![]

View File

@ -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;
} }
} }