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