Skip to main content

ftml_solver/impls/
simplify.rs

1use std::borrow::Cow;
2
3use ftml_ontology::terms::{
4    ApplicationTerm, Argument, BindingTerm, BoundArgument, ComponentVar, MaybeSequence, Term,
5};
6use ftml_solver_trace::{CheckerRule, CheckingTask, traceref};
7use ftml_uris::Id;
8
9use crate::{
10    CheckRef,
11    impls::solving::{TermExtSolvable, is_solvable_var},
12    rules::{
13        implicits::{ImplicitExtApp, ImplicitExtBound},
14        unknowns::beta_unknowns_cow,
15    },
16    split::SplitStrategy,
17};
18
19const LOOP_LIMIT: usize = 64;
20const RECURSION_LIMIT: usize = 128;
21const TOTAL_LIMIT: usize = 4096 * 512;
22
23static NOEXPAND: std::sync::LazyLock<Id> =
24    std::sync::LazyLock::new(|| unsafe { "noexpand".parse().unwrap_unchecked() });
25
26#[derive(Debug, Copy, Clone, PartialEq, Eq)]
27#[allow(clippy::enum_variant_names)]
28pub enum Expansion {
29    Full,
30    NoDefinitionExpansion,
31    NoNoexpands,
32}
33impl Expansion {
34    fn with_defs(self) -> Self {
35        if self == Self::NoNoexpands {
36            Self::NoNoexpands
37        } else {
38            Self::Full
39        }
40    }
41}
42
43impl<'t, Split: SplitStrategy> CheckRef<'t, '_, Split> {
44    pub fn simplify_full(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
45        if matches!(term, Term::Symbol { .. } | Term::Number(_)) {
46            return None;
47        }
48        self./*wrap_check*/untraced(CheckingTask::Simplify(term), |slf| {
49            slf.simplify_full_i(expand, term,&mut 0,&mut 0)
50        }).inspect(|t| {
51            self.add_msg(traceref!("Simplified: ",t.clone()).into());
52        })
53    }
54    fn simplify_full_first(
55        &mut self,
56        expand: Expansion,
57        term: &'t Term,
58        recursion_limit: &mut usize,
59        total_limit: &mut usize,
60    ) -> Option<Cow<'t, Term>> {
61        match term {
62            Term::Symbol { uri, .. } if expand == Expansion::NoNoexpands => {
63                let s = self.get_symbol(uri).ok()?;
64                if s.data.role.contains(&NOEXPAND) {
65                    None
66                } else {
67                    self.get_symbol_definiens(uri).map(|t| {
68                        self.comment("expanded definition");
69                        Some(Cow::Owned(t))
70                    })?
71                }
72            }
73            Term::Symbol { uri, .. } /*if expand == Expansion::Full*/ => {
74                self.get_symbol_definiens(uri).map(|t| {
75                    self.comment("expanded definition");
76                    Some(Cow::Owned(t))
77                })?
78            }
79            Term::Var { variable, .. } => {
80                if let Some(name) = is_solvable_var(variable)
81                    && let Some(t) = self.get_solution(name)
82                {
83                    Some(Cow::Owned(t))
84                } else if
85                /*expand != Expansion::NoDefinitionExpansion
86                &&*/
87                let Some(df) = self.get_var_definiens(variable) {
88                    Some(Cow::Owned(df))
89                } else {
90                    //println!("  : None");
91                    None
92                }
93            }
94            Term::Number(_) => {
95                //println!("  : None");
96                None
97            }
98            Term::Application(app) => {
99                let mut changed = false;
100                let nhead = self
101                    .simplify_full_i(expand, &app.head, recursion_limit, total_limit)
102                    .map_or(Cow::Borrowed(&app.head), |t| {
103                        changed = true;
104                        Cow::Owned(t)
105                    });
106                let args = app
107                    .arguments
108                    .iter()
109                    .map(|a| {
110                        self.arg_full(expand, a, recursion_limit, total_limit)
111                            .map_or(Cow::Borrowed(a), |a| {
112                                changed = true;
113                                Cow::Owned(a)
114                            })
115                    })
116                    .collect::<Vec<_>>();
117                Some(if changed {
118                    Cow::Owned(Term::Application(ApplicationTerm::new(
119                        nhead.into_owned(),
120                        args.into_iter().map(Cow::into_owned).collect(),
121                        app.presentation.clone(),
122                    )))
123                } else {
124                    Cow::Borrowed(term)
125                })
126            }
127            Term::Bound(app) => {
128                let mut changed = false;
129                let nhead = self
130                    .simplify_full_i(expand.with_defs(), &app.head, recursion_limit, total_limit)
131                    .map_or(Cow::Borrowed(&app.head), |t| {
132                        changed = true;
133                        Cow::Owned(t)
134                    });
135                let args = app
136                    .arguments
137                    .iter()
138                    .map(|a| {
139                        self.bound_arg_full(expand, a, recursion_limit, total_limit)
140                            .map_or(Cow::Borrowed(a), |a| {
141                                changed = true;
142                                Cow::Owned(a)
143                            })
144                    })
145                    .collect::<Vec<_>>();
146                Some(if changed {
147                    Cow::Owned(Term::Bound(BindingTerm::new(
148                        nhead.into_owned(),
149                        args.into_iter().map(Cow::into_owned).collect(),
150                        app.presentation.clone(),
151                    )))
152                } else {
153                    Cow::Borrowed(term)
154                })
155            }
156            _ => Some(Cow::Borrowed(term)),
157        }
158    }
159    fn simplify_full_i(
160        &mut self,
161        expand: Expansion,
162        term: &'t Term,
163        recursion_limit: &mut usize,
164        total_limit: &mut usize,
165    ) -> Option<Term> {
166        if expand == Expansion::Full
167            && let Some(r) = self
168                .judgment_cache
169                .get_simplification(term, self.context.as_ref())
170        {
171            return Some(r);
172        }
173        tracing::debug!(
174            "Fully Simplifying {:?} (expand:{expand:?})",
175            term.debug_short()
176        );
177        if
178        /*expand != Expansion::NoDefinitionExpansion
179        &&*/
180        true {
181            match self.simplify_implicit(term) {
182                Ok(Some(t)) => {
183                    let r = self
184                        .scoped(|slf| slf.simplify_full_i(expand, &t, recursion_limit, total_limit))
185                        .unwrap_or(t);
186                    return Some(r);
187                }
188                Ok(None) => (),
189                Err(()) => return None,
190            }
191        }
192        /*if term.unapply_implicits().is_some() {
193            return None;
194        } else*/
195        //self.scoped(|slf| {
196        *recursion_limit += 1;
197        let Some(mut current) =
198            self.simplify_full_first(expand, term, recursion_limit, total_limit)
199        else {
200            *recursion_limit -= 1;
201            return None;
202        };
203        let mut loop_limit = 0;
204        loop {
205            loop_limit += 1;
206            *total_limit += 1;
207            if loop_limit >= LOOP_LIMIT
208                || *recursion_limit >= RECURSION_LIMIT
209                || *total_limit >= TOTAL_LIMIT
210            {
211                *recursion_limit -= 1;
212                return match current {
213                    Cow::Borrowed(_) => {
214                        //println!("  : None");
215                        None
216                    }
217                    Cow::Owned(t) => {
218                        /*if loop_limit >= LOOP_LIMIT {
219                            panic!("LOOP_LIMIT");
220                        }
221                        if *recursion_limit >= RECURSION_LIMIT {
222                            panic!("RECURSION_LIMIT");
223                        }
224                        if *total_limit >= TOTAL_LIMIT {
225                            panic!("TOTAL_LIMIT");
226                        }*/
227                        if expand == Expansion::Full {
228                            self.judgment_cache
229                                .add_simplification(term, &t, self.context.as_ref());
230                        }
231                        //println!("  : {:?}", t.debug_short());
232                        Some(t)
233                    }
234                };
235            }
236            if let Some(next) = self.scoped(|slf| slf.simplify_one(expand, &current)) {
237                current = Cow::Owned(next);
238            } else {
239                return match current {
240                    Cow::Borrowed(_) => {
241                        //println!("  : None");
242                        *recursion_limit -= 1;
243                        None
244                    }
245                    Cow::Owned(mut t) => {
246                        while let Some(r) = self.scoped(|slf| {
247                            slf.simplify_full_i(expand, &t, recursion_limit, total_limit)
248                        }) {
249                            t = r;
250                        }
251                        //println!("  : {:?}", t.debug_short());
252
253                        if expand == Expansion::Full {
254                            self.judgment_cache
255                                .add_simplification(term, &t, self.context.as_ref());
256                        }
257                        *recursion_limit -= 1;
258                        Some(t)
259                    }
260                };
261            }
262        }
263        //})
264    }
265
266    pub fn simplify_until(
267        &mut self,
268        term: &'t Term,
269        mut until: impl FnMut(&Self, &Term) -> bool,
270    ) -> Option<Cow<'t, Term>> {
271        if until(self, term) {
272            return Some(Cow::Borrowed(term));
273        }
274        self.wrap_check(CheckingTask::Simplify(term), |slf| {
275            slf.simplify_until_i(term, until, &mut 0, &mut 0)
276        })
277    }
278    fn simplify_until_i(
279        &mut self,
280        term: &'t Term,
281        mut until: impl FnMut(&Self, &Term) -> bool,
282        recursion_limit: &mut usize,
283        total_limit: &mut usize,
284    ) -> Option<Cow<'t, Term>> {
285        if until(self, term) {
286            return Some(Cow::Borrowed(term));
287        }
288        let mut current = Cow::<'t, _>::Borrowed(term);
289        *recursion_limit += 1;
290        let mut loop_limit = 0;
291        loop {
292            loop_limit += 1;
293            *total_limit += 1;
294            if *recursion_limit >= RECURSION_LIMIT
295                || loop_limit >= LOOP_LIMIT
296                || *total_limit >= TOTAL_LIMIT
297            {
298                *recursion_limit -= 1;
299                return None;
300            }
301            let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &current)) else {
302                *recursion_limit -= 1;
303                //self.comment(format!("Final simplification: {:?}", current.debug_short()));
304                return None;
305            };
306            if until(self, &next) {
307                *recursion_limit -= 1;
308                return Some(Cow::Owned(next));
309            }
310            current = Cow::Owned(next);
311        }
312    }
313
314    pub(crate) fn simplify_rules<Rl: CheckerRule + ?Sized, R>(
315        &mut self,
316        rules: &'t [Box<Rl>],
317        term: &'t Term,
318        applicable: impl Fn(&Rl, &Term) -> bool,
319        apply: impl for<'s> Fn(CheckRef<'s, '_, Split>, &Rl, &'s Term) -> Option<R> + Send + Sync,
320    ) -> Option<R>
321    where
322        R: Send + Sync + std::fmt::Debug + Clone + 'static,
323    {
324        let mut applicables = smallvec::SmallVec::<_, 2>::default();
325        match self.simplify_until(term, |_, t| {
326            applicables = rules
327                .iter()
328                .filter_map(|rl| {
329                    if applicable(&**rl, t) {
330                        Some(&**rl)
331                    } else {
332                        None
333                    }
334                })
335                .collect();
336            !applicables.is_empty()
337        }) {
338            Some(Cow::Borrowed(term)) => {
339                if let Some(r) =
340                    Split::split(self, true, applicables, |slf, rl| apply(slf, rl, term))
341                {
342                    return Some(r);
343                }
344                self.simplify_one(Expansion::Full, term).and_then(|term| {
345                    self.scoped(|slf| slf.simplify_rules(rules, &term, applicable, apply))
346                })
347            }
348            Some(Cow::Owned(term)) => self.scoped(|slf| {
349                if let Some(r) =
350                    Split::split(slf, true, applicables, |slf, rl| apply(slf, rl, &term))
351                {
352                    return Some(r);
353                }
354                slf.simplify_one(Expansion::Full, &term).and_then(|term| {
355                    slf.scoped(|slf| slf.simplify_rules(rules, &term, applicable, apply))
356                })
357            }),
358            None => {
359                self.failure("No rule applicable (1)");
360                //println!("Here: {}", term.debug_short());
361                None
362            }
363        }
364    }
365
366    pub(crate) fn simplify_until_two(
367        &mut self,
368        term1: &'t Term,
369        term2: &'t Term,
370        mut until: impl FnMut(&Self, &Term, &Term) -> bool,
371    ) -> Option<(Cow<'t, Term>, Cow<'t, Term>)> {
372        let mut left = true;
373        let mut right = true;
374        let mut next_left = true;
375        let mut t1 = Cow::Borrowed(term1);
376        let mut t2 = Cow::Borrowed(term2);
377        loop {
378            if next_left && left {
379                if until(self, &t1, &t2) {
380                    return Some((t1, t2));
381                }
382                if right {
383                    next_left = false;
384                }
385                if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t1)) {
386                    t1 = Cow::Owned(next);
387                    continue;
388                }
389                left = false;
390            }
391            if right {
392                if until(self, &t1, &t2) {
393                    return Some((t1, t2));
394                }
395                next_left = true;
396                if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t2)) {
397                    t2 = Cow::Owned(next);
398                    continue;
399                }
400                right = false;
401                continue;
402            }
403            break;
404        }
405        self.add_msg(
406            traceref!(FAIL
407                "Final simplifications: ",
408                t1.into_owned(),
409                " and ",
410                t2.into_owned()
411            )
412            .into(),
413        );
414        None
415    }
416
417    pub(crate) fn simplify_rules_two<Rl: CheckerRule + ?Sized + 'static, R>(
418        &mut self,
419        rules: &'t [Box<Rl>],
420        term1: &'t Term,
421        term2: &'t Term,
422        applicable: impl Fn(&CheckRef<'_, '_, Split>, &Rl, &Term, &Term) -> bool,
423        apply: impl for<'s> Fn(CheckRef<'s, '_, Split>, &Rl, &'s Term, &'s Term) -> Option<R> + Sync,
424        abort: impl Fn(&Term, &Term) -> bool + Send + Sync,
425    ) -> either::Either<Option<R>, (Term, Term)>
426    where
427        R: Send + Sync + std::fmt::Debug + Clone + 'static,
428    {
429        //println!("Simplify rules two {{");
430        let mut applicables = smallvec::SmallVec::<_, 2>::default();
431        let mut left = true;
432        let mut right = true;
433        let mut next_left = true;
434        let mut t1 = Cow::Borrowed(term1);
435        let mut t2 = Cow::Borrowed(term2);
436        loop {
437            macro_rules! set {
438                () => {
439                    set!(NOBREAK);
440                    if !applicables.is_empty() {
441                        break;
442                    }
443                };
444                (NOBREAK) => {
445                    if abort(&*t1, &*t2) {
446                        //println!("}}");
447                        return either::Right((t1.into_owned(), t2.into_owned()));
448                    }
449                    applicables = rules
450                        .iter()
451                        .filter_map(|rl| {
452                            if applicable(self, &**rl, &*t1, &*t2) {
453                                Some(&**rl)
454                            } else {
455                                None
456                            }
457                        })
458                        .collect();
459                };
460            }
461            loop {
462                /*let s = t1.debug_short().to_string();
463                let s2 = t2.debug_short().to_string();
464                if s.contains("\"universal quantifier\"[") || s2.contains("\"universal quantifier\"[") {
465                    println!("Here: {s}  ===  {s2}");
466                }*/
467
468                if next_left && left {
469                    set!();
470                    if right {
471                        next_left = false;
472                    }
473                    if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t1)) {
474                        t1 = Cow::Owned(next);
475                        continue;
476                    }
477                    left = false;
478                }
479                if right {
480                    set!();
481                    if left {
482                        next_left = true;
483                    }
484                    if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t2)) {
485                        t2 = Cow::Owned(next);
486                        continue;
487                    }
488                    right = false;
489                    if left {
490                        continue;
491                    }
492                }
493                break;
494            }
495
496            if applicables.is_empty() {
497                self.failure("No rule applicable (2)");
498                self.add_msg(
499                    traceref!(FAIL
500                        "Final simplifications: ",
501                        t1.into_owned(),
502                        " and ",
503                        t2.into_owned()
504                    )
505                    .into(),
506                );
507                //println!("}}");
508                return either::Left(None);
509            }
510            if let Some(r) = self.scoped(|slf| {
511                Split::split(slf, true, std::mem::take(&mut applicables), |slf, rl| {
512                    apply(slf, rl, &t1, &t2)
513                })
514            }) {
515                //println!("}}");
516                return either::Left(Some(r));
517            }
518            if next_left && left {
519                if right {
520                    next_left = false;
521                }
522                if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t1)) {
523                    t1 = Cow::Owned(next);
524                    //set!(NOBREAK);
525                    continue;
526                }
527                left = false;
528            }
529            if right {
530                if left {
531                    next_left = true;
532                }
533                if let Some(next) = self.scoped(|slf| slf.simplify_one(Expansion::Full, &t2)) {
534                    t2 = Cow::Owned(next);
535                    //set!(NOBREAK);
536                    continue;
537                }
538                right = false;
539                if left {
540                    continue;
541                }
542            }
543            break;
544        }
545        self.failure("No rule applicable (3)");
546        //println!("}}");
547        either::Left(None)
548    }
549
550    pub(super) fn simplify_one(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
551        if term.has_solvable() {
552            let nterm = self.subst(term.clone());
553            if *term != nterm {
554                return Some(nterm); //self.scoped(|slf| slf.simplify_one_i(expand, &nterm));
555            }
556        }
557        if let Cow::Owned(nterm) = beta_unknowns_cow(term)
558            && *term != nterm
559        {
560            return Some(nterm); //self.scoped(|slf| slf.simplify_one_i(expand, &nterm));
561        }
562
563        /*
564        let s = term.debug_short().to_string();
565        if s.contains("\"universal quantifier\"[") {
566            println!("Here: {:?}", term.debug_short());
567        }
568        */
569
570        if
571        /*expand != Expansion::NoDefinitionExpansion
572        &&*/
573        true {
574            match self.simplify_implicit(term) {
575                Ok(Some(t)) => return Some(t),
576                Ok(None) => (),
577                Err(()) => return None,
578            }
579        }
580        self.simplify_one_i(expand, term)
581    }
582    fn simplify_one_i(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
583        /**/
584        let applicables = self
585            .top
586            .rules
587            .simplification()
588            .iter()
589            .filter_map(|rl| {
590                if rl.applicable(term) {
591                    Some(&**rl)
592                } else {
593                    None
594                }
595            })
596            .collect::<smallvec::SmallVec<_, 2>>();
597        match Split::split(self, false, applicables, |slf, rl| {
598            match rl.apply(slf, term) {
599                Ok(t) => Some(either::Left(t)),
600                Err(Some(v)) => Some(either::Right(v)),
601                _ => None,
602            }
603        }) {
604            Some(either::Left(t)) => return Some(t),
605            Some(_) => {
606                // TODO
607            }
608            None => (),
609        }
610
611        /*
612        let s = term.debug_short().to_string();
613        if s.contains("\"universal quantifier\"[") {
614            println!("here: {s}");
615        }
616         */
617
618        self.simplify_one_default(expand, term)
619    }
620
621    fn simplify_morph(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
622        let (m, r) = crate::rules::MorphismRule::is_morphism_appl(term, self)?;
623        /*if let Some((m2, r2)) = crate::rules::MorphismRule::is_morphism_appl(r, self)
624            && let Ok(t) = m2.apply(r2, |s| {
625                self.top
626                    .get_symbol_like(s, |t| self.prepare(t, None).1)
627                    .ok()
628            })
629            && *t != *r2
630        {
631            let r = Term::Application(ApplicationTerm::new(
632                m.uri.clone().into(),
633                Box::new([Argument::Simple(t.into_owned())]),
634                None,
635            ));
636            return self.scoped(|slf| slf.simplify_morph(expand, &r));
637        }*/
638        if matches!(r, Term::Symbol { .. })
639            && let Some(nt) = self.simplify_one_default(expand, r)
640            && let Ok(nt) = m.apply(&nt, &mut |s| {
641                self.top
642                    .get_symbol_like(s, |t| self.prepare(t, None).1)
643                    .ok()
644            })
645            && *nt != *term
646        {
647            Some(nt.into_owned())
648        } else if let Ok(Some(nt)) = self.simplify_implicit(r)
649            && let Ok(nt) = m.apply(&nt, &mut |s| {
650                self.top
651                    .get_symbol_like(s, |t| self.prepare(t, None).1)
652                    .ok()
653            })
654            && *nt != *term
655        {
656            Some(nt.into_owned())
657        } else {
658            None
659        }
660    }
661
662    fn simplify_one_default(&mut self, expand: Expansion, term: &'t Term) -> Option<Term> {
663        if
664        /*expand != Expansion::NoDefinitionExpansion
665        &&*/
666        true {
667            match self.simplify_implicit(term) {
668                Ok(Some(t)) => return Some(t),
669                Ok(None) => (),
670                Err(()) => return None,
671            }
672        }
673        if let Some(t) = self.simplify_morph(expand, term) {
674            return Some(t);
675        }
676        match term {
677            // Definition Expansion
678            Term::Symbol { uri, .. } if expand == Expansion::NoNoexpands => {
679                let s = self.get_symbol(uri).ok()?;
680                if s.data.role.contains(&NOEXPAND) {
681                    None
682                } else {
683                    self.get_symbol_definiens(uri).inspect(|_| {
684                        self.comment("expanded definition");
685                    })
686                }
687            }
688            Term::Symbol { uri, .. } /*if expand == Expansion::Full*/ => {
689                self.get_symbol_definiens(uri).inspect(|_| {
690                    self.comment("expanded definition");
691                })
692            }
693            Term::Var { variable, .. }
694                if true/*expand != Expansion::NoDefinitionExpansion*/
695                    || is_solvable_var(variable).is_some() =>
696            {
697                self.get_var_definiens(variable).inspect(|_| {
698                    self.comment("expanded definition");
699                })
700            }
701
702            Term::Application(app) if self.top.hoas().is_some_and(|h| h.judgment.as_ref().is_some_and(|j|
703                app.head.is(j)
704            )) && let [Argument::Simple(p)] = &*app.arguments => {
705                self.simplify_one(expand, p).map(|r| Term::Application(ApplicationTerm::new(
706                    app.head.clone(),Box::new([Argument::Simple(r)]),app.presentation.clone()
707                )))
708            }
709
710            Term::Application(app) => self.simplify_one(expand, &app.head).map(|nh| {
711                Term::Application(ApplicationTerm::new(
712                    nh,
713                    app.arguments.clone(),
714                    app.presentation.clone(),
715                ))
716            }),
717            Term::Bound(app) => self.simplify_one(expand.with_defs(), &app.head).map(|nh| {
718                Term::Bound(BindingTerm::new(
719                    nh,
720                    app.arguments.clone(),
721                    app.presentation.clone(),
722                ))
723            }),
724            _ => None,
725        }
726    }
727
728    fn arg_full(
729        &mut self,
730        expand: Expansion,
731        arg: &'t Argument,
732        recursion_limit: &mut usize,
733        total_limit: &mut usize,
734    ) -> Option<Argument> {
735        match arg {
736            Argument::Simple(t) => self
737                .simplify_full_i(expand, t, recursion_limit, total_limit)
738                .map(Argument::Simple),
739            Argument::Sequence(MaybeSequence::One(t)) => self
740                .simplify_full_i(expand, t, recursion_limit, total_limit)
741                .map(|t| Argument::Sequence(MaybeSequence::One(t))),
742            Argument::Sequence(MaybeSequence::Seq(ts)) => {
743                let mut changed = false;
744                let nts = ts
745                    .iter()
746                    .map(|t| {
747                        self.simplify_full_i(expand, t, recursion_limit, total_limit)
748                            .map_or(Cow::Borrowed(t), |a| {
749                                changed = true;
750                                Cow::Owned(a)
751                            })
752                    })
753                    .collect::<Vec<_>>();
754                if changed {
755                    Some(Argument::Sequence(MaybeSequence::Seq(
756                        nts.into_iter().map(Cow::into_owned).collect(),
757                    )))
758                } else {
759                    None
760                }
761            }
762        }
763    }
764    fn bound_arg_full(
765        &mut self,
766        expand: Expansion,
767        arg: &'t BoundArgument,
768        recusion_limit: &mut usize,
769        total_limit: &mut usize,
770    ) -> Option<BoundArgument> {
771        match arg {
772            BoundArgument::Simple(t) => self
773                .simplify_full_i(expand, t, recusion_limit, total_limit)
774                .map(BoundArgument::Simple),
775            BoundArgument::Bound(cv) => self
776                .cv_full(expand, cv, recusion_limit, total_limit)
777                .map(BoundArgument::Bound),
778            BoundArgument::Sequence(MaybeSequence::One(t)) => self
779                .simplify_full_i(expand, t, recusion_limit, total_limit)
780                .map(|t| BoundArgument::Sequence(MaybeSequence::One(t))),
781            BoundArgument::BoundSeq(MaybeSequence::One(cv)) => self
782                .cv_full(expand, cv, recusion_limit, total_limit)
783                .map(|t| BoundArgument::BoundSeq(MaybeSequence::One(t))),
784            BoundArgument::Sequence(MaybeSequence::Seq(ts)) => {
785                let mut changed = false;
786                let nts = ts
787                    .iter()
788                    .map(|t| {
789                        self.simplify_full_i(expand, t, recusion_limit, total_limit)
790                            .map_or(Cow::Borrowed(t), |a| {
791                                changed = true;
792                                Cow::Owned(a)
793                            })
794                    })
795                    .collect::<Vec<_>>();
796                if changed {
797                    Some(BoundArgument::Sequence(MaybeSequence::Seq(
798                        nts.into_iter().map(Cow::into_owned).collect(),
799                    )))
800                } else {
801                    None
802                }
803            }
804            BoundArgument::BoundSeq(MaybeSequence::Seq(cvs)) => {
805                let mut changed = false;
806                let ncvs = cvs
807                    .iter()
808                    .map(|t| {
809                        self.cv_full(expand, t, recusion_limit, total_limit).map_or(
810                            Cow::Borrowed(t),
811                            |a| {
812                                changed = true;
813                                Cow::Owned(a)
814                            },
815                        )
816                    })
817                    .collect::<Vec<_>>();
818                if changed {
819                    Some(BoundArgument::BoundSeq(MaybeSequence::Seq(
820                        ncvs.into_iter().map(Cow::into_owned).collect(),
821                    )))
822                } else {
823                    None
824                }
825            }
826        }
827    }
828
829    fn cv_full(
830        &mut self,
831        expand: Expansion,
832        arg: &'t ComponentVar,
833        recursion_limit: &mut usize,
834        total_limit: &mut usize,
835    ) -> Option<ComponentVar> {
836        match (arg.tp.as_ref(), arg.df.as_ref()) {
837            (None, None) => None,
838            (Some(tp), None) => self
839                .simplify_full_i(expand, tp, recursion_limit, total_limit)
840                .map(|tp| ComponentVar {
841                    var: arg.var.clone(),
842                    tp: Some(tp),
843                    df: None,
844                }),
845            (None, Some(df)) => self
846                .simplify_full_i(expand, df, recursion_limit, total_limit)
847                .map(|df| ComponentVar {
848                    var: arg.var.clone(),
849                    tp: None,
850                    df: Some(df),
851                }),
852            (Some(tp), Some(df)) => {
853                let ntp = self.simplify_full_i(expand, tp, recursion_limit, total_limit);
854                let ndf = self.simplify_full_i(expand, df, recursion_limit, total_limit);
855                if ntp.is_none() && ndf.is_none() {
856                    return None;
857                }
858                Some(ComponentVar {
859                    var: arg.var.clone(),
860                    tp: Some(ntp.unwrap_or_else(|| tp.clone())),
861                    df: Some(ndf.unwrap_or_else(|| df.clone())),
862                })
863            }
864        }
865    }
866
867    pub(crate) fn simplify_implicit(&mut self, term: &'t Term) -> Result<Option<Term>, ()> {
868        let Some((Term::Symbol { uri, .. }, args)) = term.unapply_implicits(false) else {
869            return Ok(None);
870        };
871        let Some(def) = self.get_symbol_definiens(uri) else {
872            self.comment(format!("Symbol has no definiens: {uri}"));
873            return Err(());
874        };
875        let Some((def, vars)) = def.get_bound_implicits() else {
876            self.failure("definiens has no implicit arguments");
877            return Err(());
878        };
879        if args.len() != vars.len() {
880            self.failure("number of implicit arguments don't match");
881            return Err(());
882        };
883        let mut substs = Vec::new();
884        for (ComponentVar { var, tp, .. }, arg) in vars.iter().zip(args) {
885            if let Some(tp) = tp {
886                let tp: Cow<Term> = tp / &*substs;
887                if self.scoped(|checker| checker.check_type(arg, &tp)) != Some(true) {
888                    return Err(());
889                }
890                substs.push((var.name(), arg));
891            }
892        }
893        let r = def / &*substs;
894        tracing::debug!("Unapplied implicits: {:?}", r.debug_short());
895        Ok(Some(r.into_owned()))
896    }
897}