fn transform(&self, target: RcExpr) -> RcExpr {
        fn fill(cache: &mut HashMap<u64, RcExpr>, t: RcExpr, r: RcExpr) -> RcExpr {
            cache.entry(hash(t.as_ref())).or_insert_with(|| r).clone()
        }

        fn transform_inner(
            rule: &Rule,
            target: RcExpr,
            cache: &mut HashMap<u64, RcExpr>,
        ) -> RcExpr {
            match target.as_ref() {
                Expr::Const(_) => target,
                Expr::Var(_) => target,
                Expr::BinaryExpr(binary_expr) => rc_expr!(
                    Expr::BinaryExpr(BinaryExpr {
                        op: binary_expr.op,
                        lhs: transform(rule, binary_expr.lhs.clone(), cache),
                        rhs: transform(rule, binary_expr.rhs.clone(), cache),
                    }),
                    target.span
                ),
                Expr::UnaryExpr(unary_expr) => rc_expr!(
                    Expr::UnaryExpr(UnaryExpr {
                        op: unary_expr.op,
                        rhs: transform(rule, unary_expr.rhs.clone(), cache),
                    }),
                    target.span
                ),
                Expr::Parend(expr) => {
                    let inner = transform(rule, expr.clone(), cache);
                    rc_expr!(Expr::Parend(inner), target.span)
                }
                Expr::Bracketed(expr) => {
                    let inner = transform(rule, expr.clone(), cache);
                    rc_expr!(Expr::Bracketed(inner), target.span)
                }
            }
        }

        fn transform(rule: &Rule, target: RcExpr, cache: &mut HashMap<u64, RcExpr>) -> RcExpr {
            if let Some(result) = cache.get(&hash(target.as_ref())) {
                return result.clone();
            }

            let mut result = target.clone();
            match rule {
                Rule::PatternMap(PatternMap { from, to }) => {
                    for target in get_symmetric_expressions(target.clone()) {
                        // First, apply the rule recursively on the target's subexpressions.
                        let partially_transformed = transform_inner(rule, target, cache);
                        if partially_transformed.complexity() < result.complexity() {
                            result = partially_transformed.clone();
                        }

                        if let Some(transformed) =
                            PatternMatch::match_rule(from.clone(), partially_transformed)
                                // If the rule was matched on the expression, we have replacements for rule
                                // patterns -> target subexpressions. Apply the rule by transforming the
                                // rule's RHS with the replacements.
                                .map(|repls| repls.transform(to.clone()))
                        {
                            result = transformed;
                        }
                    }
                }
                Rule::Evaluate(f) => {
                    // First, apply the rule recursively on the target's subexpressions.
                    let partially_transformed = transform_inner(rule, target.clone(), cache);
                    result = f(partially_transformed.clone()).unwrap_or(partially_transformed);
                }
            }

            fill(cache, target, result)
        }

        let mut cache: HashMap<u64, RcExpr> = HashMap::new();
        transform(self, target, &mut cache)
    }
/// Attempts to apply a rule on a target expression by
///
/// 1. Applying the rule recursively on the target's subexpression to obtain a
///    partially-transformed target expression.
///
/// 2. Pattern matching the lhs of the rule with the partially-transformed target expression.
///   - If pattern matching is unsuccessful, no application is done and the original expression
///     is returned.
///
/// 3. Expanding the rhs of the rule using the results of the pattern matching.
///
/// Examples:
///
/// ```ignore
/// "$x + 0 -> $x".try_apply("x + 0")  // Some(x)
/// "$x + 0 -> $x".try_apply("x + 1")  // None
/// "$x + 0 -> $x".try_apply("x")      // None
/// ```
Attempts to apply a rule on a target expression by
1. Applying the rule recursively on the target's subexpression to obtain a
partially-transformed target expression.

2. Pattern matching the lhs of the rule with the partially-transformed target expression.
If pattern matching is unsuccessful, no application is done and the original expression
is returned.

3. Expanding the rhs of the rule using the results of the pattern matching.




Attempts to apply a rule on a target expression by 1 . Applying the rule recursively on the target ' s subexpression to obtain a partially - transformed target expression . 2 . Pattern matching the lhs of the rule with the partially - transformed target expression . If pattern matching is unsuccessful no application is done and the original expression is returned . 3 . Expanding the rhs of the rule using the results of the pattern matching .
fn transform(&self, target: RcExpr) -> RcExpr {
        fn fill(cache: &mut HashMap<u64, RcExpr>, t: RcExpr, r: RcExpr) -> RcExpr {
            cache.entry(hash(t.as_ref())).or_insert_with(|| r).clone()
        }
        fn transform_inner(
            rule: &Rule,
            target: RcExpr,
            cache: &mut HashMap<u64, RcExpr>,
        ) -> RcExpr {
            match target.as_ref() {
                Expr::Const(_) => target,
                Expr::Var(_) => target,
                Expr::BinaryExpr(binary_expr) => rc_expr!(
                    Expr::BinaryExpr(BinaryExpr {
                        op: binary_expr.op,
                        lhs: transform(rule, binary_expr.lhs.clone(), cache),
                        rhs: transform(rule, binary_expr.rhs.clone(), cache),
                    }),
                    target.span
                ),
                Expr::UnaryExpr(unary_expr) => rc_expr!(
                    Expr::UnaryExpr(UnaryExpr {
                        op: unary_expr.op,
                        rhs: transform(rule, unary_expr.rhs.clone(), cache),
                    }),
                    target.span
                ),
                Expr::Parend(expr) => {
                    let inner = transform(rule, expr.clone(), cache);
                    rc_expr!(Expr::Parend(inner), target.span)
                }
                Expr::Bracketed(expr) => {
                    let inner = transform(rule, expr.clone(), cache);
                    rc_expr!(Expr::Bracketed(inner), target.span)
                }
            }
        }
        fn transform(rule: &Rule, target: RcExpr, cache: &mut HashMap<u64, RcExpr>) -> RcExpr {
            if let Some(result) = cache.get(&hash(target.as_ref())) {
                return result.clone();
            }
            let mut result = target.clone();
            match rule {
                Rule::PatternMap(PatternMap { from, to }) => {
                    for target in get_symmetric_expressions(target.clone()) {
                        // First, apply the rule recursively on the target's subexpressions.
                        let partially_transformed = transform_inner(rule, target, cache);
                        if partially_transformed.complexity() < result.complexity() {
                            result = partially_transformed.clone();
                        }
                        if let Some(transformed) =
                            PatternMatch::match_rule(from.clone(), partially_transformed)
                                // If the rule was matched on the expression, we have replacements for rule
                                // patterns -> target subexpressions. Apply the rule by transforming the
                                // rule's RHS with the replacements.
                                .map(|repls| repls.transform(to.clone()))
                        {
                            result = transformed;
                        }
                    }
                }
                Rule::Evaluate(f) => {
                    // First, apply the rule recursively on the target's subexpressions.
                    let partially_transformed = transform_inner(rule, target.clone(), cache);
                    result = f(partially_transformed.clone()).unwrap_or(partially_transformed);
                }
            }
            fill(cache, target, result)
        }
        let mut cache: HashMap<u64, RcExpr> = HashMap::new();
        transform(self, target, &mut cache)
    }
fn transform ( & self , target : RcExpr ) -> RcExpr { fn fill ( cache : & mut HashMap < u64 , RcExpr > , t : RcExpr , r : RcExpr ) -> RcExpr { cache . entry ( hash ( t . as_ref ( ) ) ) . or_insert_with ( | | r ) . clone ( ) } fn transform_inner ( rule : & Rule , target : RcExpr , cache : & mut HashMap < u64 , RcExpr > , ) -> RcExpr { match target . as_ref ( ) { Expr :: Const ( _ ) => target , Expr :: Var ( _ ) => target , Expr :: BinaryExpr ( binary_expr ) => rc_expr ! ( Expr BinaryExpr ( BinaryExpr { op binary_expr op lhs transform ( rule binary_expr lhs clone ( ) cache ) rhs transform ( rule binary_expr rhs clone ( ) cache ) } ) target span ) , Expr :: UnaryExpr ( unary_expr ) => rc_expr ! ( Expr UnaryExpr ( UnaryExpr { op unary_expr op rhs transform ( rule unary_expr rhs clone ( ) cache ) } ) target span ) , Expr :: Parend ( expr ) => { let inner = transform ( rule , expr . clone ( ) , cache ) ; rc_expr ! ( Expr Parend ( inner ) target span ) } Expr :: Bracketed ( expr ) => { let inner = transform ( rule , expr . clone ( ) , cache ) ; rc_expr ! ( Expr Bracketed ( inner ) target span ) } } } fn transform ( rule : & Rule , target : RcExpr , cache : & mut HashMap < u64 , RcExpr > ) -> RcExpr { if let Some ( result ) = cache . get ( & hash ( target . as_ref ( ) ) ) { return result . clone ( ) ; } let mut result = target . clone ( ) ; match rule { Rule :: PatternMap ( PatternMap { from , to } ) => { for target in get_symmetric_expressions ( target . clone ( ) ) { // First, apply the rule recursively on the target's subexpressions. let partially_transformed = transform_inner ( rule , target , cache ) ; if partially_transformed . complexity ( ) < result . complexity ( ) { result = partially_transformed . clone ( ) ; } if let Some ( transformed ) = PatternMatch :: match_rule ( from . clone ( ) , partially_transformed ) // If the rule was matched on the expression, we have replacements for rule // patterns -> target subexpressions. Apply the rule by transforming the // rule's RHS with the replacements. . map ( | repls | repls . transform ( to . clone ( ) ) ) { result = transformed ; } } } Rule :: Evaluate ( f ) => { // First, apply the rule recursively on the target's subexpressions. let partially_transformed = transform_inner ( rule , target . clone ( ) , cache ) ; result = f ( partially_transformed . clone ( ) ) . unwrap_or ( partially_transformed ) ; } } fill ( cache , target , result ) } let mut cache : HashMap < u64 , RcExpr > = HashMap :: new ( ) ; transform ( self , target , & mut cache ) }
Attempts to apply a rule on a target expression by
1.
Attempts to apply a rule on a target expression by 1 .
&self
target
RcExpr
&self
target
RcExpr