1use super::check::DefnDecl;
10use super::env::Safety;
11use super::error::{KResult, KernelFailure};
12use super::expr::ExprId;
13use super::level::LevelsId;
14use super::name::NameId;
15use super::tc::Kernel;
16
17impl Kernel {
18 fn prim_fail(&self, n: NameId) -> KernelFailure {
19 KernelFailure::reject(format!(
20 "invalid form for primitive definition '{}'",
21 self.s.names.display(n)
22 ))
23 }
24
25 fn c0(&mut self, n: NameId) -> ExprId {
26 self.s.cnst(n, LevelsId::EMPTY)
27 }
28
29 fn defeq1(&mut self, a: ExprId, b: ExprId) -> KResult<bool> {
31 let nat = self.c0(self.wk.nat);
32 let pa = self.s.pi(nat, a);
33 let pb = self.s.pi(nat, b);
34 self.is_def_eq(pa, pb)
35 }
36
37 fn defeq2(&mut self, a: ExprId, b: ExprId) -> KResult<bool> {
39 let nat = self.c0(self.wk.nat);
40 let pa = self.s.pi(nat, a);
41 let pb = self.s.pi(nat, b);
42 self.defeq1(pa, pb)
43 }
44
45 fn arrow(&mut self, a: ExprId, b: ExprId) -> ExprId {
46 let b = self.s.lift_loose(b, 0, 1);
47 self.s.pi(a, b)
48 }
49
50 fn app2(&mut self, f: ExprId, a: ExprId, b: ExprId) -> ExprId {
51 self.s.mk_app_n(f, &[a, b])
52 }
53
54 pub fn check_primitive_def(&mut self, d: &DefnDecl) -> KResult<bool> {
62 let checked = self.check_primitive_form(d);
63 if self.theory == super::tc::Theory::Logos {
64 return Ok(matches!(checked, Ok(true)));
65 }
66 checked
67 }
68
69 fn check_primitive_form(&mut self, d: &DefnDecl) -> KResult<bool> {
70 let n = d.header.name;
71 if d.safety != Safety::Safe || !self.wk.primitives().contains(&n) {
72 return Ok(false);
73 }
74 if !d.header.lparams.is_empty() {
75 return Err(self.prim_fail(n));
76 }
77 let w = WellKnownIds::of(self);
78 let nat = self.c0(w.nat);
79 let bool_ = self.c0(w.bool_);
80 let tru = self.c0(w.tru);
81 let fal = self.c0(w.fal);
82 let zero = self.c0(w.zero);
83 let succ_c = self.c0(w.succ);
84 let x = self.s.bvar(0);
85 let y = self.s.bvar(1);
86 let succ = |k: &mut Kernel, e: ExprId| k.s.app(succ_c, e);
87 let nn = self.arrow(nat, nat);
88 let nnn = self.arrow(nat, nn);
89 let nb = self.arrow(nat, bool_);
90 let nnb = self.arrow(nat, nb);
91 let v = d.value;
92 let ty = d.header.ty;
93 let ok = if n == w.add {
94 self.env.contains(w.nat)
95 && self.is_def_eq(ty, nnn)?
96 && {
97 let lhs = self.app2(v, x, zero);
98 self.defeq1(lhs, x)?
99 }
100 && {
101 let sx = succ(self, x);
102 let lhs = self.app2(v, y, sx);
103 let r = self.app2(v, y, x);
104 let rhs = succ(self, r);
105 self.defeq2(lhs, rhs)?
106 }
107 } else if n == w.pred {
108 self.env.contains(w.nat)
109 && self.is_def_eq(ty, nn)?
110 && {
111 let lhs = self.s.app(v, zero);
112 self.is_def_eq(lhs, zero)?
113 }
114 && {
115 let sx = succ(self, x);
116 let lhs = self.s.app(v, sx);
117 self.defeq1(lhs, x)?
118 }
119 } else if n == w.sub {
120 self.env.contains(w.pred)
121 && self.is_def_eq(ty, nnn)?
122 && {
123 let lhs = self.app2(v, x, zero);
124 self.defeq1(lhs, x)?
125 }
126 && {
127 let pred = self.c0(w.pred);
128 let sx = succ(self, x);
129 let lhs = self.app2(v, y, sx);
130 let r = self.app2(v, y, x);
131 let rhs = self.s.app(pred, r);
132 self.defeq2(lhs, rhs)?
133 }
134 } else if n == w.mul {
135 self.env.contains(w.add)
136 && self.is_def_eq(ty, nnn)?
137 && {
138 let lhs = self.app2(v, x, zero);
139 self.defeq1(lhs, zero)?
140 }
141 && {
142 let add = self.c0(w.add);
143 let sx = succ(self, x);
144 let lhs = self.app2(v, y, sx);
145 let r = self.app2(v, y, x);
146 let rhs = self.app2(add, r, y);
147 self.defeq2(lhs, rhs)?
148 }
149 } else if n == w.pow {
150 self.env.contains(w.mul)
151 && self.is_def_eq(ty, nnn)?
152 && {
153 let one = succ(self, zero);
154 let lhs = self.app2(v, x, zero);
155 self.defeq1(lhs, one)?
156 }
157 && {
158 let mul = self.c0(w.mul);
159 let sx = succ(self, x);
160 let lhs = self.app2(v, y, sx);
161 let r = self.app2(v, y, x);
162 let rhs = self.app2(mul, r, y);
163 self.defeq2(lhs, rhs)?
164 }
165 } else if n == w.beq || n == w.ble {
166 let is_beq = n == w.beq;
167 self.env.contains(w.nat)
168 && self.env.contains(w.bool_)
169 && self.is_def_eq(ty, nnb)?
170 && {
171 let lhs = self.app2(v, zero, zero);
172 self.is_def_eq(lhs, tru)?
173 }
174 && {
175 let sx = succ(self, x);
176 let lhs = self.app2(v, zero, sx);
177 let expect = if is_beq { fal } else { tru };
178 self.defeq1(lhs, expect)?
179 }
180 && {
181 let sx = succ(self, x);
182 let lhs = self.app2(v, sx, zero);
183 self.defeq1(lhs, fal)?
184 }
185 && {
186 let sx = succ(self, x);
187 let sy = succ(self, y);
188 let lhs = self.app2(v, sy, sx);
189 let rhs = self.app2(v, y, x);
190 self.defeq2(lhs, rhs)?
191 }
192 } else if n == w.shl {
193 self.env.contains(w.mul)
194 && self.is_def_eq(ty, nnn)?
195 && {
196 let lhs = self.app2(v, x, zero);
197 self.defeq1(lhs, x)?
198 }
199 && {
200 let mul = self.c0(w.mul);
201 let one = succ(self, zero);
202 let two = succ(self, one);
203 let sy = succ(self, y);
204 let lhs = self.app2(v, x, sy);
205 let tx = self.app2(mul, two, x);
206 let rhs = self.app2(v, tx, y);
207 self.defeq2(lhs, rhs)?
208 }
209 } else if n == w.shr {
210 self.env.contains(w.div)
211 && self.is_def_eq(ty, nnn)?
212 && {
213 let lhs = self.app2(v, x, zero);
214 self.defeq1(lhs, x)?
215 }
216 && {
217 let div = self.c0(w.div);
218 let one = succ(self, zero);
219 let two = succ(self, one);
220 let sy = succ(self, y);
221 let lhs = self.app2(v, x, sy);
222 let r = self.app2(v, x, y);
223 let rhs = self.app2(div, r, two);
224 self.defeq2(lhs, rhs)?
225 }
226 } else if n == w.land || n == w.lor || n == w.xor {
227 self.env.contains(w.bitwise)
228 && self.is_def_eq(ty, nnn)?
229 && self.check_bitwise_op(n, v, &w)?
230 } else if n == w.char_of_nat {
231 let ch = self.c0(w.char_);
232 self.env.contains(w.nat) && self.env.contains(w.char_) && {
233 let t = self.arrow(nat, ch);
234 self.is_def_eq(ty, t)?
235 }
236 } else if n == w.string_of_list {
237 self.check_string_of_list(ty)?
238 } else if n == w.mod_ || n == w.div || n == w.gcd || n == w.bitwise {
239 let admitted = self.env.contains(w.nat) && {
240 let expect = if n == w.bitwise {
241 let bb = self.arrow(bool_, bool_);
242 let bbb = self.arrow(bool_, bb);
243 self.arrow(bbb, nnn)
244 } else {
245 nnn
246 };
247 self.is_def_eq(ty, expect)?
248 };
249 if admitted && self.check_wf_primitive(d)? && self.accelerable_after_validation(n) {
250 self.validated_primitives.insert(n);
251 }
252 if !admitted {
253 return Err(self.prim_fail(n));
254 }
255 return Ok(true);
256 } else {
257 return Ok(false);
258 };
259 if !ok {
260 return Err(self.prim_fail(n));
261 }
262 if self.accelerable_after_validation(n) {
263 self.validated_primitives.insert(n);
264 }
265 Ok(true)
266 }
267
268 fn accelerable_after_validation(&self, n: NameId) -> bool {
274 let w = &self.wk;
275 let deps: &[NameId] = if n == w.nat_mod || n == w.nat_div {
276 &[w.nat_sub]
277 } else if n == w.nat_gcd {
278 &[w.nat_mod]
279 } else if n == w.nat_bitwise {
280 &[w.nat_div, w.nat_mod, w.nat_add]
281 } else if n == w.nat_sub {
282 &[w.nat_pred]
283 } else if n == w.nat_mul || n == w.nat_shift_left {
284 &[w.nat_add, w.nat_mul]
285 } else if n == w.nat_pow {
286 &[w.nat_add, w.nat_mul]
287 } else if n == w.nat_shift_right {
288 &[w.nat_div]
289 } else if [w.nat_land, w.nat_lor, w.nat_xor].contains(&n) {
290 &[w.nat_bitwise]
291 } else {
292 &[]
293 };
294 deps.iter()
295 .all(|d| *d == n || self.validated_primitives.contains(d))
296 }
297
298 fn check_bitwise_op(&mut self, n: NameId, v: ExprId, w: &WellKnownIds) -> KResult<bool> {
299 let super::expr::Node::App(f, op) = self.s.node(v) else {
300 return Ok(false);
301 };
302 if f != self.c0(w.bitwise) {
303 return Ok(false);
304 }
305 let tru = self.c0(w.tru);
306 let fal = self.c0(w.fal);
307 let x = self.s.bvar(0);
308 let bool_ = self.c0(w.bool_);
309 let under_bool = |k: &mut Kernel, a: ExprId, b: ExprId| -> KResult<bool> {
310 let pa = k.s.pi(bool_, a);
311 let pb = k.s.pi(bool_, b);
312 k.is_def_eq(pa, pb)
313 };
314 let app = |k: &mut Kernel, a: ExprId, b: ExprId| k.s.mk_app_n(op, &[a, b]);
315 Ok(if n == w.land {
316 let a = app(self, fal, x);
317 let b = app(self, tru, x);
318 under_bool(self, a, fal)? && under_bool(self, b, x)?
319 } else if n == w.lor {
320 let a = app(self, fal, x);
321 let b = app(self, tru, x);
322 under_bool(self, a, x)? && under_bool(self, b, tru)?
323 } else {
324 let cases = [
325 (fal, fal, fal),
326 (tru, fal, tru),
327 (fal, tru, tru),
328 (tru, tru, fal),
329 ];
330 let mut all = true;
331 for (a, b, r) in cases {
332 let e = app(self, a, b);
333 if !self.is_def_eq(e, r)? {
334 all = false;
335 break;
336 }
337 }
338 all
339 })
340 }
341
342 fn check_string_of_list(&mut self, ty: ExprId) -> KResult<bool> {
343 let w = WellKnownIds::of(self);
344 for needed in [w.char_, w.list, w.list_nil, w.list_cons, w.string] {
345 if !self.env.contains(needed) {
346 return Ok(false);
347 }
348 }
349 let zero = self.s.levels.list(&[super::level::LevelId::ZERO]);
350 let ch = self.c0(w.char_);
351 let list_c = self.s.cnst(w.list, zero);
352 let list_char = self.s.app(list_c, ch);
353 let string = self.c0(w.string);
354 let expect = self.arrow(list_char, string);
355 let nil_c = self.s.cnst(w.list_nil, zero);
356 let nil = self.s.app(nil_c, ch);
357 let nil_t = self.check(nil)?;
358 let cons_c = self.s.cnst(w.list_cons, zero);
359 let cons = self.s.app(cons_c, ch);
360 let cons_t = self.check(cons)?;
361 let lc_lc = self.arrow(list_char, list_char);
362 let cons_expect = self.arrow(ch, lc_lc);
363 Ok(self.is_def_eq(nil_t, list_char)?
364 && self.is_def_eq(cons_t, cons_expect)?
365 && self.is_def_eq(ty, expect)?)
366 }
367}
368
369pub(crate) struct WellKnownIds {
371 nat: NameId,
372 zero: NameId,
373 succ: NameId,
374 add: NameId,
375 pred: NameId,
376 sub: NameId,
377 mul: NameId,
378 pow: NameId,
379 div: NameId,
380 mod_: NameId,
381 gcd: NameId,
382 beq: NameId,
383 ble: NameId,
384 shl: NameId,
385 shr: NameId,
386 land: NameId,
387 lor: NameId,
388 xor: NameId,
389 bitwise: NameId,
390 bool_: NameId,
391 tru: NameId,
392 fal: NameId,
393 char_: NameId,
394 char_of_nat: NameId,
395 string: NameId,
396 string_of_list: NameId,
397 list: NameId,
398 list_nil: NameId,
399 list_cons: NameId,
400}
401
402impl WellKnownIds {
403 fn of(k: &Kernel) -> WellKnownIds {
404 let w = &k.wk;
405 WellKnownIds {
406 nat: w.nat,
407 zero: w.nat_zero,
408 succ: w.nat_succ,
409 add: w.nat_add,
410 pred: w.nat_pred,
411 sub: w.nat_sub,
412 mul: w.nat_mul,
413 pow: w.nat_pow,
414 div: w.nat_div,
415 mod_: w.nat_mod,
416 gcd: w.nat_gcd,
417 beq: w.nat_beq,
418 ble: w.nat_ble,
419 shl: w.nat_shift_left,
420 shr: w.nat_shift_right,
421 land: w.nat_land,
422 lor: w.nat_lor,
423 xor: w.nat_xor,
424 bitwise: w.nat_bitwise,
425 bool_: w.bool_,
426 tru: w.bool_true,
427 fal: w.bool_false,
428 char_: w.char_,
429 char_of_nat: w.char_of_nat,
430 string: w.string,
431 string_of_list: w.string_of_list,
432 list: w.list,
433 list_nil: w.list_nil,
434 list_cons: w.list_cons,
435 }
436 }
437}