use std::rc::Rc; use super::matcher::RuleExpr; use crate::ast::{Clause, Expr}; use crate::utils::replace_first; use crate::Sym; /// Traverse the tree, calling pred on every sibling list until it returns /// some vec then replace the sibling list with that vec and return true /// return false if pred never returned some pub fn exprv>) -> Option>>>( input: Rc>, pred: &mut F, ) -> Option>> { if let Some(v) = pred(input.clone()) { return Some(v); } replace_first(input.as_ref(), |ex| expr(ex, pred)) .map(|i| Rc::new(i.collect())) } pub fn expr>) -> Option>>>( input: &RuleExpr, pred: &mut F, ) -> Option { clause(&input.value, pred) .map(|value| Expr { value, location: input.location.clone() }) } pub fn clause>) -> Option>>>( c: &Clause, pred: &mut F, ) -> Option> { match c { Clause::P(_) | Clause::Placeh { .. } | Clause::Name { .. } => None, Clause::Lambda(arg, body) => if let Some(arg) = expr(arg.as_ref(), pred) { Some(Clause::Lambda(Rc::new(arg), body.clone())) } else { exprv(body.clone(), pred).map(|body| Clause::Lambda(arg.clone(), body)) }, Clause::S(c, body) => Some(Clause::S(*c, exprv(body.clone(), pred)?)), } }