Skip to main content

oxilean_kernel/export/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use 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
21/// Export an environment to a module.
22///
23/// Exports all declarations and constant info entries from the environment.
24pub 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}
31/// Import a module into an environment.
32///
33/// Imports both legacy declarations and constant info entries.
34pub 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}
56/// Serialization format identifier.
57pub const MAGIC_NUMBER: u32 = 0x4F584C4E;
58/// Module format version.
59pub 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            // Tag 0: small Nat, single u64 payload (backwards compatible).
132            Some(small) => {
133                write_u8(buf, 0);
134                write_u64(buf, small);
135            }
136            // Tag 3: big Nat, limb-count-prefixed little-endian u64 limbs.
137            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        // Tag 2 was the removed (non-Lean) Int literal.
392        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            // Guard against corrupt counts: each limb costs 8 bytes.
396            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}
535/// Serialize an `ExportedModule` to a compact binary format.
536///
537/// The format is:
538/// - 4-byte magic number (`OXLN`)
539/// - 4-byte format version
540/// - module name (length-prefixed UTF-8)
541/// - version string (length-prefixed UTF-8)
542/// - dependency count + dependency name strings
543/// - declaration count + serialized `Declaration` values
544/// - metadata count + (key, value) string pairs
545pub 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}
566/// Deserialize an `ExportedModule` from bytes produced by [`serialize_module`].
567///
568/// Returns an error if the bytes are malformed, truncated, or have an
569/// incompatible format version.
570pub 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}
610/// Deserialize only the module header (name, version, declaration count).
611///
612/// Useful for quickly inspecting module metadata without decoding all declarations.
613pub 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}
852/// Compute the diff between two module versions.
853///
854/// Returns a `ModuleDiff` describing what was added, removed, or changed.
855pub 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}
873/// Check the integrity of a module.
874pub 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}
891/// Check the integrity of serialized module bytes.
892pub 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}