use std::cmp::Ordering;
use crate::term::syntax::{LanguageOperatorArity, LanguageTerm, RewritableLanguageOperatorSymbol};
fn resolve_arity<LOS: RewritableLanguageOperatorSymbol>(term: &LanguageTerm<LOS>) -> usize {
match term.operator.arity() {
LanguageOperatorArity::Fixed(n) => n,
LanguageOperatorArity::Variadic => term.sub_terms.len(),
}
}
pub fn lexicographic_path_ordering<LOS: RewritableLanguageOperatorSymbol>(
s: &LanguageTerm<LOS>,
t: &LanguageTerm<LOS>,
compare_operators: &dyn Fn(&LOS, &LOS) -> Ordering,
) -> std::cmp::Ordering {
if s == t {
std::cmp::Ordering::Equal
} else if is_greater_as_per_lexicographic_path_ordering(s, t, compare_operators) {
std::cmp::Ordering::Greater
} else {
debug_assert!(is_greater_as_per_lexicographic_path_ordering(
t,
s,
compare_operators
));
std::cmp::Ordering::Less
}
}
pub fn is_greater_as_per_lexicographic_path_ordering<LOS: RewritableLanguageOperatorSymbol>(
s: &LanguageTerm<LOS>,
t: &LanguageTerm<LOS>,
compare_operators: &dyn Fn(&LOS, &LOS) -> Ordering,
) -> bool {
match compare_operators(&s.operator, &t.operator) {
Ordering::Greater => {
let mut is_greater = true;
'iter_tjs: for j in 0..resolve_arity(t) {
let tj = t.sub_terms.get(j).unwrap();
if !is_greater_as_per_lexicographic_path_ordering(s, tj, compare_operators) {
is_greater = false;
break 'iter_tjs;
}
}
if is_greater {
return true;
}
}
Ordering::Less => {
for i in 0..resolve_arity(s) {
let si = s.sub_terms.get(i).unwrap();
if si == t
|| is_greater_as_per_lexicographic_path_ordering(si, t, compare_operators)
{
return true;
}
}
}
Ordering::Equal => {
let arity = resolve_arity(s);
for i in 0..arity {
let si = s.sub_terms.get(i).unwrap();
let ti = t.sub_terms.get(i).unwrap();
if is_greater_as_per_lexicographic_path_ordering(si, ti, compare_operators) {
for j in (i + 1)..arity {
let tj = t.sub_terms.get(j).unwrap();
if !is_greater_as_per_lexicographic_path_ordering(s, tj, compare_operators)
{
return false;
}
}
return true;
}
if is_greater_as_per_lexicographic_path_ordering(ti, si, compare_operators) {
return false;
}
}
}
}
false
}