1use 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
14pub fn get_app_fn(e: &Expr) -> &Expr {
18 match e {
19 Expr::App(f, _) => get_app_fn(f),
20 _ => e,
21 }
22}
23pub 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}
37pub 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}
55pub 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}
62pub 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}
70pub 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}
78pub fn has_loose_bvars(e: &Expr) -> bool {
83 has_loose_bvar_ge(e, 0)
84}
85pub 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}
102pub 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}
119pub 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}
134pub 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}
147pub 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}
178pub 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}
225pub 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}
238pub 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}
251pub 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}
303pub 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}
318pub fn count_lambdas(e: &Expr) -> u32 {
320 match e {
321 Expr::Lam(_, _, _, body) => 1 + count_lambdas(body),
322 _ => 0,
323 }
324}
325pub fn count_pis(e: &Expr) -> u32 {
327 match e {
328 Expr::Pi(_, _, _, body) => 1 + count_pis(body),
329 _ => 0,
330 }
331}
332pub 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}
342pub 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}
352pub 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}
361pub 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}
377pub 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}
401pub 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}
414pub fn is_app_of(e: &Expr, name: &Name) -> bool {
416 matches!(get_app_fn(e), Expr::Const(n, _) if n == name)
417}
418pub 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}
427pub fn mk_prop() -> Expr {
429 Expr::Sort(Level::zero())
430}
431pub fn mk_type(u: Level) -> Expr {
433 Expr::Sort(Level::succ(u))
434}
435pub fn mk_type0() -> Expr {
437 Expr::Sort(Level::succ(Level::zero()))
438}
439pub fn var(name: &str) -> Expr {
441 Expr::Const(Name::str(name), vec![])
442}
443pub fn bvar(idx: u32) -> Expr {
445 Expr::BVar(idx)
446}
447pub fn app(f: Expr, a: Expr) -> Expr {
449 Expr::App(Box::new(f), Box::new(a))
450}
451pub 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}
460pub 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}
469pub fn prop() -> Expr {
471 Expr::Sort(crate::Level::zero())
472}
473pub fn sort() -> Expr {
475 Expr::Sort(crate::Level::zero())
476}
477pub 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#[inline]
677pub fn is_sort(e: &Expr) -> bool {
678 matches!(e, Expr::Sort(_))
679}
680#[inline]
682pub fn is_prop(e: &Expr) -> bool {
683 matches!(e, Expr::Sort(l) if matches!(l, Level::Zero))
684}
685#[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#[inline]
692pub fn is_lambda(e: &Expr) -> bool {
693 matches!(e, Expr::Lam(_, _, _, _))
694}
695#[inline]
697pub fn is_pi(e: &Expr) -> bool {
698 matches!(e, Expr::Pi(_, _, _, _))
699}
700#[inline]
702pub fn is_fvar(e: &Expr) -> bool {
703 matches!(e, Expr::FVar(_))
704}
705#[inline]
707pub fn is_bvar(e: &Expr) -> bool {
708 matches!(e, Expr::BVar(_))
709}
710#[inline]
712pub fn is_literal(e: &Expr) -> bool {
713 matches!(e, Expr::Lit(_))
714}
715#[inline]
717pub fn is_const(e: &Expr) -> bool {
718 matches!(e, Expr::Const(_, _))
719}
720#[inline]
722pub fn is_app(e: &Expr) -> bool {
723 matches!(e, Expr::App(_, _))
724}
725#[inline]
727pub fn is_let(e: &Expr) -> bool {
728 matches!(e, Expr::Let(_, _, _, _))
729}
730#[inline]
732pub fn is_proj(e: &Expr) -> bool {
733 matches!(e, Expr::Proj(_, _, _))
734}
735#[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#[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#[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#[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#[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#[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#[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#[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#[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}
816pub 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}
830pub 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}
841pub fn is_app_of_fvar(e: &Expr, id: FVarId) -> bool {
843 get_app_fn(e) == &Expr::FVar(id)
844}
845pub fn get_nth_arg(e: &Expr, n: usize) -> Option<&Expr> {
847 let args = get_app_args(e);
848 args.get(n).copied()
849}
850pub 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}