diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 901c783..0ed0860 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -64,6 +64,8 @@ pub enum BinaryOperation { NotEqual, And, Or, + GreaterThanEquals, + LessThanEquals } #[derive(Debug, Clone)] diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 05d529c..bcb1027 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -33,6 +33,8 @@ pub enum Instruction { Divide, Negate, Greater, + GreaterThanEquals, + LessThanEquals, Less, Equal, NotEqual, @@ -92,6 +94,8 @@ fn compile_expr(instructions: &mut Vec, expr: &Expression) { instructions[jump_instructions_index] = Instruction::JumpIfTrue(instructions.len()); } + BinaryOperation::GreaterThanEquals => instructions.push(Instruction::GreaterThanEquals), + BinaryOperation::LessThanEquals => instructions.push(Instruction::LessThanEquals), } } Expression::Unary { op, expr } => { diff --git a/src/main.rs b/src/main.rs index d3c14cf..c34ac7e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,7 @@ fn main() { let filename = &run_args[2]; let source = std::fs::read_to_string(filename).expect("Failed to read source file"); let tokens = tokenize(&source); + // println!("{:?}", tokens); let mut parser = Parser::new(tokens); let ast = parser.parse(); // println!("Parsed AST: {:#?}", ast); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index b8e9363..4c22973 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -16,16 +16,6 @@ fn is_arithmetic_operator(tkn: &Token) -> Option { } } -fn is_compare_operator(tkn: &Token) -> Option { - match tkn { - Token::Greater => Some(BinaryOperation::Greater), - Token::Less => Some(BinaryOperation::Less), - Token::EqualEqual => Some(BinaryOperation::Equal), - Token::NotEqual => Some(BinaryOperation::NotEqual), - _ => None, - } -} - impl Parser { pub fn new(tokens: Vec) -> Self { Self { tokens, pos: 0 } @@ -51,6 +41,54 @@ impl Parser { statements } + fn parse_comparison(&mut self) -> Expression { + let mut left = self.parse_expression(); + + loop { + let op = match self.peek() { + Some(Token::Greater) => { + self.advance(); + if let Some(Token::Equals) = self.peek() { + self.advance(); + Some(BinaryOperation::GreaterThanEquals) + } else { + Some(BinaryOperation::Greater) + } + } + Some(Token::Less) => { + self.advance(); + if let Some(Token::Equals) = self.peek() { + self.advance(); + Some(BinaryOperation::LessThanEquals) + } else { + Some(BinaryOperation::Less) + } + } + Some(Token::EqualEqual) => { + self.advance(); + Some(BinaryOperation::Equal) + } + Some(Token::NotEqual) => { + self.advance(); + Some(BinaryOperation::NotEqual) + } + _ => None, + }; + + if let Some(opr) = op { + let right = self.parse_expression(); + left = Expression::Binary { + left: Box::new(left), + op: opr, + right: Box::new(right), + }; + } else { + break; + } + } + left + } + fn parse_statement(&mut self) -> Statement { match self.peek() { Some(Token::Let) => self.parse_var_decl(), @@ -280,25 +318,6 @@ impl Parser { left } - fn parse_comparison(&mut self) -> Expression { - let mut left = self.parse_expression(); - - while let Some(token) = self.peek() { - if let Some(opr) = is_compare_operator(token) { - self.advance(); - let right = self.parse_expression(); - left = Expression::Binary { - left: Box::new(left), - op: opr, - right: Box::new(right), - }; - } else { - break; - } - } - left - } - fn parse_expression(&mut self) -> Expression { let mut left = self.parse_term(); diff --git a/src/vm/mod.rs b/src/vm/mod.rs index a1a8be3..b716fea 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -170,6 +170,26 @@ impl Runtime { panic!("Greater comparison is only supported between values of the same type"); } } + BinaryOperation::GreaterThanEquals => { + if matches!( + (&value1, &value2), + (Value::Number(_), Value::Number(_)) | (Value::String(_), Value::String(_)) + ) { + value2 >= value1 + } else { + panic!("Greater comparison is only supported between values of the same type"); + } + } + BinaryOperation::LessThanEquals => { + if matches!( + (&value1, &value2), + (Value::Number(_), Value::Number(_)) | (Value::String(_), Value::String(_)) + ) { + value2 <= value1 + } else { + panic!("Less comparison is only supported between values of the same type"); + } + } BinaryOperation::Less => { if matches!( (&value1, &value2), @@ -246,6 +266,12 @@ pub fn execute(program: Program, runtime: &mut Runtime) { Instruction::Greater => { runtime.compare_opr(BinaryOperation::Greater); } + Instruction::GreaterThanEquals => { + runtime.compare_opr(BinaryOperation::GreaterThanEquals); + } + Instruction::LessThanEquals => { + runtime.compare_opr(BinaryOperation::LessThanEquals); + } Instruction::Less => { runtime.compare_opr(BinaryOperation::Less); } diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index e605975..feb6d2d 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1358,3 +1358,31 @@ print obj.inner["val"]; let out = run_rts(code); assert_eq!(out, "5"); } + +#[test] +fn test_greater_than_equals() { + let code = r#" +let a = 10; +let b = 10; +let c = 9; +print a >= b; +print a >= c; +print c >= a; +"#; + let out = run_rts(code); + assert_eq!(out, "1\n1\n0"); +} + +#[test] +fn test_less_than_equals() { + let code = r#" +let a = 10; +let b = 10; +let c = 11; +print a <= b; +print a <= c; +print c <= a; +"#; + let out = run_rts(code); + assert_eq!(out, "1\n1\n0"); +}