1use crate::reduce::ReducibilityHint;
6use crate::Node;
7use crate::{
8 BinderInfo, Declaration, Environment, Expr, FVarId, Level, LevelMVarId, LevelView, Literal,
9 Name, NameView,
10};
11use std::collections::HashMap;
12use std::rc::Rc;
13
14use super::types::{
15 ConfigNode, ExportedModule, FocusStack, IntegrityCheckResult, LabelSet, ModuleCache,
16 ModuleDependencyGraph, ModuleDiff, ModuleInfo, ModuleRegistry, ModuleVersion, NonEmptyVec,
17 PathBuf, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum, SmallMap, StatSummary, StringPool,
18 TokenBucket, TransformStat, TransitiveClosure, VersionedRecord, WindowIterator,
19};
20
21pub fn export_environment(env: &Environment, module_name: String) -> ExportedModule {
25 let mut module = ExportedModule::new(module_name);
26 for (name, ci) in env.constant_infos() {
27 module.add_constant(name.clone(), ci.clone());
28 }
29 module
30}
31pub fn import_module(env: &mut Environment, module: &ExportedModule) -> Result<(), String> {
35 for (name, decl) in &module.declarations {
36 env.add(decl.clone()).map_err(|e| {
37 format!(
38 "Failed to import {} from module {}: {}",
39 name, module.name, e
40 )
41 })?;
42 }
43 for (name, ci) in &module.constants {
44 if env.find(name).is_some() {
45 continue;
46 }
47 env.add_constant(ci.clone()).map_err(|e| {
48 format!(
49 "Failed to import constant {} from module {}: {}",
50 name, module.name, e
51 )
52 })?;
53 }
54 Ok(())
55}
56pub const MAGIC_NUMBER: u32 = 0x4F584C4E;
58pub const FORMAT_VERSION: u32 = 2;
60#[inline]
61fn write_u8(buf: &mut Vec<u8>, v: u8) {
62 buf.push(v);
63}
64#[inline]
65fn write_u32(buf: &mut Vec<u8>, v: u32) {
66 buf.extend_from_slice(&v.to_le_bytes());
67}
68#[inline]
69fn write_u64(buf: &mut Vec<u8>, v: u64) {
70 buf.extend_from_slice(&v.to_le_bytes());
71}
72fn write_str(buf: &mut Vec<u8>, s: &str) {
73 let bytes = s.as_bytes();
74 write_u32(buf, bytes.len() as u32);
75 buf.extend_from_slice(bytes);
76}
77fn write_name(buf: &mut Vec<u8>, name: &Name) {
78 match name.view() {
79 NameView::Anonymous => write_u8(buf, 0),
80 NameView::Str(parent, s) => {
81 write_u8(buf, 1);
82 write_name(buf, parent);
83 write_str(buf, s);
84 }
85 NameView::Num(parent, n) => {
86 write_u8(buf, 2);
87 write_name(buf, parent);
88 write_u64(buf, n);
89 }
90 }
91}
92fn write_level(buf: &mut Vec<u8>, level: &Level) {
93 match level.view() {
94 LevelView::Zero => write_u8(buf, 0),
95 LevelView::Succ(inner) => {
96 write_u8(buf, 1);
97 write_level(buf, inner);
98 }
99 LevelView::Max(l, r) => {
100 write_u8(buf, 2);
101 write_level(buf, l);
102 write_level(buf, r);
103 }
104 LevelView::IMax(l, r) => {
105 write_u8(buf, 3);
106 write_level(buf, l);
107 write_level(buf, r);
108 }
109 LevelView::Param(name) => {
110 write_u8(buf, 4);
111 write_name(buf, name);
112 }
113 LevelView::MVar(LevelMVarId(id)) => {
114 write_u8(buf, 5);
115 write_u64(buf, id);
116 }
117 }
118}
119fn write_binder_info(buf: &mut Vec<u8>, bi: BinderInfo) {
120 let tag: u8 = match bi {
121 BinderInfo::Default => 0,
122 BinderInfo::Implicit => 1,
123 BinderInfo::StrictImplicit => 2,
124 BinderInfo::InstImplicit => 3,
125 };
126 write_u8(buf, tag);
127}
128fn write_literal(buf: &mut Vec<u8>, lit: &Literal) {
129 match lit {
130 Literal::Nat(n) => match n.to_u64() {
131 Some(small) => {
133 write_u8(buf, 0);
134 write_u64(buf, small);
135 }
136 None => {
138 write_u8(buf, 3);
139 let limbs = n.as_limbs();
140 write_u64(buf, limbs.len() as u64);
141 for limb in limbs {
142 write_u64(buf, *limb);
143 }
144 }
145 },
146 Literal::Str(s) => {
147 write_u8(buf, 1);
148 write_str(buf, s);
149 }
150 }
151}
152fn write_expr(buf: &mut Vec<u8>, expr: &Expr) {
153 match expr {
154 Expr::Sort(level) => {
155 write_u8(buf, 0);
156 write_level(buf, level);
157 }
158 Expr::BVar(idx) => {
159 write_u8(buf, 1);
160 write_u32(buf, *idx);
161 }
162 Expr::FVar(FVarId(id)) => {
163 write_u8(buf, 2);
164 write_u64(buf, *id);
165 }
166 Expr::Const(name, levels) => {
167 write_u8(buf, 3);
168 write_name(buf, name);
169 write_u32(buf, levels.len() as u32);
170 for l in levels {
171 write_level(buf, l);
172 }
173 }
174 Expr::App(f, a) => {
175 write_u8(buf, 4);
176 write_expr(buf, f);
177 write_expr(buf, a);
178 }
179 Expr::Lam(bi, name, ty, body) => {
180 write_u8(buf, 5);
181 write_binder_info(buf, *bi);
182 write_name(buf, name);
183 write_expr(buf, ty);
184 write_expr(buf, body);
185 }
186 Expr::Pi(bi, name, ty, body) => {
187 write_u8(buf, 6);
188 write_binder_info(buf, *bi);
189 write_name(buf, name);
190 write_expr(buf, ty);
191 write_expr(buf, body);
192 }
193 Expr::Let(name, ty, val, body) => {
194 write_u8(buf, 7);
195 write_name(buf, name);
196 write_expr(buf, ty);
197 write_expr(buf, val);
198 write_expr(buf, body);
199 }
200 Expr::Lit(lit) => {
201 write_u8(buf, 8);
202 write_literal(buf, lit);
203 }
204 Expr::Proj(name, idx, inner) => {
205 write_u8(buf, 9);
206 write_name(buf, name);
207 write_u32(buf, *idx);
208 write_expr(buf, inner);
209 }
210 }
211}
212fn write_reducibility_hint(buf: &mut Vec<u8>, hint: ReducibilityHint) {
213 match hint {
214 ReducibilityHint::Opaque => write_u8(buf, 0),
215 ReducibilityHint::Abbrev => write_u8(buf, 1),
216 ReducibilityHint::Regular(h) => {
217 write_u8(buf, 2);
218 write_u32(buf, h);
219 }
220 }
221}
222fn write_names(buf: &mut Vec<u8>, names: &[Name]) {
223 write_u32(buf, names.len() as u32);
224 for n in names {
225 write_name(buf, n);
226 }
227}
228fn write_declaration(buf: &mut Vec<u8>, decl: &Declaration) {
229 match decl {
230 Declaration::Axiom {
231 name,
232 univ_params,
233 ty,
234 } => {
235 write_u8(buf, 0);
236 write_name(buf, name);
237 write_names(buf, univ_params);
238 write_expr(buf, ty);
239 }
240 Declaration::Definition {
241 name,
242 univ_params,
243 ty,
244 val,
245 hint,
246 } => {
247 write_u8(buf, 1);
248 write_name(buf, name);
249 write_names(buf, univ_params);
250 write_expr(buf, ty);
251 write_expr(buf, val);
252 write_reducibility_hint(buf, *hint);
253 }
254 Declaration::Theorem {
255 name,
256 univ_params,
257 ty,
258 val,
259 } => {
260 write_u8(buf, 2);
261 write_name(buf, name);
262 write_names(buf, univ_params);
263 write_expr(buf, ty);
264 write_expr(buf, val);
265 }
266 Declaration::Opaque {
267 name,
268 univ_params,
269 ty,
270 val,
271 } => {
272 write_u8(buf, 3);
273 write_name(buf, name);
274 write_names(buf, univ_params);
275 write_expr(buf, ty);
276 write_expr(buf, val);
277 }
278 }
279}
280type ReadResult<T> = Result<T, String>;
281fn read_u8(bytes: &[u8], pos: &mut usize) -> ReadResult<u8> {
282 if *pos >= bytes.len() {
283 return Err(format!("unexpected end of data at pos {}", *pos));
284 }
285 let v = bytes[*pos];
286 *pos += 1;
287 Ok(v)
288}
289fn read_u32(bytes: &[u8], pos: &mut usize) -> ReadResult<u32> {
290 if *pos + 4 > bytes.len() {
291 return Err(format!("unexpected end of data at pos {}", *pos));
292 }
293 let v = u32::from_le_bytes([
294 bytes[*pos],
295 bytes[*pos + 1],
296 bytes[*pos + 2],
297 bytes[*pos + 3],
298 ]);
299 *pos += 4;
300 Ok(v)
301}
302fn read_u64(bytes: &[u8], pos: &mut usize) -> ReadResult<u64> {
303 if *pos + 8 > bytes.len() {
304 return Err(format!("unexpected end of data at pos {}", *pos));
305 }
306 let v = u64::from_le_bytes([
307 bytes[*pos],
308 bytes[*pos + 1],
309 bytes[*pos + 2],
310 bytes[*pos + 3],
311 bytes[*pos + 4],
312 bytes[*pos + 5],
313 bytes[*pos + 6],
314 bytes[*pos + 7],
315 ]);
316 *pos += 8;
317 Ok(v)
318}
319fn read_str(bytes: &[u8], pos: &mut usize) -> ReadResult<String> {
320 let len = read_u32(bytes, pos)? as usize;
321 if *pos + len > bytes.len() {
322 return Err(format!("string truncated at pos {}", *pos));
323 }
324 let s = std::str::from_utf8(&bytes[*pos..*pos + len])
325 .map_err(|e| format!("invalid UTF-8: {}", e))?
326 .to_owned();
327 *pos += len;
328 Ok(s)
329}
330fn read_name(bytes: &[u8], pos: &mut usize) -> ReadResult<Name> {
331 let tag = read_u8(bytes, pos)?;
332 match tag {
333 0 => Ok(Name::anonymous()),
334 1 => {
335 let parent = read_name(bytes, pos)?;
336 let s = read_str(bytes, pos)?;
337 Ok(Name::mk_str(parent, s))
338 }
339 2 => {
340 let parent = read_name(bytes, pos)?;
341 let n = read_u64(bytes, pos)?;
342 Ok(Name::mk_num(parent, n))
343 }
344 other => Err(format!("unknown Name tag: {}", other)),
345 }
346}
347fn read_level(bytes: &[u8], pos: &mut usize) -> ReadResult<Level> {
348 let tag = read_u8(bytes, pos)?;
349 match tag {
350 0 => Ok(Level::zero()),
351 1 => {
352 let inner = read_level(bytes, pos)?;
353 Ok(Level::succ(inner))
354 }
355 2 => {
356 let l = read_level(bytes, pos)?;
357 let r = read_level(bytes, pos)?;
358 Ok(Level::max(l, r))
359 }
360 3 => {
361 let l = read_level(bytes, pos)?;
362 let r = read_level(bytes, pos)?;
363 Ok(Level::imax(l, r))
364 }
365 4 => {
366 let name = read_name(bytes, pos)?;
367 Ok(Level::param(name))
368 }
369 5 => {
370 let id = read_u64(bytes, pos)?;
371 Ok(Level::mvar(LevelMVarId(id)))
372 }
373 other => Err(format!("unknown Level tag: {}", other)),
374 }
375}
376fn read_binder_info(bytes: &[u8], pos: &mut usize) -> ReadResult<BinderInfo> {
377 let tag = read_u8(bytes, pos)?;
378 match tag {
379 0 => Ok(BinderInfo::Default),
380 1 => Ok(BinderInfo::Implicit),
381 2 => Ok(BinderInfo::StrictImplicit),
382 3 => Ok(BinderInfo::InstImplicit),
383 other => Err(format!("unknown BinderInfo tag: {}", other)),
384 }
385}
386fn read_literal(bytes: &[u8], pos: &mut usize) -> ReadResult<Literal> {
387 let tag = read_u8(bytes, pos)?;
388 match tag {
389 0 => Ok(Literal::nat(read_u64(bytes, pos)?)),
390 1 => Ok(Literal::Str(read_str(bytes, pos)?)),
391 2 => Err("Int literals are no longer supported by the kernel".to_string()),
393 3 => {
394 let count = read_u64(bytes, pos)? as usize;
395 if count > bytes.len().saturating_sub(*pos) / 8 {
397 return Err("BigNat limb count exceeds remaining input".to_string());
398 }
399 let mut limbs = Vec::with_capacity(count);
400 for _ in 0..count {
401 limbs.push(read_u64(bytes, pos)?);
402 }
403 Ok(Literal::Nat(crate::bignat::BigNat::from_limbs(limbs)))
404 }
405 other => Err(format!("unknown Literal tag: {}", other)),
406 }
407}
408fn read_expr(bytes: &[u8], pos: &mut usize) -> ReadResult<Expr> {
409 let tag = read_u8(bytes, pos)?;
410 match tag {
411 0 => Ok(Expr::Sort(read_level(bytes, pos)?)),
412 1 => Ok(Expr::BVar(read_u32(bytes, pos)?)),
413 2 => Ok(Expr::FVar(FVarId(read_u64(bytes, pos)?))),
414 3 => {
415 let name = read_name(bytes, pos)?;
416 let count = read_u32(bytes, pos)? as usize;
417 let mut levels = Vec::with_capacity(count);
418 for _ in 0..count {
419 levels.push(read_level(bytes, pos)?);
420 }
421 Ok(Expr::Const(name, levels))
422 }
423 4 => {
424 let f = read_expr(bytes, pos)?;
425 let a = read_expr(bytes, pos)?;
426 Ok(Expr::App(Node::new(f), Node::new(a)))
427 }
428 5 => {
429 let bi = read_binder_info(bytes, pos)?;
430 let name = read_name(bytes, pos)?;
431 let ty = read_expr(bytes, pos)?;
432 let body = read_expr(bytes, pos)?;
433 Ok(Expr::Lam(bi, name, Node::new(ty), Node::new(body)))
434 }
435 6 => {
436 let bi = read_binder_info(bytes, pos)?;
437 let name = read_name(bytes, pos)?;
438 let ty = read_expr(bytes, pos)?;
439 let body = read_expr(bytes, pos)?;
440 Ok(Expr::Pi(bi, name, Node::new(ty), Node::new(body)))
441 }
442 7 => {
443 let name = read_name(bytes, pos)?;
444 let ty = read_expr(bytes, pos)?;
445 let val = read_expr(bytes, pos)?;
446 let body = read_expr(bytes, pos)?;
447 Ok(Expr::Let(
448 name,
449 Node::new(ty),
450 Node::new(val),
451 Node::new(body),
452 ))
453 }
454 8 => Ok(Expr::Lit(read_literal(bytes, pos)?)),
455 9 => {
456 let name = read_name(bytes, pos)?;
457 let idx = read_u32(bytes, pos)?;
458 let inner = read_expr(bytes, pos)?;
459 Ok(Expr::Proj(name, idx, Node::new(inner)))
460 }
461 other => Err(format!("unknown Expr tag: {}", other)),
462 }
463}
464fn read_reducibility_hint(bytes: &[u8], pos: &mut usize) -> ReadResult<ReducibilityHint> {
465 let tag = read_u8(bytes, pos)?;
466 match tag {
467 0 => Ok(ReducibilityHint::Opaque),
468 1 => Ok(ReducibilityHint::Abbrev),
469 2 => Ok(ReducibilityHint::Regular(read_u32(bytes, pos)?)),
470 other => Err(format!("unknown ReducibilityHint tag: {}", other)),
471 }
472}
473fn read_names(bytes: &[u8], pos: &mut usize) -> ReadResult<Vec<Name>> {
474 let count = read_u32(bytes, pos)? as usize;
475 let mut names = Vec::with_capacity(count);
476 for _ in 0..count {
477 names.push(read_name(bytes, pos)?);
478 }
479 Ok(names)
480}
481fn read_declaration(bytes: &[u8], pos: &mut usize) -> ReadResult<Declaration> {
482 let tag = read_u8(bytes, pos)?;
483 match tag {
484 0 => {
485 let name = read_name(bytes, pos)?;
486 let univ_params = read_names(bytes, pos)?;
487 let ty = read_expr(bytes, pos)?;
488 Ok(Declaration::Axiom {
489 name,
490 univ_params,
491 ty,
492 })
493 }
494 1 => {
495 let name = read_name(bytes, pos)?;
496 let univ_params = read_names(bytes, pos)?;
497 let ty = read_expr(bytes, pos)?;
498 let val = read_expr(bytes, pos)?;
499 let hint = read_reducibility_hint(bytes, pos)?;
500 Ok(Declaration::Definition {
501 name,
502 univ_params,
503 ty,
504 val,
505 hint,
506 })
507 }
508 2 => {
509 let name = read_name(bytes, pos)?;
510 let univ_params = read_names(bytes, pos)?;
511 let ty = read_expr(bytes, pos)?;
512 let val = read_expr(bytes, pos)?;
513 Ok(Declaration::Theorem {
514 name,
515 univ_params,
516 ty,
517 val,
518 })
519 }
520 3 => {
521 let name = read_name(bytes, pos)?;
522 let univ_params = read_names(bytes, pos)?;
523 let ty = read_expr(bytes, pos)?;
524 let val = read_expr(bytes, pos)?;
525 Ok(Declaration::Opaque {
526 name,
527 univ_params,
528 ty,
529 val,
530 })
531 }
532 other => Err(format!("unknown Declaration tag: {}", other)),
533 }
534}
535pub fn serialize_module(module: &ExportedModule) -> Vec<u8> {
546 let mut buf = Vec::new();
547 write_u32(&mut buf, MAGIC_NUMBER);
548 write_u32(&mut buf, FORMAT_VERSION);
549 write_str(&mut buf, &module.name);
550 write_str(&mut buf, &module.version);
551 write_u32(&mut buf, module.dependencies.len() as u32);
552 for dep in &module.dependencies {
553 write_str(&mut buf, dep);
554 }
555 write_u32(&mut buf, module.declarations.len() as u32);
556 for (_name, decl) in &module.declarations {
557 write_declaration(&mut buf, decl);
558 }
559 write_u32(&mut buf, module.metadata.len() as u32);
560 for (k, v) in &module.metadata {
561 write_str(&mut buf, k);
562 write_str(&mut buf, v);
563 }
564 buf
565}
566pub fn deserialize_module(bytes: &[u8]) -> Result<ExportedModule, String> {
571 let mut pos = 0;
572 let magic = read_u32(bytes, &mut pos)?;
573 if magic != MAGIC_NUMBER {
574 return Err(format!("invalid magic number: 0x{:08X}", magic));
575 }
576 let version = read_u32(bytes, &mut pos)?;
577 if version != FORMAT_VERSION {
578 return Err(format!("unsupported format version: {}", version));
579 }
580 let name = read_str(bytes, &mut pos)?;
581 let ver = read_str(bytes, &mut pos)?;
582 let dep_count = read_u32(bytes, &mut pos)? as usize;
583 let mut dependencies = Vec::with_capacity(dep_count);
584 for _ in 0..dep_count {
585 dependencies.push(read_str(bytes, &mut pos)?);
586 }
587 let decl_count = read_u32(bytes, &mut pos)? as usize;
588 let mut declarations = Vec::with_capacity(decl_count);
589 for _ in 0..decl_count {
590 let decl = read_declaration(bytes, &mut pos)?;
591 let decl_name = decl.name().clone();
592 declarations.push((decl_name, decl));
593 }
594 let meta_count = read_u32(bytes, &mut pos)? as usize;
595 let mut metadata = HashMap::new();
596 for _ in 0..meta_count {
597 let k = read_str(bytes, &mut pos)?;
598 let v = read_str(bytes, &mut pos)?;
599 metadata.insert(k, v);
600 }
601 Ok(ExportedModule {
602 name,
603 declarations,
604 constants: Vec::new(),
605 dependencies,
606 version: ver,
607 metadata,
608 })
609}
610pub fn deserialize_module_header(bytes: &[u8]) -> Result<(String, u32, u32), String> {
614 let mut pos = 0;
615 let magic = read_u32(bytes, &mut pos)?;
616 if magic != MAGIC_NUMBER {
617 return Err(format!("Invalid magic number: 0x{:08X}", magic));
618 }
619 let version = read_u32(bytes, &mut pos)?;
620 if version != FORMAT_VERSION {
621 return Err(format!("Unsupported format version: {}", version));
622 }
623 let name = read_str(bytes, &mut pos)?;
624 let _ver_str = read_str(bytes, &mut pos)?;
625 let _dep_count = read_u32(bytes, &mut pos)?;
626 let dep_count = _dep_count as usize;
627 for _ in 0..dep_count {
628 let len = read_u32(bytes, &mut pos)? as usize;
629 if pos + len > bytes.len() {
630 return Err("truncated dependency list".to_string());
631 }
632 pos += len;
633 }
634 let num_entries = read_u32(bytes, &mut pos)?;
635 Ok((name, version, num_entries))
636}
637#[cfg(test)]
638mod tests {
639 use super::*;
640 use crate::{Expr, Level};
641 #[test]
642 fn test_exported_module_create() {
643 let module = ExportedModule::new("test".to_string());
644 assert_eq!(module.name, "test");
645 assert_eq!(module.num_entries(), 0);
646 assert!(module.is_empty());
647 }
648 #[test]
649 fn test_add_declaration() {
650 let mut module = ExportedModule::new("test".to_string());
651 let decl = Declaration::Axiom {
652 name: Name::str("foo"),
653 univ_params: vec![],
654 ty: Expr::Sort(Level::zero()),
655 };
656 module.add_declaration(Name::str("foo"), decl);
657 assert_eq!(module.declarations.len(), 1);
658 assert!(!module.is_empty());
659 }
660 #[test]
661 fn test_add_dependency() {
662 let mut module = ExportedModule::new("test".to_string());
663 module.add_dependency("base".to_string());
664 module.add_dependency("base".to_string());
665 assert_eq!(module.dependencies.len(), 1);
666 assert_eq!(module.dependencies[0], "base");
667 }
668 #[test]
669 fn test_export_environment() {
670 let env = Environment::new();
671 let module = export_environment(&env, "test".to_string());
672 assert_eq!(module.name, "test");
673 }
674 #[test]
675 fn test_import_module() {
676 let mut module = ExportedModule::new("test".to_string());
677 module.add_declaration(
678 Name::str("foo"),
679 Declaration::Axiom {
680 name: Name::str("foo"),
681 univ_params: vec![],
682 ty: Expr::Sort(Level::zero()),
683 },
684 );
685 let mut target_env = Environment::new();
686 assert!(import_module(&mut target_env, &module).is_ok());
687 assert!(target_env.get(&Name::str("foo")).is_some());
688 }
689 #[test]
690 fn test_module_cache() {
691 let mut cache = ModuleCache::new();
692 let module = ExportedModule::new("test".to_string());
693 cache.add(module);
694 assert!(cache.contains("test"));
695 assert_eq!(cache.all_modules().len(), 1);
696 assert_eq!(cache.num_modules(), 1);
697 }
698 #[test]
699 fn test_import_all() {
700 let mut cache = ModuleCache::new();
701 let mut module = ExportedModule::new("mod1".to_string());
702 module.add_declaration(
703 Name::str("foo"),
704 Declaration::Axiom {
705 name: Name::str("foo"),
706 univ_params: vec![],
707 ty: Expr::Sort(Level::zero()),
708 },
709 );
710 cache.add(module);
711 let mut target = Environment::new();
712 assert!(cache.import_all(&mut target).is_ok());
713 assert!(target.get(&Name::str("foo")).is_some());
714 }
715 #[test]
716 fn test_serialize_deserialize_header() {
717 let mut module = ExportedModule::new("test_mod".to_string());
718 module.add_dependency("base".to_string());
719 let bytes = serialize_module(&module);
720 let (name, version, _entries) =
721 deserialize_module_header(&bytes).expect("value should be present");
722 assert_eq!(name, "test_mod");
723 assert_eq!(version, FORMAT_VERSION);
724 }
725 #[test]
726 fn test_serialize_invalid_magic() {
727 let bytes = vec![0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
728 assert!(deserialize_module_header(&bytes).is_err());
729 }
730 #[test]
731 fn test_serialize_deserialize_round_trip() {
732 let mut module = ExportedModule::new("my_module".to_string());
733 module.add_dependency("base".to_string());
734 module.set_metadata("author".to_string(), "alice".to_string());
735 let axiom = Declaration::Axiom {
736 name: Name::str("MyAxiom"),
737 univ_params: vec![Name::str("u")],
738 ty: Expr::Sort(Level::param(Name::str("u"))),
739 };
740 module.add_declaration(Name::str("MyAxiom"), axiom);
741 let def = Declaration::Definition {
742 name: Name::str("myDef"),
743 univ_params: vec![],
744 ty: Expr::Sort(Level::zero()),
745 val: Expr::Lit(Literal::nat(42)),
746 hint: ReducibilityHint::Regular(1),
747 };
748 module.add_declaration(Name::str("myDef"), def);
749 let thm = Declaration::Theorem {
750 name: Name::str("myThm"),
751 univ_params: vec![],
752 ty: Expr::Pi(
753 BinderInfo::Default,
754 Name::str("x"),
755 Node::new(Expr::Sort(Level::zero())),
756 Node::new(Expr::BVar(0)),
757 ),
758 val: Expr::Lam(
759 BinderInfo::Default,
760 Name::str("x"),
761 Node::new(Expr::Sort(Level::zero())),
762 Node::new(Expr::BVar(0)),
763 ),
764 };
765 module.add_declaration(Name::str("myThm"), thm);
766 let bytes = serialize_module(&module);
767 let decoded = deserialize_module(&bytes).expect("decoded should be present");
768 assert_eq!(decoded.name, "my_module");
769 assert_eq!(decoded.dependencies, vec!["base"]);
770 assert_eq!(
771 decoded
772 .metadata
773 .get("author")
774 .expect("element at \'author\' should exist"),
775 "alice"
776 );
777 assert_eq!(decoded.declarations.len(), 3);
778 assert_eq!(decoded.declarations[0].0, Name::str("MyAxiom"));
779 assert_eq!(decoded.declarations[1].0, Name::str("myDef"));
780 assert_eq!(decoded.declarations[2].0, Name::str("myThm"));
781 }
782 #[test]
783 fn test_serialize_complex_expr() {
784 let expr = Expr::App(
785 Node::new(Expr::Lam(
786 BinderInfo::Implicit,
787 Name::str("x"),
788 Node::new(Expr::Const(Name::str("Nat"), vec![])),
789 Node::new(Expr::BVar(0)),
790 )),
791 Node::new(Expr::Lit(Literal::nat(7))),
792 );
793 let mut buf = Vec::new();
794 write_expr(&mut buf, &expr);
795 let decoded = read_expr(&buf, &mut 0).expect("decoded should be present");
796 assert_eq!(decoded, expr);
797 }
798 #[test]
799 fn test_serialize_name_components() {
800 let name = Name::str("Nat").append_str("add").append_num(3);
801 let mut buf = Vec::new();
802 write_name(&mut buf, &name);
803 let decoded = read_name(&buf, &mut 0).expect("decoded should be present");
804 assert_eq!(decoded, name);
805 }
806 #[test]
807 fn test_serialize_level_variants() {
808 let levels = vec![
809 Level::zero(),
810 Level::succ(Level::zero()),
811 Level::max(Level::zero(), Level::param(Name::str("u"))),
812 Level::imax(Level::param(Name::str("u")), Level::param(Name::str("v"))),
813 Level::mvar(LevelMVarId(99)),
814 ];
815 for level in &levels {
816 let mut buf = Vec::new();
817 write_level(&mut buf, level);
818 let decoded = read_level(&buf, &mut 0).expect("decoded should be present");
819 assert_eq!(&decoded, level);
820 }
821 }
822 #[test]
823 fn test_module_metadata() {
824 let mut module = ExportedModule::new("test".to_string());
825 module.set_metadata("author".to_string(), "oxilean".to_string());
826 assert_eq!(
827 module
828 .metadata
829 .get("author")
830 .expect("element at \'author\' should exist"),
831 "oxilean"
832 );
833 }
834 #[test]
835 fn test_cache_remove() {
836 let mut cache = ModuleCache::new();
837 cache.add(ExportedModule::new("mod1".to_string()));
838 cache.add(ExportedModule::new("mod2".to_string()));
839 assert_eq!(cache.num_modules(), 2);
840 cache.remove("mod1");
841 assert_eq!(cache.num_modules(), 1);
842 assert!(!cache.contains("mod1"));
843 }
844 #[test]
845 fn test_cache_clear() {
846 let mut cache = ModuleCache::new();
847 cache.add(ExportedModule::new("mod1".to_string()));
848 cache.clear();
849 assert_eq!(cache.num_modules(), 0);
850 }
851}
852pub fn diff_modules(old: &ExportedModule, new: &ExportedModule) -> ModuleDiff {
856 let old_names: std::collections::HashSet<&Name> = old.declaration_names().into_iter().collect();
857 let new_names: std::collections::HashSet<&Name> = new.declaration_names().into_iter().collect();
858 let added = new_names
859 .difference(&old_names)
860 .map(|n| (*n).clone())
861 .collect();
862 let removed = old_names
863 .difference(&new_names)
864 .map(|n| (*n).clone())
865 .collect();
866 let changed = Vec::new();
867 ModuleDiff {
868 added,
869 removed,
870 changed,
871 }
872}
873pub fn check_module_integrity(module: &ExportedModule) -> IntegrityCheckResult {
875 if module.is_empty() {
876 return IntegrityCheckResult::EmptyModule;
877 }
878 let names = module.declaration_names();
879 let mut seen = std::collections::HashSet::new();
880 let mut duplicates = Vec::new();
881 for name in names {
882 if !seen.insert(name) {
883 duplicates.push(name.clone());
884 }
885 }
886 if !duplicates.is_empty() {
887 return IntegrityCheckResult::DuplicateNames(duplicates);
888 }
889 IntegrityCheckResult::Ok
890}
891pub fn check_bytes_integrity(bytes: &[u8]) -> IntegrityCheckResult {
893 if bytes.len() < 8 {
894 return IntegrityCheckResult::BadMagicNumber;
895 }
896 let magic = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
897 if magic != MAGIC_NUMBER {
898 return IntegrityCheckResult::BadMagicNumber;
899 }
900 let version = u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
901 if version != FORMAT_VERSION {
902 return IntegrityCheckResult::UnsupportedVersion(version);
903 }
904 IntegrityCheckResult::Ok
905}
906#[cfg(test)]
907mod extra_tests {
908 use super::*;
909 use crate::{Expr, Level};
910 #[test]
911 fn test_module_diff_empty() {
912 let m1 = ExportedModule::new("m1".to_string());
913 let m2 = ExportedModule::new("m1".to_string());
914 let diff = diff_modules(&m1, &m2);
915 assert!(diff.is_empty());
916 assert_eq!(diff.total_changes(), 0);
917 }
918 #[test]
919 fn test_module_diff_added() {
920 let m1 = ExportedModule::new("m1".to_string());
921 let mut m2 = ExportedModule::new("m1".to_string());
922 m2.add_declaration(
923 Name::str("foo"),
924 Declaration::Axiom {
925 name: Name::str("foo"),
926 univ_params: vec![],
927 ty: Expr::Sort(Level::zero()),
928 },
929 );
930 let diff = diff_modules(&m1, &m2);
931 assert_eq!(diff.added.len(), 1);
932 assert_eq!(diff.removed.len(), 0);
933 }
934 #[test]
935 fn test_module_diff_removed() {
936 let mut m1 = ExportedModule::new("m1".to_string());
937 m1.add_declaration(
938 Name::str("foo"),
939 Declaration::Axiom {
940 name: Name::str("foo"),
941 univ_params: vec![],
942 ty: Expr::Sort(Level::zero()),
943 },
944 );
945 let m2 = ExportedModule::new("m1".to_string());
946 let diff = diff_modules(&m1, &m2);
947 assert_eq!(diff.removed.len(), 1);
948 }
949 #[test]
950 fn test_module_registry_register() {
951 let mut reg = ModuleRegistry::new();
952 reg.register(Name::str("foo"), "base".to_string());
953 assert_eq!(reg.module_for(&Name::str("foo")), Some("base"));
954 assert!(reg.contains_decl(&Name::str("foo")));
955 assert_eq!(reg.num_decls(), 1);
956 }
957 #[test]
958 fn test_module_registry_register_module() {
959 let mut module = ExportedModule::new("mymod".to_string());
960 module.add_declaration(
961 Name::str("bar"),
962 Declaration::Axiom {
963 name: Name::str("bar"),
964 univ_params: vec![],
965 ty: Expr::Sort(Level::zero()),
966 },
967 );
968 let mut reg = ModuleRegistry::new();
969 reg.register_module(&module);
970 assert_eq!(reg.module_for(&Name::str("bar")), Some("mymod"));
971 }
972 #[test]
973 fn test_module_registry_decls_for_module() {
974 let mut reg = ModuleRegistry::new();
975 reg.register(Name::str("a"), "mod".to_string());
976 reg.register(Name::str("b"), "mod".to_string());
977 assert_eq!(reg.decls_for_module("mod").len(), 2);
978 }
979 #[test]
980 fn test_dep_graph_topological_order() {
981 let mut g = ModuleDependencyGraph::new();
982 g.add_module("a".to_string());
983 g.add_module("b".to_string());
984 g.add_dep("b".to_string(), "a".to_string());
985 let order = g.topological_order().expect("order should be present");
986 assert_eq!(order.len(), 2);
987 assert!(order.contains(&"a".to_string()));
988 assert!(order.contains(&"b".to_string()));
989 }
990 #[test]
991 fn test_dep_graph_depends_on() {
992 let mut g = ModuleDependencyGraph::new();
993 g.add_module("a".to_string());
994 g.add_module("b".to_string());
995 g.add_dep("b".to_string(), "a".to_string());
996 assert!(g.depends_on("b", "a"));
997 assert!(!g.depends_on("a", "b"));
998 }
999 #[test]
1000 fn test_check_module_integrity_ok() {
1001 let mut m = ExportedModule::new("test".to_string());
1002 m.add_declaration(
1003 Name::str("foo"),
1004 Declaration::Axiom {
1005 name: Name::str("foo"),
1006 univ_params: vec![],
1007 ty: Expr::Sort(Level::zero()),
1008 },
1009 );
1010 assert_eq!(check_module_integrity(&m), IntegrityCheckResult::Ok);
1011 }
1012 #[test]
1013 fn test_check_module_integrity_empty() {
1014 let m = ExportedModule::new("test".to_string());
1015 assert_eq!(
1016 check_module_integrity(&m),
1017 IntegrityCheckResult::EmptyModule
1018 );
1019 }
1020 #[test]
1021 fn test_check_bytes_integrity_ok() {
1022 let module = ExportedModule::new("t".to_string());
1023 let bytes = serialize_module(&module);
1024 assert_eq!(check_bytes_integrity(&bytes), IntegrityCheckResult::Ok);
1025 }
1026 #[test]
1027 fn test_check_bytes_integrity_bad_magic() {
1028 let bytes = vec![0u8; 16];
1029 assert_eq!(
1030 check_bytes_integrity(&bytes),
1031 IntegrityCheckResult::BadMagicNumber
1032 );
1033 }
1034 #[test]
1035 fn test_module_diff_total_changes() {
1036 let diff = ModuleDiff {
1037 added: vec![Name::str("a")],
1038 removed: vec![Name::str("b"), Name::str("c")],
1039 changed: vec![],
1040 };
1041 assert_eq!(diff.total_changes(), 3);
1042 assert!(!diff.is_empty());
1043 }
1044}
1045#[cfg(test)]
1046mod version_tests {
1047 use super::*;
1048 #[test]
1049 fn test_version_display() {
1050 let v = ModuleVersion::new(1, 2, 3);
1051 assert_eq!(v.to_string(), "1.2.3");
1052 }
1053 #[test]
1054 fn test_version_parse_ok() {
1055 let v = ModuleVersion::parse("2.3.4").expect("v should be present");
1056 assert_eq!(v.major, 2);
1057 assert_eq!(v.minor, 3);
1058 assert_eq!(v.patch, 4);
1059 }
1060 #[test]
1061 fn test_version_parse_invalid() {
1062 assert!(ModuleVersion::parse("1.2").is_none());
1063 assert!(ModuleVersion::parse("a.b.c").is_none());
1064 }
1065 #[test]
1066 fn test_version_compatible_same() {
1067 let v1 = ModuleVersion::new(1, 0, 0);
1068 let v2 = ModuleVersion::new(1, 0, 0);
1069 assert!(v1.is_compatible_with(&v2));
1070 }
1071 #[test]
1072 fn test_version_compatible_newer_minor() {
1073 let newer = ModuleVersion::new(1, 1, 0);
1074 let older = ModuleVersion::new(1, 0, 0);
1075 assert!(newer.is_compatible_with(&older));
1076 }
1077 #[test]
1078 fn test_version_incompatible_different_major() {
1079 let v1 = ModuleVersion::new(2, 0, 0);
1080 let v2 = ModuleVersion::new(1, 5, 0);
1081 assert!(!v1.is_compatible_with(&v2));
1082 }
1083 #[test]
1084 fn test_module_info_builder() {
1085 let info = ModuleInfo::new()
1086 .with_version(ModuleVersion::new(0, 1, 0))
1087 .with_author("oxilean")
1088 .with_license("MIT")
1089 .with_description("core library");
1090 assert_eq!(info.author.as_deref(), Some("oxilean"));
1091 assert_eq!(info.license.as_deref(), Some("MIT"));
1092 assert!(info.version.is_some());
1093 }
1094 #[test]
1095 fn test_module_info_default_empty() {
1096 let info = ModuleInfo::new();
1097 assert!(info.version.is_none());
1098 assert!(info.author.is_none());
1099 }
1100 #[test]
1101 fn test_version_ordering() {
1102 let v1 = ModuleVersion::new(1, 0, 0);
1103 let v2 = ModuleVersion::new(1, 1, 0);
1104 assert!(v1 < v2);
1105 }
1106 #[test]
1107 fn test_version_roundtrip() {
1108 let v = ModuleVersion::new(3, 14, 159);
1109 let s = v.to_string();
1110 let v2 = ModuleVersion::parse(&s).expect("v2 should be present");
1111 assert_eq!(v, v2);
1112 }
1113}
1114#[cfg(test)]
1115mod tests_padding_infra {
1116 use super::*;
1117 #[test]
1118 fn test_stat_summary() {
1119 let mut ss = StatSummary::new();
1120 ss.record(10.0);
1121 ss.record(20.0);
1122 ss.record(30.0);
1123 assert_eq!(ss.count(), 3);
1124 assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
1125 assert_eq!(ss.min().expect("min should succeed") as i64, 10);
1126 assert_eq!(ss.max().expect("max should succeed") as i64, 30);
1127 }
1128 #[test]
1129 fn test_transform_stat() {
1130 let mut ts = TransformStat::new();
1131 ts.record_before(100.0);
1132 ts.record_after(80.0);
1133 let ratio = ts.mean_ratio().expect("ratio should be present");
1134 assert!((ratio - 0.8).abs() < 1e-9);
1135 }
1136 #[test]
1137 fn test_small_map() {
1138 let mut m: SmallMap<u32, &str> = SmallMap::new();
1139 m.insert(3, "three");
1140 m.insert(1, "one");
1141 m.insert(2, "two");
1142 assert_eq!(m.get(&2), Some(&"two"));
1143 assert_eq!(m.len(), 3);
1144 let keys = m.keys();
1145 assert_eq!(*keys[0], 1);
1146 assert_eq!(*keys[2], 3);
1147 }
1148 #[test]
1149 fn test_label_set() {
1150 let mut ls = LabelSet::new();
1151 ls.add("foo");
1152 ls.add("bar");
1153 ls.add("foo");
1154 assert_eq!(ls.count(), 2);
1155 assert!(ls.has("bar"));
1156 assert!(!ls.has("baz"));
1157 }
1158 #[test]
1159 fn test_config_node() {
1160 let mut root = ConfigNode::section("root");
1161 let child = ConfigNode::leaf("key", "value");
1162 root.add_child(child);
1163 assert_eq!(root.num_children(), 1);
1164 }
1165 #[test]
1166 fn test_versioned_record() {
1167 let mut vr = VersionedRecord::new(0u32);
1168 vr.update(1);
1169 vr.update(2);
1170 assert_eq!(*vr.current(), 2);
1171 assert_eq!(vr.version(), 2);
1172 assert!(vr.has_history());
1173 assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
1174 }
1175 #[test]
1176 fn test_simple_dag() {
1177 let mut dag = SimpleDag::new(4);
1178 dag.add_edge(0, 1);
1179 dag.add_edge(1, 2);
1180 dag.add_edge(2, 3);
1181 assert!(dag.can_reach(0, 3));
1182 assert!(!dag.can_reach(3, 0));
1183 let order = dag.topological_sort().expect("order should be present");
1184 assert_eq!(order, vec![0, 1, 2, 3]);
1185 }
1186 #[test]
1187 fn test_focus_stack() {
1188 let mut fs: FocusStack<&str> = FocusStack::new();
1189 fs.focus("a");
1190 fs.focus("b");
1191 assert_eq!(fs.current(), Some(&"b"));
1192 assert_eq!(fs.depth(), 2);
1193 fs.blur();
1194 assert_eq!(fs.current(), Some(&"a"));
1195 }
1196}
1197#[cfg(test)]
1198mod tests_extra_iterators {
1199 use super::*;
1200 #[test]
1201 fn test_window_iterator() {
1202 let data = vec![1u32, 2, 3, 4, 5];
1203 let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
1204 assert_eq!(windows.len(), 3);
1205 assert_eq!(windows[0], &[1, 2, 3]);
1206 assert_eq!(windows[2], &[3, 4, 5]);
1207 }
1208 #[test]
1209 fn test_non_empty_vec() {
1210 let mut nev = NonEmptyVec::singleton(10u32);
1211 nev.push(20);
1212 nev.push(30);
1213 assert_eq!(nev.len(), 3);
1214 assert_eq!(*nev.first(), 10);
1215 assert_eq!(*nev.last(), 30);
1216 }
1217}
1218#[cfg(test)]
1219mod tests_padding2 {
1220 use super::*;
1221 #[test]
1222 fn test_sliding_sum() {
1223 let mut ss = SlidingSum::new(3);
1224 ss.push(1.0);
1225 ss.push(2.0);
1226 ss.push(3.0);
1227 assert!((ss.sum() - 6.0).abs() < 1e-9);
1228 ss.push(4.0);
1229 assert!((ss.sum() - 9.0).abs() < 1e-9);
1230 assert_eq!(ss.count(), 3);
1231 }
1232 #[test]
1233 fn test_path_buf() {
1234 let mut pb = PathBuf::new();
1235 pb.push("src");
1236 pb.push("main");
1237 assert_eq!(pb.as_str(), "src/main");
1238 assert_eq!(pb.depth(), 2);
1239 pb.pop();
1240 assert_eq!(pb.as_str(), "src");
1241 }
1242 #[test]
1243 fn test_string_pool() {
1244 let mut pool = StringPool::new();
1245 let s = pool.take();
1246 assert!(s.is_empty());
1247 pool.give("hello".to_string());
1248 let s2 = pool.take();
1249 assert!(s2.is_empty());
1250 assert_eq!(pool.free_count(), 0);
1251 }
1252 #[test]
1253 fn test_transitive_closure() {
1254 let mut tc = TransitiveClosure::new(4);
1255 tc.add_edge(0, 1);
1256 tc.add_edge(1, 2);
1257 tc.add_edge(2, 3);
1258 assert!(tc.can_reach(0, 3));
1259 assert!(!tc.can_reach(3, 0));
1260 let r = tc.reachable_from(0);
1261 assert_eq!(r.len(), 4);
1262 }
1263 #[test]
1264 fn test_token_bucket() {
1265 let mut tb = TokenBucket::new(100, 0);
1266 assert_eq!(tb.available(), 100);
1267 assert!(tb.try_consume(50));
1268 assert_eq!(tb.available(), 50);
1269 assert!(!tb.try_consume(60));
1270 assert_eq!(tb.capacity(), 100);
1271 }
1272 #[test]
1273 fn test_rewrite_rule_set() {
1274 let mut rrs = RewriteRuleSet::new();
1275 rrs.add(RewriteRule::unconditional(
1276 "beta",
1277 "App(Lam(x, b), v)",
1278 "b[x:=v]",
1279 ));
1280 rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
1281 assert_eq!(rrs.len(), 2);
1282 assert_eq!(rrs.unconditional_rules().len(), 1);
1283 assert_eq!(rrs.conditional_rules().len(), 1);
1284 assert!(rrs.get("beta").is_some());
1285 let disp = rrs
1286 .get("beta")
1287 .expect("element at \'beta\' should exist")
1288 .display();
1289 assert!(disp.contains("→"));
1290 }
1291}