ftml_solver/rules/fixity/
reorder.rs1use crate::{
2 CheckRef,
3 rules::{PreparationRule, SizedSolverRule},
4 split::SplitStrategy,
5};
6use ftml_ontology::{
7 terms::{ApplicationTerm, BindingTerm, Term},
8 utils::Permutation,
9};
10use ftml_uris::SymbolUri;
11use std::ops::ControlFlow;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct ReorderRule {
15 pub symbol: SymbolUri,
16 pub reorder: Permutation,
17}
18impl SizedSolverRule for ReorderRule {
19 fn priority(&self) -> isize {
20 100_000
21 }
22 fn display(&self) -> Vec<crate::trace::Displayable> {
23 ftml_solver_trace::trace!(
24 &self.symbol,
25 format!("reorders argument {:?}", self.reorder)
26 )
27 }
28}
29impl std::fmt::Display for ReorderRule {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "{} reorder arguments {:?}", self.symbol, self.reorder)
32 }
33}
34
35impl<Split: SplitStrategy> PreparationRule<Split> for ReorderRule {
36 fn applicable(&self, _: &CheckRef<'_, '_, Split>, t: &Term) -> bool {
37 match t {
38 Term::Application(a) => {
39 matches!(&a.head,Term::Symbol { uri, .. } if *uri == self.symbol)
40 && a.arguments.len() == self.reorder.len()
41 }
42 Term::Bound(b) => {
43 matches!(&b.head,Term::Symbol { uri, .. } if *uri == self.symbol)
44 && b.arguments.len() == self.reorder.len()
45 }
46 _ => false,
47 }
48 }
49 fn apply(
50 &self,
51 _: &mut CheckRef<'_, '_, Split>,
52 t: Term,
53 path: Option<(&mut smallvec::SmallVec<u8, 16>, usize)>,
54 ) -> ControlFlow<Term, Term> {
55 if let Some(i) = path.and_then(|(v, i)| {
56 v.get_mut(i)
57 .and_then(|i| if *i > 0 { Some(i) } else { None })
58 }) {
59 *i = self.reorder.of(*i).unwrap_or(*i);
60 }
61
62 let r = match t {
64 Term::Application(app) => Term::Application(ApplicationTerm::new(
65 app.head.clone(),
66 unsafe {
68 debug_assert_eq!(app.arguments.len(), self.reorder.len());
69 self.reorder.apply_unchecked(&app.arguments)
70 }
71 .into_boxed_slice(),
72 app.presentation.clone(),
73 )),
74 Term::Bound(app) => Term::Bound(BindingTerm::new(
75 app.head.clone(),
76 unsafe {
78 debug_assert_eq!(app.arguments.len(), self.reorder.len());
79 self.reorder.apply_unchecked(&app.arguments)
80 }
81 .into_boxed_slice(),
82 app.presentation.clone(),
83 )),
84 t => t,
85 };
86 ControlFlow::Continue(r)
88 }
89 fn applicable_revert(&self, checker: &CheckRef<'_, '_, Split>, t: &Term) -> bool {
90 <Self as PreparationRule<Split>>::applicable(self, checker, t)
91 }
92 fn revert(&self, _: &CheckRef<'_, '_, Split>, t: Term) -> ControlFlow<Term, Term> {
93 let r = match t {
95 Term::Application(app) => Term::Application(ApplicationTerm::new(
96 app.head.clone(),
97 unsafe {
99 debug_assert_eq!(app.arguments.len(), self.reorder.len());
100 self.reorder.revert_unchecked(&app.arguments)
101 }
102 .into_boxed_slice(),
103 app.presentation.clone(),
104 )),
105 Term::Bound(app) => Term::Bound(BindingTerm::new(
106 app.head.clone(),
107 unsafe {
109 debug_assert_eq!(app.arguments.len(), self.reorder.len());
110 self.reorder.revert_unchecked(&app.arguments)
111 }
112 .into_boxed_slice(),
113 app.presentation.clone(),
114 )),
115 t => t,
116 };
117 ControlFlow::Continue(r)
119 }
120}