Skip to main content

ftml_solver/impls/
typing.rs

1use std::borrow::Cow;
2
3use crate::{
4    CheckRef,
5    impls::solving::TermExtSolvable,
6    rules::{InhabitableRule, UniverseRule},
7    split::SplitStrategy,
8    trace::CheckingTask,
9};
10use ftml_ontology::terms::Term;
11use smallvec::SmallVec;
12
13impl<'t, Split: SplitStrategy> CheckRef<'t, '_, Split> {
14    pub fn check_type(&mut self, tm: &'t Term, tp: &'t Term) -> Option<bool> {
15        tracing::debug!(
16            "Checking Typing {:?}   ::   {:?}",
17            tm.debug_short(),
18            tp.debug_short()
19        );
20        self.wrap_check(CheckingTask::HasType(tm, tp), |slf| {
21            slf.check_type_i(tm, tp)
22        })
23    }
24
25    pub fn check_subtype(&mut self, sub: &'t Term, sup: &'t Term) -> Option<bool> {
26        tracing::debug!(
27            "Checking Subtyping {:?}   <:   {:?}",
28            sub.debug_short(),
29            sup.debug_short()
30        );
31        self.wrap_check(CheckingTask::Subtype(sub, sup), |slf| {
32            slf.check_subtype_i(sub, sup)
33        })
34    }
35
36    pub fn check_inhabitable(&mut self, t: &'t Term) -> Option<bool> {
37        tracing::debug!("Checking Inhabitability of {:?}", t.debug_short());
38        if t.has_solvable() {
39            let nt = self.subst(t.clone());
40            self.scoped(|slf| {
41                slf.wrap_check(CheckingTask::Inhabitable(&nt), |slf| {
42                    slf.check_inhabitable_i(&nt)
43                })
44            })
45        } else {
46            self.wrap_check(CheckingTask::Inhabitable(t), |slf| {
47                slf.check_inhabitable_i(t)
48            })
49        }
50    }
51
52    pub fn check_universe(&mut self, t: &'t Term) -> Option<bool> {
53        tracing::debug!("Checking Universe {:?}", t.debug_short());
54        //self.wrap_check(CheckingTask::Universe(t), |slf| slf.check_universe_i(t))
55        if t.has_solvable() {
56            let nt = self.subst(t.clone());
57            self.scoped(|slf| {
58                slf.wrap_check(CheckingTask::Universe(&nt), |slf| slf.check_universe_i(&nt))
59            })
60        } else {
61            self.wrap_check(CheckingTask::Universe(t), |slf| slf.check_universe_i(t))
62        }
63    }
64
65    pub(crate) fn check_type_i(&mut self, tm: &'t Term, tp: &'t Term) -> Option<bool> {
66        //self.cancellable(|slf| {
67        Split::strategies(
68            self,
69            "Using type inference",
70            |slf| {
71                let subtp = slf.infer_type(tm)?;
72                slf.scoped(|slf| slf.check_subtype(&subtp, tp))
73            },
74            "Using checking rules",
75            |slf| {
76                if let either::Left(r) = slf.simplify_rules_two(
77                    self.top.rules.checking(),
78                    tm,
79                    tp,
80                    |slf, rl, tm, tp| rl.applicable(slf, tm, tp),
81                    |slf, rl, tm, tp| rl.apply(slf, tm, tp),
82                    |_, _| false,
83                ) {
84                    r
85                } else {
86                    None
87                }
88                /*
89                let rules = slf
90                    .top
91                    .rules
92                    .checking()
93                    .iter()
94                    .filter_map(|rl| {
95                        if rl.applicable(slf, tm, tp) {
96                            Some(&**rl)
97                        } else {
98                            None
99                        }
100                    })
101                    .collect::<smallvec::SmallVec<_, 2>>();
102                Split::split(slf, true, rules, |slf, rl| rl.apply(slf, tm, tp))
103                */
104            },
105        )
106        //})
107    }
108
109    pub(crate) fn check_subtype_i(&mut self, sub: &'t Term, sup: &'t Term) -> Option<bool> {
110        if sub.alpha_equal(sup) {
111            self.comment("trivial");
112            tracing::debug!("trivial");
113            return Some(true);
114        }
115        if let Some(unk) = sub.is_solvable() {
116            return self.solve_upper_bound(unk, sup);
117        }
118        if let Some(unk) = sup.is_solvable() {
119            return self.solve_lower_bound(unk, sub);
120        }
121        match self.simplify_rules_two(
122            self.top.rules.subtyping(),
123            sub,
124            sup,
125            |slf, rl, sub, sup| rl.applicable(slf, sub, sup),
126            |slf, rl, sub, sup| rl.apply(slf, sub, sup),
127            |sub, sup| {
128                sub.alpha_equal(sup) || sub.is_solvable().is_some() || sup.is_solvable().is_some()
129            },
130        ) {
131            either::Left(opt) => {
132                if opt.is_some() {
133                    return opt;
134                }
135                tracing::debug!("Proving subtyping failed; Falling back to checking equality");
136                match self.traced(
137                    CheckingTask::Strategy(
138                        "Proving subtyping failed; Falling back to checking equality",
139                    ),
140                    |slf| slf.check_equality_i(sub, sup),
141                ) {
142                    Ok(r) => Some(r),
143                    Err(ls) => {
144                        self.add_msg(ls.into());
145                        None
146                    }
147                }
148            }
149            either::Right((sub, sup)) => {
150                if sub.alpha_equal(&sup) {
151                    self.comment("trivial");
152                    tracing::debug!("trivial");
153                    return Some(true);
154                }
155                self.scoped(|slf| {
156                    if let Some(unk) = sub.is_solvable() {
157                        tracing::debug!("solving");
158                        return slf.solve_upper_bound(unk, &sup);
159                    }
160                    if let Some(unk) = sup.is_solvable() {
161                        tracing::debug!("solving");
162                        return slf.solve_lower_bound(unk, &sub);
163                    }
164                    tracing::debug!("Proving subtyping failed; Falling back to checking equality");
165                    match slf.traced(
166                        CheckingTask::Strategy(
167                            "Proving subtyping failed; Falling back to checking equality",
168                        ),
169                        |slf| slf.check_equality_i(&sub, &sup),
170                    ) {
171                        Ok(r) => Some(r),
172                        Err(ls) => {
173                            slf.add_msg(ls.into());
174                            None
175                        }
176                    }
177                })
178            }
179        }
180
181        /*
182        let sub = self
183            .simplify_full(false, sub)
184            .map_or(Cow::Borrowed(sub), Cow::Owned);
185        let sup = self
186            .simplify_full(false, sup)
187            .map_or(Cow::Borrowed(sup), Cow::Owned);
188        if self.alpha_equal(&sub, &sup) {
189            self.comment("trivial");
190            return Some(true);
191        }
192        self.scoped(|slf| {
193            if let Some(unk) = sub.is_solvable() {
194                tracing::debug!("solving");
195                return slf.solve_upper_bound(unk, &sup);
196            }
197            if let Some(unk) = sup.is_solvable() {
198                tracing::debug!("solving");
199                return slf.solve_lower_bound(unk, &sub);
200            }
201            let rules = slf
202                .top
203                .rules
204                .subtyping()
205                .iter()
206                .filter_map(|rl| {
207                    if rl.applicable(slf, &sub, &sup) {
208                        Some(&**rl)
209                    } else {
210                        None
211                    }
212                })
213                .collect::<smallvec::SmallVec<_, 2>>();
214            let lines = match Split::split_i(slf, true, rules, |slf, rl| rl.apply(slf, &sub, &sup))
215            {
216                Ok(r) => return Some(r),
217                Err(ls) => ls,
218            };
219            match slf.traced(
220                CheckingTask::Strategy(
221                    "Proving subtyping failed; Falling back to checking equality",
222                ),
223                |slf| slf.check_equality_i(&sub, &sup),
224            ) {
225                Ok(b) => Some(b),
226                Err(l) => {
227                    for l in lines {
228                        slf.add_msg(l.into());
229                    }
230                    slf.add_msg(l.into());
231                    None
232                }
233            }
234        })
235         */
236    }
237
238    pub(crate) fn check_inhabitable_i(&mut self, tm: &'t Term) -> Option<bool> {
239        Split::strategies(
240            self,
241            "Using type inference",
242            |slf| {
243                let tp = slf.infer_type(tm)?;
244                slf.scoped(|slf| slf.check_universe(&tp))
245            },
246            "Using inhabitable rules",
247            |slf| {
248                slf.simplify_rules(
249                    slf.top.rules.inhabitable(),
250                    tm,
251                    InhabitableRule::applicable,
252                    |slf, rl, t| rl.apply(slf, t),
253                )
254            },
255        )
256    }
257
258    fn check_universe_i(&mut self, tm: &'t Term) -> Option<bool> {
259        //self.comment(format!("{:?}", self.top.rules.universe()));
260        self.simplify_rules(
261            self.top.rules.universe(),
262            tm,
263            UniverseRule::applicable,
264            |slf, rl, t| rl.apply(slf, t),
265        )
266
267        /*let rules = self
268            .top
269            .rules
270            .universe()
271            .iter()
272            .filter_map(|rl| if rl.applicable(t) { Some(&**rl) } else { None });
273        Split::split(self, true, rules, |slf, rl| rl.apply(slf, t))*/
274    }
275}