pub fn flatten_expr(expr: RcExpr) -> RcExpr {
    match expr.as_ref() {
        // #a -> #a, $a -> $a
        // We can't do better than this.
        Expr::Const(_) | Expr::Var(_) => expr,

        // (_a) -> _a, [_a] -> _a
        // We can't do better than this.
        Expr::Parend(inner) | Expr::Bracketed(inner) => flatten_expr(inner.clone()),

        // _a + _b -> _c
        // _a - _b -> _c
        Expr::BinaryExpr(BinaryExpr { op, lhs, rhs })
            if op == &BinaryOperator::Plus || op == &BinaryOperator::Minus =>
        {
            flatten_add_or_sub(lhs.clone(), rhs.clone(), op == &BinaryOperator::Minus)
        }

        // _a * _b -> _c
        // _a / _b -> _c
        Expr::BinaryExpr(BinaryExpr { op, lhs, rhs })
            if op == &BinaryOperator::Mult || op == &BinaryOperator::Div =>
        {
            flatten_mul_or_div(lhs.clone(), rhs.clone(), op == &BinaryOperator::Div)
        }

        // TODO: handle everything else better
        Expr::BinaryExpr(BinaryExpr { op, lhs, rhs }) => {
            let lhs = flatten_expr(lhs.clone());
            let rhs = flatten_expr(rhs.clone());
            rc_expr!(
                Expr::BinaryExpr(BinaryExpr { op: *op, lhs, rhs }),
                expr.span
            )
        }

        Expr::UnaryExpr(UnaryExpr { op, rhs }) => {
            let rhs = flatten_expr(rhs.clone());
            rc_expr!(Expr::UnaryExpr(UnaryExpr { op: *op, rhs }), expr.span)
        }
    }
}
/// Attempts to flatten an expression, folding constant expressions and like terms.
///
/// ## Examples
///
/// ```text
/// 1 + 2 + 3 -> 6
/// 1 - 5x / x -> -4
/// ```
///
/// Expressions flattened to a binary operation have the following conditions:
///
/// - Additions and subtractions become additions
Attempts to flatten an expression, folding constant expressions and like terms.
Attempts to flatten an expression folding constant expressions and like terms .
pub fn flatten_expr(expr: RcExpr) -> RcExpr {
    match expr.as_ref() {
        // #a -> #a, $a -> $a
        // We can't do better than this.
        Expr::Const(_) | Expr::Var(_) => expr,
        // (_a) -> _a, [_a] -> _a
        // We can't do better than this.
        Expr::Parend(inner) | Expr::Bracketed(inner) => flatten_expr(inner.clone()),
        // _a + _b -> _c
        // _a - _b -> _c
        Expr::BinaryExpr(BinaryExpr { op, lhs, rhs })
            if op == &BinaryOperator::Plus || op == &BinaryOperator::Minus =>
        {
            flatten_add_or_sub(lhs.clone(), rhs.clone(), op == &BinaryOperator::Minus)
        }
        // _a * _b -> _c
        // _a / _b -> _c
        Expr::BinaryExpr(BinaryExpr { op, lhs, rhs })
            if op == &BinaryOperator::Mult || op == &BinaryOperator::Div =>
        {
            flatten_mul_or_div(lhs.clone(), rhs.clone(), op == &BinaryOperator::Div)
        }
        // TODO: handle everything else better
        Expr::BinaryExpr(BinaryExpr { op, lhs, rhs }) => {
            let lhs = flatten_expr(lhs.clone());
            let rhs = flatten_expr(rhs.clone());
            rc_expr!(
                Expr::BinaryExpr(BinaryExpr { op: *op, lhs, rhs }),
                expr.span
            )
        }
        Expr::UnaryExpr(UnaryExpr { op, rhs }) => {
            let rhs = flatten_expr(rhs.clone());
            rc_expr!(Expr::UnaryExpr(UnaryExpr { op: *op, rhs }), expr.span)
        }
    }
}
pub fn flatten_expr ( expr : RcExpr ) -> RcExpr { match expr . as_ref ( ) { // #a -> #a, $a -> $a // We can't do better than this. Expr :: Const ( _ ) | Expr :: Var ( _ ) => expr , // (_a) -> _a, [_a] -> _a // We can't do better than this. Expr :: Parend ( inner ) | Expr :: Bracketed ( inner ) => flatten_expr ( inner . clone ( ) ) , // _a + _b -> _c // _a - _b -> _c Expr :: BinaryExpr ( BinaryExpr { op , lhs , rhs } ) if op == & BinaryOperator :: Plus || op == & BinaryOperator :: Minus => { flatten_add_or_sub ( lhs . clone ( ) , rhs . clone ( ) , op == & BinaryOperator :: Minus ) } // _a * _b -> _c // _a / _b -> _c Expr :: BinaryExpr ( BinaryExpr { op , lhs , rhs } ) if op == & BinaryOperator :: Mult || op == & BinaryOperator :: Div => { flatten_mul_or_div ( lhs . clone ( ) , rhs . clone ( ) , op == & BinaryOperator :: Div ) } // TODO: handle everything else better Expr :: BinaryExpr ( BinaryExpr { op , lhs , rhs } ) => { let lhs = flatten_expr ( lhs . clone ( ) ) ; let rhs = flatten_expr ( rhs . clone ( ) ) ; rc_expr ! ( Expr BinaryExpr ( BinaryExpr { op op lhs rhs } ) expr span ) } Expr :: UnaryExpr ( UnaryExpr { op , rhs } ) => { let rhs = flatten_expr ( rhs . clone ( ) ) ; rc_expr ! ( Expr UnaryExpr ( UnaryExpr { op op rhs } ) expr span ) } } }
Attempts to flatten an expression, folding constant expressions and like terms.
Attempts to flatten an expression folding constant expressions and like terms .
expr
RcExpr
expr
RcExpr
examples


Expressions flattened to a binary operation have the following conditions.

Additions and subtractions become additions
Expressions flattened to a binary operation have the following conditions . Additions and subtractions become additions