diff options
-rw-r--r-- | users/tazjin/rlox/src/bytecode/compiler.rs | 16 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/opcode.rs | 3 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/tests.rs | 31 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/vm.rs | 6 |
4 files changed, 50 insertions, 6 deletions
diff --git a/users/tazjin/rlox/src/bytecode/compiler.rs b/users/tazjin/rlox/src/bytecode/compiler.rs index 1ab42c705ab4..8eef40f0e669 100644 --- a/users/tazjin/rlox/src/bytecode/compiler.rs +++ b/users/tazjin/rlox/src/bytecode/compiler.rs @@ -120,6 +120,14 @@ fn rule_for<T: Iterator<Item = Token>>(token: &TokenKind) -> ParseRule<T> { ParseRule::new(Some(Compiler::unary), None, Precedence::None) } + TokenKind::BangEqual => { + ParseRule::new(None, Some(Compiler::binary), Precedence::Equality) + } + + TokenKind::EqualEqual => { + ParseRule::new(None, Some(Compiler::binary), Precedence::Equality) + } + _ => ParseRule::new(None, None, Precedence::None), } } @@ -194,6 +202,14 @@ impl<T: Iterator<Item = Token>> Compiler<T> { TokenKind::Plus => self.emit_op(OpCode::OpAdd), TokenKind::Star => self.emit_op(OpCode::OpMultiply), TokenKind::Slash => self.emit_op(OpCode::OpDivide), + + TokenKind::BangEqual => { + self.emit_op(OpCode::OpEqual); + self.emit_op(OpCode::OpNot); + } + + TokenKind::EqualEqual => self.emit_op(OpCode::OpEqual), + _ => unreachable!("only called for binary operator tokens"), } diff --git a/users/tazjin/rlox/src/bytecode/opcode.rs b/users/tazjin/rlox/src/bytecode/opcode.rs index a4a4871a2cc2..e50fdfed9338 100644 --- a/users/tazjin/rlox/src/bytecode/opcode.rs +++ b/users/tazjin/rlox/src/bytecode/opcode.rs @@ -11,8 +11,9 @@ pub enum OpCode { /// Return from the current function. OpReturn, - // Boolean operators + // Boolean & comparison operators OpNot, + OpEqual, /// Unary negation OpNegate, diff --git a/users/tazjin/rlox/src/bytecode/tests.rs b/users/tazjin/rlox/src/bytecode/tests.rs index d02f021ff0fd..500779301b04 100644 --- a/users/tazjin/rlox/src/bytecode/tests.rs +++ b/users/tazjin/rlox/src/bytecode/tests.rs @@ -14,6 +14,10 @@ fn expect_num(code: &str, value: f64) { expect(code, Value::Number(value)) } +fn expect_bool(code: &str, value: bool) { + expect(code, Value::Bool(value)) +} + #[test] fn numbers() { expect_num("1", 1.0); @@ -61,9 +65,26 @@ fn trivial_literals() { #[test] fn negation() { - expect("!true", Value::Bool(false)); - expect("!false", Value::Bool(true)); - expect("!nil", Value::Bool(true)); - expect("!13.5", Value::Bool(false)); - expect("!-42", Value::Bool(false)); + expect_bool("!true", false); + expect_bool("!false", true); + expect_bool("!nil", true); + expect_bool("!13.5", false); + expect_bool("!-42", false); +} + +#[test] +fn equality() { + expect_bool("42 == 42", true); + expect_bool("42 != 42", false); + expect_bool("42 == 42.0", true); + + expect_bool("true == true", true); + expect_bool("true == false", false); + expect_bool("true == !false", true); + expect_bool("true != true", false); + expect_bool("true != false", true); + + expect_bool("42 == false", false); + expect_bool("42 == true", false); + expect_bool("!42 == !true", true); } diff --git a/users/tazjin/rlox/src/bytecode/vm.rs b/users/tazjin/rlox/src/bytecode/vm.rs index acfb522a9c47..0b24dc46cdb9 100644 --- a/users/tazjin/rlox/src/bytecode/vm.rs +++ b/users/tazjin/rlox/src/bytecode/vm.rs @@ -85,6 +85,12 @@ impl VM { self.push(Value::Bool(v.is_falsey())); } + OpCode::OpEqual => { + let b = self.pop(); + let a = self.pop(); + self.push(Value::Bool(a == b)); + } + OpCode::OpNegate => { let v = self.pop(); with_type!( |