mago_syntax/utils/
condition.rs

1use crate::ast::*;
2
3/// Determine if an expression is truthy.
4///
5/// This function will return true if the expression is truthy, and false otherwise.
6///
7/// When this function returns true, it does not necessarily mean that the expression will always evaluate to true.
8/// It simply means that the expression is truthy in the context of PHP.
9#[inline]
10pub fn is_truthy(expression: &Expression<'_>) -> bool {
11    match &expression {
12        Expression::Parenthesized(parenthesized) => is_truthy(parenthesized.expression),
13        Expression::Literal(Literal::True(_)) => true,
14        Expression::AnonymousClass(_) => true,
15        Expression::Closure(_) => true,
16        Expression::ArrowFunction(_) => true,
17        Expression::Array(array) => !array.elements.is_empty(),
18        Expression::LegacyArray(array) => !array.elements.is_empty(),
19        Expression::ClosureCreation(_) => true,
20        Expression::Binary(operation) => match operation.operator {
21            BinaryOperator::Or(_) | BinaryOperator::LowOr(_) => is_truthy(operation.lhs) || is_truthy(operation.rhs),
22            BinaryOperator::And(_) | BinaryOperator::LowAnd(_) => is_truthy(operation.lhs) && is_truthy(operation.rhs),
23            BinaryOperator::NullCoalesce(_) => is_truthy(operation.lhs),
24            BinaryOperator::LowXor(_) => is_truthy(operation.lhs) ^ is_truthy(operation.rhs),
25            _ => false,
26        },
27        Expression::UnaryPrefix(operation) => match operation.operator {
28            UnaryPrefixOperator::ErrorControl(_) => is_truthy(operation.operand),
29            UnaryPrefixOperator::Reference(_) => is_truthy(operation.operand),
30            UnaryPrefixOperator::Not(_) => is_falsy(operation.operand),
31            _ => false,
32        },
33        Expression::Assignment(assignment) => is_truthy(assignment.rhs),
34        _ => false,
35    }
36}
37
38/// Determine if an expression is falsy.
39///
40/// This function will return true if the expression is falsy, and false otherwise.
41///
42/// When this function returns false, it does not mean that the expression is truthy,
43/// it just means that we could not determine if the expression is falsy.
44#[inline]
45pub fn is_falsy(expression: &Expression<'_>) -> bool {
46    match &expression {
47        Expression::Parenthesized(parenthesized) => is_falsy(parenthesized.expression),
48        Expression::Literal(Literal::False(_) | Literal::Null(_)) => true,
49        Expression::Array(array) => array.elements.is_empty(),
50        Expression::LegacyArray(array) => array.elements.is_empty(),
51        Expression::Assignment(assignment) => is_falsy(assignment.rhs),
52        Expression::Binary(operation) => match operation.operator {
53            BinaryOperator::Or(_) | BinaryOperator::LowOr(_) => is_falsy(operation.lhs) && is_falsy(operation.rhs),
54            BinaryOperator::And(_) | BinaryOperator::LowAnd(_) => is_falsy(operation.lhs) || is_falsy(operation.rhs),
55            BinaryOperator::NullCoalesce(_) => is_falsy(operation.lhs) && is_falsy(operation.rhs),
56            BinaryOperator::LowXor(_) => is_falsy(operation.lhs) ^ is_falsy(operation.rhs),
57            _ => false,
58        },
59        Expression::UnaryPrefix(operation) => match operation.operator {
60            UnaryPrefixOperator::ErrorControl(_) => is_falsy(operation.operand),
61            UnaryPrefixOperator::Reference(_) => is_falsy(operation.operand),
62            UnaryPrefixOperator::Not(_) => is_truthy(operation.operand),
63            _ => false,
64        },
65        _ => false,
66    }
67}