mago_syntax/utils/
condition.rs

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