use crate::builtin_trs::util::{fold_associative_sub_terms_recursively, get_associative_sub_terms_recursively};
use crate::core::terms::position::PositionInLanguageTerm;
use crate::core::terms::term::{LanguageTerm, RewritableLanguageOperatorSymbol};
pub trait ModuloAssociativeGenericFlattenedChecker<LOS : RewritableLanguageOperatorSymbol> {
fn is_an_associative_binary_operator_we_may_consider(
&self,
op : &LOS
) -> bool;
fn requires_a_specific_parent_operator(
&self,
) -> Option<Box<dyn Fn(&LOS) -> bool>>;
fn transform_flattened_sub_terms(
&self,
considered_ac_op : &LOS,
considered_parent_op : Option<&LOS>,
flattened_subterms : Vec<&LanguageTerm<LOS>>
) -> Option<Vec<LanguageTerm<LOS>>>;
}
fn ad_hoc_parent_checking_for_modulo_assoc_flattened_transfo<'a,LOS : RewritableLanguageOperatorSymbol>(
checker : &Box<dyn ModuloAssociativeGenericFlattenedChecker<LOS>>,
context_term : &'a LanguageTerm<LOS>,
position_in_context_term : &PositionInLanguageTerm,
considered_associative_operator : &LOS
) -> Option<Option<&'a LOS>> {
match position_in_context_term.get_parent_position() {
None => {
if checker.requires_a_specific_parent_operator().is_some() {
None
} else {
Some(None)
}
},
Some(parent_position) => {
let parent_operator = &context_term.get_sub_term_at_position(&parent_position).unwrap().operator;
if let Some(parent_requirement) = checker.requires_a_specific_parent_operator() {
if parent_requirement(parent_operator) {
Some(Some(parent_operator))
} else {
None
}
} else {
if parent_operator == considered_associative_operator {
None
} else {
Some(None)
}
}
}
}
}
pub(crate) fn transformation_modulo_associative_generic_flattened_transfo<
LOS : RewritableLanguageOperatorSymbol
>(
checker : &Box<dyn ModuloAssociativeGenericFlattenedChecker<LOS>>,
term : &LanguageTerm<LOS>,
context_term : &LanguageTerm<LOS>,
position_in_context_term : &PositionInLanguageTerm
) -> Option<LanguageTerm<LOS>> {
if checker.is_an_associative_binary_operator_we_may_consider(&term.operator) {
let considered_associative_operator = &term.operator;
if let Some(if_req_parent_op) = ad_hoc_parent_checking_for_modulo_assoc_flattened_transfo(
checker,context_term,position_in_context_term,considered_associative_operator
) {
let flattened_sub_terms = get_associative_sub_terms_recursively(
term,
considered_associative_operator
);
if let Some( mut transformed_flattened ) = checker.transform_flattened_sub_terms(
considered_associative_operator,
if_req_parent_op,
flattened_sub_terms
) {
let folded_transformed = fold_associative_sub_terms_recursively(
considered_associative_operator,
&mut transformed_flattened,
&None
);
let got = match if_req_parent_op {
None => {
folded_transformed
},
Some(parent_op) => {
LanguageTerm::new(
parent_op.clone(),
vec![folded_transformed]
)
}
};
return Some(got);
}
}
}
None
}