1use crate::node_memo::NodeMemo;
6use crate::Node;
7use crate::{Expr, FVarId, Level, LevelView, Name};
8use std::rc::Rc;
9
10use super::types::{
11 ConfigNode, DecisionNode, Either2, Fixture, FlatSubstitution, FocusStack, LabelSet, MinHeap,
12 NonEmptyVec, PathBuf, PrefixCounter, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum,
13 SmallMap, SparseVec, StackCalc, StatSummary, Stopwatch, StringPool, TokenBucket, TransformStat,
14 TransitiveClosure, VersionedRecord, WindowIterator, WriteOnce,
15};
16
17pub fn get_app_fn(e: &Expr) -> &Expr {
21 match e {
22 Expr::App(f, _) => get_app_fn(f),
23 _ => e,
24 }
25}
26pub fn get_app_args(e: &Expr) -> Vec<&Expr> {
30 let mut args = Vec::new();
31 get_app_args_aux(e, &mut args);
32 args
33}
34fn get_app_args_aux<'a>(e: &'a Expr, args: &mut Vec<&'a Expr>) {
35 if let Expr::App(f, a) = e {
36 get_app_args_aux(f, args);
37 args.push(a);
38 }
39}
40pub fn get_app_fn_args(e: &Expr) -> (&Expr, Vec<&Expr>) {
44 let mut args = Vec::new();
45 let f = get_app_fn_args_aux(e, &mut args);
46 (f, args)
47}
48fn get_app_fn_args_aux<'a>(e: &'a Expr, args: &mut Vec<&'a Expr>) -> &'a Expr {
49 match e {
50 Expr::App(f, a) => {
51 let head = get_app_fn_args_aux(f, args);
52 args.push(a);
53 head
54 }
55 _ => e,
56 }
57}
58pub fn get_app_num_args(e: &Expr) -> usize {
60 match e {
61 Expr::App(f, _) => 1 + get_app_num_args(f),
62 _ => 0,
63 }
64}
65pub fn mk_app(f: Expr, args: &[Expr]) -> Expr {
69 args.iter().fold(f, |acc, arg| {
70 Expr::App(Node::new(acc), Node::new(arg.clone()))
71 })
72}
73pub fn mk_app_refs(f: Expr, args: &[&Expr]) -> Expr {
81 args.iter().fold(f, |acc, arg| {
82 Expr::App(Node::new(acc), Node::new((*arg).clone()))
83 })
84}
85pub(crate) fn get_app_arg_nodes(e: &Expr) -> Vec<&Node> {
93 let mut args = Vec::new();
94 let mut cur = e;
95 while let Expr::App(f, a) = cur {
96 args.push(a);
97 cur = f;
98 }
99 args.reverse();
100 args
101}
102pub(crate) fn mk_app_nodes(f: Expr, args: &[&Node]) -> Expr {
109 crate::fuel::charge(args.len() as u64);
111 args.iter()
112 .fold(f, |acc, arg| Expr::App(Node::new(acc), (*arg).clone()))
113}
114pub fn mk_app_range(f: Expr, args: &[Expr], begin: usize, end: usize) -> Expr {
118 let end = end.min(args.len());
119 let begin = begin.min(end);
120 mk_app(f, &args[begin..end])
121}
122pub fn has_loose_bvars(e: &Expr) -> bool {
130 e.range() > 0
131}
132pub fn has_loose_bvar_ge(e: &Expr, depth: u32) -> bool {
134 match e {
135 Expr::BVar(n) => *n >= depth,
136 Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
137 Expr::App(f, a) => has_loose_bvar_ge(f, depth) || has_loose_bvar_ge(a, depth),
138 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
139 has_loose_bvar_ge(ty, depth) || has_loose_bvar_ge(body, depth + 1)
140 }
141 Expr::Let(_, ty, val, body) => {
142 has_loose_bvar_ge(ty, depth)
143 || has_loose_bvar_ge(val, depth)
144 || has_loose_bvar_ge(body, depth + 1)
145 }
146 Expr::Proj(_, _, e) => has_loose_bvar_ge(e, depth),
147 }
148}
149pub fn expr_size_within(e: &Expr, cap: usize) -> bool {
174 let cost = u64::from(e.rebuild_cost());
175 let cap_wide = cap as u64;
177 if cost < u64::from(crate::expr::REBUILD_COST_MAX) && cost <= cap_wide {
178 return true;
179 }
180 if cost > cap_wide.saturating_mul(2) {
181 return false;
182 }
183 expr_size_within_by_walk(e, cap)
184}
185fn expr_size_within_by_walk(e: &Expr, cap: usize) -> bool {
189 let mut remaining = cap;
190 let mut stack: Vec<&Expr> = vec![e];
191 while let Some(cur) = stack.pop() {
192 if remaining == 0 {
193 return false;
194 }
195 remaining -= 1;
196 match cur {
197 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => {}
198 Expr::App(f, a) => {
199 stack.push(f);
200 stack.push(a);
201 }
202 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
203 stack.push(ty);
204 stack.push(body);
205 }
206 Expr::Let(_, ty, val, body) => {
207 stack.push(ty);
208 stack.push(val);
209 stack.push(body);
210 }
211 Expr::Proj(_, _, inner) => stack.push(inner),
212 }
213 }
214 true
215}
216pub fn has_loose_bvar(e: &Expr, level: u32) -> bool {
218 match e {
219 Expr::BVar(n) => *n == level,
220 Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
221 Expr::App(f, a) => has_loose_bvar(f, level) || has_loose_bvar(a, level),
222 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
223 has_loose_bvar(ty, level) || has_loose_bvar(body, level + 1)
224 }
225 Expr::Let(_, ty, val, body) => {
226 has_loose_bvar(ty, level)
227 || has_loose_bvar(val, level)
228 || has_loose_bvar(body, level + 1)
229 }
230 Expr::Proj(_, _, e) => has_loose_bvar(e, level),
231 }
232}
233pub fn has_fvar(e: &Expr, fvar: FVarId) -> bool {
235 match e {
236 Expr::FVar(id) => *id == fvar,
237 Expr::Sort(_) | Expr::BVar(_) | Expr::Const(_, _) | Expr::Lit(_) => false,
238 Expr::App(f, a) => has_fvar(f, fvar) || has_fvar(a, fvar),
239 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
240 has_fvar(ty, fvar) || has_fvar(body, fvar)
241 }
242 Expr::Let(_, ty, val, body) => {
243 has_fvar(ty, fvar) || has_fvar(val, fvar) || has_fvar(body, fvar)
244 }
245 Expr::Proj(_, _, e) => has_fvar(e, fvar),
246 }
247}
248pub fn has_any_fvar(e: &Expr) -> bool {
252 e.has_fvar()
253}
254pub fn for_each_expr(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> bool) {
259 for_each_expr_aux(e, f, 0);
260}
261fn for_each_expr_aux(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> bool, depth: u32) {
262 if !f(e, depth) {
263 return;
264 }
265 match e {
266 Expr::App(fun, arg) => {
267 for_each_expr_aux(fun, f, depth);
268 for_each_expr_aux(arg, f, depth);
269 }
270 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
271 for_each_expr_aux(ty, f, depth);
272 for_each_expr_aux(body, f, depth + 1);
273 }
274 Expr::Let(_, ty, val, body) => {
275 for_each_expr_aux(ty, f, depth);
276 for_each_expr_aux(val, f, depth);
277 for_each_expr_aux(body, f, depth + 1);
278 }
279 Expr::Proj(_, _, e) => {
280 for_each_expr_aux(e, f, depth);
281 }
282 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => {}
283 }
284}
285pub fn replace_expr(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> Option<Expr>) -> Expr {
290 replace_expr_aux(e, f, 0)
291}
292fn replace_expr_aux(e: &Expr, f: &mut dyn FnMut(&Expr, u32) -> Option<Expr>, depth: u32) -> Expr {
293 if let Some(replacement) = f(e, depth) {
294 return replacement;
295 }
296 match e {
297 Expr::App(fun, arg) => {
298 let new_fun = replace_expr_aux(fun, f, depth);
299 let new_arg = replace_expr_aux(arg, f, depth);
300 Expr::App(Node::new(new_fun), Node::new(new_arg))
301 }
302 Expr::Lam(bi, name, ty, body) => {
303 let new_ty = replace_expr_aux(ty, f, depth);
304 let new_body = replace_expr_aux(body, f, depth + 1);
305 Expr::Lam(*bi, name.clone(), Node::new(new_ty), Node::new(new_body))
306 }
307 Expr::Pi(bi, name, ty, body) => {
308 let new_ty = replace_expr_aux(ty, f, depth);
309 let new_body = replace_expr_aux(body, f, depth + 1);
310 Expr::Pi(*bi, name.clone(), Node::new(new_ty), Node::new(new_body))
311 }
312 Expr::Let(name, ty, val, body) => {
313 let new_ty = replace_expr_aux(ty, f, depth);
314 let new_val = replace_expr_aux(val, f, depth);
315 let new_body = replace_expr_aux(body, f, depth + 1);
316 Expr::Let(
317 name.clone(),
318 Node::new(new_ty),
319 Node::new(new_val),
320 Node::new(new_body),
321 )
322 }
323 Expr::Proj(name, idx, e_inner) => {
324 let new_e = replace_expr_aux(e_inner, f, depth);
325 Expr::Proj(name.clone(), *idx, Node::new(new_e))
326 }
327 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => {
328 e.clone()
329 }
330 }
331}
332pub fn collect_fvars(e: &Expr) -> Vec<FVarId> {
334 let mut fvars = Vec::new();
335 for_each_expr(e, &mut |sub, _depth| {
336 if let Expr::FVar(id) = sub {
337 if !fvars.contains(id) {
338 fvars.push(*id);
339 }
340 }
341 true
342 });
343 fvars
344}
345pub fn collect_consts(e: &Expr) -> Vec<Name> {
347 let mut consts = Vec::new();
348 for_each_expr(e, &mut |sub, _depth| {
349 if let Expr::Const(name, _) = sub {
350 if !consts.contains(name) {
351 consts.push(name.clone());
352 }
353 }
354 true
355 });
356 consts
357}
358pub fn lift_loose_bvars(e: &Expr, n: u32, offset: u32) -> Expr {
368 if n == 0 || e.range() <= offset {
369 return e.clone();
371 }
372 let mut walk = Lift {
373 by: n,
374 lifted: NodeMemo::new(),
375 };
376 crate::fuel::charge(1);
377 walk.rebuild(e, offset)
378}
379
380struct Lift<'term> {
382 by: u32,
384 lifted: NodeMemo<'term, Node>,
387}
388
389impl<'term> Lift<'term> {
390 fn node(&mut self, node: &'term Node, depth: u32) -> Node {
392 crate::fuel::charge(1);
393 if node.range() <= depth {
394 return node.clone();
396 }
397 if matches!(&**node, Expr::BVar(_)) {
398 return Node::new(self.rebuild(node, depth));
400 }
401 let shared = node.is_shared();
402 if shared {
403 if let Some(done) = self.lifted.get(node, depth) {
404 return done.clone();
405 }
406 }
407 let result = Node::new(self.rebuild(node, depth));
408 if shared {
409 self.lifted.insert(node, depth, result.clone());
410 }
411 result
412 }
413
414 fn rebuild(&mut self, e: &'term Expr, depth: u32) -> Expr {
416 match e {
417 Expr::BVar(idx) => {
418 if *idx >= depth {
419 Expr::BVar(idx.saturating_add(self.by))
423 } else {
424 e.clone()
425 }
426 }
427 Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => e.clone(),
428 Expr::App(f, a) => Expr::App(self.node(f, depth), self.node(a, depth)),
429 Expr::Lam(bi, name, ty, body) => Expr::Lam(
430 *bi,
431 name.clone(),
432 self.node(ty, depth),
433 self.node(body, depth + 1),
434 ),
435 Expr::Pi(bi, name, ty, body) => Expr::Pi(
436 *bi,
437 name.clone(),
438 self.node(ty, depth),
439 self.node(body, depth + 1),
440 ),
441 Expr::Let(name, ty, val, body) => Expr::Let(
442 name.clone(),
443 self.node(ty, depth),
444 self.node(val, depth),
445 self.node(body, depth + 1),
446 ),
447 Expr::Proj(name, idx, inner) => Expr::Proj(name.clone(), *idx, self.node(inner, depth)),
448 }
449 }
450}
451pub fn occurs_const(e: &Expr, name: &Name) -> bool {
453 match e {
454 Expr::Const(n, _) => n == name,
455 Expr::App(f, a) => occurs_const(f, name) || occurs_const(a, name),
456 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
457 occurs_const(ty, name) || occurs_const(body, name)
458 }
459 Expr::Let(_, ty, val, body) => {
460 occurs_const(ty, name) || occurs_const(val, name) || occurs_const(body, name)
461 }
462 Expr::Proj(_, _, e) => occurs_const(e, name),
463 _ => false,
464 }
465}
466pub fn count_lambdas(e: &Expr) -> u32 {
468 match e {
469 Expr::Lam(_, _, _, body) => 1 + count_lambdas(body),
470 _ => 0,
471 }
472}
473pub fn count_pis(e: &Expr) -> u32 {
475 match e {
476 Expr::Pi(_, _, _, body) => 1 + count_pis(body),
477 _ => 0,
478 }
479}
480pub fn strip_lambdas(e: &Expr, n: u32) -> &Expr {
482 if n == 0 {
483 return e;
484 }
485 match e {
486 Expr::Lam(_, _, _, body) => strip_lambdas(body, n - 1),
487 _ => e,
488 }
489}
490pub fn strip_pis(e: &Expr, n: u32) -> &Expr {
492 if n == 0 {
493 return e;
494 }
495 match e {
496 Expr::Pi(_, _, _, body) => strip_pis(body, n - 1),
497 _ => e,
498 }
499}
500pub fn level_has_mvar(l: &Level) -> bool {
502 match l.view() {
503 LevelView::MVar(_) => true,
504 LevelView::Succ(l) => level_has_mvar(l),
505 LevelView::Max(l1, l2) | LevelView::IMax(l1, l2) => {
506 level_has_mvar(l1) || level_has_mvar(l2)
507 }
508 LevelView::Zero | LevelView::Param(_) => false,
509 }
510}
511pub fn has_level_mvar(e: &Expr) -> bool {
516 e.has_level_mvar()
517}
518pub fn has_level_param(e: &Expr) -> bool {
522 e.has_level_param()
523}
524pub fn expr_weight(e: &Expr) -> usize {
526 match e {
527 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Lit(_) => 1,
528 Expr::Const(_, _) => 1,
529 Expr::App(f, a) => 1 + expr_weight(f) + expr_weight(a),
530 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
531 1 + expr_weight(ty) + expr_weight(body)
532 }
533 Expr::Let(_, ty, val, body) => 1 + expr_weight(ty) + expr_weight(val) + expr_weight(body),
534 Expr::Proj(_, _, e) => 1 + expr_weight(e),
535 }
536}
537pub fn is_app_of(e: &Expr, name: &Name) -> bool {
539 matches!(get_app_fn(e), Expr::Const(n, _) if n == name)
540}
541pub fn mk_arrow(a: Expr, b: Expr) -> Expr {
543 Expr::Pi(
544 crate::BinderInfo::Default,
545 Name::anonymous(),
546 Node::new(a),
547 Node::new(lift_loose_bvars(&b, 1, 0)),
548 )
549}
550pub fn mk_prop() -> Expr {
552 Expr::Sort(Level::zero())
553}
554pub fn mk_type(u: Level) -> Expr {
556 Expr::Sort(Level::succ(u))
557}
558pub fn mk_type0() -> Expr {
560 Expr::Sort(Level::succ(Level::zero()))
561}
562pub fn var(name: &str) -> Expr {
564 Expr::Const(Name::str(name), vec![])
565}
566pub fn bvar(idx: u32) -> Expr {
568 Expr::BVar(idx)
569}
570pub fn app(f: Expr, a: Expr) -> Expr {
572 Expr::App(Node::new(f), Node::new(a))
573}
574pub fn lam(name: &str, ty: Expr, body: Expr) -> Expr {
576 Expr::Lam(
577 crate::BinderInfo::Default,
578 Name::str(name),
579 Node::new(ty),
580 Node::new(body),
581 )
582}
583pub fn pi(name: &str, ty: Expr, body: Expr) -> Expr {
585 Expr::Pi(
586 crate::BinderInfo::Default,
587 Name::str(name),
588 Node::new(ty),
589 Node::new(body),
590 )
591}
592pub fn prop() -> Expr {
594 Expr::Sort(crate::Level::zero())
595}
596pub fn sort() -> Expr {
598 Expr::Sort(crate::Level::zero())
599}
600pub fn type0() -> Expr {
602 Expr::Sort(crate::Level::succ(crate::Level::zero()))
603}
604#[cfg(test)]
605mod size_tests {
606 use super::*;
607 use crate::{BinderInfo, Level, Literal};
608
609 fn leaf(i: u32) -> Expr {
610 match i % 5 {
611 0 => Expr::BVar(i),
612 1 => Expr::Const(Name::str("c"), vec![Level::zero()]),
613 2 => Expr::Sort(Level::zero()),
614 3 => Expr::Lit(Literal::nat(u64::from(i))),
615 _ => Expr::FVar(crate::FVarId(u64::from(i))),
616 }
617 }
618
619 fn shapes() -> Vec<Expr> {
623 let mut terms: Vec<Expr> = (0..5).map(leaf).collect();
624 let mut chain = leaf(1);
626 for i in 0..12 {
627 chain = Expr::Proj(Name::str("S"), i, Node::new(chain));
628 terms.push(chain.clone());
629 }
630 let mut spine = leaf(1);
632 for i in 0..12 {
633 spine = Expr::App(Node::new(spine), Node::new(leaf(i)));
634 terms.push(spine.clone());
635 }
636 let mut tree = leaf(0);
639 for _ in 0..8 {
640 let shared = Node::new(tree);
641 tree = Expr::App(shared.clone(), shared);
642 terms.push(tree.clone());
643 }
644 for i in 0..6usize {
646 let ty = Node::new(terms[i * 3].clone());
647 let body = Node::new(terms[i * 5 + 1].clone());
648 terms.push(Expr::Lam(
649 BinderInfo::Default,
650 Name::str("x"),
651 ty.clone(),
652 body.clone(),
653 ));
654 terms.push(Expr::Pi(
655 BinderInfo::Implicit,
656 Name::str("x"),
657 ty.clone(),
658 body.clone(),
659 ));
660 terms.push(Expr::Let(Name::str("x"), ty.clone(), body.clone(), ty));
661 }
662 terms
663 }
664
665 fn size(e: &Expr) -> usize {
667 match e {
668 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 1,
669 Expr::App(f, a) => 1 + size(f) + size(a),
670 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => 1 + size(ty) + size(body),
671 Expr::Let(_, ty, val, body) => 1 + size(ty) + size(val) + size(body),
672 Expr::Proj(_, _, inner) => 1 + size(inner),
673 }
674 }
675
676 #[test]
677 fn the_cached_cost_brackets_the_size() {
678 for (i, term) in shapes().iter().enumerate() {
679 let n = size(term) as u64;
680 let cost = u64::from(term.rebuild_cost());
681 assert!(
682 n <= cost && cost <= 2 * n,
683 "term {i}: size {n}, cost {cost}"
684 );
685 }
686 }
687
688 #[test]
689 fn size_within_agrees_with_counting_at_every_cap() {
690 let terms = shapes();
691 let mut by_cost = 0usize;
692 let mut by_walk = 0usize;
693 for (i, term) in terms.iter().enumerate() {
694 let n = size(term);
695 let cost = term.rebuild_cost() as usize;
696 for cap in (0..=2 * n + 3).chain([4096, usize::MAX / 2, usize::MAX]) {
697 let expected = n <= cap;
698 assert_eq!(
699 expr_size_within(term, cap),
700 expected,
701 "term {i} (size {n}, cost {cost}) at cap {cap}"
702 );
703 assert_eq!(
704 expr_size_within_by_walk(term, cap),
705 expected,
706 "walk: term {i} (size {n}) at cap {cap}"
707 );
708 if cost <= cap || cost > 2 * cap {
709 by_cost += 1;
710 } else {
711 by_walk += 1;
712 }
713 }
714 }
715 assert!(by_cost > 1000, "{by_cost} caps decided by the cost");
717 assert!(by_walk > 1000, "{by_walk} caps decided by counting");
718 }
719
720 #[test]
721 fn a_saturated_cost_never_reads_as_small() {
722 use crate::expr::REBUILD_COST_MAX;
723 let mut tower = leaf(0);
725 for _ in 0..40 {
726 let shared = Node::new(tower);
727 tower = Expr::App(shared.clone(), shared);
728 }
729 assert_eq!(tower.rebuild_cost(), REBUILD_COST_MAX);
730 assert!(!expr_size_within(&tower, 0));
733 assert!(!expr_size_within(&tower, 4096));
734 assert!(!expr_size_within(
735 &tower,
736 (REBUILD_COST_MAX as usize) / 2 - 1
737 ));
738 let mut smaller = leaf(0);
742 for _ in 0..28 {
743 let shared = Node::new(smaller);
744 smaller = Expr::App(shared.clone(), shared);
745 }
746 assert_eq!(smaller.rebuild_cost(), REBUILD_COST_MAX);
747 assert!(!expr_size_within(&smaller, 1 << 27));
748 let mut exact = leaf(0);
750 for _ in 0..26 {
751 let shared = Node::new(exact);
752 exact = Expr::App(shared.clone(), shared);
753 }
754 assert_eq!(exact.rebuild_cost(), 3 * (1 << 26) - 1);
756 assert!(exact.rebuild_cost() < REBUILD_COST_MAX);
757 assert!(expr_size_within(&exact, 3 * (1 << 26)));
758 assert!(!expr_size_within(&exact, 1 << 20));
759 }
760}
761#[cfg(test)]
762mod tests {
763 use super::*;
764 use crate::BinderInfo;
765 fn nat() -> Expr {
766 Expr::Const(Name::str("Nat"), vec![])
767 }
768 fn bool_ty() -> Expr {
769 Expr::Const(Name::str("Bool"), vec![])
770 }
771 #[test]
772 fn test_get_app_fn() {
773 let f = nat();
774 let e = Expr::App(
775 Node::new(Expr::App(Node::new(f.clone()), Node::new(Expr::BVar(0)))),
776 Node::new(Expr::BVar(1)),
777 );
778 assert_eq!(get_app_fn(&e), &f);
779 }
780 #[test]
781 fn test_get_app_args() {
782 let f = nat();
783 let a1 = Expr::BVar(0);
784 let a2 = Expr::BVar(1);
785 let e = Expr::App(
786 Node::new(Expr::App(Node::new(f), Node::new(a1.clone()))),
787 Node::new(a2.clone()),
788 );
789 let args = get_app_args(&e);
790 assert_eq!(args.len(), 2);
791 assert_eq!(args[0], &a1);
792 assert_eq!(args[1], &a2);
793 }
794 #[test]
795 fn test_get_app_fn_args() {
796 let f = nat();
797 let a = Expr::BVar(0);
798 let e = Expr::App(Node::new(f.clone()), Node::new(a.clone()));
799 let (head, args) = get_app_fn_args(&e);
800 assert_eq!(head, &f);
801 assert_eq!(args, vec![&a]);
802 }
803 #[test]
804 fn test_mk_app() {
805 let f = nat();
806 let a1 = Expr::BVar(0);
807 let a2 = Expr::BVar(1);
808 let result = mk_app(f.clone(), &[a1.clone(), a2.clone()]);
809 let (head, args) = get_app_fn_args(&result);
810 assert_eq!(head, &f);
811 assert_eq!(args.len(), 2);
812 }
813 #[test]
814 fn test_has_loose_bvars() {
815 assert!(has_loose_bvars(&Expr::BVar(0)));
816 assert!(!has_loose_bvars(&nat()));
817 assert!(!has_loose_bvars(&Expr::FVar(FVarId(1))));
818 let lam = Expr::Lam(
819 BinderInfo::Default,
820 Name::str("x"),
821 Node::new(nat()),
822 Node::new(Expr::BVar(0)),
823 );
824 assert!(!has_loose_bvars(&lam));
825 let lam2 = Expr::Lam(
826 BinderInfo::Default,
827 Name::str("x"),
828 Node::new(nat()),
829 Node::new(Expr::BVar(1)),
830 );
831 assert!(has_loose_bvars(&lam2));
832 }
833 #[test]
834 fn test_has_fvar() {
835 let id = FVarId(42);
836 let e = Expr::App(Node::new(Expr::FVar(id)), Node::new(Expr::FVar(FVarId(99))));
837 assert!(has_fvar(&e, id));
838 assert!(has_fvar(&e, FVarId(99)));
839 assert!(!has_fvar(&e, FVarId(1)));
840 }
841 #[test]
842 fn test_collect_fvars() {
843 let e = Expr::App(
844 Node::new(Expr::FVar(FVarId(1))),
845 Node::new(Expr::App(
846 Node::new(Expr::FVar(FVarId(2))),
847 Node::new(Expr::FVar(FVarId(1))),
848 )),
849 );
850 let fvars = collect_fvars(&e);
851 assert_eq!(fvars.len(), 2);
852 assert!(fvars.contains(&FVarId(1)));
853 assert!(fvars.contains(&FVarId(2)));
854 }
855 #[test]
856 fn test_for_each_expr() {
857 let e = Expr::App(Node::new(nat()), Node::new(Expr::BVar(0)));
858 let mut count = 0;
859 for_each_expr(&e, &mut |_, _| {
860 count += 1;
861 true
862 });
863 assert_eq!(count, 3);
864 }
865 #[test]
866 fn test_replace_expr() {
867 let e = Expr::App(Node::new(Expr::BVar(0)), Node::new(Expr::BVar(1)));
868 let result = replace_expr(&e, &mut |sub, _depth| {
869 if let Expr::BVar(0) = sub {
870 Some(nat())
871 } else {
872 None
873 }
874 });
875 match &result {
876 Expr::App(f, _) => assert_eq!(**f, nat()),
877 _ => panic!("Expected App"),
878 }
879 }
880 #[test]
881 fn test_lift_loose_bvars() {
882 let e = Expr::BVar(0);
883 let lifted = lift_loose_bvars(&e, 2, 0);
884 assert_eq!(lifted, Expr::BVar(2));
885 let lam = Expr::Lam(
886 BinderInfo::Default,
887 Name::str("x"),
888 Node::new(nat()),
889 Node::new(Expr::BVar(0)),
890 );
891 let lifted_lam = lift_loose_bvars(&lam, 1, 0);
892 if let Expr::Lam(_, _, _, body) = &lifted_lam {
893 assert_eq!(**body, Expr::BVar(0));
894 } else {
895 panic!("Expected Lam");
896 }
897 }
898 #[test]
899 fn test_count_lambdas_pis() {
900 let e = Expr::Lam(
901 BinderInfo::Default,
902 Name::str("x"),
903 Node::new(nat()),
904 Node::new(Expr::Lam(
905 BinderInfo::Default,
906 Name::str("y"),
907 Node::new(nat()),
908 Node::new(Expr::BVar(0)),
909 )),
910 );
911 assert_eq!(count_lambdas(&e), 2);
912 let pi = Expr::Pi(
913 BinderInfo::Default,
914 Name::str("x"),
915 Node::new(nat()),
916 Node::new(nat()),
917 );
918 assert_eq!(count_pis(&pi), 1);
919 }
920 #[test]
921 fn test_is_app_of() {
922 let e = Expr::App(
923 Node::new(Expr::Const(Name::str("f"), vec![])),
924 Node::new(Expr::BVar(0)),
925 );
926 assert!(is_app_of(&e, &Name::str("f")));
927 assert!(!is_app_of(&e, &Name::str("g")));
928 }
929 #[test]
930 fn test_mk_arrow() {
931 let arrow = mk_arrow(nat(), bool_ty());
932 assert!(arrow.is_pi());
933 }
934 #[test]
935 fn test_expr_weight() {
936 assert_eq!(expr_weight(&nat()), 1);
937 let app = Expr::App(Node::new(nat()), Node::new(Expr::BVar(0)));
938 assert_eq!(expr_weight(&app), 3);
939 }
940 #[test]
941 fn test_mk_app_range() {
942 let f = nat();
943 let args = vec![Expr::BVar(0), Expr::BVar(1), Expr::BVar(2)];
944 let result = mk_app_range(f.clone(), &args, 1, 3);
945 assert_eq!(get_app_num_args(&result), 2);
946 }
947 #[test]
948 fn test_occurs_const() {
949 let e = Expr::App(Node::new(nat()), Node::new(bool_ty()));
950 assert!(occurs_const(&e, &Name::str("Nat")));
951 assert!(occurs_const(&e, &Name::str("Bool")));
952 assert!(!occurs_const(&e, &Name::str("Int")));
953 }
954}
955#[inline]
957pub fn is_sort(e: &Expr) -> bool {
958 matches!(e, Expr::Sort(_))
959}
960#[inline]
962pub fn is_prop(e: &Expr) -> bool {
963 matches!(e, Expr::Sort(l) if matches!(l.view(), LevelView::Zero))
964}
965#[inline]
967pub fn is_type0(e: &Expr) -> bool {
968 matches!(e, Expr::Sort(l) if matches!(l.view(), LevelView::Succ(inner) if matches!(inner.view(), LevelView::Zero)))
969}
970#[inline]
972pub fn is_lambda(e: &Expr) -> bool {
973 matches!(e, Expr::Lam(_, _, _, _))
974}
975#[inline]
977pub fn is_pi(e: &Expr) -> bool {
978 matches!(e, Expr::Pi(_, _, _, _))
979}
980#[inline]
982pub fn is_fvar(e: &Expr) -> bool {
983 matches!(e, Expr::FVar(_))
984}
985#[inline]
987pub fn is_bvar(e: &Expr) -> bool {
988 matches!(e, Expr::BVar(_))
989}
990#[inline]
992pub fn is_literal(e: &Expr) -> bool {
993 matches!(e, Expr::Lit(_))
994}
995#[inline]
997pub fn is_const(e: &Expr) -> bool {
998 matches!(e, Expr::Const(_, _))
999}
1000#[inline]
1002pub fn is_app(e: &Expr) -> bool {
1003 matches!(e, Expr::App(_, _))
1004}
1005#[inline]
1007pub fn is_let(e: &Expr) -> bool {
1008 matches!(e, Expr::Let(_, _, _, _))
1009}
1010#[inline]
1012pub fn is_proj(e: &Expr) -> bool {
1013 matches!(e, Expr::Proj(_, _, _))
1014}
1015#[inline]
1017pub fn get_sort_level(e: &Expr) -> Option<&Level> {
1018 if let Expr::Sort(l) = e {
1019 Some(l)
1020 } else {
1021 None
1022 }
1023}
1024#[inline]
1026pub fn get_const_name(e: &Expr) -> Option<&Name> {
1027 if let Expr::Const(n, _) = e {
1028 Some(n)
1029 } else {
1030 None
1031 }
1032}
1033#[inline]
1035pub fn get_const_levels(e: &Expr) -> Option<&[Level]> {
1036 if let Expr::Const(_, ls) = e {
1037 Some(ls)
1038 } else {
1039 None
1040 }
1041}
1042#[inline]
1044pub fn get_fvar_id(e: &Expr) -> Option<FVarId> {
1045 if let Expr::FVar(id) = e {
1046 Some(*id)
1047 } else {
1048 None
1049 }
1050}
1051#[inline]
1053pub fn get_bvar_idx(e: &Expr) -> Option<u32> {
1054 if let Expr::BVar(i) = e {
1055 Some(*i)
1056 } else {
1057 None
1058 }
1059}
1060#[inline]
1062pub fn decompose_let(e: &Expr) -> Option<(&Expr, &Expr, &Expr)> {
1063 if let Expr::Let(_, ty, val, body) = e {
1064 Some((ty, val, body))
1065 } else {
1066 None
1067 }
1068}
1069#[inline]
1071pub fn decompose_pi(e: &Expr) -> Option<(crate::BinderInfo, &Expr, &Expr)> {
1072 if let Expr::Pi(bi, _, dom, cod) = e {
1073 Some((*bi, dom, cod))
1074 } else {
1075 None
1076 }
1077}
1078#[inline]
1080pub fn decompose_lam(e: &Expr) -> Option<(crate::BinderInfo, &Expr, &Expr)> {
1081 if let Expr::Lam(bi, _, dom, body) = e {
1082 Some((*bi, dom, body))
1083 } else {
1084 None
1085 }
1086}
1087#[inline]
1089pub fn decompose_proj(e: &Expr) -> Option<(&Name, usize, &Expr)> {
1090 if let Expr::Proj(n, idx, val) = e {
1091 Some((n, *idx as usize, val))
1092 } else {
1093 None
1094 }
1095}
1096pub fn mk_pi_n(binders: &[(crate::BinderInfo, Expr)], ret: Expr) -> Expr {
1101 binders.iter().rev().fold(ret, |acc, (bi, ty)| {
1102 Expr::Pi(
1103 *bi,
1104 crate::Name::anonymous(),
1105 Node::new(ty.clone()),
1106 Node::new(acc),
1107 )
1108 })
1109}
1110pub fn mk_lam_n(binders: &[(crate::BinderInfo, Expr)], body: Expr) -> Expr {
1112 binders.iter().rev().fold(body, |acc, (bi, ty)| {
1113 Expr::Lam(
1114 *bi,
1115 crate::Name::anonymous(),
1116 Node::new(ty.clone()),
1117 Node::new(acc),
1118 )
1119 })
1120}
1121pub fn is_app_of_fvar(e: &Expr, id: FVarId) -> bool {
1123 get_app_fn(e) == &Expr::FVar(id)
1124}
1125pub fn get_nth_arg(e: &Expr, n: usize) -> Option<&Expr> {
1127 let args = get_app_args(e);
1128 args.get(n).copied()
1129}
1130pub fn is_simple(e: &Expr) -> bool {
1132 matches!(
1133 e,
1134 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_)
1135 )
1136}
1137#[cfg(test)]
1138mod extended_tests {
1139 use super::*;
1140 use crate::{BinderInfo, Level};
1141 fn nat() -> Expr {
1142 Expr::Const(Name::str("Nat"), vec![])
1143 }
1144 fn prop() -> Expr {
1145 Expr::Sort(Level::zero())
1146 }
1147 fn bv(i: u32) -> Expr {
1148 Expr::BVar(i)
1149 }
1150 #[test]
1151 fn test_is_prop() {
1152 assert!(is_prop(&prop()));
1153 assert!(!is_prop(&nat()));
1154 }
1155 #[test]
1156 fn test_is_sort() {
1157 assert!(is_sort(&prop()));
1158 assert!(is_sort(&Expr::Sort(Level::succ(Level::zero()))));
1159 assert!(!is_sort(&nat()));
1160 }
1161 #[test]
1162 fn test_is_lambda_pi() {
1163 let lam = Expr::Lam(
1164 BinderInfo::Default,
1165 crate::Name::anonymous(),
1166 Node::new(prop()),
1167 Node::new(bv(0)),
1168 );
1169 let pi = Expr::Pi(
1170 BinderInfo::Default,
1171 crate::Name::anonymous(),
1172 Node::new(prop()),
1173 Node::new(bv(0)),
1174 );
1175 assert!(is_lambda(&lam));
1176 assert!(!is_lambda(&pi));
1177 assert!(is_pi(&pi));
1178 assert!(!is_pi(&lam));
1179 }
1180 #[test]
1181 fn test_is_fvar_bvar() {
1182 use crate::FVarId;
1183 assert!(is_fvar(&Expr::FVar(FVarId(0))));
1184 assert!(is_bvar(&bv(0)));
1185 assert!(!is_fvar(&nat()));
1186 }
1187 #[test]
1188 fn test_get_sort_level() {
1189 let s = Expr::Sort(Level::zero());
1190 assert_eq!(get_sort_level(&s), Some(&Level::zero()));
1191 assert_eq!(get_sort_level(&nat()), None);
1192 }
1193 #[test]
1194 fn test_get_const_name() {
1195 assert_eq!(get_const_name(&nat()), Some(&Name::str("Nat")));
1196 assert_eq!(get_const_name(&prop()), None);
1197 }
1198 #[test]
1199 fn test_get_bvar_idx() {
1200 assert_eq!(get_bvar_idx(&bv(3)), Some(3));
1201 assert_eq!(get_bvar_idx(&nat()), None);
1202 }
1203 #[test]
1204 fn test_decompose_let() {
1205 let e = Expr::Let(
1206 crate::Name::anonymous(),
1207 Node::new(nat()),
1208 Node::new(bv(0)),
1209 Node::new(bv(0)),
1210 );
1211 let (ty, val, body) = decompose_let(&e).expect("value should be present");
1212 assert_eq!(ty, &nat());
1213 assert_eq!(val, &bv(0));
1214 assert_eq!(body, &bv(0));
1215 }
1216 #[test]
1217 fn test_decompose_pi() {
1218 let e = Expr::Pi(
1219 BinderInfo::Default,
1220 crate::Name::anonymous(),
1221 Node::new(nat()),
1222 Node::new(prop()),
1223 );
1224 let (bi, dom, cod) = decompose_pi(&e).expect("value should be present");
1225 assert_eq!(bi, BinderInfo::Default);
1226 assert_eq!(dom, &nat());
1227 assert_eq!(cod, &prop());
1228 }
1229 #[test]
1230 fn test_decompose_lam() {
1231 let e = Expr::Lam(
1232 BinderInfo::Implicit,
1233 crate::Name::anonymous(),
1234 Node::new(nat()),
1235 Node::new(bv(0)),
1236 );
1237 let (bi, dom, body) = decompose_lam(&e).expect("value should be present");
1238 assert_eq!(bi, BinderInfo::Implicit);
1239 assert_eq!(dom, &nat());
1240 assert_eq!(body, &bv(0));
1241 }
1242 #[test]
1243 fn test_mk_pi_n_empty() {
1244 let ret = nat();
1245 let result = mk_pi_n(&[], ret.clone());
1246 assert_eq!(result, ret);
1247 }
1248 #[test]
1249 fn test_mk_pi_n_two() {
1250 let binders = vec![(BinderInfo::Default, nat()), (BinderInfo::Default, prop())];
1251 let ret = bv(0);
1252 let result = mk_pi_n(&binders, ret);
1253 assert!(is_pi(&result));
1254 let (_, _, inner) = decompose_pi(&result).expect("value should be present");
1255 assert!(is_pi(inner));
1256 }
1257 #[test]
1258 fn test_mk_lam_n_two() {
1259 let binders = vec![(BinderInfo::Default, nat()), (BinderInfo::Implicit, prop())];
1260 let result = mk_lam_n(&binders, bv(0));
1261 assert!(is_lambda(&result));
1262 }
1263 #[test]
1264 fn test_is_simple() {
1265 assert!(is_simple(&nat()));
1266 assert!(is_simple(&bv(0)));
1267 assert!(is_simple(&prop()));
1268 let app = Expr::App(Node::new(nat()), Node::new(bv(0)));
1269 assert!(!is_simple(&app));
1270 }
1271 #[test]
1272 fn test_get_nth_arg() {
1273 let f = nat();
1274 let arg0 = bv(0);
1275 let arg1 = bv(1);
1276 let app = Expr::App(
1277 Node::new(Expr::App(Node::new(f), Node::new(arg0.clone()))),
1278 Node::new(arg1.clone()),
1279 );
1280 assert_eq!(get_nth_arg(&app, 0), Some(&arg0));
1281 assert_eq!(get_nth_arg(&app, 1), Some(&arg1));
1282 assert_eq!(get_nth_arg(&app, 2), None);
1283 }
1284 #[test]
1285 fn test_is_literal() {
1286 use crate::Literal;
1287 let lit = Expr::Lit(Literal::nat(42));
1288 assert!(is_literal(&lit));
1289 assert!(!is_literal(&nat()));
1290 }
1291}
1292#[cfg(test)]
1293mod tests_padding_infra {
1294 use super::*;
1295 #[test]
1296 fn test_stat_summary() {
1297 let mut ss = StatSummary::new();
1298 ss.record(10.0);
1299 ss.record(20.0);
1300 ss.record(30.0);
1301 assert_eq!(ss.count(), 3);
1302 assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
1303 assert_eq!(ss.min().expect("min should succeed") as i64, 10);
1304 assert_eq!(ss.max().expect("max should succeed") as i64, 30);
1305 }
1306 #[test]
1307 fn test_transform_stat() {
1308 let mut ts = TransformStat::new();
1309 ts.record_before(100.0);
1310 ts.record_after(80.0);
1311 let ratio = ts.mean_ratio().expect("ratio should be present");
1312 assert!((ratio - 0.8).abs() < 1e-9);
1313 }
1314 #[test]
1315 fn test_small_map() {
1316 let mut m: SmallMap<u32, &str> = SmallMap::new();
1317 m.insert(3, "three");
1318 m.insert(1, "one");
1319 m.insert(2, "two");
1320 assert_eq!(m.get(&2), Some(&"two"));
1321 assert_eq!(m.len(), 3);
1322 let keys = m.keys();
1323 assert_eq!(*keys[0], 1);
1324 assert_eq!(*keys[2], 3);
1325 }
1326 #[test]
1327 fn test_label_set() {
1328 let mut ls = LabelSet::new();
1329 ls.add("foo");
1330 ls.add("bar");
1331 ls.add("foo");
1332 assert_eq!(ls.count(), 2);
1333 assert!(ls.has("bar"));
1334 assert!(!ls.has("baz"));
1335 }
1336 #[test]
1337 fn test_config_node() {
1338 let mut root = ConfigNode::section("root");
1339 let child = ConfigNode::leaf("key", "value");
1340 root.add_child(child);
1341 assert_eq!(root.num_children(), 1);
1342 }
1343 #[test]
1344 fn test_versioned_record() {
1345 let mut vr = VersionedRecord::new(0u32);
1346 vr.update(1);
1347 vr.update(2);
1348 assert_eq!(*vr.current(), 2);
1349 assert_eq!(vr.version(), 2);
1350 assert!(vr.has_history());
1351 assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
1352 }
1353 #[test]
1354 fn test_simple_dag() {
1355 let mut dag = SimpleDag::new(4);
1356 dag.add_edge(0, 1);
1357 dag.add_edge(1, 2);
1358 dag.add_edge(2, 3);
1359 assert!(dag.can_reach(0, 3));
1360 assert!(!dag.can_reach(3, 0));
1361 let order = dag.topological_sort().expect("order should be present");
1362 assert_eq!(order, vec![0, 1, 2, 3]);
1363 }
1364 #[test]
1365 fn test_focus_stack() {
1366 let mut fs: FocusStack<&str> = FocusStack::new();
1367 fs.focus("a");
1368 fs.focus("b");
1369 assert_eq!(fs.current(), Some(&"b"));
1370 assert_eq!(fs.depth(), 2);
1371 fs.blur();
1372 assert_eq!(fs.current(), Some(&"a"));
1373 }
1374}
1375#[cfg(test)]
1376mod tests_extra_iterators {
1377 use super::*;
1378 #[test]
1379 fn test_window_iterator() {
1380 let data = vec![1u32, 2, 3, 4, 5];
1381 let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
1382 assert_eq!(windows.len(), 3);
1383 assert_eq!(windows[0], &[1, 2, 3]);
1384 assert_eq!(windows[2], &[3, 4, 5]);
1385 }
1386 #[test]
1387 fn test_non_empty_vec() {
1388 let mut nev = NonEmptyVec::singleton(10u32);
1389 nev.push(20);
1390 nev.push(30);
1391 assert_eq!(nev.len(), 3);
1392 assert_eq!(*nev.first(), 10);
1393 assert_eq!(*nev.last(), 30);
1394 }
1395}
1396#[cfg(test)]
1397mod tests_padding2 {
1398 use super::*;
1399 #[test]
1400 fn test_sliding_sum() {
1401 let mut ss = SlidingSum::new(3);
1402 ss.push(1.0);
1403 ss.push(2.0);
1404 ss.push(3.0);
1405 assert!((ss.sum() - 6.0).abs() < 1e-9);
1406 ss.push(4.0);
1407 assert!((ss.sum() - 9.0).abs() < 1e-9);
1408 assert_eq!(ss.count(), 3);
1409 }
1410 #[test]
1411 fn test_path_buf() {
1412 let mut pb = PathBuf::new();
1413 pb.push("src");
1414 pb.push("main");
1415 assert_eq!(pb.as_str(), "src/main");
1416 assert_eq!(pb.depth(), 2);
1417 pb.pop();
1418 assert_eq!(pb.as_str(), "src");
1419 }
1420 #[test]
1421 fn test_string_pool() {
1422 let mut pool = StringPool::new();
1423 let s = pool.take();
1424 assert!(s.is_empty());
1425 pool.give("hello".to_string());
1426 let s2 = pool.take();
1427 assert!(s2.is_empty());
1428 assert_eq!(pool.free_count(), 0);
1429 }
1430 #[test]
1431 fn test_transitive_closure() {
1432 let mut tc = TransitiveClosure::new(4);
1433 tc.add_edge(0, 1);
1434 tc.add_edge(1, 2);
1435 tc.add_edge(2, 3);
1436 assert!(tc.can_reach(0, 3));
1437 assert!(!tc.can_reach(3, 0));
1438 let r = tc.reachable_from(0);
1439 assert_eq!(r.len(), 4);
1440 }
1441 #[test]
1442 fn test_token_bucket() {
1443 let mut tb = TokenBucket::new(100, 0);
1444 assert_eq!(tb.available(), 100);
1445 assert!(tb.try_consume(50));
1446 assert_eq!(tb.available(), 50);
1447 assert!(!tb.try_consume(60));
1448 assert_eq!(tb.capacity(), 100);
1449 }
1450 #[test]
1451 fn test_rewrite_rule_set() {
1452 let mut rrs = RewriteRuleSet::new();
1453 rrs.add(RewriteRule::unconditional(
1454 "beta",
1455 "App(Lam(x, b), v)",
1456 "b[x:=v]",
1457 ));
1458 rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
1459 assert_eq!(rrs.len(), 2);
1460 assert_eq!(rrs.unconditional_rules().len(), 1);
1461 assert_eq!(rrs.conditional_rules().len(), 1);
1462 assert!(rrs.get("beta").is_some());
1463 let disp = rrs
1464 .get("beta")
1465 .expect("element at \'beta\' should exist")
1466 .display();
1467 assert!(disp.contains("→"));
1468 }
1469}
1470#[cfg(test)]
1471mod tests_padding3 {
1472 use super::*;
1473 #[test]
1474 fn test_decision_node() {
1475 let tree = DecisionNode::Branch {
1476 key: "x".into(),
1477 val: "1".into(),
1478 yes_branch: Box::new(DecisionNode::Leaf("yes".into())),
1479 no_branch: Box::new(DecisionNode::Leaf("no".into())),
1480 };
1481 let mut ctx = std::collections::HashMap::new();
1482 ctx.insert("x".into(), "1".into());
1483 assert_eq!(tree.evaluate(&ctx), "yes");
1484 ctx.insert("x".into(), "2".into());
1485 assert_eq!(tree.evaluate(&ctx), "no");
1486 assert_eq!(tree.depth(), 1);
1487 }
1488 #[test]
1489 fn test_flat_substitution() {
1490 let mut sub = FlatSubstitution::new();
1491 sub.add("foo", "bar");
1492 sub.add("baz", "qux");
1493 assert_eq!(sub.apply("foo and baz"), "bar and qux");
1494 assert_eq!(sub.len(), 2);
1495 }
1496 #[test]
1497 fn test_stopwatch() {
1498 let mut sw = Stopwatch::start();
1499 sw.split();
1500 sw.split();
1501 assert_eq!(sw.num_splits(), 2);
1502 assert!(sw.elapsed_ms() >= 0.0);
1503 for &s in sw.splits() {
1504 assert!(s >= 0.0);
1505 }
1506 }
1507 #[test]
1508 fn test_either2() {
1509 let e: Either2<i32, &str> = Either2::First(42);
1510 assert!(e.is_first());
1511 let mapped = e.map_first(|x| x * 2);
1512 assert_eq!(mapped.first(), Some(84));
1513 let e2: Either2<i32, &str> = Either2::Second("hello");
1514 assert!(e2.is_second());
1515 assert_eq!(e2.second(), Some("hello"));
1516 }
1517 #[test]
1518 fn test_write_once() {
1519 let wo: WriteOnce<u32> = WriteOnce::new();
1520 assert!(!wo.is_written());
1521 assert!(wo.write(42));
1522 assert!(!wo.write(99));
1523 assert_eq!(wo.read(), Some(42));
1524 }
1525 #[test]
1526 fn test_sparse_vec() {
1527 let mut sv: SparseVec<i32> = SparseVec::new(100);
1528 sv.set(5, 10);
1529 sv.set(50, 20);
1530 assert_eq!(*sv.get(5), 10);
1531 assert_eq!(*sv.get(50), 20);
1532 assert_eq!(*sv.get(0), 0);
1533 assert_eq!(sv.nnz(), 2);
1534 sv.set(5, 0);
1535 assert_eq!(sv.nnz(), 1);
1536 }
1537 #[test]
1538 fn test_stack_calc() {
1539 let mut calc = StackCalc::new();
1540 calc.push(3);
1541 calc.push(4);
1542 assert_eq!(calc.add(), Some(7));
1543 assert_eq!(calc.peek(), Some(7));
1544 calc.push(2);
1545 assert_eq!(calc.mul(), Some(14));
1546 assert_eq!(calc.peek(), Some(14));
1547 }
1548}
1549#[cfg(test)]
1550mod tests_final_padding {
1551 use super::*;
1552 #[test]
1553 fn test_min_heap() {
1554 let mut h = MinHeap::new();
1555 h.push(5u32);
1556 h.push(1u32);
1557 h.push(3u32);
1558 assert_eq!(h.peek(), Some(&1));
1559 assert_eq!(h.pop(), Some(1));
1560 assert_eq!(h.pop(), Some(3));
1561 assert_eq!(h.pop(), Some(5));
1562 assert!(h.is_empty());
1563 }
1564 #[test]
1565 fn test_prefix_counter() {
1566 let mut pc = PrefixCounter::new();
1567 pc.record("hello");
1568 pc.record("help");
1569 pc.record("world");
1570 assert_eq!(pc.count_with_prefix("hel"), 2);
1571 assert_eq!(pc.count_with_prefix("wor"), 1);
1572 assert_eq!(pc.count_with_prefix("xyz"), 0);
1573 }
1574 #[test]
1575 fn test_fixture() {
1576 let mut f = Fixture::new();
1577 f.set("key1", "val1");
1578 f.set("key2", "val2");
1579 assert_eq!(f.get("key1"), Some("val1"));
1580 assert_eq!(f.get("key3"), None);
1581 assert_eq!(f.len(), 2);
1582 }
1583}