use crate::builtin_trs::util::is_greater_as_per_lexicographic_path_ordering;
use crate::core::terms::position::PositionInLanguageTerm;
use crate::core::terms::term::{LanguageTerm, RewritableLanguageOperatorSymbol};
pub trait BasicCommutativeCheckerAndOrderer<LOS : RewritableLanguageOperatorSymbol> {
fn is_a_binary_operator_we_may_consider(
&self,
op : &LOS
) -> bool;
fn may_commute_under(
&self,
parent_op :&LOS,
left_sub_term : &LanguageTerm<LOS>,
right_sub_term : &LanguageTerm<LOS>,
) -> bool;
fn compare_operators(
&self,
op1 : &LOS,
op2 : &LOS
) -> std::cmp::Ordering;
fn get_arity(
&self,
op : &LOS
) -> usize;
fn is_associative(
&self,
op : &LOS
) -> bool;
}
pub(crate) fn transformation_basic_reorder_subterms_under_commutative_operator<
LOS : RewritableLanguageOperatorSymbol
>(
checker : &Box<dyn BasicCommutativeCheckerAndOrderer<LOS>>,
term : &LanguageTerm<LOS>,
_context_term : &LanguageTerm<LOS>,
_position_in_context_term : &PositionInLanguageTerm
) -> Option<LanguageTerm<LOS>> {
if !checker.is_a_binary_operator_we_may_consider(&term.operator) {
return None;
}
let considered_op = &term.operator;
let left_sub_term = term.sub_terms.first().unwrap();
let right_sub_term = term.sub_terms.get(1).unwrap();
if checker.may_commute_under(
considered_op,
left_sub_term,
right_sub_term
) && is_greater_as_per_lexicographic_path_ordering::<LOS>(
left_sub_term,
right_sub_term,
&|x,y| checker.compare_operators(x,y),
&|x| checker.get_arity(x),
) {
let new_term = LanguageTerm::new(
considered_op.clone(),
vec![
right_sub_term.clone(),
left_sub_term.clone()
]
);
return Some(new_term);
}
if checker.is_associative(considered_op) {
if &right_sub_term.operator == considered_op {
let t21 = right_sub_term.sub_terms.first().unwrap();
let t22 = right_sub_term.sub_terms.get(1).unwrap();
if checker.may_commute_under(
considered_op,
left_sub_term,
t21
) && is_greater_as_per_lexicographic_path_ordering::<LOS>(
left_sub_term,
t21,
&|x,y| checker.compare_operators(x,y),
&|x| checker.get_arity(x),
) {
let new_term = LanguageTerm::new(
considered_op.clone(),
vec![
t21.clone(),
LanguageTerm::new(
considered_op.clone(),
vec![
left_sub_term.clone(),
t22.clone()
]
)
]
);
return Some(new_term);
}
}
if &left_sub_term.operator == considered_op {
let t11 = left_sub_term.sub_terms.first().unwrap();
let t12 = left_sub_term.sub_terms.get(1).unwrap();
if checker.may_commute_under(
considered_op,
t12,
right_sub_term
) && is_greater_as_per_lexicographic_path_ordering::<LOS>(
t12,
right_sub_term,
&|x,y| checker.compare_operators(x,y),
&|x| checker.get_arity(x),
) {
let new_term = LanguageTerm::new(
considered_op.clone(),
vec![
LanguageTerm::new(
considered_op.clone(),
vec![
t11.clone(),
right_sub_term.clone()
]
),
t12.clone()
]
);
return Some(new_term);
}
}
}
None
}