feat(tazjin/rlox): Implement comparison operators

Change-Id: I03b751db52a3bd502fb4fbda6e89cad087ccad74
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2575
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2021-02-28 16:00:01 +02:00 committed by tazjin
parent c58fe2093e
commit 369f504250
4 changed files with 43 additions and 0 deletions

View file

@ -128,6 +128,22 @@ fn rule_for<T: Iterator<Item = Token>>(token: &TokenKind) -> ParseRule<T> {
ParseRule::new(None, Some(Compiler::binary), Precedence::Equality)
}
TokenKind::Greater => {
ParseRule::new(None, Some(Compiler::binary), Precedence::Comparison)
}
TokenKind::GreaterEqual => {
ParseRule::new(None, Some(Compiler::binary), Precedence::Comparison)
}
TokenKind::Less => {
ParseRule::new(None, Some(Compiler::binary), Precedence::Comparison)
}
TokenKind::LessEqual => {
ParseRule::new(None, Some(Compiler::binary), Precedence::Comparison)
}
_ => ParseRule::new(None, None, Precedence::None),
}
}
@ -209,6 +225,18 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
}
TokenKind::EqualEqual => self.emit_op(OpCode::OpEqual),
TokenKind::Greater => self.emit_op(OpCode::OpGreater),
TokenKind::GreaterEqual => {
self.emit_op(OpCode::OpLess);
self.emit_op(OpCode::OpNot);
}
TokenKind::Less => self.emit_op(OpCode::OpLess),
TokenKind::LessEqual => {
self.emit_op(OpCode::OpGreater);
self.emit_op(OpCode::OpNot);
}
_ => unreachable!("only called for binary operator tokens"),
}

View file

@ -14,6 +14,8 @@ pub enum OpCode {
// Boolean & comparison operators
OpNot,
OpEqual,
OpGreater,
OpLess,
/// Unary negation
OpNegate,

View file

@ -88,3 +88,13 @@ fn equality() {
expect_bool("42 == true", false);
expect_bool("!42 == !true", true);
}
#[test]
fn comparisons() {
expect_bool("42 > 23", true);
expect_bool("42 < 23", false);
expect_bool("42 <= 42", true);
expect_bool("42 <= 23", false);
expect_bool("42 >= 42", true);
expect_bool("42 >= 23", true);
}

View file

@ -91,6 +91,9 @@ impl VM {
self.push(Value::Bool(a == b));
}
OpCode::OpLess => binary_op!(self, Number, Bool, <),
OpCode::OpGreater => binary_op!(self, Number, Bool, >),
OpCode::OpNegate => {
let v = self.pop();
with_type!(