1use crate::{Expr, FVarId, Name};
6
7use super::types::{
8 AlphaCache, ConfigNode, DecisionNode, Either2, Fixture, FlatSubstitution, FocusStack, LabelSet,
9 MinHeap, NonEmptyVec, PathBuf, PrefixCounter, RewriteRule, RewriteRuleSet, SimpleDag,
10 SlidingSum, SmallMap, SparseVec, StackCalc, StatSummary, Stopwatch, StringPool, TokenBucket,
11 TransformStat, TransitiveClosure, VersionedRecord, WindowIterator, WriteOnce,
12};
13
14pub fn alpha_equiv(e1: &Expr, e2: &Expr) -> bool {
19 alpha_equiv_impl(e1, e2, &mut Vec::new(), &mut Vec::new())
20}
21pub(super) fn alpha_equiv_impl(
23 e1: &Expr,
24 e2: &Expr,
25 ctx1: &mut Vec<FVarId>,
26 ctx2: &mut Vec<FVarId>,
27) -> bool {
28 match (e1, e2) {
29 (Expr::BVar(i), Expr::BVar(j)) => i == j,
30 (Expr::FVar(f1), Expr::FVar(f2)) => {
31 match (
32 ctx1.iter().position(|f| f == f1),
33 ctx2.iter().position(|f| f == f2),
34 ) {
35 (Some(i), Some(j)) => i == j,
36 (None, None) => f1 == f2,
37 _ => false,
38 }
39 }
40 (Expr::Sort(l1), Expr::Sort(l2)) => l1 == l2,
41 (Expr::Const(n1, _), Expr::Const(n2, _)) => n1 == n2,
42 (Expr::App(f1, a1), Expr::App(f2, a2)) => {
43 alpha_equiv_impl(f1, f2, ctx1, ctx2) && alpha_equiv_impl(a1, a2, ctx1, ctx2)
44 }
45 (Expr::Lam(bi1, _n1, ty1, body1), Expr::Lam(bi2, _n2, ty2, body2)) => {
46 if bi1 != bi2 {
47 return false;
48 }
49 if !alpha_equiv_impl(ty1, ty2, ctx1, ctx2) {
50 return false;
51 }
52 let fvar1 = FVarId::new(ctx1.len() as u64);
53 let fvar2 = FVarId::new(ctx2.len() as u64);
54 ctx1.push(fvar1);
55 ctx2.push(fvar2);
56 let result = alpha_equiv_impl(body1, body2, ctx1, ctx2);
57 ctx1.pop();
58 ctx2.pop();
59 result
60 }
61 (Expr::Pi(bi1, _n1, ty1, body1), Expr::Pi(bi2, _n2, ty2, body2)) => {
62 if bi1 != bi2 {
63 return false;
64 }
65 if !alpha_equiv_impl(ty1, ty2, ctx1, ctx2) {
66 return false;
67 }
68 let fvar1 = FVarId::new(ctx1.len() as u64);
69 let fvar2 = FVarId::new(ctx2.len() as u64);
70 ctx1.push(fvar1);
71 ctx2.push(fvar2);
72 let result = alpha_equiv_impl(body1, body2, ctx1, ctx2);
73 ctx1.pop();
74 ctx2.pop();
75 result
76 }
77 (Expr::Let(_n1, ty1, val1, body1), Expr::Let(_n2, ty2, val2, body2)) => {
78 if !alpha_equiv_impl(ty1, ty2, ctx1, ctx2) {
79 return false;
80 }
81 if !alpha_equiv_impl(val1, val2, ctx1, ctx2) {
82 return false;
83 }
84 let fvar1 = FVarId::new(ctx1.len() as u64);
85 let fvar2 = FVarId::new(ctx2.len() as u64);
86 ctx1.push(fvar1);
87 ctx2.push(fvar2);
88 let result = alpha_equiv_impl(body1, body2, ctx1, ctx2);
89 ctx1.pop();
90 ctx2.pop();
91 result
92 }
93 (Expr::Proj(n1, i1, s1), Expr::Proj(n2, i2, s2)) => {
94 n1 == n2 && i1 == i2 && alpha_equiv_impl(s1, s2, ctx1, ctx2)
95 }
96 (Expr::Lit(l1), Expr::Lit(l2)) => l1 == l2,
97 _ => false,
98 }
99}
100pub fn canonicalize(expr: &Expr) -> Expr {
103 canonicalize_impl(expr, 0)
104}
105pub(super) fn canonicalize_impl(expr: &Expr, depth: u32) -> Expr {
106 match expr {
107 Expr::BVar(i) => Expr::BVar(*i),
108 Expr::FVar(f) => Expr::FVar(*f),
109 Expr::Sort(l) => Expr::Sort(l.clone()),
110 Expr::Const(n, ls) => Expr::Const(n.clone(), ls.clone()),
111 Expr::App(f, a) => Expr::App(
112 Box::new(canonicalize_impl(f, depth)),
113 Box::new(canonicalize_impl(a, depth)),
114 ),
115 Expr::Lam(bi, _n, ty, body) => {
116 let canonical_name = Name::str(format!("x{}", depth));
117 Expr::Lam(
118 *bi,
119 canonical_name,
120 Box::new(canonicalize_impl(ty, depth)),
121 Box::new(canonicalize_impl(body, depth + 1)),
122 )
123 }
124 Expr::Pi(bi, _n, ty, body) => {
125 let canonical_name = Name::str(format!("x{}", depth));
126 Expr::Pi(
127 *bi,
128 canonical_name,
129 Box::new(canonicalize_impl(ty, depth)),
130 Box::new(canonicalize_impl(body, depth + 1)),
131 )
132 }
133 Expr::Let(_n, ty, val, body) => {
134 let canonical_name = Name::str(format!("x{}", depth));
135 Expr::Let(
136 canonical_name,
137 Box::new(canonicalize_impl(ty, depth)),
138 Box::new(canonicalize_impl(val, depth)),
139 Box::new(canonicalize_impl(body, depth + 1)),
140 )
141 }
142 Expr::Proj(n, i, s) => Expr::Proj(n.clone(), *i, Box::new(canonicalize_impl(s, depth))),
143 Expr::Lit(l) => Expr::Lit(l.clone()),
144 }
145}
146#[cfg(test)]
147mod tests {
148 use super::*;
149 use crate::{BinderInfo, Level, Literal};
150 #[test]
151 fn test_alpha_equiv_bvar() {
152 let e1 = Expr::BVar(0);
153 let e2 = Expr::BVar(0);
154 assert!(alpha_equiv(&e1, &e2));
155 let e3 = Expr::BVar(1);
156 assert!(!alpha_equiv(&e1, &e3));
157 }
158 #[test]
159 fn test_alpha_equiv_sort() {
160 let e1 = Expr::Sort(Level::zero());
161 let e2 = Expr::Sort(Level::zero());
162 assert!(alpha_equiv(&e1, &e2));
163 }
164 #[test]
165 fn test_alpha_equiv_const() {
166 let e1 = Expr::Const(Name::str("Nat"), vec![]);
167 let e2 = Expr::Const(Name::str("Nat"), vec![]);
168 assert!(alpha_equiv(&e1, &e2));
169 let e3 = Expr::Const(Name::str("Bool"), vec![]);
170 assert!(!alpha_equiv(&e1, &e3));
171 }
172 #[test]
173 fn test_alpha_equiv_app() {
174 let f = Expr::Const(Name::str("f"), vec![]);
175 let a = Expr::Lit(Literal::Nat(42));
176 let e1 = Expr::App(Box::new(f.clone()), Box::new(a.clone()));
177 let e2 = Expr::App(Box::new(f), Box::new(a));
178 assert!(alpha_equiv(&e1, &e2));
179 }
180 #[test]
181 fn test_alpha_equiv_lambda() {
182 let nat = Expr::Const(Name::str("Nat"), vec![]);
183 let e1 = Expr::Lam(
184 BinderInfo::Default,
185 Name::str("x"),
186 Box::new(nat.clone()),
187 Box::new(Expr::BVar(0)),
188 );
189 let e2 = Expr::Lam(
190 BinderInfo::Default,
191 Name::str("y"),
192 Box::new(nat),
193 Box::new(Expr::BVar(0)),
194 );
195 assert!(alpha_equiv(&e1, &e2));
196 }
197 #[test]
198 fn test_canonicalize() {
199 let nat = Expr::Const(Name::str("Nat"), vec![]);
200 let e1 = Expr::Lam(
201 BinderInfo::Default,
202 Name::str("different_name"),
203 Box::new(nat.clone()),
204 Box::new(Expr::BVar(0)),
205 );
206 let e2 = Expr::Lam(
207 BinderInfo::Default,
208 Name::str("another_name"),
209 Box::new(nat),
210 Box::new(Expr::BVar(0)),
211 );
212 let c1 = canonicalize(&e1);
213 let c2 = canonicalize(&e2);
214 assert_eq!(c1, c2);
215 }
216}
217pub fn alpha_equiv_mod_levels(e1: &Expr, e2: &Expr) -> bool {
221 alpha_equiv_mod_levels_impl(e1, e2, &mut Vec::new(), &mut Vec::new())
222}
223pub(super) fn alpha_equiv_mod_levels_impl(
224 e1: &Expr,
225 e2: &Expr,
226 ctx1: &mut Vec<FVarId>,
227 ctx2: &mut Vec<FVarId>,
228) -> bool {
229 match (e1, e2) {
230 (Expr::BVar(i), Expr::BVar(j)) => i == j,
231 (Expr::FVar(f1), Expr::FVar(f2)) => {
232 match (
233 ctx1.iter().position(|f| f == f1),
234 ctx2.iter().position(|f| f == f2),
235 ) {
236 (Some(i), Some(j)) => i == j,
237 (None, None) => f1 == f2,
238 _ => false,
239 }
240 }
241 (Expr::Sort(l1), Expr::Sort(l2)) => l1 == l2,
242 (Expr::Const(n1, _), Expr::Const(n2, _)) => n1 == n2,
243 (Expr::App(f1, a1), Expr::App(f2, a2)) => {
244 alpha_equiv_mod_levels_impl(f1, f2, ctx1, ctx2)
245 && alpha_equiv_mod_levels_impl(a1, a2, ctx1, ctx2)
246 }
247 (Expr::Lam(bi1, _n1, ty1, body1), Expr::Lam(bi2, _n2, ty2, body2)) => {
248 if bi1 != bi2 {
249 return false;
250 }
251 if !alpha_equiv_mod_levels_impl(ty1, ty2, ctx1, ctx2) {
252 return false;
253 }
254 let fvar1 = FVarId::new(ctx1.len() as u64);
255 let fvar2 = FVarId::new(ctx2.len() as u64);
256 ctx1.push(fvar1);
257 ctx2.push(fvar2);
258 let result = alpha_equiv_mod_levels_impl(body1, body2, ctx1, ctx2);
259 ctx1.pop();
260 ctx2.pop();
261 result
262 }
263 (Expr::Pi(bi1, _n1, ty1, body1), Expr::Pi(bi2, _n2, ty2, body2)) => {
264 if bi1 != bi2 {
265 return false;
266 }
267 if !alpha_equiv_mod_levels_impl(ty1, ty2, ctx1, ctx2) {
268 return false;
269 }
270 let fvar1 = FVarId::new(ctx1.len() as u64);
271 let fvar2 = FVarId::new(ctx2.len() as u64);
272 ctx1.push(fvar1);
273 ctx2.push(fvar2);
274 let result = alpha_equiv_mod_levels_impl(body1, body2, ctx1, ctx2);
275 ctx1.pop();
276 ctx2.pop();
277 result
278 }
279 (Expr::Let(_n1, ty1, val1, body1), Expr::Let(_n2, ty2, val2, body2)) => {
280 if !alpha_equiv_mod_levels_impl(ty1, ty2, ctx1, ctx2) {
281 return false;
282 }
283 if !alpha_equiv_mod_levels_impl(val1, val2, ctx1, ctx2) {
284 return false;
285 }
286 let fvar1 = FVarId::new(ctx1.len() as u64);
287 let fvar2 = FVarId::new(ctx2.len() as u64);
288 ctx1.push(fvar1);
289 ctx2.push(fvar2);
290 let result = alpha_equiv_mod_levels_impl(body1, body2, ctx1, ctx2);
291 ctx1.pop();
292 ctx2.pop();
293 result
294 }
295 (Expr::Proj(n1, i1, s1), Expr::Proj(n2, i2, s2)) => {
296 n1 == n2 && i1 == i2 && alpha_equiv_mod_levels_impl(s1, s2, ctx1, ctx2)
297 }
298 (Expr::Lit(l1), Expr::Lit(l2)) => l1 == l2,
299 _ => false,
300 }
301}
302pub fn alpha_class_rep(expr: &Expr) -> Expr {
307 canonicalize(expr)
308}
309pub fn all_alpha_equiv(exprs: &[Expr]) -> bool {
311 if exprs.len() <= 1 {
312 return true;
313 }
314 let first = &exprs[0];
315 exprs[1..].iter().all(|e| alpha_equiv(first, e))
316}
317pub fn find_non_equiv_pair(exprs: &[Expr]) -> Option<(usize, usize)> {
321 for i in 0..exprs.len() {
322 for j in (i + 1)..exprs.len() {
323 if !alpha_equiv(&exprs[i], &exprs[j]) {
324 return Some((i, j));
325 }
326 }
327 }
328 None
329}
330pub fn alpha_hash(expr: &Expr) -> u64 {
335 alpha_hash_impl(expr, 0)
336}
337#[allow(clippy::only_used_in_recursion)]
338pub(super) fn alpha_hash_impl(expr: &Expr, depth: u32) -> u64 {
339 use std::collections::hash_map::DefaultHasher;
340 use std::hash::{Hash, Hasher};
341 let mut h = DefaultHasher::new();
342 match expr {
343 Expr::BVar(i) => {
344 0u8.hash(&mut h);
345 i.hash(&mut h);
346 }
347 Expr::FVar(id) => {
348 1u8.hash(&mut h);
349 id.0.hash(&mut h);
350 }
351 Expr::Sort(l) => {
352 2u8.hash(&mut h);
353 format!("{:?}", l).hash(&mut h);
354 }
355 Expr::Const(n, _) => {
356 3u8.hash(&mut h);
357 format!("{}", n).hash(&mut h);
358 }
359 Expr::App(f, a) => {
360 4u8.hash(&mut h);
361 alpha_hash_impl(f, depth).hash(&mut h);
362 alpha_hash_impl(a, depth).hash(&mut h);
363 }
364 Expr::Lam(bi, _, ty, body) => {
365 5u8.hash(&mut h);
366 format!("{:?}", bi).hash(&mut h);
367 alpha_hash_impl(ty, depth).hash(&mut h);
368 alpha_hash_impl(body, depth + 1).hash(&mut h);
369 }
370 Expr::Pi(bi, _, ty, body) => {
371 6u8.hash(&mut h);
372 format!("{:?}", bi).hash(&mut h);
373 alpha_hash_impl(ty, depth).hash(&mut h);
374 alpha_hash_impl(body, depth + 1).hash(&mut h);
375 }
376 Expr::Let(_, ty, val, body) => {
377 7u8.hash(&mut h);
378 alpha_hash_impl(ty, depth).hash(&mut h);
379 alpha_hash_impl(val, depth).hash(&mut h);
380 alpha_hash_impl(body, depth + 1).hash(&mut h);
381 }
382 Expr::Proj(n, i, s) => {
383 8u8.hash(&mut h);
384 format!("{}", n).hash(&mut h);
385 i.hash(&mut h);
386 alpha_hash_impl(s, depth).hash(&mut h);
387 }
388 Expr::Lit(l) => {
389 9u8.hash(&mut h);
390 format!("{:?}", l).hash(&mut h);
391 }
392 }
393 h.finish()
394}
395#[cfg(test)]
396mod alpha_extended_tests {
397 use super::*;
398 use crate::{BinderInfo, Level, Literal};
399 fn nat() -> Expr {
400 Expr::Const(Name::str("Nat"), vec![])
401 }
402 #[test]
403 fn test_alpha_equiv_mod_levels() {
404 let e1 = Expr::Const(Name::str("f"), vec![Level::zero()]);
405 let e2 = Expr::Const(Name::str("f"), vec![Level::succ(Level::zero())]);
406 assert!(alpha_equiv_mod_levels(&e1, &e2));
407 assert!(alpha_equiv(&e1, &e2));
408 let e3 = Expr::Const(Name::str("g"), vec![Level::zero()]);
409 assert!(!alpha_equiv(&e1, &e3));
410 }
411 #[test]
412 fn test_all_alpha_equiv_empty() {
413 assert!(all_alpha_equiv(&[]));
414 }
415 #[test]
416 fn test_all_alpha_equiv_single() {
417 assert!(all_alpha_equiv(&[nat()]));
418 }
419 #[test]
420 fn test_all_alpha_equiv_same() {
421 let exprs = vec![nat(), nat(), nat()];
422 assert!(all_alpha_equiv(&exprs));
423 }
424 #[test]
425 fn test_all_alpha_equiv_different() {
426 let exprs = vec![nat(), Expr::Const(Name::str("Bool"), vec![])];
427 assert!(!all_alpha_equiv(&exprs));
428 }
429 #[test]
430 fn test_find_non_equiv_pair() {
431 let exprs = vec![nat(), nat(), Expr::Sort(Level::zero())];
432 let pair = find_non_equiv_pair(&exprs);
433 assert!(pair.is_some());
434 let (i, j) = pair.expect("pair should be valid");
435 assert!(i < j);
436 }
437 #[test]
438 fn test_find_non_equiv_pair_all_equiv() {
439 let lam1 = Expr::Lam(
440 BinderInfo::Default,
441 Name::str("x"),
442 Box::new(nat()),
443 Box::new(Expr::BVar(0)),
444 );
445 let lam2 = Expr::Lam(
446 BinderInfo::Default,
447 Name::str("y"),
448 Box::new(nat()),
449 Box::new(Expr::BVar(0)),
450 );
451 assert!(find_non_equiv_pair(&[lam1, lam2]).is_none());
452 }
453 #[test]
454 fn test_alpha_hash_same_expr() {
455 let h1 = alpha_hash(&nat());
456 let h2 = alpha_hash(&nat());
457 assert_eq!(h1, h2);
458 }
459 #[test]
460 fn test_alpha_hash_alpha_equiv() {
461 let lam1 = Expr::Lam(
462 BinderInfo::Default,
463 Name::str("x"),
464 Box::new(nat()),
465 Box::new(Expr::BVar(0)),
466 );
467 let lam2 = Expr::Lam(
468 BinderInfo::Default,
469 Name::str("y"),
470 Box::new(nat()),
471 Box::new(Expr::BVar(0)),
472 );
473 assert_eq!(alpha_hash(&lam1), alpha_hash(&lam2));
474 }
475 #[test]
476 fn test_alpha_cache_basic() {
477 let mut cache = AlphaCache::new();
478 let e1 = nat();
479 let _e2 = Expr::Const(Name::str("Bool"), vec![]);
480 assert!(cache.query(&e1, &e1).is_none());
481 let result = cache.alpha_equiv_cached(&e1, &e1);
482 assert!(result);
483 assert_eq!(cache.num_equiv(), 1);
484 }
485 #[test]
486 fn test_alpha_cache_non_equiv() {
487 let mut cache = AlphaCache::new();
488 let e1 = nat();
489 let e2 = Expr::Const(Name::str("Bool"), vec![]);
490 let result = cache.alpha_equiv_cached(&e1, &e2);
491 assert!(!result);
492 assert_eq!(cache.num_non_equiv(), 1);
493 let result2 = cache.alpha_equiv_cached(&e1, &e2);
494 assert!(!result2);
495 }
496 #[test]
497 fn test_alpha_cache_clear() {
498 let mut cache = AlphaCache::new();
499 cache.alpha_equiv_cached(&nat(), &nat());
500 assert_eq!(cache.num_equiv(), 1);
501 cache.clear();
502 assert_eq!(cache.num_equiv(), 0);
503 assert_eq!(cache.num_non_equiv(), 0);
504 }
505 #[test]
506 fn test_alpha_class_rep() {
507 let e = Expr::Lam(
508 BinderInfo::Default,
509 Name::str("uniqueName"),
510 Box::new(nat()),
511 Box::new(Expr::BVar(0)),
512 );
513 let rep = alpha_class_rep(&e);
514 if let Expr::Lam(_, name, _, _) = &rep {
515 assert!(name.to_string().starts_with('x'));
516 }
517 }
518 #[test]
519 fn test_alpha_hash_lit() {
520 let h1 = alpha_hash(&Expr::Lit(Literal::Nat(42)));
521 let h2 = alpha_hash(&Expr::Lit(Literal::Nat(42)));
522 let h3 = alpha_hash(&Expr::Lit(Literal::Nat(43)));
523 assert_eq!(h1, h2);
524 assert_ne!(h1, h3);
525 }
526}
527pub fn rename_bvar(expr: &Expr, from_idx: u32, to_idx: u32) -> Expr {
532 rename_bvar_impl(expr, from_idx, to_idx, 0)
533}
534pub(super) fn rename_bvar_impl(expr: &Expr, from: u32, to: u32, depth: u32) -> Expr {
535 match expr {
536 Expr::BVar(i) => {
537 if *i == from + depth {
538 Expr::BVar(to + depth)
539 } else {
540 Expr::BVar(*i)
541 }
542 }
543 Expr::App(f, a) => Expr::App(
544 Box::new(rename_bvar_impl(f, from, to, depth)),
545 Box::new(rename_bvar_impl(a, from, to, depth)),
546 ),
547 Expr::Lam(bi, n, ty, body) => Expr::Lam(
548 *bi,
549 n.clone(),
550 Box::new(rename_bvar_impl(ty, from, to, depth)),
551 Box::new(rename_bvar_impl(body, from, to, depth + 1)),
552 ),
553 Expr::Pi(bi, n, ty, body) => Expr::Pi(
554 *bi,
555 n.clone(),
556 Box::new(rename_bvar_impl(ty, from, to, depth)),
557 Box::new(rename_bvar_impl(body, from, to, depth + 1)),
558 ),
559 Expr::Let(n, ty, val, body) => Expr::Let(
560 n.clone(),
561 Box::new(rename_bvar_impl(ty, from, to, depth)),
562 Box::new(rename_bvar_impl(val, from, to, depth)),
563 Box::new(rename_bvar_impl(body, from, to, depth + 1)),
564 ),
565 Expr::Proj(n, i, s) => Expr::Proj(
566 n.clone(),
567 *i,
568 Box::new(rename_bvar_impl(s, from, to, depth)),
569 ),
570 e => e.clone(),
571 }
572}
573pub fn swap_bvars(expr: &Expr, i: u32, j: u32) -> Expr {
577 swap_bvars_impl(expr, i, j, 0)
578}
579pub(super) fn swap_bvars_impl(expr: &Expr, i: u32, j: u32, depth: u32) -> Expr {
580 match expr {
581 Expr::BVar(k) => {
582 let adjusted_i = i + depth;
583 let adjusted_j = j + depth;
584 if *k == adjusted_i {
585 Expr::BVar(adjusted_j)
586 } else if *k == adjusted_j {
587 Expr::BVar(adjusted_i)
588 } else {
589 Expr::BVar(*k)
590 }
591 }
592 Expr::App(f, a) => Expr::App(
593 Box::new(swap_bvars_impl(f, i, j, depth)),
594 Box::new(swap_bvars_impl(a, i, j, depth)),
595 ),
596 Expr::Lam(bi, n, ty, body) => Expr::Lam(
597 *bi,
598 n.clone(),
599 Box::new(swap_bvars_impl(ty, i, j, depth)),
600 Box::new(swap_bvars_impl(body, i, j, depth + 1)),
601 ),
602 Expr::Pi(bi, n, ty, body) => Expr::Pi(
603 *bi,
604 n.clone(),
605 Box::new(swap_bvars_impl(ty, i, j, depth)),
606 Box::new(swap_bvars_impl(body, i, j, depth + 1)),
607 ),
608 Expr::Let(n, ty, val, body) => Expr::Let(
609 n.clone(),
610 Box::new(swap_bvars_impl(ty, i, j, depth)),
611 Box::new(swap_bvars_impl(val, i, j, depth)),
612 Box::new(swap_bvars_impl(body, i, j, depth + 1)),
613 ),
614 Expr::Proj(n, k, s) => Expr::Proj(n.clone(), *k, Box::new(swap_bvars_impl(s, i, j, depth))),
615 e => e.clone(),
616 }
617}
618#[cfg(test)]
619mod rename_tests {
620 use super::*;
621 #[allow(dead_code)]
622 fn nat() -> Expr {
623 Expr::Const(Name::str("Nat"), vec![])
624 }
625 #[test]
626 fn test_rename_bvar_basic() {
627 let e = Expr::BVar(0);
628 let result = rename_bvar(&e, 0, 1);
629 assert_eq!(result, Expr::BVar(1));
630 }
631 #[test]
632 fn test_rename_bvar_no_match() {
633 let e = Expr::BVar(2);
634 let result = rename_bvar(&e, 0, 1);
635 assert_eq!(result, Expr::BVar(2));
636 }
637 #[test]
638 fn test_rename_bvar_in_app() {
639 let e = Expr::App(Box::new(Expr::BVar(0)), Box::new(Expr::BVar(0)));
640 let result = rename_bvar(&e, 0, 5);
641 if let Expr::App(f, a) = result {
642 assert_eq!(*f, Expr::BVar(5));
643 assert_eq!(*a, Expr::BVar(5));
644 }
645 }
646 #[test]
647 fn test_swap_bvars() {
648 let e = Expr::App(Box::new(Expr::BVar(0)), Box::new(Expr::BVar(1)));
649 let result = swap_bvars(&e, 0, 1);
650 if let Expr::App(f, a) = result {
651 assert_eq!(*f, Expr::BVar(1));
652 assert_eq!(*a, Expr::BVar(0));
653 }
654 }
655 #[test]
656 fn test_swap_same_idx_noop() {
657 let e = Expr::BVar(3);
658 let result = swap_bvars(&e, 3, 3);
659 assert_eq!(result, Expr::BVar(3));
660 }
661}
662pub fn shift(expr: &Expr, amount: i32, cutoff: u32) -> Expr {
667 shift_impl(expr, amount, cutoff)
668}
669pub(super) fn shift_impl(expr: &Expr, amount: i32, cutoff: u32) -> Expr {
670 match expr {
671 Expr::BVar(i) => {
672 if *i >= cutoff {
673 let new_i = (*i as i32 + amount).max(0) as u32;
674 Expr::BVar(new_i)
675 } else {
676 Expr::BVar(*i)
677 }
678 }
679 Expr::FVar(f) => Expr::FVar(*f),
680 Expr::Sort(l) => Expr::Sort(l.clone()),
681 Expr::Const(n, ls) => Expr::Const(n.clone(), ls.clone()),
682 Expr::App(f, a) => Expr::App(
683 Box::new(shift_impl(f, amount, cutoff)),
684 Box::new(shift_impl(a, amount, cutoff)),
685 ),
686 Expr::Lam(bi, n, ty, body) => Expr::Lam(
687 *bi,
688 n.clone(),
689 Box::new(shift_impl(ty, amount, cutoff)),
690 Box::new(shift_impl(body, amount, cutoff + 1)),
691 ),
692 Expr::Pi(bi, n, ty, body) => Expr::Pi(
693 *bi,
694 n.clone(),
695 Box::new(shift_impl(ty, amount, cutoff)),
696 Box::new(shift_impl(body, amount, cutoff + 1)),
697 ),
698 Expr::Let(n, ty, val, body) => Expr::Let(
699 n.clone(),
700 Box::new(shift_impl(ty, amount, cutoff)),
701 Box::new(shift_impl(val, amount, cutoff)),
702 Box::new(shift_impl(body, amount, cutoff + 1)),
703 ),
704 Expr::Proj(n, i, s) => Expr::Proj(n.clone(), *i, Box::new(shift_impl(s, amount, cutoff))),
705 Expr::Lit(l) => Expr::Lit(l.clone()),
706 }
707}
708pub fn lift(expr: &Expr) -> Expr {
710 shift(expr, 1, 0)
711}
712pub fn lower(expr: &Expr) -> Expr {
714 shift(expr, -1, 0)
715}
716pub fn structurally_equal(e1: &Expr, e2: &Expr) -> bool {
721 alpha_equiv(e1, e2)
722}
723pub fn alpha_subst(body: &Expr, replacement: &Expr) -> Expr {
728 alpha_subst_impl(body, replacement, 0)
729}
730pub(super) fn alpha_subst_impl(body: &Expr, replacement: &Expr, depth: u32) -> Expr {
731 match body {
732 Expr::BVar(i) => {
733 if *i == depth {
734 shift(replacement, depth as i32, 0)
735 } else if *i > depth {
736 Expr::BVar(i - 1)
737 } else {
738 Expr::BVar(*i)
739 }
740 }
741 Expr::App(f, a) => Expr::App(
742 Box::new(alpha_subst_impl(f, replacement, depth)),
743 Box::new(alpha_subst_impl(a, replacement, depth)),
744 ),
745 Expr::Lam(bi, n, ty, b) => Expr::Lam(
746 *bi,
747 n.clone(),
748 Box::new(alpha_subst_impl(ty, replacement, depth)),
749 Box::new(alpha_subst_impl(b, replacement, depth + 1)),
750 ),
751 Expr::Pi(bi, n, ty, b) => Expr::Pi(
752 *bi,
753 n.clone(),
754 Box::new(alpha_subst_impl(ty, replacement, depth)),
755 Box::new(alpha_subst_impl(b, replacement, depth + 1)),
756 ),
757 Expr::Let(n, ty, val, b) => Expr::Let(
758 n.clone(),
759 Box::new(alpha_subst_impl(ty, replacement, depth)),
760 Box::new(alpha_subst_impl(val, replacement, depth)),
761 Box::new(alpha_subst_impl(b, replacement, depth + 1)),
762 ),
763 Expr::Proj(n, i, s) => Expr::Proj(
764 n.clone(),
765 *i,
766 Box::new(alpha_subst_impl(s, replacement, depth)),
767 ),
768 e => e.clone(),
769 }
770}
771pub fn fvar_occurs(expr: &Expr, id: FVarId) -> bool {
773 match expr {
774 Expr::FVar(f) => *f == id,
775 Expr::App(f, a) => fvar_occurs(f, id) || fvar_occurs(a, id),
776 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
777 fvar_occurs(ty, id) || fvar_occurs(body, id)
778 }
779 Expr::Let(_, ty, val, body) => {
780 fvar_occurs(ty, id) || fvar_occurs(val, id) || fvar_occurs(body, id)
781 }
782 Expr::Proj(_, _, s) => fvar_occurs(s, id),
783 _ => false,
784 }
785}
786pub fn free_fvars(expr: &Expr) -> std::collections::HashSet<FVarId> {
788 let mut set = std::collections::HashSet::new();
789 free_fvars_impl(expr, &mut set);
790 set
791}
792pub(super) fn free_fvars_impl(expr: &Expr, acc: &mut std::collections::HashSet<FVarId>) {
793 match expr {
794 Expr::FVar(f) => {
795 acc.insert(*f);
796 }
797 Expr::App(f, a) => {
798 free_fvars_impl(f, acc);
799 free_fvars_impl(a, acc);
800 }
801 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
802 free_fvars_impl(ty, acc);
803 free_fvars_impl(body, acc);
804 }
805 Expr::Let(_, ty, val, body) => {
806 free_fvars_impl(ty, acc);
807 free_fvars_impl(val, acc);
808 free_fvars_impl(body, acc);
809 }
810 Expr::Proj(_, _, s) => free_fvars_impl(s, acc),
811 _ => {}
812 }
813}
814pub fn count_bvar0_occurrences(expr: &Expr) -> usize {
816 count_bvar0_impl(expr, 0)
817}
818pub(super) fn count_bvar0_impl(expr: &Expr, depth: u32) -> usize {
819 match expr {
820 Expr::BVar(i) if *i == depth => 1,
821 Expr::BVar(_) => 0,
822 Expr::App(f, a) => count_bvar0_impl(f, depth) + count_bvar0_impl(a, depth),
823 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
824 count_bvar0_impl(ty, depth) + count_bvar0_impl(body, depth + 1)
825 }
826 Expr::Let(_, ty, val, body) => {
827 count_bvar0_impl(ty, depth)
828 + count_bvar0_impl(val, depth)
829 + count_bvar0_impl(body, depth + 1)
830 }
831 Expr::Proj(_, _, s) => count_bvar0_impl(s, depth),
832 _ => 0,
833 }
834}
835pub fn bvar0_free(body: &Expr) -> bool {
839 count_bvar0_occurrences(body) == 0
840}
841pub fn alpha_equiv_under_subst(
846 e1: &Expr,
847 e2: &Expr,
848 subst: &std::collections::HashMap<FVarId, Expr>,
849) -> bool {
850 let e1_inst = apply_fvar_subst(e1, subst);
851 alpha_equiv(&e1_inst, e2)
852}
853pub fn apply_fvar_subst(expr: &Expr, subst: &std::collections::HashMap<FVarId, Expr>) -> Expr {
855 match expr {
856 Expr::FVar(id) => subst.get(id).cloned().unwrap_or_else(|| expr.clone()),
857 Expr::App(f, a) => Expr::App(
858 Box::new(apply_fvar_subst(f, subst)),
859 Box::new(apply_fvar_subst(a, subst)),
860 ),
861 Expr::Lam(bi, n, ty, body) => Expr::Lam(
862 *bi,
863 n.clone(),
864 Box::new(apply_fvar_subst(ty, subst)),
865 Box::new(apply_fvar_subst(body, subst)),
866 ),
867 Expr::Pi(bi, n, ty, body) => Expr::Pi(
868 *bi,
869 n.clone(),
870 Box::new(apply_fvar_subst(ty, subst)),
871 Box::new(apply_fvar_subst(body, subst)),
872 ),
873 Expr::Let(n, ty, val, body) => Expr::Let(
874 n.clone(),
875 Box::new(apply_fvar_subst(ty, subst)),
876 Box::new(apply_fvar_subst(val, subst)),
877 Box::new(apply_fvar_subst(body, subst)),
878 ),
879 Expr::Proj(n, i, s) => Expr::Proj(n.clone(), *i, Box::new(apply_fvar_subst(s, subst))),
880 e => e.clone(),
881 }
882}
883#[cfg(test)]
884mod shift_subst_tests {
885 use super::*;
886 use crate::BinderInfo;
887 use std::collections::HashMap;
888 fn nat() -> Expr {
889 Expr::Const(Name::str("Nat"), vec![])
890 }
891 #[test]
892 fn test_shift_bvar_above_cutoff() {
893 let e = Expr::BVar(1);
894 let shifted = shift(&e, 2, 0);
895 assert_eq!(shifted, Expr::BVar(3));
896 }
897 #[test]
898 fn test_shift_bvar_below_cutoff() {
899 let e = Expr::BVar(0);
900 let shifted = shift(&e, 5, 1);
901 assert_eq!(shifted, Expr::BVar(0));
902 }
903 #[test]
904 fn test_lift_basic() {
905 let e = Expr::BVar(0);
906 assert_eq!(lift(&e), Expr::BVar(1));
907 }
908 #[test]
909 fn test_lower_basic() {
910 let e = Expr::BVar(1);
911 assert_eq!(lower(&e), Expr::BVar(0));
912 }
913 #[test]
914 fn test_alpha_subst_simple() {
915 let body = Expr::BVar(0);
916 let result = alpha_subst(&body, &nat());
917 assert_eq!(result, nat());
918 }
919 #[test]
920 fn test_alpha_subst_no_occurrence() {
921 let body = Expr::BVar(1);
922 let result = alpha_subst(&body, &nat());
923 assert_eq!(result, Expr::BVar(0));
924 }
925 #[test]
926 fn test_fvar_occurs_true() {
927 let id = FVarId(42);
928 let e = Expr::FVar(id);
929 assert!(fvar_occurs(&e, id));
930 }
931 #[test]
932 fn test_fvar_occurs_false() {
933 let e = Expr::FVar(FVarId(1));
934 assert!(!fvar_occurs(&e, FVarId(2)));
935 }
936 #[test]
937 fn test_free_fvars_collects_all() {
938 let e = Expr::App(
939 Box::new(Expr::FVar(FVarId(1))),
940 Box::new(Expr::FVar(FVarId(2))),
941 );
942 let fvars = free_fvars(&e);
943 assert!(fvars.contains(&FVarId(1)));
944 assert!(fvars.contains(&FVarId(2)));
945 assert_eq!(fvars.len(), 2);
946 }
947 #[test]
948 fn test_count_bvar0_none() {
949 let e = nat();
950 assert_eq!(count_bvar0_occurrences(&e), 0);
951 }
952 #[test]
953 fn test_count_bvar0_one() {
954 let e = Expr::BVar(0);
955 assert_eq!(count_bvar0_occurrences(&e), 1);
956 }
957 #[test]
958 fn test_count_bvar0_in_app() {
959 let e = Expr::App(Box::new(Expr::BVar(0)), Box::new(Expr::BVar(0)));
960 assert_eq!(count_bvar0_occurrences(&e), 2);
961 }
962 #[test]
963 fn test_bvar0_free_true() {
964 assert!(bvar0_free(&nat()));
965 assert!(bvar0_free(&Expr::BVar(1)));
966 }
967 #[test]
968 fn test_bvar0_free_false() {
969 assert!(!bvar0_free(&Expr::BVar(0)));
970 }
971 #[test]
972 fn test_apply_fvar_subst() {
973 let id = FVarId(0);
974 let mut subst = HashMap::new();
975 subst.insert(id, nat());
976 let e = Expr::FVar(id);
977 let result = apply_fvar_subst(&e, &subst);
978 assert_eq!(result, nat());
979 }
980 #[test]
981 fn test_alpha_equiv_under_subst_same() {
982 let id = FVarId(0);
983 let mut subst = HashMap::new();
984 subst.insert(id, nat());
985 let e1 = Expr::FVar(id);
986 let e2 = nat();
987 assert!(alpha_equiv_under_subst(&e1, &e2, &subst));
988 }
989 #[test]
990 fn test_structurally_equal() {
991 let lam1 = Expr::Lam(
992 BinderInfo::Default,
993 Name::str("x"),
994 Box::new(nat()),
995 Box::new(Expr::BVar(0)),
996 );
997 let lam2 = Expr::Lam(
998 BinderInfo::Default,
999 Name::str("y"),
1000 Box::new(nat()),
1001 Box::new(Expr::BVar(0)),
1002 );
1003 assert!(structurally_equal(&lam1, &lam2));
1004 }
1005 #[test]
1006 fn test_shift_preserves_const() {
1007 let e = Expr::Const(Name::str("f"), vec![]);
1008 assert_eq!(shift(&e, 3, 0), e);
1009 }
1010 #[test]
1011 fn test_shift_in_lam() {
1012 let lam = Expr::Lam(
1013 BinderInfo::Default,
1014 Name::str("x"),
1015 Box::new(nat()),
1016 Box::new(Expr::BVar(1)),
1017 );
1018 let shifted = shift(&lam, 1, 0);
1019 if let Expr::Lam(_, _, _, body) = &shifted {
1020 assert_eq!(**body, Expr::BVar(2));
1021 } else {
1022 panic!("expected Lam");
1023 }
1024 }
1025}
1026#[cfg(test)]
1027mod tests_padding_infra {
1028 use super::*;
1029 #[test]
1030 fn test_stat_summary() {
1031 let mut ss = StatSummary::new();
1032 ss.record(10.0);
1033 ss.record(20.0);
1034 ss.record(30.0);
1035 assert_eq!(ss.count(), 3);
1036 assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
1037 assert_eq!(ss.min().expect("min should succeed") as i64, 10);
1038 assert_eq!(ss.max().expect("max should succeed") as i64, 30);
1039 }
1040 #[test]
1041 fn test_transform_stat() {
1042 let mut ts = TransformStat::new();
1043 ts.record_before(100.0);
1044 ts.record_after(80.0);
1045 let ratio = ts.mean_ratio().expect("ratio should be present");
1046 assert!((ratio - 0.8).abs() < 1e-9);
1047 }
1048 #[test]
1049 fn test_small_map() {
1050 let mut m: SmallMap<u32, &str> = SmallMap::new();
1051 m.insert(3, "three");
1052 m.insert(1, "one");
1053 m.insert(2, "two");
1054 assert_eq!(m.get(&2), Some(&"two"));
1055 assert_eq!(m.len(), 3);
1056 let keys = m.keys();
1057 assert_eq!(*keys[0], 1);
1058 assert_eq!(*keys[2], 3);
1059 }
1060 #[test]
1061 fn test_label_set() {
1062 let mut ls = LabelSet::new();
1063 ls.add("foo");
1064 ls.add("bar");
1065 ls.add("foo");
1066 assert_eq!(ls.count(), 2);
1067 assert!(ls.has("bar"));
1068 assert!(!ls.has("baz"));
1069 }
1070 #[test]
1071 fn test_config_node() {
1072 let mut root = ConfigNode::section("root");
1073 let child = ConfigNode::leaf("key", "value");
1074 root.add_child(child);
1075 assert_eq!(root.num_children(), 1);
1076 }
1077 #[test]
1078 fn test_versioned_record() {
1079 let mut vr = VersionedRecord::new(0u32);
1080 vr.update(1);
1081 vr.update(2);
1082 assert_eq!(*vr.current(), 2);
1083 assert_eq!(vr.version(), 2);
1084 assert!(vr.has_history());
1085 assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
1086 }
1087 #[test]
1088 fn test_simple_dag() {
1089 let mut dag = SimpleDag::new(4);
1090 dag.add_edge(0, 1);
1091 dag.add_edge(1, 2);
1092 dag.add_edge(2, 3);
1093 assert!(dag.can_reach(0, 3));
1094 assert!(!dag.can_reach(3, 0));
1095 let order = dag.topological_sort().expect("order should be present");
1096 assert_eq!(order, vec![0, 1, 2, 3]);
1097 }
1098 #[test]
1099 fn test_focus_stack() {
1100 let mut fs: FocusStack<&str> = FocusStack::new();
1101 fs.focus("a");
1102 fs.focus("b");
1103 assert_eq!(fs.current(), Some(&"b"));
1104 assert_eq!(fs.depth(), 2);
1105 fs.blur();
1106 assert_eq!(fs.current(), Some(&"a"));
1107 }
1108}
1109#[cfg(test)]
1110mod tests_extra_iterators {
1111 use super::*;
1112 #[test]
1113 fn test_window_iterator() {
1114 let data = vec![1u32, 2, 3, 4, 5];
1115 let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
1116 assert_eq!(windows.len(), 3);
1117 assert_eq!(windows[0], &[1, 2, 3]);
1118 assert_eq!(windows[2], &[3, 4, 5]);
1119 }
1120 #[test]
1121 fn test_non_empty_vec() {
1122 let mut nev = NonEmptyVec::singleton(10u32);
1123 nev.push(20);
1124 nev.push(30);
1125 assert_eq!(nev.len(), 3);
1126 assert_eq!(*nev.first(), 10);
1127 assert_eq!(*nev.last(), 30);
1128 }
1129}
1130#[cfg(test)]
1131mod tests_padding2 {
1132 use super::*;
1133 #[test]
1134 fn test_sliding_sum() {
1135 let mut ss = SlidingSum::new(3);
1136 ss.push(1.0);
1137 ss.push(2.0);
1138 ss.push(3.0);
1139 assert!((ss.sum() - 6.0).abs() < 1e-9);
1140 ss.push(4.0);
1141 assert!((ss.sum() - 9.0).abs() < 1e-9);
1142 assert_eq!(ss.count(), 3);
1143 }
1144 #[test]
1145 fn test_path_buf() {
1146 let mut pb = PathBuf::new();
1147 pb.push("src");
1148 pb.push("main");
1149 assert_eq!(pb.as_str(), "src/main");
1150 assert_eq!(pb.depth(), 2);
1151 pb.pop();
1152 assert_eq!(pb.as_str(), "src");
1153 }
1154 #[test]
1155 fn test_string_pool() {
1156 let mut pool = StringPool::new();
1157 let s = pool.take();
1158 assert!(s.is_empty());
1159 pool.give("hello".to_string());
1160 let s2 = pool.take();
1161 assert!(s2.is_empty());
1162 assert_eq!(pool.free_count(), 0);
1163 }
1164 #[test]
1165 fn test_transitive_closure() {
1166 let mut tc = TransitiveClosure::new(4);
1167 tc.add_edge(0, 1);
1168 tc.add_edge(1, 2);
1169 tc.add_edge(2, 3);
1170 assert!(tc.can_reach(0, 3));
1171 assert!(!tc.can_reach(3, 0));
1172 let r = tc.reachable_from(0);
1173 assert_eq!(r.len(), 4);
1174 }
1175 #[test]
1176 fn test_token_bucket() {
1177 let mut tb = TokenBucket::new(100, 10);
1178 assert_eq!(tb.available(), 100);
1179 assert!(tb.try_consume(50));
1180 assert_eq!(tb.available(), 50);
1181 assert!(!tb.try_consume(60));
1182 assert_eq!(tb.capacity(), 100);
1183 }
1184 #[test]
1185 fn test_rewrite_rule_set() {
1186 let mut rrs = RewriteRuleSet::new();
1187 rrs.add(RewriteRule::unconditional(
1188 "beta",
1189 "App(Lam(x, b), v)",
1190 "b[x:=v]",
1191 ));
1192 rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
1193 assert_eq!(rrs.len(), 2);
1194 assert_eq!(rrs.unconditional_rules().len(), 1);
1195 assert_eq!(rrs.conditional_rules().len(), 1);
1196 assert!(rrs.get("beta").is_some());
1197 let disp = rrs
1198 .get("beta")
1199 .expect("element at \'beta\' should exist")
1200 .display();
1201 assert!(disp.contains("→"));
1202 }
1203}
1204#[cfg(test)]
1205mod tests_padding3 {
1206 use super::*;
1207 #[test]
1208 fn test_decision_node() {
1209 let tree = DecisionNode::Branch {
1210 key: "x".into(),
1211 val: "1".into(),
1212 yes_branch: Box::new(DecisionNode::Leaf("yes".into())),
1213 no_branch: Box::new(DecisionNode::Leaf("no".into())),
1214 };
1215 let mut ctx = std::collections::HashMap::new();
1216 ctx.insert("x".into(), "1".into());
1217 assert_eq!(tree.evaluate(&ctx), "yes");
1218 ctx.insert("x".into(), "2".into());
1219 assert_eq!(tree.evaluate(&ctx), "no");
1220 assert_eq!(tree.depth(), 1);
1221 }
1222 #[test]
1223 fn test_flat_substitution() {
1224 let mut sub = FlatSubstitution::new();
1225 sub.add("foo", "bar");
1226 sub.add("baz", "qux");
1227 assert_eq!(sub.apply("foo and baz"), "bar and qux");
1228 assert_eq!(sub.len(), 2);
1229 }
1230 #[test]
1231 fn test_stopwatch() {
1232 let mut sw = Stopwatch::start();
1233 sw.split();
1234 sw.split();
1235 assert_eq!(sw.num_splits(), 2);
1236 assert!(sw.elapsed_ms() >= 0.0);
1237 for &s in sw.splits() {
1238 assert!(s >= 0.0);
1239 }
1240 }
1241 #[test]
1242 fn test_either2() {
1243 let e: Either2<i32, &str> = Either2::First(42);
1244 assert!(e.is_first());
1245 let mapped = e.map_first(|x| x * 2);
1246 assert_eq!(mapped.first(), Some(84));
1247 let e2: Either2<i32, &str> = Either2::Second("hello");
1248 assert!(e2.is_second());
1249 assert_eq!(e2.second(), Some("hello"));
1250 }
1251 #[test]
1252 fn test_write_once() {
1253 let wo: WriteOnce<u32> = WriteOnce::new();
1254 assert!(!wo.is_written());
1255 assert!(wo.write(42));
1256 assert!(!wo.write(99));
1257 assert_eq!(wo.read(), Some(42));
1258 }
1259 #[test]
1260 fn test_sparse_vec() {
1261 let mut sv: SparseVec<i32> = SparseVec::new(100);
1262 sv.set(5, 10);
1263 sv.set(50, 20);
1264 assert_eq!(*sv.get(5), 10);
1265 assert_eq!(*sv.get(50), 20);
1266 assert_eq!(*sv.get(0), 0);
1267 assert_eq!(sv.nnz(), 2);
1268 sv.set(5, 0);
1269 assert_eq!(sv.nnz(), 1);
1270 }
1271 #[test]
1272 fn test_stack_calc() {
1273 let mut calc = StackCalc::new();
1274 calc.push(3);
1275 calc.push(4);
1276 calc.add();
1277 assert_eq!(calc.peek(), Some(7));
1278 calc.push(2);
1279 calc.mul();
1280 assert_eq!(calc.peek(), Some(14));
1281 }
1282}
1283#[cfg(test)]
1284mod tests_final_padding {
1285 use super::*;
1286 #[test]
1287 fn test_min_heap() {
1288 let mut h = MinHeap::new();
1289 h.push(5u32);
1290 h.push(1u32);
1291 h.push(3u32);
1292 assert_eq!(h.peek(), Some(&1));
1293 assert_eq!(h.pop(), Some(1));
1294 assert_eq!(h.pop(), Some(3));
1295 assert_eq!(h.pop(), Some(5));
1296 assert!(h.is_empty());
1297 }
1298 #[test]
1299 fn test_prefix_counter() {
1300 let mut pc = PrefixCounter::new();
1301 pc.record("hello");
1302 pc.record("help");
1303 pc.record("world");
1304 assert_eq!(pc.count_with_prefix("hel"), 2);
1305 assert_eq!(pc.count_with_prefix("wor"), 1);
1306 assert_eq!(pc.count_with_prefix("xyz"), 0);
1307 }
1308 #[test]
1309 fn test_fixture() {
1310 let mut f = Fixture::new();
1311 f.set("key1", "val1");
1312 f.set("key2", "val2");
1313 assert_eq!(f.get("key1"), Some("val1"));
1314 assert_eq!(f.get("key3"), None);
1315 assert_eq!(f.len(), 2);
1316 }
1317}