Skip to content

Commit

Permalink
Logical expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
lgyanf committed Oct 8, 2023
1 parent e57ad01 commit 0f33f92
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
6 changes: 6 additions & 0 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub enum BinaryOp {
LessEqual,
EqualEqual,
BangEqual,
And,
Or,
}

impl Display for BinaryOp {
Expand All @@ -32,6 +34,8 @@ impl Display for BinaryOp {
BinaryOp::LessEqual => "<=",
BinaryOp::EqualEqual => "==",
BinaryOp::BangEqual => "!=",
BinaryOp::And => "and",
BinaryOp::Or => "or",
};
write!(f, "{}", s)
}
Expand All @@ -48,6 +52,8 @@ impl From<Token> for BinaryOp {
TokenType::GreaterEqual => Self::GreaterEqual,
TokenType::Less => Self::Less,
TokenType::LessEqual => Self::LessEqual,
TokenType::And => Self::And,
TokenType::Or => Self::Or,
_ => unreachable!(
"Cannot create binary operator from {} at {:?}",
t.type_, t.position
Expand Down
28 changes: 27 additions & 1 deletion src/ast/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ impl Parser<'_> {
}

fn assignment(&mut self) -> Result<Expr, LoxError> {
let expr = self.equality()?;
let expr = self.or()?;

if let Some(_equals) = self.consume_if_matches(&[TokenType::Equal]) {
let value = self.assignment()?;
Expand All @@ -211,6 +211,32 @@ impl Parser<'_> {
}
}

fn or(&mut self) -> Result<Expr, LoxError> {
let mut left = self.and()?;
while let Some(operator) = self.consume_if_matches(&[TokenType::Or]) {
let right = self.and()?;
left = Expr {
expr_type: ExprType::Binary(
left.boxed(), BinaryOp::from(operator), right.boxed()
),
position: PositionRange::from_bounds(&left.position, &right.position)
}
}
Ok(left)
}

fn and(&mut self) -> Result<Expr, LoxError> {
let mut left = self.equality()?;
while let Some(operator) = self.consume_if_matches(&[TokenType::And]) {
let right = self.equality()?;
left = Expr {
expr_type: ExprType::Binary(left.boxed(), BinaryOp::from(operator), right.boxed()),
position: PositionRange::from_bounds(&left.position, &right.position),
}
}
Ok(left)
}

fn equality(&mut self) -> Result<Expr, LoxError> {
let mut left = self.comparison()?;
while let Some(operator) =
Expand Down
33 changes: 33 additions & 0 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl<'a> Interpreter<'a> {
match value {
Value::Nil => false,
Value::Boolean(b) => *b,
Value::Number(f) => *f > 0.0,
_ => true,
}
}
Expand All @@ -90,6 +91,8 @@ impl<'a> Interpreter<'a> {
}
(_, BinaryOp::EqualEqual, _) => Ok(Value::Boolean(left_value == right_value)),
(_, BinaryOp::BangEqual, _) => Ok(Value::Boolean(left_value != right_value)),
(_, BinaryOp::And, _) => Ok(Value::Boolean(Self::is_truthy(&left_value) && Self::is_truthy(&right_value))),
(_, BinaryOp::Or, _) => Ok(Value::Boolean(Self::is_truthy(&left_value) || Self::is_truthy(&right_value))),
_ => Err(LoxError {
kind: LoxErrorKind::Runtime,
position: position.clone(),
Expand Down Expand Up @@ -120,6 +123,8 @@ impl<'a> Interpreter<'a> {
BinaryOp::LessEqual => Value::Boolean(left <= right),
BinaryOp::EqualEqual => Value::Boolean(left == right),
BinaryOp::BangEqual => Value::Boolean(left != right),
BinaryOp::And => Value::Boolean((left > 0.) && (right > 0.)),
BinaryOp::Or => Value::Boolean((left > 0.) || (right > 0.)),
}
}

Expand Down Expand Up @@ -428,5 +433,33 @@ global c
Ok(()),
"false\n",
),
or_statement: (
"var a = true;
var b = false;
print a or b;",
Ok(()),
"true\n",
),
or_statement_false: (
"var a = false;
var b = false;
print a or b;",
Ok(()),
"false\n",
),
and_statement: (
"var a = true;
var b = true;
print a and b;",
Ok(()),
"true\n",
),
and_statement_false: (
"var a = true;
var b = false;
print a and b;",
Ok(()),
"false\n",
),
);
}

0 comments on commit 0f33f92

Please sign in to comment.