Skip to main content

oxilean_kernel/expr_util/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use crate::{Expr, FVarId, Level, Name};
6
7use super::types::{
8    ConfigNode, DecisionNode, Either2, Fixture, FlatSubstitution, FocusStack, LabelSet, MinHeap,
9    NonEmptyVec, PathBuf, PrefixCounter, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum,
10    SmallMap, SparseVec, StackCalc, StatSummary, Stopwatch, StringPool, TokenBucket, TransformStat,
11    TransitiveClosure, VersionedRecord, WindowIterator, WriteOnce,
12};
13
14/// Extract the function head from a chain of applications.
15///
16/// `get_app_fn(f a1 a2 a3)` returns `f`.
17pub fn get_app_fn(e: &Expr) -> &Expr {
18    match e {
19        Expr::App(f, _) => get_app_fn(f),
20        _ => e,
21    }
22}
23/// Extract all arguments from a chain of applications.
24///
25/// `get_app_args(f a1 a2 a3)` returns `[a1, a2, a3]`.
26pub fn get_app_args(e: &Expr) -> Vec<&Expr> {
27    let mut args = Vec::new();
28    get_app_args_aux(e, &mut args);
29    args
30}
31fn get_app_args_aux<'a>(e: &'a Expr, args: &mut Vec<&'a Expr>) {
32    if let Expr::App(f, a) = e {
33        get_app_args_aux(f, args);
34        args.push(a);
35    }
36}
37/// Decompose an expression into its head function and arguments.
38///
39/// `get_app_fn_args(f a1 a2)` returns `(f, [a1, a2])`.
40pub fn get_app_fn_args(e: &Expr) -> (&Expr, Vec<&Expr>) {
41    let mut args = Vec::new();
42    let f = get_app_fn_args_aux(e, &mut args);
43    (f, args)
44}
45fn get_app_fn_args_aux<'a>(e: &'a Expr, args: &mut Vec<&'a Expr>) -> &'a Expr {
46    match e {
47        Expr::App(f, a) => {
48            let head = get_app_fn_args_aux(f, args);
49            args.push(a);
50            head
51        }
52        _ => e,
53    }
54}
55/// Get the number of arguments in an application chain.
56pub fn get_app_num_args(e: &Expr) -> usize {
57    match e {
58        Expr::App(f, _) => 1 + get_app_num_args(f),
59        _ => 0,
60    }
61}
62/// Construct an application from a function and a list of arguments.
63///
64/// `mk_app(f, [a1, a2, a3])` returns `f a1 a2 a3`.
65pub fn mk_app(f: Expr, args: &[Expr]) -> Expr {
66    args.iter().fold(f, |acc, arg| {
67        Expr::App(Box::new(acc), Box::new(arg.clone()))
68    })
69}
70/// Construct an application from a function and a range of arguments.
71///
72/// `mk_app_range(f, args, 1, 3)` returns `f args[1] args[2]`.
73pub fn mk_app_range(f: Expr, args: &[Expr], begin: usize, end: usize) -> Expr {
74    let end = end.min(args.len());
75    let begin = begin.min(end);
76    mk_app(f, &args[begin..end])
77}
78/// Check if an expression has any loose bound variables.
79///
80/// A bound variable is "loose" if its de Bruijn index refers to a binder
81/// that is not part of the expression.
82pub fn has_loose_bvars(e: &Expr) -> bool {
83    has_loose_bvar_ge(e, 0)
84}
85/// Check if an expression has a loose bound variable with index >= `depth`.
86pub fn has_loose_bvar_ge(e: &Expr, depth: u32) -> bool {
87    match e {
88        Expr::BVar(n) => *n >= depth,
89        Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
90        Expr::App(f, a) => has_loose_bvar_ge(f, depth) || has_loose_bvar_ge(a, depth),
91        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
92            has_loose_bvar_ge(ty, depth) || has_loose_bvar_ge(body, depth + 1)
93        }
94        Expr::Let(_, ty, val, body) => {
95            has_loose_bvar_ge(ty, depth)
96                || has_loose_bvar_ge(val, depth)
97                || has_loose_bvar_ge(body, depth + 1)
98        }
99        Expr::Proj(_, _, e) => has_loose_bvar_ge(e, depth),
100    }
101}
102/// Check if an expression has a specific loose bound variable at `level`.
103pub fn has_loose_bvar(e: &Expr, level: u32) -> bool {
104    match e {
105        Expr::BVar(n) => *n == level,
106        Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
107        Expr::App(f, a) => has_loose_bvar(f, level) || has_loose_bvar(a, level),
108        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
109            has_loose_bvar(ty, level) || has_loose_bvar(body, level + 1)
110        }
111        Expr::Let(_, ty, val, body) => {
112            has_loose_bvar(ty, level)
113                || has_loose_bvar(val, level)
114                || has_loose_bvar(body, level + 1)
115        }
116        Expr::Proj(_, _, e) => has_loose_bvar(e, level),
117    }
118}
119/// Check if an expression contains a specific free variable.
120pub fn has_fvar(e: &Expr, fvar: FVarId) -> bool {
121    match e {
122        Expr::FVar(id) => *id == fvar,
123        Expr::Sort(_) | Expr::BVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
124        Expr::App(f, a) => has_fvar(f, fvar) || has_fvar(a, fvar),
125        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
126            has_fvar(ty, fvar) || has_fvar(body, fvar)
127        }
128        Expr::Let(_, ty, val, body) => {
129            has_fvar(ty, fvar) || has_fvar(val, fvar) || has_fvar(body, fvar)
130        }
131        Expr::Proj(_, _, e) => has_fvar(e, fvar),
132    }
133}
134/// Check if an expression contains any free variables.
135pub fn has_any_fvar(e: &Expr) -> bool {
136    match e {
137        Expr::FVar(_) => true,
138        Expr::Sort(_) | Expr::BVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
139        Expr::App(f, a) => has_any_fvar(f) || has_any_fvar(a),
140        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
141            has_any_fvar(ty) || has_any_fvar(body)
142        }
143        Expr::Let(_, ty, val, body) => has_any_fvar(ty) || has_any_fvar(val) || has_any_fvar(body),
144        Expr::Proj(_, _, e) => has_any_fvar(e),
145    }
146}
147/// Traverse every sub-expression, calling `f` on each.
148///
149/// The callback receives the expression and the current binding depth.
150/// Return `false` from `f` to stop traversal early.
151pub fn for_each_expr(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> bool) {
152    for_each_expr_aux(e, f, 0);
153}
154fn for_each_expr_aux(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> bool, depth: u32) {
155    if !f(e, depth) {
156        return;
157    }
158    match e {
159        Expr::App(fun, arg) => {
160            for_each_expr_aux(fun, f, depth);
161            for_each_expr_aux(arg, f, depth);
162        }
163        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
164            for_each_expr_aux(ty, f, depth);
165            for_each_expr_aux(body, f, depth + 1);
166        }
167        Expr::Let(_, ty, val, body) => {
168            for_each_expr_aux(ty, f, depth);
169            for_each_expr_aux(val, f, depth);
170            for_each_expr_aux(body, f, depth + 1);
171        }
172        Expr::Proj(_, _, e) => {
173            for_each_expr_aux(e, f, depth);
174        }
175        Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => {}
176    }
177}
178/// Replace sub-expressions using a callback.
179///
180/// The callback receives the expression and binding depth.
181/// Return `Some(replacement)` to replace, or `None` to recurse.
182pub fn replace_expr(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> Option<Expr>) -> Expr {
183    replace_expr_aux(e, f, 0)
184}
185fn replace_expr_aux(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> Option<Expr>, depth: u32) -> Expr {
186    if let Some(replacement) = f(e, depth) {
187        return replacement;
188    }
189    match e {
190        Expr::App(fun, arg) => {
191            let new_fun = replace_expr_aux(fun, f, depth);
192            let new_arg = replace_expr_aux(arg, f, depth);
193            Expr::App(Box::new(new_fun), Box::new(new_arg))
194        }
195        Expr::Lam(bi, name, ty, body) => {
196            let new_ty = replace_expr_aux(ty, f, depth);
197            let new_body = replace_expr_aux(body, f, depth + 1);
198            Expr::Lam(*bi, name.clone(), Box::new(new_ty), Box::new(new_body))
199        }
200        Expr::Pi(bi, name, ty, body) => {
201            let new_ty = replace_expr_aux(ty, f, depth);
202            let new_body = replace_expr_aux(body, f, depth + 1);
203            Expr::Pi(*bi, name.clone(), Box::new(new_ty), Box::new(new_body))
204        }
205        Expr::Let(name, ty, val, body) => {
206            let new_ty = replace_expr_aux(ty, f, depth);
207            let new_val = replace_expr_aux(val, f, depth);
208            let new_body = replace_expr_aux(body, f, depth + 1);
209            Expr::Let(
210                name.clone(),
211                Box::new(new_ty),
212                Box::new(new_val),
213                Box::new(new_body),
214            )
215        }
216        Expr::Proj(name, idx, e_inner) => {
217            let new_e = replace_expr_aux(e_inner, f, depth);
218            Expr::Proj(name.clone(), *idx, Box::new(new_e))
219        }
220        Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => {
221            e.clone()
222        }
223    }
224}
225/// Collect all free variables in an expression.
226pub fn collect_fvars(e: &Expr) -> Vec<FVarId> {
227    let mut fvars = Vec::new();
228    for_each_expr(e, &mut |sub, _depth| {
229        if let Expr::FVar(id) = sub {
230            if !fvars.contains(id) {
231                fvars.push(*id);
232            }
233        }
234        true
235    });
236    fvars
237}
238/// Collect all constant names referenced in an expression.
239pub fn collect_consts(e: &Expr) -> Vec<Name> {
240    let mut consts = Vec::new();
241    for_each_expr(e, &mut |sub, _depth| {
242        if let Expr::Const(name, _) = sub {
243            if !consts.contains(name) {
244                consts.push(name.clone());
245            }
246        }
247        true
248    });
249    consts
250}
251/// Lift (shift) loose bound variables by `n`.
252///
253/// Increments the index of all loose bound variables (with index >= `offset`)
254/// by `n`. Used when inserting an expression under additional binders.
255pub fn lift_loose_bvars(e: &Expr, n: u32, offset: u32) -> Expr {
256    if n == 0 {
257        return e.clone();
258    }
259    lift_loose_bvars_aux(e, n, offset)
260}
261fn lift_loose_bvars_aux(e: &Expr, n: u32, depth: u32) -> Expr {
262    match e {
263        Expr::BVar(idx) => {
264            if *idx >= depth {
265                Expr::BVar(idx + n)
266            } else {
267                e.clone()
268            }
269        }
270        Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => e.clone(),
271        Expr::App(f, a) => {
272            let f_new = lift_loose_bvars_aux(f, n, depth);
273            let a_new = lift_loose_bvars_aux(a, n, depth);
274            Expr::App(Box::new(f_new), Box::new(a_new))
275        }
276        Expr::Lam(bi, name, ty, body) => {
277            let ty_new = lift_loose_bvars_aux(ty, n, depth);
278            let body_new = lift_loose_bvars_aux(body, n, depth + 1);
279            Expr::Lam(*bi, name.clone(), Box::new(ty_new), Box::new(body_new))
280        }
281        Expr::Pi(bi, name, ty, body) => {
282            let ty_new = lift_loose_bvars_aux(ty, n, depth);
283            let body_new = lift_loose_bvars_aux(body, n, depth + 1);
284            Expr::Pi(*bi, name.clone(), Box::new(ty_new), Box::new(body_new))
285        }
286        Expr::Let(name, ty, val, body) => {
287            let ty_new = lift_loose_bvars_aux(ty, n, depth);
288            let val_new = lift_loose_bvars_aux(val, n, depth);
289            let body_new = lift_loose_bvars_aux(body, n, depth + 1);
290            Expr::Let(
291                name.clone(),
292                Box::new(ty_new),
293                Box::new(val_new),
294                Box::new(body_new),
295            )
296        }
297        Expr::Proj(name, idx, inner) => {
298            let inner_new = lift_loose_bvars_aux(inner, n, depth);
299            Expr::Proj(name.clone(), *idx, Box::new(inner_new))
300        }
301    }
302}
303/// Check if a constant name occurs anywhere in an expression.
304pub fn occurs_const(e: &Expr, name: &Name) -> bool {
305    match e {
306        Expr::Const(n, _) => n == name,
307        Expr::App(f, a) => occurs_const(f, name) || occurs_const(a, name),
308        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
309            occurs_const(ty, name) || occurs_const(body, name)
310        }
311        Expr::Let(_, ty, val, body) => {
312            occurs_const(ty, name) || occurs_const(val, name) || occurs_const(body, name)
313        }
314        Expr::Proj(_, _, e) => occurs_const(e, name),
315        _ => false,
316    }
317}
318/// Count the number of leading lambdas.
319pub fn count_lambdas(e: &Expr) -> u32 {
320    match e {
321        Expr::Lam(_, _, _, body) => 1 + count_lambdas(body),
322        _ => 0,
323    }
324}
325/// Count the number of leading Pi binders.
326pub fn count_pis(e: &Expr) -> u32 {
327    match e {
328        Expr::Pi(_, _, _, body) => 1 + count_pis(body),
329        _ => 0,
330    }
331}
332/// Get the body after stripping `n` leading lambdas.
333pub fn strip_lambdas(e: &Expr, n: u32) -> &Expr {
334    if n == 0 {
335        return e;
336    }
337    match e {
338        Expr::Lam(_, _, _, body) => strip_lambdas(body, n - 1),
339        _ => e,
340    }
341}
342/// Get the body after stripping `n` leading Pis.
343pub fn strip_pis(e: &Expr, n: u32) -> &Expr {
344    if n == 0 {
345        return e;
346    }
347    match e {
348        Expr::Pi(_, _, _, body) => strip_pis(body, n - 1),
349        _ => e,
350    }
351}
352/// Check if a level has metavariables.
353pub fn level_has_mvar(l: &Level) -> bool {
354    match l {
355        Level::MVar(_) => true,
356        Level::Succ(l) => level_has_mvar(l),
357        Level::Max(l1, l2) | Level::IMax(l1, l2) => level_has_mvar(l1) || level_has_mvar(l2),
358        Level::Zero | Level::Param(_) => false,
359    }
360}
361/// Check if an expression has universe level metavariables.
362pub fn has_level_mvar(e: &Expr) -> bool {
363    match e {
364        Expr::Sort(l) => level_has_mvar(l),
365        Expr::Const(_, ls) => ls.iter().any(level_has_mvar),
366        Expr::App(f, a) => has_level_mvar(f) || has_level_mvar(a),
367        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
368            has_level_mvar(ty) || has_level_mvar(body)
369        }
370        Expr::Let(_, ty, val, body) => {
371            has_level_mvar(ty) || has_level_mvar(val) || has_level_mvar(body)
372        }
373        Expr::Proj(_, _, e) => has_level_mvar(e),
374        Expr::BVar(_) | Expr::FVar(_) | Expr::Lit(_) => false,
375    }
376}
377/// Check if an expression contains any level parameters.
378pub fn has_level_param(e: &Expr) -> bool {
379    match e {
380        Expr::Sort(l) => level_has_param(l),
381        Expr::Const(_, ls) => ls.iter().any(level_has_param),
382        Expr::App(f, a) => has_level_param(f) || has_level_param(a),
383        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
384            has_level_param(ty) || has_level_param(body)
385        }
386        Expr::Let(_, ty, val, body) => {
387            has_level_param(ty) || has_level_param(val) || has_level_param(body)
388        }
389        Expr::Proj(_, _, e) => has_level_param(e),
390        Expr::BVar(_) | Expr::FVar(_) | Expr::Lit(_) => false,
391    }
392}
393fn level_has_param(l: &Level) -> bool {
394    match l {
395        Level::Param(_) => true,
396        Level::Succ(l) => level_has_param(l),
397        Level::Max(l1, l2) | Level::IMax(l1, l2) => level_has_param(l1) || level_has_param(l2),
398        Level::Zero | Level::MVar(_) => false,
399    }
400}
401/// Compute the "weight" of an expression (rough size metric).
402pub fn expr_weight(e: &Expr) -> usize {
403    match e {
404        Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Lit(_) => 1,
405        Expr::Const(_, _) => 1,
406        Expr::App(f, a) => 1 + expr_weight(f) + expr_weight(a),
407        Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
408            1 + expr_weight(ty) + expr_weight(body)
409        }
410        Expr::Let(_, ty, val, body) => 1 + expr_weight(ty) + expr_weight(val) + expr_weight(body),
411        Expr::Proj(_, _, e) => 1 + expr_weight(e),
412    }
413}
414/// Check if the head of an application is a constant with a specific name.
415pub fn is_app_of(e: &Expr, name: &Name) -> bool {
416    matches!(get_app_fn(e), Expr::Const(n, _) if n == name)
417}
418/// Build a non-dependent arrow type: `a → b`.
419pub fn mk_arrow(a: Expr, b: Expr) -> Expr {
420    Expr::Pi(
421        crate::BinderInfo::Default,
422        Name::Anonymous,
423        Box::new(a),
424        Box::new(lift_loose_bvars(&b, 1, 0)),
425    )
426}
427/// Build `Sort 0` (Prop).
428pub fn mk_prop() -> Expr {
429    Expr::Sort(Level::zero())
430}
431/// Build `Sort (u + 1)` (Type u).
432pub fn mk_type(u: Level) -> Expr {
433    Expr::Sort(Level::succ(u))
434}
435/// Build `Sort 1` (Type 0).
436pub fn mk_type0() -> Expr {
437    Expr::Sort(Level::succ(Level::zero()))
438}
439/// Shorthand: create a constant expression.
440pub fn var(name: &str) -> Expr {
441    Expr::Const(Name::str(name), vec![])
442}
443/// Shorthand: create a bound variable.
444pub fn bvar(idx: u32) -> Expr {
445    Expr::BVar(idx)
446}
447/// Shorthand: create an application.
448pub fn app(f: Expr, a: Expr) -> Expr {
449    Expr::App(Box::new(f), Box::new(a))
450}
451/// Shorthand: create a lambda.
452pub fn lam(name: &str, ty: Expr, body: Expr) -> Expr {
453    Expr::Lam(
454        crate::BinderInfo::Default,
455        Name::str(name),
456        Box::new(ty),
457        Box::new(body),
458    )
459}
460/// Shorthand: create a pi type.
461pub fn pi(name: &str, ty: Expr, body: Expr) -> Expr {
462    Expr::Pi(
463        crate::BinderInfo::Default,
464        Name::str(name),
465        Box::new(ty),
466        Box::new(body),
467    )
468}
469/// Shorthand: `Prop` = `Sort 0`.
470pub fn prop() -> Expr {
471    Expr::Sort(crate::Level::zero())
472}
473/// Shorthand: `Sort(Level::zero())`.
474pub fn sort() -> Expr {
475    Expr::Sort(crate::Level::zero())
476}
477/// Shorthand: `Type 0` = `Sort 1`.
478pub fn type0() -> Expr {
479    Expr::Sort(crate::Level::succ(crate::Level::zero()))
480}
481#[cfg(test)]
482mod tests {
483    use super::*;
484    use crate::BinderInfo;
485    fn nat() -> Expr {
486        Expr::Const(Name::str("Nat"), vec![])
487    }
488    fn bool_ty() -> Expr {
489        Expr::Const(Name::str("Bool"), vec![])
490    }
491    #[test]
492    fn test_get_app_fn() {
493        let f = nat();
494        let e = Expr::App(
495            Box::new(Expr::App(Box::new(f.clone()), Box::new(Expr::BVar(0)))),
496            Box::new(Expr::BVar(1)),
497        );
498        assert_eq!(get_app_fn(&e), &f);
499    }
500    #[test]
501    fn test_get_app_args() {
502        let f = nat();
503        let a1 = Expr::BVar(0);
504        let a2 = Expr::BVar(1);
505        let e = Expr::App(
506            Box::new(Expr::App(Box::new(f), Box::new(a1.clone()))),
507            Box::new(a2.clone()),
508        );
509        let args = get_app_args(&e);
510        assert_eq!(args.len(), 2);
511        assert_eq!(args[0], &a1);
512        assert_eq!(args[1], &a2);
513    }
514    #[test]
515    fn test_get_app_fn_args() {
516        let f = nat();
517        let a = Expr::BVar(0);
518        let e = Expr::App(Box::new(f.clone()), Box::new(a.clone()));
519        let (head, args) = get_app_fn_args(&e);
520        assert_eq!(head, &f);
521        assert_eq!(args, vec![&a]);
522    }
523    #[test]
524    fn test_mk_app() {
525        let f = nat();
526        let a1 = Expr::BVar(0);
527        let a2 = Expr::BVar(1);
528        let result = mk_app(f.clone(), &[a1.clone(), a2.clone()]);
529        let (head, args) = get_app_fn_args(&result);
530        assert_eq!(head, &f);
531        assert_eq!(args.len(), 2);
532    }
533    #[test]
534    fn test_has_loose_bvars() {
535        assert!(has_loose_bvars(&Expr::BVar(0)));
536        assert!(!has_loose_bvars(&nat()));
537        assert!(!has_loose_bvars(&Expr::FVar(FVarId(1))));
538        let lam = Expr::Lam(
539            BinderInfo::Default,
540            Name::str("x"),
541            Box::new(nat()),
542            Box::new(Expr::BVar(0)),
543        );
544        assert!(!has_loose_bvars(&lam));
545        let lam2 = Expr::Lam(
546            BinderInfo::Default,
547            Name::str("x"),
548            Box::new(nat()),
549            Box::new(Expr::BVar(1)),
550        );
551        assert!(has_loose_bvars(&lam2));
552    }
553    #[test]
554    fn test_has_fvar() {
555        let id = FVarId(42);
556        let e = Expr::App(Box::new(Expr::FVar(id)), Box::new(Expr::FVar(FVarId(99))));
557        assert!(has_fvar(&e, id));
558        assert!(has_fvar(&e, FVarId(99)));
559        assert!(!has_fvar(&e, FVarId(1)));
560    }
561    #[test]
562    fn test_collect_fvars() {
563        let e = Expr::App(
564            Box::new(Expr::FVar(FVarId(1))),
565            Box::new(Expr::App(
566                Box::new(Expr::FVar(FVarId(2))),
567                Box::new(Expr::FVar(FVarId(1))),
568            )),
569        );
570        let fvars = collect_fvars(&e);
571        assert_eq!(fvars.len(), 2);
572        assert!(fvars.contains(&FVarId(1)));
573        assert!(fvars.contains(&FVarId(2)));
574    }
575    #[test]
576    fn test_for_each_expr() {
577        let e = Expr::App(Box::new(nat()), Box::new(Expr::BVar(0)));
578        let mut count = 0;
579        for_each_expr(&e, &mut |_, _| {
580            count += 1;
581            true
582        });
583        assert_eq!(count, 3);
584    }
585    #[test]
586    fn test_replace_expr() {
587        let e = Expr::App(Box::new(Expr::BVar(0)), Box::new(Expr::BVar(1)));
588        let result = replace_expr(&e, &mut |sub, _depth| {
589            if let Expr::BVar(0) = sub {
590                Some(nat())
591            } else {
592                None
593            }
594        });
595        match &result {
596            Expr::App(f, _) => assert_eq!(**f, nat()),
597            _ => panic!("Expected App"),
598        }
599    }
600    #[test]
601    fn test_lift_loose_bvars() {
602        let e = Expr::BVar(0);
603        let lifted = lift_loose_bvars(&e, 2, 0);
604        assert_eq!(lifted, Expr::BVar(2));
605        let lam = Expr::Lam(
606            BinderInfo::Default,
607            Name::str("x"),
608            Box::new(nat()),
609            Box::new(Expr::BVar(0)),
610        );
611        let lifted_lam = lift_loose_bvars(&lam, 1, 0);
612        if let Expr::Lam(_, _, _, body) = &lifted_lam {
613            assert_eq!(**body, Expr::BVar(0));
614        } else {
615            panic!("Expected Lam");
616        }
617    }
618    #[test]
619    fn test_count_lambdas_pis() {
620        let e = Expr::Lam(
621            BinderInfo::Default,
622            Name::str("x"),
623            Box::new(nat()),
624            Box::new(Expr::Lam(
625                BinderInfo::Default,
626                Name::str("y"),
627                Box::new(nat()),
628                Box::new(Expr::BVar(0)),
629            )),
630        );
631        assert_eq!(count_lambdas(&e), 2);
632        let pi = Expr::Pi(
633            BinderInfo::Default,
634            Name::str("x"),
635            Box::new(nat()),
636            Box::new(nat()),
637        );
638        assert_eq!(count_pis(&pi), 1);
639    }
640    #[test]
641    fn test_is_app_of() {
642        let e = Expr::App(
643            Box::new(Expr::Const(Name::str("f"), vec![])),
644            Box::new(Expr::BVar(0)),
645        );
646        assert!(is_app_of(&e, &Name::str("f")));
647        assert!(!is_app_of(&e, &Name::str("g")));
648    }
649    #[test]
650    fn test_mk_arrow() {
651        let arrow = mk_arrow(nat(), bool_ty());
652        assert!(arrow.is_pi());
653    }
654    #[test]
655    fn test_expr_weight() {
656        assert_eq!(expr_weight(&nat()), 1);
657        let app = Expr::App(Box::new(nat()), Box::new(Expr::BVar(0)));
658        assert_eq!(expr_weight(&app), 3);
659    }
660    #[test]
661    fn test_mk_app_range() {
662        let f = nat();
663        let args = vec![Expr::BVar(0), Expr::BVar(1), Expr::BVar(2)];
664        let result = mk_app_range(f.clone(), &args, 1, 3);
665        assert_eq!(get_app_num_args(&result), 2);
666    }
667    #[test]
668    fn test_occurs_const() {
669        let e = Expr::App(Box::new(nat()), Box::new(bool_ty()));
670        assert!(occurs_const(&e, &Name::str("Nat")));
671        assert!(occurs_const(&e, &Name::str("Bool")));
672        assert!(!occurs_const(&e, &Name::str("Int")));
673    }
674}
675/// Check if the expression is a `Sort`.
676#[inline]
677pub fn is_sort(e: &Expr) -> bool {
678    matches!(e, Expr::Sort(_))
679}
680/// Check if the expression is `Sort(Level::Zero)` (i.e. `Prop`).
681#[inline]
682pub fn is_prop(e: &Expr) -> bool {
683    matches!(e, Expr::Sort(l) if matches!(l, Level::Zero))
684}
685/// Check if the expression is `Sort(Level::Succ(Level::Zero))` (i.e. `Type 0`).
686#[inline]
687pub fn is_type0(e: &Expr) -> bool {
688    matches!(e, Expr::Sort(Level::Succ(inner)) if matches!(inner.as_ref(), Level::Zero))
689}
690/// Check if the expression is a lambda abstraction.
691#[inline]
692pub fn is_lambda(e: &Expr) -> bool {
693    matches!(e, Expr::Lam(_, _, _, _))
694}
695/// Check if the expression is a Pi type.
696#[inline]
697pub fn is_pi(e: &Expr) -> bool {
698    matches!(e, Expr::Pi(_, _, _, _))
699}
700/// Check if the expression is an FVar.
701#[inline]
702pub fn is_fvar(e: &Expr) -> bool {
703    matches!(e, Expr::FVar(_))
704}
705/// Check if the expression is a BVar.
706#[inline]
707pub fn is_bvar(e: &Expr) -> bool {
708    matches!(e, Expr::BVar(_))
709}
710/// Check if the expression is a Literal.
711#[inline]
712pub fn is_literal(e: &Expr) -> bool {
713    matches!(e, Expr::Lit(_))
714}
715/// Check if the expression is a Const.
716#[inline]
717pub fn is_const(e: &Expr) -> bool {
718    matches!(e, Expr::Const(_, _))
719}
720/// Check if the expression is an App.
721#[inline]
722pub fn is_app(e: &Expr) -> bool {
723    matches!(e, Expr::App(_, _))
724}
725/// Check if the expression is a Let.
726#[inline]
727pub fn is_let(e: &Expr) -> bool {
728    matches!(e, Expr::Let(_, _, _, _))
729}
730/// Check if the expression is a Proj.
731#[inline]
732pub fn is_proj(e: &Expr) -> bool {
733    matches!(e, Expr::Proj(_, _, _))
734}
735/// Extract the level from a Sort expression.
736#[inline]
737pub fn get_sort_level(e: &Expr) -> Option<&Level> {
738    if let Expr::Sort(l) = e {
739        Some(l)
740    } else {
741        None
742    }
743}
744/// Extract the name from a Const expression.
745#[inline]
746pub fn get_const_name(e: &Expr) -> Option<&Name> {
747    if let Expr::Const(n, _) = e {
748        Some(n)
749    } else {
750        None
751    }
752}
753/// Extract the universe levels from a Const expression.
754#[inline]
755pub fn get_const_levels(e: &Expr) -> Option<&[Level]> {
756    if let Expr::Const(_, ls) = e {
757        Some(ls)
758    } else {
759        None
760    }
761}
762/// Extract the FVarId from an FVar expression.
763#[inline]
764pub fn get_fvar_id(e: &Expr) -> Option<FVarId> {
765    if let Expr::FVar(id) = e {
766        Some(*id)
767    } else {
768        None
769    }
770}
771/// Extract the BVar index from a BVar expression.
772#[inline]
773pub fn get_bvar_idx(e: &Expr) -> Option<u32> {
774    if let Expr::BVar(i) = e {
775        Some(*i)
776    } else {
777        None
778    }
779}
780/// Decompose a Let expression into `(type, value, body)`.
781#[inline]
782pub fn decompose_let(e: &Expr) -> Option<(&Expr, &Expr, &Expr)> {
783    if let Expr::Let(_, ty, val, body) = e {
784        Some((ty, val, body))
785    } else {
786        None
787    }
788}
789/// Decompose a Pi expression into `(binder_info, domain, codomain)`.
790#[inline]
791pub fn decompose_pi(e: &Expr) -> Option<(crate::BinderInfo, &Expr, &Expr)> {
792    if let Expr::Pi(bi, _, dom, cod) = e {
793        Some((*bi, dom, cod))
794    } else {
795        None
796    }
797}
798/// Decompose a Lam expression into `(binder_info, domain, body)`.
799#[inline]
800pub fn decompose_lam(e: &Expr) -> Option<(crate::BinderInfo, &Expr, &Expr)> {
801    if let Expr::Lam(bi, _, dom, body) = e {
802        Some((*bi, dom, body))
803    } else {
804        None
805    }
806}
807/// Decompose a Proj expression into `(struct_name, field_index, value)`.
808#[inline]
809pub fn decompose_proj(e: &Expr) -> Option<(&Name, usize, &Expr)> {
810    if let Expr::Proj(n, idx, val) = e {
811        Some((n, *idx as usize, val))
812    } else {
813        None
814    }
815}
816/// Build a nested Pi type from a list of binders and a return type.
817///
818/// `mk_pi_n([(bi1, ty1), ..., (bin, tyn)], ret)` produces
819/// `Pi bi1 ty1 (Pi bi2 ty2 (... (Pi bin tyn ret) ...))`.
820pub fn mk_pi_n(binders: &[(crate::BinderInfo, Expr)], ret: Expr) -> Expr {
821    binders.iter().rev().fold(ret, |acc, (bi, ty)| {
822        Expr::Pi(
823            *bi,
824            crate::Name::Anonymous,
825            Box::new(ty.clone()),
826            Box::new(acc),
827        )
828    })
829}
830/// Build a nested Lam abstraction from a list of binders and a body.
831pub fn mk_lam_n(binders: &[(crate::BinderInfo, Expr)], body: Expr) -> Expr {
832    binders.iter().rev().fold(body, |acc, (bi, ty)| {
833        Expr::Lam(
834            *bi,
835            crate::Name::Anonymous,
836            Box::new(ty.clone()),
837            Box::new(acc),
838        )
839    })
840}
841/// Check if `e` is an application of FVar `id`.
842pub fn is_app_of_fvar(e: &Expr, id: FVarId) -> bool {
843    get_app_fn(e) == &Expr::FVar(id)
844}
845/// Get the `n`-th argument in an application chain (0-indexed).
846pub fn get_nth_arg(e: &Expr, n: usize) -> Option<&Expr> {
847    let args = get_app_args(e);
848    args.get(n).copied()
849}
850/// Check if an expression is "simple" (atomic: no subexpressions).
851pub fn is_simple(e: &Expr) -> bool {
852    matches!(
853        e,
854        Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_)
855    )
856}
857#[cfg(test)]
858mod extended_tests {
859    use super::*;
860    use crate::{BinderInfo, Level};
861    fn nat() -> Expr {
862        Expr::Const(Name::str("Nat"), vec![])
863    }
864    fn prop() -> Expr {
865        Expr::Sort(Level::Zero)
866    }
867    fn bv(i: u32) -> Expr {
868        Expr::BVar(i)
869    }
870    #[test]
871    fn test_is_prop() {
872        assert!(is_prop(&prop()));
873        assert!(!is_prop(&nat()));
874    }
875    #[test]
876    fn test_is_sort() {
877        assert!(is_sort(&prop()));
878        assert!(is_sort(&Expr::Sort(Level::Succ(Box::new(Level::Zero)))));
879        assert!(!is_sort(&nat()));
880    }
881    #[test]
882    fn test_is_lambda_pi() {
883        let lam = Expr::Lam(
884            BinderInfo::Default,
885            crate::Name::Anonymous,
886            Box::new(prop()),
887            Box::new(bv(0)),
888        );
889        let pi = Expr::Pi(
890            BinderInfo::Default,
891            crate::Name::Anonymous,
892            Box::new(prop()),
893            Box::new(bv(0)),
894        );
895        assert!(is_lambda(&lam));
896        assert!(!is_lambda(&pi));
897        assert!(is_pi(&pi));
898        assert!(!is_pi(&lam));
899    }
900    #[test]
901    fn test_is_fvar_bvar() {
902        use crate::FVarId;
903        assert!(is_fvar(&Expr::FVar(FVarId(0))));
904        assert!(is_bvar(&bv(0)));
905        assert!(!is_fvar(&nat()));
906    }
907    #[test]
908    fn test_get_sort_level() {
909        let s = Expr::Sort(Level::Zero);
910        assert_eq!(get_sort_level(&s), Some(&Level::Zero));
911        assert_eq!(get_sort_level(&nat()), None);
912    }
913    #[test]
914    fn test_get_const_name() {
915        assert_eq!(get_const_name(&nat()), Some(&Name::str("Nat")));
916        assert_eq!(get_const_name(&prop()), None);
917    }
918    #[test]
919    fn test_get_bvar_idx() {
920        assert_eq!(get_bvar_idx(&bv(3)), Some(3));
921        assert_eq!(get_bvar_idx(&nat()), None);
922    }
923    #[test]
924    fn test_decompose_let() {
925        let e = Expr::Let(
926            crate::Name::Anonymous,
927            Box::new(nat()),
928            Box::new(bv(0)),
929            Box::new(bv(0)),
930        );
931        let (ty, val, body) = decompose_let(&e).expect("value should be present");
932        assert_eq!(ty, &nat());
933        assert_eq!(val, &bv(0));
934        assert_eq!(body, &bv(0));
935    }
936    #[test]
937    fn test_decompose_pi() {
938        let e = Expr::Pi(
939            BinderInfo::Default,
940            crate::Name::Anonymous,
941            Box::new(nat()),
942            Box::new(prop()),
943        );
944        let (bi, dom, cod) = decompose_pi(&e).expect("value should be present");
945        assert_eq!(bi, BinderInfo::Default);
946        assert_eq!(dom, &nat());
947        assert_eq!(cod, &prop());
948    }
949    #[test]
950    fn test_decompose_lam() {
951        let e = Expr::Lam(
952            BinderInfo::Implicit,
953            crate::Name::Anonymous,
954            Box::new(nat()),
955            Box::new(bv(0)),
956        );
957        let (bi, dom, body) = decompose_lam(&e).expect("value should be present");
958        assert_eq!(bi, BinderInfo::Implicit);
959        assert_eq!(dom, &nat());
960        assert_eq!(body, &bv(0));
961    }
962    #[test]
963    fn test_mk_pi_n_empty() {
964        let ret = nat();
965        let result = mk_pi_n(&[], ret.clone());
966        assert_eq!(result, ret);
967    }
968    #[test]
969    fn test_mk_pi_n_two() {
970        let binders = vec![(BinderInfo::Default, nat()), (BinderInfo::Default, prop())];
971        let ret = bv(0);
972        let result = mk_pi_n(&binders, ret);
973        assert!(is_pi(&result));
974        let (_, _, inner) = decompose_pi(&result).expect("value should be present");
975        assert!(is_pi(inner));
976    }
977    #[test]
978    fn test_mk_lam_n_two() {
979        let binders = vec![(BinderInfo::Default, nat()), (BinderInfo::Implicit, prop())];
980        let result = mk_lam_n(&binders, bv(0));
981        assert!(is_lambda(&result));
982    }
983    #[test]
984    fn test_is_simple() {
985        assert!(is_simple(&nat()));
986        assert!(is_simple(&bv(0)));
987        assert!(is_simple(&prop()));
988        let app = Expr::App(Box::new(nat()), Box::new(bv(0)));
989        assert!(!is_simple(&app));
990    }
991    #[test]
992    fn test_get_nth_arg() {
993        let f = nat();
994        let arg0 = bv(0);
995        let arg1 = bv(1);
996        let app = Expr::App(
997            Box::new(Expr::App(Box::new(f), Box::new(arg0.clone()))),
998            Box::new(arg1.clone()),
999        );
1000        assert_eq!(get_nth_arg(&app, 0), Some(&arg0));
1001        assert_eq!(get_nth_arg(&app, 1), Some(&arg1));
1002        assert_eq!(get_nth_arg(&app, 2), None);
1003    }
1004    #[test]
1005    fn test_is_literal() {
1006        use crate::Literal;
1007        let lit = Expr::Lit(Literal::Nat(42));
1008        assert!(is_literal(&lit));
1009        assert!(!is_literal(&nat()));
1010    }
1011}
1012#[cfg(test)]
1013mod tests_padding_infra {
1014    use super::*;
1015    #[test]
1016    fn test_stat_summary() {
1017        let mut ss = StatSummary::new();
1018        ss.record(10.0);
1019        ss.record(20.0);
1020        ss.record(30.0);
1021        assert_eq!(ss.count(), 3);
1022        assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
1023        assert_eq!(ss.min().expect("min should succeed") as i64, 10);
1024        assert_eq!(ss.max().expect("max should succeed") as i64, 30);
1025    }
1026    #[test]
1027    fn test_transform_stat() {
1028        let mut ts = TransformStat::new();
1029        ts.record_before(100.0);
1030        ts.record_after(80.0);
1031        let ratio = ts.mean_ratio().expect("ratio should be present");
1032        assert!((ratio - 0.8).abs() < 1e-9);
1033    }
1034    #[test]
1035    fn test_small_map() {
1036        let mut m: SmallMap<u32, &str> = SmallMap::new();
1037        m.insert(3, "three");
1038        m.insert(1, "one");
1039        m.insert(2, "two");
1040        assert_eq!(m.get(&2), Some(&"two"));
1041        assert_eq!(m.len(), 3);
1042        let keys = m.keys();
1043        assert_eq!(*keys[0], 1);
1044        assert_eq!(*keys[2], 3);
1045    }
1046    #[test]
1047    fn test_label_set() {
1048        let mut ls = LabelSet::new();
1049        ls.add("foo");
1050        ls.add("bar");
1051        ls.add("foo");
1052        assert_eq!(ls.count(), 2);
1053        assert!(ls.has("bar"));
1054        assert!(!ls.has("baz"));
1055    }
1056    #[test]
1057    fn test_config_node() {
1058        let mut root = ConfigNode::section("root");
1059        let child = ConfigNode::leaf("key", "value");
1060        root.add_child(child);
1061        assert_eq!(root.num_children(), 1);
1062    }
1063    #[test]
1064    fn test_versioned_record() {
1065        let mut vr = VersionedRecord::new(0u32);
1066        vr.update(1);
1067        vr.update(2);
1068        assert_eq!(*vr.current(), 2);
1069        assert_eq!(vr.version(), 2);
1070        assert!(vr.has_history());
1071        assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
1072    }
1073    #[test]
1074    fn test_simple_dag() {
1075        let mut dag = SimpleDag::new(4);
1076        dag.add_edge(0, 1);
1077        dag.add_edge(1, 2);
1078        dag.add_edge(2, 3);
1079        assert!(dag.can_reach(0, 3));
1080        assert!(!dag.can_reach(3, 0));
1081        let order = dag.topological_sort().expect("order should be present");
1082        assert_eq!(order, vec![0, 1, 2, 3]);
1083    }
1084    #[test]
1085    fn test_focus_stack() {
1086        let mut fs: FocusStack<&str> = FocusStack::new();
1087        fs.focus("a");
1088        fs.focus("b");
1089        assert_eq!(fs.current(), Some(&"b"));
1090        assert_eq!(fs.depth(), 2);
1091        fs.blur();
1092        assert_eq!(fs.current(), Some(&"a"));
1093    }
1094}
1095#[cfg(test)]
1096mod tests_extra_iterators {
1097    use super::*;
1098    #[test]
1099    fn test_window_iterator() {
1100        let data = vec![1u32, 2, 3, 4, 5];
1101        let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
1102        assert_eq!(windows.len(), 3);
1103        assert_eq!(windows[0], &[1, 2, 3]);
1104        assert_eq!(windows[2], &[3, 4, 5]);
1105    }
1106    #[test]
1107    fn test_non_empty_vec() {
1108        let mut nev = NonEmptyVec::singleton(10u32);
1109        nev.push(20);
1110        nev.push(30);
1111        assert_eq!(nev.len(), 3);
1112        assert_eq!(*nev.first(), 10);
1113        assert_eq!(*nev.last(), 30);
1114    }
1115}
1116#[cfg(test)]
1117mod tests_padding2 {
1118    use super::*;
1119    #[test]
1120    fn test_sliding_sum() {
1121        let mut ss = SlidingSum::new(3);
1122        ss.push(1.0);
1123        ss.push(2.0);
1124        ss.push(3.0);
1125        assert!((ss.sum() - 6.0).abs() < 1e-9);
1126        ss.push(4.0);
1127        assert!((ss.sum() - 9.0).abs() < 1e-9);
1128        assert_eq!(ss.count(), 3);
1129    }
1130    #[test]
1131    fn test_path_buf() {
1132        let mut pb = PathBuf::new();
1133        pb.push("src");
1134        pb.push("main");
1135        assert_eq!(pb.as_str(), "src/main");
1136        assert_eq!(pb.depth(), 2);
1137        pb.pop();
1138        assert_eq!(pb.as_str(), "src");
1139    }
1140    #[test]
1141    fn test_string_pool() {
1142        let mut pool = StringPool::new();
1143        let s = pool.take();
1144        assert!(s.is_empty());
1145        pool.give("hello".to_string());
1146        let s2 = pool.take();
1147        assert!(s2.is_empty());
1148        assert_eq!(pool.free_count(), 0);
1149    }
1150    #[test]
1151    fn test_transitive_closure() {
1152        let mut tc = TransitiveClosure::new(4);
1153        tc.add_edge(0, 1);
1154        tc.add_edge(1, 2);
1155        tc.add_edge(2, 3);
1156        assert!(tc.can_reach(0, 3));
1157        assert!(!tc.can_reach(3, 0));
1158        let r = tc.reachable_from(0);
1159        assert_eq!(r.len(), 4);
1160    }
1161    #[test]
1162    fn test_token_bucket() {
1163        let mut tb = TokenBucket::new(100, 10);
1164        assert_eq!(tb.available(), 100);
1165        assert!(tb.try_consume(50));
1166        assert_eq!(tb.available(), 50);
1167        assert!(!tb.try_consume(60));
1168        assert_eq!(tb.capacity(), 100);
1169    }
1170    #[test]
1171    fn test_rewrite_rule_set() {
1172        let mut rrs = RewriteRuleSet::new();
1173        rrs.add(RewriteRule::unconditional(
1174            "beta",
1175            "App(Lam(x, b), v)",
1176            "b[x:=v]",
1177        ));
1178        rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
1179        assert_eq!(rrs.len(), 2);
1180        assert_eq!(rrs.unconditional_rules().len(), 1);
1181        assert_eq!(rrs.conditional_rules().len(), 1);
1182        assert!(rrs.get("beta").is_some());
1183        let disp = rrs
1184            .get("beta")
1185            .expect("element at \'beta\' should exist")
1186            .display();
1187        assert!(disp.contains("→"));
1188    }
1189}
1190#[cfg(test)]
1191mod tests_padding3 {
1192    use super::*;
1193    #[test]
1194    fn test_decision_node() {
1195        let tree = DecisionNode::Branch {
1196            key: "x".into(),
1197            val: "1".into(),
1198            yes_branch: Box::new(DecisionNode::Leaf("yes".into())),
1199            no_branch: Box::new(DecisionNode::Leaf("no".into())),
1200        };
1201        let mut ctx = std::collections::HashMap::new();
1202        ctx.insert("x".into(), "1".into());
1203        assert_eq!(tree.evaluate(&ctx), "yes");
1204        ctx.insert("x".into(), "2".into());
1205        assert_eq!(tree.evaluate(&ctx), "no");
1206        assert_eq!(tree.depth(), 1);
1207    }
1208    #[test]
1209    fn test_flat_substitution() {
1210        let mut sub = FlatSubstitution::new();
1211        sub.add("foo", "bar");
1212        sub.add("baz", "qux");
1213        assert_eq!(sub.apply("foo and baz"), "bar and qux");
1214        assert_eq!(sub.len(), 2);
1215    }
1216    #[test]
1217    fn test_stopwatch() {
1218        let mut sw = Stopwatch::start();
1219        sw.split();
1220        sw.split();
1221        assert_eq!(sw.num_splits(), 2);
1222        assert!(sw.elapsed_ms() >= 0.0);
1223        for &s in sw.splits() {
1224            assert!(s >= 0.0);
1225        }
1226    }
1227    #[test]
1228    fn test_either2() {
1229        let e: Either2<i32, &str> = Either2::First(42);
1230        assert!(e.is_first());
1231        let mapped = e.map_first(|x| x * 2);
1232        assert_eq!(mapped.first(), Some(84));
1233        let e2: Either2<i32, &str> = Either2::Second("hello");
1234        assert!(e2.is_second());
1235        assert_eq!(e2.second(), Some("hello"));
1236    }
1237    #[test]
1238    fn test_write_once() {
1239        let wo: WriteOnce<u32> = WriteOnce::new();
1240        assert!(!wo.is_written());
1241        assert!(wo.write(42));
1242        assert!(!wo.write(99));
1243        assert_eq!(wo.read(), Some(42));
1244    }
1245    #[test]
1246    fn test_sparse_vec() {
1247        let mut sv: SparseVec<i32> = SparseVec::new(100);
1248        sv.set(5, 10);
1249        sv.set(50, 20);
1250        assert_eq!(*sv.get(5), 10);
1251        assert_eq!(*sv.get(50), 20);
1252        assert_eq!(*sv.get(0), 0);
1253        assert_eq!(sv.nnz(), 2);
1254        sv.set(5, 0);
1255        assert_eq!(sv.nnz(), 1);
1256    }
1257    #[test]
1258    fn test_stack_calc() {
1259        let mut calc = StackCalc::new();
1260        calc.push(3);
1261        calc.push(4);
1262        calc.add();
1263        assert_eq!(calc.peek(), Some(7));
1264        calc.push(2);
1265        calc.mul();
1266        assert_eq!(calc.peek(), Some(14));
1267    }
1268}
1269#[cfg(test)]
1270mod tests_final_padding {
1271    use super::*;
1272    #[test]
1273    fn test_min_heap() {
1274        let mut h = MinHeap::new();
1275        h.push(5u32);
1276        h.push(1u32);
1277        h.push(3u32);
1278        assert_eq!(h.peek(), Some(&1));
1279        assert_eq!(h.pop(), Some(1));
1280        assert_eq!(h.pop(), Some(3));
1281        assert_eq!(h.pop(), Some(5));
1282        assert!(h.is_empty());
1283    }
1284    #[test]
1285    fn test_prefix_counter() {
1286        let mut pc = PrefixCounter::new();
1287        pc.record("hello");
1288        pc.record("help");
1289        pc.record("world");
1290        assert_eq!(pc.count_with_prefix("hel"), 2);
1291        assert_eq!(pc.count_with_prefix("wor"), 1);
1292        assert_eq!(pc.count_with_prefix("xyz"), 0);
1293    }
1294    #[test]
1295    fn test_fixture() {
1296        let mut f = Fixture::new();
1297        f.set("key1", "val1");
1298        f.set("key2", "val2");
1299        assert_eq!(f.get("key1"), Some("val1"));
1300        assert_eq!(f.get("key3"), None);
1301        assert_eq!(f.len(), 2);
1302    }
1303}