1use super::check::{Decl, DefnDecl, Header};
9use super::env::{Const, CtorInfo, Hint, InductiveInfo, Kind, QuotKind, RecInfo, RecRule, Safety};
10use super::error::{FailKind, KResult, KernelFailure};
11use super::expr::{ExprId, Node};
12use super::inductive::{IndType, InductiveDecl};
13use super::json::{Tape, Tok};
14use super::level::{LevelId, LevelNode};
15use super::name::NameId;
16use super::nat::Nat;
17use super::tc::Kernel;
18use rustc_hash::FxHashMap as FxMap;
19use std::io::BufRead;
20use std::rc::Rc;
21
22const ABSENT: u32 = u32::MAX;
23
24struct IdMap {
26 dense: Vec<u32>,
27 sparse: FxMap<u64, u32>,
28}
29
30impl IdMap {
31 fn new() -> IdMap {
32 IdMap {
33 dense: Vec::new(),
34 sparse: FxMap::default(),
35 }
36 }
37
38 #[inline]
39 fn insert(&mut self, k: u64, v: u32) -> bool {
40 if k == self.dense.len() as u64 && k < u32::MAX as u64 {
41 self.dense.push(v);
42 return true;
43 }
44 if k < (self.dense.len() as u64) * 2 + 1024 && k < u32::MAX as u64 {
45 let k = k as usize;
46 if self.dense.len() <= k {
47 self.dense.resize(k + 1, ABSENT);
48 }
49 let fresh = self.dense[k] == ABSENT;
50 self.dense[k] = v;
51 fresh
52 } else {
53 self.sparse.insert(k, v).is_none()
54 }
55 }
56
57 fn get(&self, k: u64) -> Option<u32> {
58 match self.dense.get(k as usize) {
59 Some(&v) if v != ABSENT => Some(v),
60 _ => self.sparse.get(&k).copied(),
61 }
62 }
63}
64
65pub struct Stats {
66 pub memory: Vec<(&'static str, usize)>,
68 pub records: u64,
69 pub declarations: u64,
70 pub validated_primitives: Vec<String>,
72}
73
74pub trait DeclMeter {
78 fn begin(&mut self);
79 fn end(&mut self, name: &str, kind: &'static str, admitted: bool);
80}
81
82#[derive(Default)]
84pub struct Observe {
85 pub meter: Option<Box<dyn DeclMeter>>,
87 pub trust_before: u64,
93}
94
95pub struct Reader<'k> {
96 pub k: &'k mut Kernel,
97 names: IdMap,
98 levels: IdMap,
99 exprs: IdMap,
100 pending_mutual: Vec<(Rc<[NameId]>, DefnDecl)>,
101 pub refs: FxMap<String, ExprId>,
103 pub parse_only: bool,
105 pub stats: Stats,
106 pub meter: Option<Box<dyn DeclMeter>>,
107 pub trust_before: u64,
109 pub fast_paths: bool,
112}
113
114enum NamePart<'a> {
115 Str(&'a str),
116 Num(u64),
117}
118
119const POW10: [u64; 9] = [
121 1,
122 10,
123 100,
124 1_000,
125 10_000,
126 100_000,
127 1_000_000,
128 10_000_000,
129 100_000_000,
130];
131
132#[inline(always)]
136fn swar_digits(x: u64) -> (u32, u64) {
137 let non_digit = (x.wrapping_add(0x7676_7676_7676_7676) | x) & 0x8080_8080_8080_8080;
141 let n = if non_digit == 0 {
142 8
143 } else {
144 non_digit.trailing_zeros() / 8
145 };
146 if n == 0 {
147 return (0, 0);
148 }
149 let mut d = x << (64 - 8 * n);
152 d = (d * 10 + (d >> 8)) & 0x00FF_00FF_00FF_00FF;
153 d = (d * 100 + (d >> 16)) & 0x0000_FFFF_0000_FFFF;
154 d = (d * 10_000 + (d >> 32)) & 0x0000_0000_FFFF_FFFF;
155 (n, d)
156}
157
158const WIDE: usize = 64;
161
162#[inline(always)]
163fn word(w: &[u8; WIDE], at: usize) -> u64 {
164 u64::from_le_bytes(*w[at..].first_chunk::<8>().unwrap())
165}
166
167#[inline(always)]
170fn wide_id(w: &[u8; WIDE], at: usize) -> Option<(u64, usize)> {
171 let x = word(w, at) ^ 0x3030_3030_3030_3030;
172 let (n, v) = swar_digits(x);
173 if n == 0 || (n > 1 && x & 0xFF == 0) {
174 return None;
175 }
176 Some((v, n as usize))
177}
178
179#[inline(always)]
184fn wide_app(w: &[u8; WIDE]) -> Option<(usize, u64, u64, u64)> {
185 const HEAD: u64 = u64::from_le_bytes(*b"{\"app\":{");
186 const ARG: u64 = u64::from_le_bytes(*b":{\"arg\":");
187 const FN: u64 = u64::from_le_bytes(*b",\"fn\":\0\0");
188 const IE: u64 = u64::from_le_bytes(*b"},\"ie\":\0");
189 if word(w, 0) != HEAD || word(w, 6) != ARG {
190 return None;
191 }
192 let (a, n) = wide_id(w, 14)?;
193 let p = 14 + n;
194 if word(w, p) & 0xFFFF_FFFF_FFFF != FN {
195 return None;
196 }
197 let (f, n) = wide_id(w, p + 6)?;
198 let q = p + 6 + n;
199 if word(w, q) & 0xFF_FFFF_FFFF_FFFF != IE {
200 return None;
201 }
202 let (i, n) = wide_id(w, q + 7)?;
203 let r = q + 7 + n;
204 if w[r..r + 2] != *b"}\n" {
205 return None;
206 }
207 Some((r + 2, i, f, a))
208}
209
210struct Cur<'a> {
212 b: &'a [u8],
213 i: usize,
214}
215
216impl<'a> Cur<'a> {
217 #[inline(always)]
219 fn lit<const N: usize>(&mut self, s: &[u8; N]) -> Option<()> {
220 let got: &[u8; N] = self.b.get(self.i..self.i + N)?.try_into().ok()?;
221 if got == s {
222 self.i += N;
223 Some(())
224 } else {
225 None
226 }
227 }
228
229 #[inline(always)]
231 fn close<const N: usize>(&mut self, s: &[u8; N]) -> Option<()> {
232 self.lit(s)?;
233 if self.b.get(self.i) == Some(&b'\n') {
234 self.i += 1;
235 Some(())
236 } else {
237 None
238 }
239 }
240
241 #[inline]
242 fn peek(&self) -> Option<u8> {
243 self.b.get(self.i).copied()
244 }
245
246 #[inline(always)]
249 fn num(&mut self) -> Option<u64> {
250 let start = self.i;
251 let Some(chunk) = self.b.get(start..start + 8) else {
252 return self.num_tail(start, 0);
253 };
254 let x = u64::from_le_bytes(chunk.try_into().unwrap()) ^ 0x3030_3030_3030_3030;
255 let (n, v) = swar_digits(x);
256 if n < 8 {
258 if n == 0 || (n > 1 && x & 0xFF == 0) {
259 return None;
260 }
261 self.i = start + n as usize;
262 return Some(v);
263 }
264 match self.b.get(start + 8) {
266 Some(c) if !c.is_ascii_digit() => {
267 if x & 0xFF == 0 {
268 return None;
269 }
270 self.i = start + 8;
271 Some(v)
272 }
273 _ => self.num_long(start, v),
274 }
275 }
276
277 #[cold]
280 fn num_long(&mut self, start: usize, mut v: u64) -> Option<u64> {
281 if self.b[start] == b'0' {
282 return None;
283 }
284 self.i = start + 8;
285 loop {
286 let Some(chunk) = self.b.get(self.i..self.i + 8) else {
287 return self.num_tail(start, v);
288 };
289 let x = u64::from_le_bytes(chunk.try_into().unwrap()) ^ 0x3030_3030_3030_3030;
290 let (n, digits) = swar_digits(x);
291 if self.i - start + n as usize > 19 {
292 return None;
293 }
294 v = v * POW10[n as usize] + digits;
295 self.i += n as usize;
296 if n < 8 {
297 return Some(v);
298 }
299 }
300 }
301
302 #[cold]
305 fn num_tail(&mut self, start: usize, mut v: u64) -> Option<u64> {
306 while let Some(&d) = self.b.get(self.i) {
307 let d = d.wrapping_sub(b'0');
308 if d > 9 {
309 break;
310 }
311 if self.i - start == 19 {
312 return None;
313 }
314 v = v * 10 + d as u64;
315 self.i += 1;
316 }
317 let len = self.i - start;
318 (len > 0 && (len == 1 || self.b[start] != b'0')).then_some(v)
319 }
320
321 #[inline]
323 fn binder_info(&mut self) -> Option<()> {
324 if self.lit(b"default\"").is_some()
325 || self.lit(b"implicit\"").is_some()
326 || self.lit(b"instImplicit\"").is_some()
327 || self.lit(b"strictImplicit\"").is_some()
328 {
329 Some(())
330 } else {
331 None
332 }
333 }
334
335 #[inline]
337 fn plain_string(&mut self) -> Option<&'a [u8]> {
338 let start = self.i;
339 while let Some(&c) = self.b.get(self.i) {
340 match c {
341 b'"' => {
342 let s = &self.b[start..self.i];
343 self.i += 1;
344 return Some(s);
345 }
346 b'\\' => return None,
347 c if c < 0x20 => return None,
348 _ => self.i += 1,
349 }
350 }
351 None
352 }
353}
354
355fn bad(m: impl Into<String>) -> KernelFailure {
356 KernelFailure::reject(format!("malformed export: {}", m.into()))
357}
358
359fn recycle<'b>(mut v: Vec<Tok<'_>>) -> Vec<Tok<'b>> {
360 v.clear();
361 v.into_iter().map(|_| unreachable!()).collect()
362}
363
364impl<'k> Reader<'k> {
365 pub fn new(k: &'k mut Kernel) -> Reader<'k> {
366 let mut names = IdMap::new();
367 names.insert(0, NameId::ANON.0);
368 let mut levels = IdMap::new();
369 levels.insert(0, LevelId::ZERO.0);
370 Reader {
371 k,
372 names,
373 levels,
374 exprs: IdMap::new(),
375 pending_mutual: Vec::new(),
376 refs: FxMap::default(),
377 parse_only: false,
378 stats: Stats {
379 memory: Vec::new(),
380 records: 0,
381 declarations: 0,
382 validated_primitives: Vec::new(),
383 },
384 meter: None,
385 trust_before: 0,
386 fast_paths: true,
387 }
388 }
389
390 pub fn size_hint(&mut self, bytes: u64) {
392 let nodes = (bytes / 45).min(u32::MAX as u64 / 2) as usize;
393 self.k.s.reserve_persistent(nodes);
394 self.exprs.dense.reserve(nodes);
395 }
396
397 pub fn run(&mut self, mut input: impl BufRead) -> KResult<()> {
399 let mut buf: Vec<u8> = vec![0; 1 << 22];
400 let (mut start, mut end, mut eof) = (0usize, 0usize, false);
401 let mut toks: Vec<Tok<'static>> = Vec::new();
402 let mut line_no = 0u64;
403 let at_line = |mut e: KernelFailure, line_no: u64| {
404 if e.detail.is_none() {
405 e.detail = Some(format!("at export line {line_no}"));
406 }
407 e
408 };
409 loop {
410 if self.fast_paths && start < end {
411 let (used, read, r) = self.fast_records(&buf[start..end]);
412 line_no += read;
413 self.stats.records += read;
414 start += used;
415 r.map_err(|e| at_line(e, line_no + 1))?;
416 }
417 if start < end {
418 let rest = &buf[start..end];
419 let line_end = match rest.iter().position(|&b| b == b'\n') {
420 Some(nl) => Some(nl),
421 None if eof => Some(rest.len()),
422 None => None,
423 };
424 if let Some(len) = line_end {
425 line_no += 1;
426 let mut line = &buf[start..start + len];
427 while let [head @ .., b'\r'] = line {
428 line = head;
429 }
430 start = (start + len + 1).min(end);
431 if line.is_empty() {
432 continue;
433 }
434 let tape = match Tape::parse(line, recycle(toks)) {
435 Ok(t) => t,
436 Err(_) => return Err(bad(format!("line {line_no} is not valid JSON"))),
437 };
438 let r = self.record(&tape);
439 toks = recycle(tape.toks);
440 r.map_err(|e| at_line(e, line_no))?;
441 self.stats.records += 1;
442 continue;
443 }
444 } else if eof {
445 break;
446 }
447 if start > 0 {
448 buf.copy_within(start..end, 0);
449 end -= start;
450 start = 0;
451 }
452 if end == buf.len() {
453 buf.resize(buf.len() * 2, 0);
454 }
455 let n = input
456 .read(&mut buf[end..])
457 .map_err(|e| KernelFailure::resource(format!("cannot read input: {e}")))?;
458 if n == 0 {
459 eof = true;
460 } else {
461 end += n;
462 }
463 }
464 if let Some((all, _)) = self.pending_mutual.first() {
465 let missing: Vec<String> = all.iter().map(|n| self.k.s.names.display(*n)).collect();
466 return Err(bad(format!(
467 "incomplete mutual block {{{}}}",
468 missing.join(", ")
469 )));
470 }
471 Ok(())
472 }
473
474 fn fast_records(&mut self, buf: &[u8]) -> (usize, u64, KResult<()>) {
479 let (mut at, mut read) = (0usize, 0u64);
480 loop {
481 let rest = &buf[at..];
482 if let Some(w) = rest.first_chunk::<WIDE>() {
484 if let Some((used, i, f, a)) = wide_app(w) {
485 if let Err(e) = self.fast_app(i, f, a) {
486 return (at, read, Err(e));
487 }
488 at += used;
489 read += 1;
490 continue;
491 }
492 }
493 match self.fast_record(rest) {
494 Some((used, Ok(()))) => {
495 at += used;
496 read += 1;
497 }
498 Some((_, Err(e))) => return (at, read, Err(e)),
499 None => return (at, read, Ok(())),
500 }
501 }
502 }
503
504 fn fast_record(&mut self, line: &[u8]) -> Option<(usize, KResult<()>)> {
513 let mut c = Cur { b: line, i: 0 };
514 c.lit(b"{\"")?;
515 match *line.get(2)? {
516 b'a' => {
517 c.lit(b"app\":{\"arg\":")?;
518 let a = c.num()?;
519 c.lit(b",\"fn\":")?;
520 let f = c.num()?;
521 c.lit(b"},\"ie\":")?;
522 let i = c.num()?;
523 c.close(b"}")?;
524 Some((c.i, self.fast_app(i, f, a)))
525 }
526 b'f' => {
527 c.lit(b"forallE\":{\"binderInfo\":\"")?;
528 c.binder_info()?;
529 c.lit(b",\"body\":")?;
530 let b = c.num()?;
531 c.lit(b",\"name\":")?;
532 c.num()?;
533 c.lit(b",\"type\":")?;
534 let t = c.num()?;
535 c.lit(b"},\"ie\":")?;
536 let i = c.num()?;
537 c.close(b"}")?;
538 Some((c.i, self.fast_binder(i, t, b, true)))
539 }
540 b'b' => {
541 c.lit(b"bvar\":")?;
542 let k = c.num()?;
543 c.lit(b",\"ie\":")?;
544 let i = c.num()?;
545 c.close(b"}")?;
546 let k = u32::try_from(k).ok()?;
547 let e = self.k.s.bvar(k);
548 Some((c.i, self.put_expr(i, e)))
549 }
550 b'c' => {
551 c.lit(b"const\":{\"name\":")?;
552 let n = c.num()?;
553 c.lit(b",\"us\":[")?;
554 let mut us: smallvec::SmallVec<[u64; 4]> = smallvec::SmallVec::new();
555 if c.peek() != Some(b']') {
556 us.push(c.num()?);
557 while c.peek() == Some(b',') {
558 c.i += 1;
559 us.push(c.num()?);
560 }
561 }
562 c.lit(b"]},\"ie\":")?;
563 let i = c.num()?;
564 c.close(b"}")?;
565 Some((c.i, self.fast_const(i, n, &us)))
566 }
567 b'i' => {
568 c.lit(b"i")?;
569 match c.peek()? {
570 b'e' => {
571 c.lit(b"e\":")?;
572 let i = c.num()?;
573 c.lit(b",\"")?;
574 match c.peek()? {
575 b'l' => {
576 if c.lit(b"lam\":{\"binderInfo\":\"").is_some() {
577 c.binder_info()?;
578 c.lit(b",\"body\":")?;
579 let b = c.num()?;
580 c.lit(b",\"name\":")?;
581 c.num()?;
582 c.lit(b",\"type\":")?;
583 let t = c.num()?;
584 c.close(b"}}")?;
585 Some((c.i, self.fast_binder(i, t, b, false)))
586 } else {
587 None
588 }
589 }
590 b's' => {
591 c.lit(b"sort\":")?;
592 let l = c.num()?;
593 c.close(b"}")?;
594 Some((c.i, self.fast_sort(i, l)))
595 }
596 _ => None,
597 }
598 }
599 b'n' => {
600 c.lit(b"n\":")?;
601 let i = c.num()?;
602 c.lit(b",\"")?;
603 match c.peek()? {
604 b's' => {
605 c.lit(b"str\":{\"pre\":")?;
606 let p = c.num()?;
607 c.lit(b",\"str\":\"")?;
608 let text = c.plain_string()?;
609 c.close(b"}}")?;
610 let text = std::str::from_utf8(text).ok()?;
611 Some((c.i, self.fast_name(i, p, NamePart::Str(text))))
612 }
613 b'n' => {
614 c.lit(b"num\":{\"i\":")?;
615 let k = c.num()?;
616 c.lit(b",\"pre\":")?;
617 let p = c.num()?;
618 c.close(b"}}")?;
619 Some((c.i, self.fast_name(i, p, NamePart::Num(k))))
620 }
621 _ => None,
622 }
623 }
624 _ => None,
625 }
626 }
627 _ => None,
628 }
629 }
630
631 fn put_expr(&mut self, idx: u64, e: ExprId) -> KResult<()> {
632 if !self.exprs.insert(idx, e.0) {
633 return Err(bad(format!("expression #{idx} is defined twice")));
634 }
635 Ok(())
636 }
637
638 fn expr_ix(&self, idx: u64) -> KResult<ExprId> {
639 self.exprs
640 .get(idx)
641 .map(ExprId)
642 .ok_or_else(|| bad(format!("undefined expression #{idx}")))
643 }
644
645 fn level_ix(&self, idx: u64) -> KResult<LevelId> {
646 self.levels
647 .get(idx)
648 .map(LevelId)
649 .ok_or_else(|| bad(format!("undefined level #{idx}")))
650 }
651
652 fn name_ix(&self, idx: u64) -> KResult<NameId> {
653 self.names
654 .get(idx)
655 .map(NameId)
656 .ok_or_else(|| bad(format!("undefined name #{idx}")))
657 }
658
659 fn fast_app(&mut self, i: u64, f: u64, a: u64) -> KResult<()> {
660 let (f, a) = (self.expr_ix(f)?, self.expr_ix(a)?);
661 let e = self.k.s.app(f, a);
662 self.put_expr(i, e)
663 }
664
665 fn fast_binder(&mut self, i: u64, t: u64, b: u64, pi: bool) -> KResult<()> {
666 let (t, b) = (self.expr_ix(t)?, self.expr_ix(b)?);
667 let e = if pi {
668 self.k.s.pi(t, b)
669 } else {
670 self.k.s.lam(t, b)
671 };
672 self.put_expr(i, e)
673 }
674
675 fn fast_sort(&mut self, i: u64, l: u64) -> KResult<()> {
676 let l = self.level_ix(l)?;
677 let e = self.k.s.sort(l);
678 self.put_expr(i, e)
679 }
680
681 fn fast_const(&mut self, i: u64, n: u64, us: &[u64]) -> KResult<()> {
682 let n = self.name_ix(n)?;
683 let us: KResult<smallvec::SmallVec<[LevelId; 4]>> =
684 us.iter().map(|u| self.level_ix(*u)).collect();
685 let e = self.k.s.cnst_levels(n, &us?);
686 self.put_expr(i, e)
687 }
688
689 fn fast_name(&mut self, i: u64, p: u64, part: NamePart<'_>) -> KResult<()> {
690 let pre = self.name_ix(p)?;
691 let id = match part {
692 NamePart::Str(s) => self.k.s.names.str(pre, s),
693 NamePart::Num(k) => self.k.s.names.num(pre, k),
694 };
695 if i == 0 || !self.names.insert(i, id.0) {
696 return Err(bad(format!("name #{i} is defined twice")));
697 }
698 Ok(())
699 }
700
701 fn name(&self, t: &Tape, i: usize) -> KResult<NameId> {
702 let idx = t.u64(i).ok_or_else(|| bad("name index expected"))?;
703 self.names
704 .get(idx)
705 .map(NameId)
706 .ok_or_else(|| bad(format!("undefined name #{idx}")))
707 }
708
709 fn level(&self, t: &Tape, i: usize) -> KResult<LevelId> {
710 let idx = t.u64(i).ok_or_else(|| bad("level index expected"))?;
711 self.levels
712 .get(idx)
713 .map(LevelId)
714 .ok_or_else(|| bad(format!("undefined level #{idx}")))
715 }
716
717 fn expr(&self, t: &Tape, i: usize) -> KResult<ExprId> {
718 let idx = t.u64(i).ok_or_else(|| bad("expression index expected"))?;
719 self.exprs
720 .get(idx)
721 .map(ExprId)
722 .ok_or_else(|| bad(format!("undefined expression #{idx}")))
723 }
724
725 fn field(&self, t: &Tape, obj: usize, key: &str) -> KResult<usize> {
726 t.get(obj, key)
727 .ok_or_else(|| bad(format!("missing field '{key}'")))
728 }
729
730 fn name_field(&self, t: &Tape, obj: usize, key: &str) -> KResult<NameId> {
731 let i = self.field(t, obj, key)?;
732 self.name(t, i)
733 }
734
735 fn expr_field(&self, t: &Tape, obj: usize, key: &str) -> KResult<ExprId> {
736 let i = self.field(t, obj, key)?;
737 self.expr(t, i)
738 }
739
740 fn u64_field(&self, t: &Tape, obj: usize, key: &str) -> KResult<u64> {
741 let i = self.field(t, obj, key)?;
742 t.u64(i)
743 .ok_or_else(|| bad(format!("field '{key}' is not a number")))
744 }
745
746 fn u32_field(&self, t: &Tape, obj: usize, key: &str) -> KResult<u32> {
747 let v = self.u64_field(t, obj, key)?;
748 u32::try_from(v).map_err(|_| bad(format!("field '{key}' is out of range")))
749 }
750
751 fn bool_field(&self, t: &Tape, obj: usize, key: &str) -> KResult<bool> {
752 let i = self.field(t, obj, key)?;
753 t.bool(i)
754 .ok_or_else(|| bad(format!("field '{key}' is not a boolean")))
755 }
756
757 fn names_field(&self, t: &Tape, obj: usize, key: &str) -> KResult<Rc<[NameId]>> {
758 let i = self.field(t, obj, key)?;
759 let v: KResult<Vec<NameId>> = t.elems(i).map(|e| self.name(t, e)).collect();
760 Ok(v?.into())
761 }
762
763 fn record(&mut self, t: &Tape) -> KResult<()> {
764 if !matches!(t.toks.first(), Some(Tok::Obj { .. })) {
765 return Err(bad("record is not an object"));
766 }
767 let mut id_key: Option<(&[u8], u64)> = None;
768 let mut kind: Option<(&[u8], usize)> = None;
769 for (k, v) in t.members(0) {
770 match k {
771 b"in" | b"il" | b"ie" => {
772 id_key = Some((
773 k,
774 t.u64(v)
775 .ok_or_else(|| bad("record index is not a number"))?,
776 ));
777 }
778 _ => {
779 if kind.is_some() {
780 return Err(bad("record has more than one payload"));
781 }
782 kind = Some((k, v));
783 }
784 }
785 }
786 let Some((kind, v)) = kind else {
787 return Err(bad("record has no payload"));
788 };
789 match id_key {
790 Some((b"in", idx)) => self.name_record(t, idx, kind, v),
791 Some((b"il", idx)) => self.level_record(t, idx, kind, v),
792 Some((b"ie", idx)) => self.expr_record(t, idx, kind, v),
793 Some(_) => unreachable!(),
794 None => self.decl_record(t, kind, v),
795 }
796 }
797
798 fn name_record(&mut self, t: &Tape, idx: u64, kind: &[u8], v: usize) -> KResult<()> {
799 let pre = self.name_field(t, v, "pre")?;
800 let id = match kind {
801 b"str" => {
802 let si = self.field(t, v, "str")?;
803 let s = t
804 .str(si)
805 .ok_or_else(|| bad("name component is not a string"))?;
806 self.k.s.names.str(pre, &s)
807 }
808 b"num" => {
809 let n = self.u64_field(t, v, "i")?;
810 self.k.s.names.num(pre, n)
811 }
812 _ => return Err(bad("unknown name record")),
813 };
814 if idx == 0 || !self.names.insert(idx, id.0) {
815 return Err(bad(format!("name #{idx} is defined twice")));
816 }
817 Ok(())
818 }
819
820 fn level_record(&mut self, t: &Tape, idx: u64, kind: &[u8], v: usize) -> KResult<()> {
821 let pair = |r: &Reader| -> KResult<(LevelId, LevelId)> {
822 let mut it = t.elems(v);
823 let a = it.next().ok_or_else(|| bad("level pair expected"))?;
824 let b = it.next().ok_or_else(|| bad("level pair expected"))?;
825 if it.next().is_some() {
826 return Err(bad("level pair expected"));
827 }
828 Ok((r.level(t, a)?, r.level(t, b)?))
829 };
830 let node = match kind {
831 b"succ" => LevelNode::Succ(self.level(t, v)?),
832 b"max" => {
833 let (a, b) = pair(self)?;
834 LevelNode::Max(a, b)
835 }
836 b"imax" => {
837 let (a, b) = pair(self)?;
838 LevelNode::IMax(a, b)
839 }
840 b"param" => LevelNode::Param(self.name(t, v)?),
841 _ => return Err(bad("unknown level record")),
842 };
843 let id = self.k.s.levels.intern(node);
844 if idx == 0 || !self.levels.insert(idx, id.0) {
845 return Err(bad(format!("level #{idx} is defined twice")));
846 }
847 Ok(())
848 }
849
850 fn expr_record(&mut self, t: &Tape, idx: u64, kind: &[u8], v: usize) -> KResult<()> {
851 let s = &mut self.k.s;
852 let e = match kind {
853 b"bvar" => {
854 let i = t.u64(v).ok_or_else(|| bad("bvar index"))?;
855 s.bvar(u32::try_from(i).map_err(|_| bad("bvar index out of range"))?)
856 }
857 b"sort" => {
858 let l = self.level(t, v)?;
859 self.k.s.sort(l)
860 }
861 b"const" => {
862 let n = self.name_field(t, v, "name")?;
863 let us_i = self.field(t, v, "us")?;
864 let us: KResult<Vec<LevelId>> = t.elems(us_i).map(|x| self.level(t, x)).collect();
865 let us = us?;
866 self.k.s.cnst_levels(n, &us)
867 }
868 b"app" => {
869 let f = self.expr_field(t, v, "fn")?;
870 let a = self.expr_field(t, v, "arg")?;
871 self.k.s.app(f, a)
872 }
873 b"lam" | b"forallE" => {
874 let ty = self.expr_field(t, v, "type")?;
875 let body = self.expr_field(t, v, "body")?;
876 if kind == b"lam" {
877 self.k.s.lam(ty, body)
878 } else {
879 self.k.s.pi(ty, body)
880 }
881 }
882 b"letE" => {
883 let ty = self.expr_field(t, v, "type")?;
884 let val = self.expr_field(t, v, "value")?;
885 let body = self.expr_field(t, v, "body")?;
886 self.k.s.let_(ty, val, body)
887 }
888 b"proj" => {
889 let sn = self.name_field(t, v, "typeName")?;
890 let i = self.u32_field(t, v, "idx")?;
891 let x = self.expr_field(t, v, "struct")?;
892 self.k.s.proj(sn, i, x)
893 }
894 b"natVal" => {
895 let digits = t.str(v).ok_or_else(|| bad("natVal is not a string"))?;
896 let n = Nat::parse_decimal(&digits)
897 .ok_or_else(|| bad("natVal is not a natural number"))?;
898 self.k.s.nat_lit(n)
899 }
900 b"strVal" => {
901 let st = t.str(v).ok_or_else(|| bad("strVal is not a string"))?;
902 self.k.s.str_lit(&st)
903 }
904 b"mdata" => self.expr_field(t, v, "expr")?,
905 _ => {
906 return Err(KernelFailure::resource(format!(
907 "unsupported expression record '{}'",
908 String::from_utf8_lossy(kind)
909 )))
910 }
911 };
912 if !self.exprs.insert(idx, e.0) {
913 return Err(bad(format!("expression #{idx} is defined twice")));
914 }
915 Ok(())
916 }
917
918 fn header(&self, t: &Tape, v: usize) -> KResult<Header> {
919 Ok(Header {
920 name: self.name_field(t, v, "name")?,
921 lparams: self.names_field(t, v, "levelParams")?,
922 ty: self.expr_field(t, v, "type")?,
923 })
924 }
925
926 fn decl_record(&mut self, t: &Tape, kind: &[u8], v: usize) -> KResult<()> {
927 if self.parse_only && kind != b"meta" && kind != b"ref" {
928 return Ok(());
929 }
930 match kind {
931 b"meta" => {
932 let fmt = t
933 .get(v, "format")
934 .and_then(|f| t.get(f, "version"))
935 .and_then(|x| t.str(x));
936 match fmt {
937 Some(ver) if ver.starts_with("3.") => Ok(()),
938 _ => Err(KernelFailure::resource("unsupported export format version")),
939 }
940 }
941 b"axiom" => {
942 let header = self.header(t, v)?;
943 let is_unsafe = self.bool_field(t, v, "isUnsafe")?;
944 self.decl(Decl::Axiom { header, is_unsafe })
945 }
946 b"thm" => {
947 let header = self.header(t, v)?;
948 let value = self.expr_field(t, v, "value")?;
949 self.decl(Decl::Thm { header, value })
950 }
951 b"opaque" => {
952 let header = self.header(t, v)?;
953 let value = self.expr_field(t, v, "value")?;
954 let is_unsafe = self.bool_field(t, v, "isUnsafe")?;
955 self.decl(Decl::Opaque {
956 header,
957 value,
958 is_unsafe,
959 })
960 }
961 b"def" => {
962 let header = self.header(t, v)?;
963 let value = self.expr_field(t, v, "value")?;
964 let hi = self.field(t, v, "hints")?;
965 let hint = match t.str(hi).as_deref() {
966 Some("abbrev") => Hint::Abbrev,
967 Some("opaque") => Hint::Opaque,
968 Some(_) => return Err(bad("unknown reducibility hint")),
969 None => {
970 let r = t
971 .get(hi, "regular")
972 .ok_or_else(|| bad("unknown reducibility hint"))?;
973 Hint::Regular(
974 t.u64(r)
975 .and_then(|x| u32::try_from(x).ok())
976 .ok_or_else(|| bad("height"))?,
977 )
978 }
979 };
980 let si = self.field(t, v, "safety")?;
981 let safety = match t.str(si).as_deref() {
982 Some("safe") => Safety::Safe,
983 Some("unsafe") => Safety::Unsafe,
984 Some("partial") => Safety::Partial,
985 _ => return Err(bad("unknown safety")),
986 };
987 let all = self.names_field(t, v, "all")?;
988 let d = DefnDecl {
989 header,
990 value,
991 hint,
992 safety,
993 };
994 if safety != Safety::Safe && all.len() > 1 {
995 self.pending_mutual.push((all.clone(), d));
996 self.flush_mutual(&all)
997 } else {
998 self.decl(Decl::Defn(d))
999 }
1000 }
1001 b"quot" => {
1002 let header = self.header(t, v)?;
1003 let ki = self.field(t, v, "kind")?;
1004 let kind = match t.str(ki).as_deref() {
1005 Some("type") => QuotKind::Type,
1006 Some("ctor") => QuotKind::Ctor,
1007 Some("lift") => QuotKind::Lift,
1008 Some("ind") => QuotKind::Ind,
1009 _ => return Err(bad("unknown quotient kind")),
1010 };
1011 self.decl(Decl::Quot { header, kind })
1012 }
1013 b"inductive" => self.inductive_record(t, v),
1014 b"ref" => {
1015 let key = self.field(t, v, "key")?;
1016 let key = t
1017 .str(key)
1018 .ok_or_else(|| bad("ref key is not a string"))?
1019 .into_owned();
1020 let value = self.expr_field(t, v, "value")?;
1021 self.refs.insert(key, value);
1022 Ok(())
1023 }
1024 _ => Err(KernelFailure::resource(format!(
1025 "unsupported declaration record '{}'",
1026 String::from_utf8_lossy(kind)
1027 ))),
1028 }
1029 }
1030
1031 fn decl(&mut self, d: Decl) -> KResult<()> {
1032 let index = self.stats.declarations;
1033 self.stats.declarations += 1;
1034 if index < self.trust_before && self.k.may_trust(&d) {
1035 self.k.admit_trusted(d);
1036 return Ok(());
1037 }
1038 if self.meter.is_none() {
1039 return self.k.add_decl(d);
1040 }
1041 let (name, kind) = (d.name(), d.kind_name());
1042 self.metered(name, kind, |k| k.add_decl(d))
1043 }
1044
1045 fn metered(
1047 &mut self,
1048 name: NameId,
1049 kind: &'static str,
1050 check: impl FnOnce(&mut Kernel) -> KResult<()>,
1051 ) -> KResult<()> {
1052 if let Some(m) = self.meter.as_mut() {
1053 m.begin();
1054 }
1055 let r = check(self.k);
1056 if let Some(m) = self.meter.as_mut() {
1057 m.end(&self.k.s.names.display(name), kind, r.is_ok());
1058 }
1059 r
1060 }
1061
1062 fn flush_mutual(&mut self, all: &Rc<[NameId]>) -> KResult<()> {
1063 let have: Vec<NameId> = self
1064 .pending_mutual
1065 .iter()
1066 .filter(|(a, _)| a == all)
1067 .map(|(_, d)| d.header.name)
1068 .collect();
1069 if !all.iter().all(|n| have.contains(n)) {
1070 return Ok(());
1071 }
1072 let mut block = Vec::new();
1073 for n in all.iter() {
1074 let pos = self
1075 .pending_mutual
1076 .iter()
1077 .position(|(a, d)| a == all && d.header.name == *n)
1078 .unwrap();
1079 block.push(self.pending_mutual.remove(pos).1);
1080 }
1081 self.decl(Decl::Mutual(block))
1082 }
1083
1084 fn inductive_record(&mut self, t: &Tape, v: usize) -> KResult<()> {
1085 let types_i = self.field(t, v, "types")?;
1086 let ctors_i = self.field(t, v, "ctors")?;
1087 let recs_i = self.field(t, v, "recs")?;
1088 let mut claimed = Vec::new();
1089 let mut ctor_types: FxMap<NameId, ExprId> = FxMap::default();
1090 for c in t.elems(ctors_i) {
1091 let h = self.header(t, c)?;
1092 ctor_types.insert(h.name, h.ty);
1093 claimed.push(Const {
1094 name: h.name,
1095 lparams: h.lparams,
1096 ty: h.ty,
1097 kind: Kind::Ctor(CtorInfo {
1098 induct: self.name_field(t, c, "induct")?,
1099 cidx: self.u32_field(t, c, "cidx")?,
1100 num_params: self.u32_field(t, c, "numParams")?,
1101 num_fields: self.u32_field(t, c, "numFields")?,
1102 is_unsafe: self.bool_field(t, c, "isUnsafe")?,
1103 }),
1104 });
1105 }
1106 let mut types = Vec::new();
1107 let mut first: Option<(Rc<[NameId]>, u32, bool)> = None;
1108 for ti in t.elems(types_i) {
1109 let h = self.header(t, ti)?;
1110 let ctors = self.names_field(t, ti, "ctors")?;
1111 let num_params = self.u32_field(t, ti, "numParams")?;
1112 let is_unsafe = self.bool_field(t, ti, "isUnsafe")?;
1113 if first.is_none() {
1114 first = Some((h.lparams.clone(), num_params, is_unsafe));
1115 }
1116 let mut cs = Vec::new();
1117 for c in ctors.iter() {
1118 let ty = *ctor_types.get(c).ok_or_else(|| {
1119 KernelFailure::reject(format!(
1120 "inductive '{}' lists constructor '{}' but the block does not declare it",
1121 self.k.s.names.display(h.name),
1122 self.k.s.names.display(*c)
1123 ))
1124 })?;
1125 cs.push((*c, ty));
1126 }
1127 types.push(IndType {
1128 name: h.name,
1129 ty: h.ty,
1130 ctors: cs,
1131 });
1132 claimed.push(Const {
1133 name: h.name,
1134 lparams: h.lparams,
1135 ty: h.ty,
1136 kind: Kind::Induct(InductiveInfo {
1137 num_params,
1138 num_indices: self.u32_field(t, ti, "numIndices")?,
1139 all: self.names_field(t, ti, "all")?,
1140 ctors,
1141 num_nested: self.u32_field(t, ti, "numNested")?,
1142 is_rec: self.bool_field(t, ti, "isRec")?,
1143 is_reflexive: self.bool_field(t, ti, "isReflexive")?,
1144 is_unsafe,
1145 rec: self.k.rec_name(h.name),
1146 }),
1147 });
1148 }
1149 for ri in t.elems(recs_i) {
1150 let h = self.header(t, ri)?;
1151 let rules_i = self.field(t, ri, "rules")?;
1152 let mut rules = Vec::new();
1153 for r in t.elems(rules_i) {
1154 rules.push(RecRule {
1155 ctor: self.name_field(t, r, "ctor")?,
1156 nfields: self.u32_field(t, r, "nfields")?,
1157 rhs: self.expr_field(t, r, "rhs")?,
1158 });
1159 }
1160 let mut info = RecInfo {
1161 all: self.names_field(t, ri, "all")?,
1162 num_params: self.u32_field(t, ri, "numParams")?,
1163 num_indices: self.u32_field(t, ri, "numIndices")?,
1164 num_motives: self.u32_field(t, ri, "numMotives")?,
1165 num_minors: self.u32_field(t, ri, "numMinors")?,
1166 rules: rules.into(),
1167 k: self.bool_field(t, ri, "k")?,
1168 is_unsafe: self.bool_field(t, ri, "isUnsafe")?,
1169 major_induct: NameId::ANON,
1170 };
1171 info.major_induct = self.major_induct(h.ty, info.major_idx());
1172 claimed.push(Const {
1173 name: h.name,
1174 lparams: h.lparams,
1175 ty: h.ty,
1176 kind: Kind::Rec(info),
1177 });
1178 }
1179 let Some((lparams, nparams, is_unsafe)) = first else {
1180 return Err(KernelFailure::reject("inductive block declares no types"));
1181 };
1182 for c in &claimed {
1183 if self.k.env.contains(c.name) {
1184 return Err(KernelFailure::reject(format!(
1185 "'{}' has already been declared",
1186 self.k.s.names.display(c.name)
1187 )));
1188 }
1189 }
1190 let index = self.stats.declarations;
1191 self.stats.declarations += 1;
1192 if index < self.trust_before && self.k.may_trust_block(&claimed) {
1193 self.k.admit_trusted_block(claimed);
1194 return Ok(());
1195 }
1196 let name = types.first().map_or(NameId::ANON, |t| t.name);
1197 let decl = InductiveDecl {
1198 lparams,
1199 nparams,
1200 types,
1201 is_unsafe,
1202 };
1203 if self.meter.is_none() {
1204 return self.k.add_inductive(decl, claimed);
1205 }
1206 self.metered(name, "inductive", |k| k.add_inductive(decl, claimed))
1207 }
1208
1209 fn major_induct(&self, mut ty: ExprId, idx: usize) -> NameId {
1210 for _ in 0..idx {
1211 match self.k.s.node(ty) {
1212 Node::Pi(_, b) => ty = b,
1213 _ => return NameId::ANON,
1214 }
1215 }
1216 match self.k.s.node(ty) {
1217 Node::Pi(d, _) => self.k.s.const_head(d).map_or(NameId::ANON, |(n, _)| n),
1218 _ => NameId::ANON,
1219 }
1220 }
1221}
1222
1223pub enum Verdict {
1225 Accept,
1226 Reject(KernelFailure),
1227 Decline(KernelFailure),
1228}
1229
1230impl Verdict {
1231 pub fn exit_code(&self) -> i32 {
1232 match self {
1233 Verdict::Accept => 0,
1234 Verdict::Reject(_) => 1,
1235 Verdict::Decline(_) => 2,
1236 }
1237 }
1238}
1239
1240pub fn check_export(input: impl BufRead) -> (Verdict, Stats) {
1242 check_export_with(input, |_| {})
1243}
1244
1245pub fn check_export_with(
1247 input: impl BufRead,
1248 configure: impl FnOnce(&mut Kernel),
1249) -> (Verdict, Stats) {
1250 check_export_sized(input, None, configure)
1251}
1252
1253pub fn check_export_sized(
1255 input: impl BufRead,
1256 bytes: Option<u64>,
1257 configure: impl FnOnce(&mut Kernel),
1258) -> (Verdict, Stats) {
1259 check_export_observed(input, bytes, configure, Observe::default())
1260}
1261
1262pub fn check_export_observed(
1264 input: impl BufRead,
1265 bytes: Option<u64>,
1266 configure: impl FnOnce(&mut Kernel),
1267 observe: Observe,
1268) -> (Verdict, Stats) {
1269 let mut k = Kernel::new();
1270 configure(&mut k);
1271 check_export_in(&mut k, input, bytes, observe)
1272}
1273
1274pub fn check_export_in(
1277 k: &mut Kernel,
1278 input: impl BufRead,
1279 bytes: Option<u64>,
1280 observe: Observe,
1281) -> (Verdict, Stats) {
1282 let mut r = Reader::new(k);
1283 r.meter = observe.meter;
1284 r.trust_before = observe.trust_before;
1285 if let Some(b) = bytes {
1286 r.size_hint(b);
1287 }
1288 let outcome = r.run(input);
1289 let v = if observe.trust_before > 0 {
1290 let prefix = format!(
1291 "trusted-prefix run: the declarations before #{} were admitted unchecked",
1292 observe.trust_before
1293 );
1294 Verdict::Decline(match outcome {
1295 Ok(()) => {
1296 KernelFailure::resource(format!("{prefix}; every checked declaration passed"))
1297 }
1298 Err(e) => {
1299 KernelFailure::resource(format!("{prefix}; a checked declaration failed: {e}"))
1300 }
1301 })
1302 } else {
1303 match outcome {
1304 Ok(()) => Verdict::Accept,
1305 Err(e) if e.kind == FailKind::Reject => Verdict::Reject(e),
1306 Err(e) => Verdict::Decline(e),
1307 }
1308 };
1309 let mut stats = r.stats;
1310 let mut prims: Vec<String> = k
1311 .validated_primitives
1312 .iter()
1313 .map(|n| k.s.names.display(*n))
1314 .collect();
1315 prims.sort();
1316 stats.validated_primitives = prims;
1317 stats.memory = k.memory_report();
1318 (v, stats)
1319}
1320
1321pub fn load_refs(k: &mut Kernel, input: impl BufRead) -> KResult<FxMap<String, ExprId>> {
1323 let mut r = Reader::new(k);
1324 r.run(input)?;
1325 Ok(std::mem::take(&mut r.refs))
1326}
1327
1328#[cfg(test)]
1329#[path = "../../../logicaffeine_tests/unit/logicaffeine_kernel/dag/export/number_tests.rs"]
1330mod number_tests;