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