feat(tazjin/rlox): Implement equality operator
Change-Id: I5587a11646e228c5af4dc7ca6da026bb4a2592a6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2574 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									93c30b339c
								
							
						
					
					
						commit
						c58fe2093e
					
				
					 4 changed files with 50 additions and 6 deletions
				
			
		|  | @ -120,6 +120,14 @@ fn rule_for<T: Iterator<Item = Token>>(token: &TokenKind) -> ParseRule<T> { | ||||||
|             ParseRule::new(Some(Compiler::unary), None, Precedence::None) |             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), |         _ => 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::Plus => self.emit_op(OpCode::OpAdd), | ||||||
|             TokenKind::Star => self.emit_op(OpCode::OpMultiply), |             TokenKind::Star => self.emit_op(OpCode::OpMultiply), | ||||||
|             TokenKind::Slash => self.emit_op(OpCode::OpDivide), |             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"), |             _ => unreachable!("only called for binary operator tokens"), | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,8 +11,9 @@ pub enum OpCode { | ||||||
|     /// Return from the current function.
 |     /// Return from the current function.
 | ||||||
|     OpReturn, |     OpReturn, | ||||||
| 
 | 
 | ||||||
|     // Boolean operators
 |     // Boolean & comparison operators
 | ||||||
|     OpNot, |     OpNot, | ||||||
|  |     OpEqual, | ||||||
| 
 | 
 | ||||||
|     /// Unary negation
 |     /// Unary negation
 | ||||||
|     OpNegate, |     OpNegate, | ||||||
|  |  | ||||||
|  | @ -14,6 +14,10 @@ fn expect_num(code: &str, value: f64) { | ||||||
|     expect(code, Value::Number(value)) |     expect(code, Value::Number(value)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn expect_bool(code: &str, value: bool) { | ||||||
|  |     expect(code, Value::Bool(value)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[test] | #[test] | ||||||
| fn numbers() { | fn numbers() { | ||||||
|     expect_num("1", 1.0); |     expect_num("1", 1.0); | ||||||
|  | @ -61,9 +65,26 @@ fn trivial_literals() { | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn negation() { | fn negation() { | ||||||
|     expect("!true", Value::Bool(false)); |     expect_bool("!true", false); | ||||||
|     expect("!false", Value::Bool(true)); |     expect_bool("!false", true); | ||||||
|     expect("!nil", Value::Bool(true)); |     expect_bool("!nil", true); | ||||||
|     expect("!13.5", Value::Bool(false)); |     expect_bool("!13.5", false); | ||||||
|     expect("!-42", Value::Bool(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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -85,6 +85,12 @@ impl VM { | ||||||
|                     self.push(Value::Bool(v.is_falsey())); |                     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 => { |                 OpCode::OpNegate => { | ||||||
|                     let v = self.pop(); |                     let v = self.pop(); | ||||||
|                     with_type!( |                     with_type!( | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue