1use crate::declaration::{
6 AxiomVal, ConstantInfo, ConstantVal, ConstructorVal, InductiveVal, RecursorRule, RecursorVal,
7};
8use crate::{BinderInfo, Declaration, Environment, Expr, Level, Name};
9
10use super::types::{
11 BuiltinInfo, BuiltinKind, ConfigNode, DecisionNode, Either2, FlatSubstitution, FocusStack,
12 LabelSet, NonEmptyVec, PathBuf, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum, SmallMap,
13 SparseVec, StackCalc, StatSummary, Stopwatch, StringPool, TokenBucket, TransformStat,
14 TransitiveClosure, VersionedRecord, WindowIterator, WriteOnce,
15};
16
17pub fn init_builtin_env(env: &mut Environment) -> Result<(), String> {
19 add_legacy_axioms(env)?;
20 add_bool_inductive(env)?;
21 add_unit_inductive(env)?;
22 add_empty_inductive(env)?;
23 add_nat_inductive(env)?;
24 add_string_type(env)?;
25 add_core_axioms(env)?;
26 add_decidable_eq(env)?;
27 add_eq_inductive(env)?;
28 add_prod_inductive(env)?;
29 add_list_inductive(env)?;
30 Ok(())
31}
32pub(super) fn add_legacy_axioms(env: &mut Environment) -> Result<(), String> {
35 let type0 = Expr::Sort(Level::zero());
36 let type1 = Expr::Sort(Level::succ(Level::zero()));
37 env.add(Declaration::Axiom {
38 name: Name::str("Bool"),
39 univ_params: vec![],
40 ty: type1.clone(),
41 })
42 .map_err(|e| e.to_string())?;
43 env.add(Declaration::Axiom {
44 name: Name::str("true"),
45 univ_params: vec![],
46 ty: Expr::Const(Name::str("Bool"), vec![]),
47 })
48 .map_err(|e| e.to_string())?;
49 env.add(Declaration::Axiom {
50 name: Name::str("false"),
51 univ_params: vec![],
52 ty: Expr::Const(Name::str("Bool"), vec![]),
53 })
54 .map_err(|e| e.to_string())?;
55 env.add(Declaration::Axiom {
56 name: Name::str("Unit"),
57 univ_params: vec![],
58 ty: type1,
59 })
60 .map_err(|e| e.to_string())?;
61 env.add(Declaration::Axiom {
62 name: Name::str("unit"),
63 univ_params: vec![],
64 ty: Expr::Const(Name::str("Unit"), vec![]),
65 })
66 .map_err(|e| e.to_string())?;
67 env.add(Declaration::Axiom {
68 name: Name::str("Empty"),
69 univ_params: vec![],
70 ty: type0.clone(),
71 })
72 .map_err(|e| e.to_string())?;
73 let rec_ty = Expr::Pi(
74 BinderInfo::Implicit,
75 Name::str("C"),
76 Box::new(type0),
77 Box::new(Expr::Pi(
78 BinderInfo::Default,
79 Name::str("_"),
80 Box::new(Expr::Const(Name::str("Empty"), vec![])),
81 Box::new(Expr::BVar(1)),
82 )),
83 );
84 env.add(Declaration::Axiom {
85 name: Name::str("Empty.rec"),
86 univ_params: vec![],
87 ty: rec_ty,
88 })
89 .map_err(|e| e.to_string())?;
90 Ok(())
91}
92pub(super) fn add_bool_inductive(env: &mut Environment) -> Result<(), String> {
94 let type1 = Expr::Sort(Level::succ(Level::zero()));
95 let bool_const = Expr::Const(Name::str("Bool"), vec![]);
96 let ctor_true = ConstantInfo::Constructor(ConstructorVal {
97 common: ConstantVal {
98 name: Name::str("Bool.true"),
99 level_params: vec![],
100 ty: bool_const.clone(),
101 },
102 induct: Name::str("Bool"),
103 cidx: 0,
104 num_params: 0,
105 num_fields: 0,
106 is_unsafe: false,
107 });
108 let ctor_false = ConstantInfo::Constructor(ConstructorVal {
109 common: ConstantVal {
110 name: Name::str("Bool.false"),
111 level_params: vec![],
112 ty: bool_const,
113 },
114 induct: Name::str("Bool"),
115 cidx: 1,
116 num_params: 0,
117 num_fields: 0,
118 is_unsafe: false,
119 });
120 let ind = ConstantInfo::Inductive(InductiveVal {
121 common: ConstantVal {
122 name: Name::str("Bool.ind"),
123 level_params: vec![],
124 ty: type1,
125 },
126 num_params: 0,
127 num_indices: 0,
128 all: vec![Name::str("Bool")],
129 ctors: vec![Name::str("Bool.true"), Name::str("Bool.false")],
130 num_nested: 0,
131 is_rec: false,
132 is_unsafe: false,
133 is_reflexive: false,
134 is_prop: false,
135 });
136 let rec = ConstantInfo::Recursor(RecursorVal {
137 common: ConstantVal {
138 name: Name::str("Bool.rec"),
139 level_params: vec![Name::str("u_1")],
140 ty: Expr::Sort(Level::zero()),
141 },
142 all: vec![Name::str("Bool")],
143 num_params: 0,
144 num_indices: 0,
145 num_motives: 1,
146 num_minors: 2,
147 rules: vec![
148 RecursorRule {
149 ctor: Name::str("Bool.true"),
150 nfields: 0,
151 rhs: Expr::BVar(0),
152 },
153 RecursorRule {
154 ctor: Name::str("Bool.false"),
155 nfields: 0,
156 rhs: Expr::BVar(0),
157 },
158 ],
159 k: false,
160 is_unsafe: false,
161 });
162 env.add_constant(ind).map_err(|e| e.to_string())?;
163 env.add_constant(ctor_true).map_err(|e| e.to_string())?;
164 env.add_constant(ctor_false).map_err(|e| e.to_string())?;
165 env.add_constant(rec).map_err(|e| e.to_string())?;
166 Ok(())
167}
168pub(super) fn add_unit_inductive(env: &mut Environment) -> Result<(), String> {
170 let type1 = Expr::Sort(Level::succ(Level::zero()));
171 let unit_const = Expr::Const(Name::str("Unit"), vec![]);
172 let ind = ConstantInfo::Inductive(InductiveVal {
173 common: ConstantVal {
174 name: Name::str("Unit.ind"),
175 level_params: vec![],
176 ty: type1,
177 },
178 num_params: 0,
179 num_indices: 0,
180 all: vec![Name::str("Unit")],
181 ctors: vec![Name::str("Unit.unit")],
182 num_nested: 0,
183 is_rec: false,
184 is_unsafe: false,
185 is_reflexive: false,
186 is_prop: false,
187 });
188 let ctor = ConstantInfo::Constructor(ConstructorVal {
189 common: ConstantVal {
190 name: Name::str("Unit.unit"),
191 level_params: vec![],
192 ty: unit_const,
193 },
194 induct: Name::str("Unit"),
195 cidx: 0,
196 num_params: 0,
197 num_fields: 0,
198 is_unsafe: false,
199 });
200 let rec = ConstantInfo::Recursor(RecursorVal {
201 common: ConstantVal {
202 name: Name::str("Unit.rec"),
203 level_params: vec![Name::str("u_1")],
204 ty: Expr::Sort(Level::zero()),
205 },
206 all: vec![Name::str("Unit")],
207 num_params: 0,
208 num_indices: 0,
209 num_motives: 1,
210 num_minors: 1,
211 rules: vec![RecursorRule {
212 ctor: Name::str("Unit.unit"),
213 nfields: 0,
214 rhs: Expr::BVar(0),
215 }],
216 k: false,
217 is_unsafe: false,
218 });
219 env.add_constant(ind).map_err(|e| e.to_string())?;
220 env.add_constant(ctor).map_err(|e| e.to_string())?;
221 env.add_constant(rec).map_err(|e| e.to_string())?;
222 Ok(())
223}
224pub(super) fn add_empty_inductive(env: &mut Environment) -> Result<(), String> {
226 let type0 = Expr::Sort(Level::zero());
227 let ind = ConstantInfo::Inductive(InductiveVal {
228 common: ConstantVal {
229 name: Name::str("Empty.ind"),
230 level_params: vec![],
231 ty: type0,
232 },
233 num_params: 0,
234 num_indices: 0,
235 all: vec![Name::str("Empty")],
236 ctors: vec![],
237 num_nested: 0,
238 is_rec: false,
239 is_unsafe: false,
240 is_reflexive: false,
241 is_prop: true,
242 });
243 env.add_constant(ind).map_err(|e| e.to_string())?;
244 Ok(())
245}
246pub(super) fn add_nat_inductive(env: &mut Environment) -> Result<(), String> {
248 let type1 = Expr::Sort(Level::succ(Level::zero()));
249 let nat_const = Expr::Const(Name::str("Nat"), vec![]);
250 let ind = ConstantInfo::Inductive(InductiveVal {
251 common: ConstantVal {
252 name: Name::str("Nat"),
253 level_params: vec![],
254 ty: type1,
255 },
256 num_params: 0,
257 num_indices: 0,
258 all: vec![Name::str("Nat")],
259 ctors: vec![Name::str("Nat.zero"), Name::str("Nat.succ")],
260 num_nested: 0,
261 is_rec: true,
262 is_unsafe: false,
263 is_reflexive: false,
264 is_prop: false,
265 });
266 let ctor_zero = ConstantInfo::Constructor(ConstructorVal {
267 common: ConstantVal {
268 name: Name::str("Nat.zero"),
269 level_params: vec![],
270 ty: nat_const.clone(),
271 },
272 induct: Name::str("Nat"),
273 cidx: 0,
274 num_params: 0,
275 num_fields: 0,
276 is_unsafe: false,
277 });
278 let succ_ty = Expr::Pi(
279 BinderInfo::Default,
280 Name::str("n"),
281 Box::new(nat_const.clone()),
282 Box::new(nat_const),
283 );
284 let ctor_succ = ConstantInfo::Constructor(ConstructorVal {
285 common: ConstantVal {
286 name: Name::str("Nat.succ"),
287 level_params: vec![],
288 ty: succ_ty,
289 },
290 induct: Name::str("Nat"),
291 cidx: 1,
292 num_params: 0,
293 num_fields: 1,
294 is_unsafe: false,
295 });
296 let rec = ConstantInfo::Recursor(RecursorVal {
297 common: ConstantVal {
298 name: Name::str("Nat.rec"),
299 level_params: vec![Name::str("u_1")],
300 ty: Expr::Sort(Level::zero()),
301 },
302 all: vec![Name::str("Nat")],
303 num_params: 0,
304 num_indices: 0,
305 num_motives: 1,
306 num_minors: 2,
307 rules: vec![
308 RecursorRule {
309 ctor: Name::str("Nat.zero"),
310 nfields: 0,
311 rhs: Expr::BVar(0),
312 },
313 RecursorRule {
314 ctor: Name::str("Nat.succ"),
315 nfields: 1,
316 rhs: Expr::BVar(0),
317 },
318 ],
319 k: false,
320 is_unsafe: false,
321 });
322 env.add_constant(ind).map_err(|e| e.to_string())?;
323 env.add_constant(ctor_zero).map_err(|e| e.to_string())?;
324 env.add_constant(ctor_succ).map_err(|e| e.to_string())?;
325 env.add_constant(rec).map_err(|e| e.to_string())?;
326 register_nat_ops(env)?;
327 Ok(())
328}
329pub(super) fn register_nat_ops(env: &mut Environment) -> Result<(), String> {
331 let nat = Expr::Const(Name::str("Nat"), vec![]);
332 let bool_ty = Expr::Const(Name::str("Bool"), vec![]);
333 let nat_binop = Expr::Pi(
334 BinderInfo::Default,
335 Name::str("a"),
336 Box::new(nat.clone()),
337 Box::new(Expr::Pi(
338 BinderInfo::Default,
339 Name::str("b"),
340 Box::new(nat.clone()),
341 Box::new(nat.clone()),
342 )),
343 );
344 let nat_cmp = Expr::Pi(
345 BinderInfo::Default,
346 Name::str("a"),
347 Box::new(nat.clone()),
348 Box::new(Expr::Pi(
349 BinderInfo::Default,
350 Name::str("b"),
351 Box::new(nat),
352 Box::new(bool_ty),
353 )),
354 );
355 let binop_names = [
356 "Nat.add",
357 "Nat.sub",
358 "Nat.mul",
359 "Nat.div",
360 "Nat.mod",
361 "Nat.pow",
362 "Nat.gcd",
363 "Nat.land",
364 "Nat.lor",
365 "Nat.xor",
366 "Nat.shiftLeft",
367 "Nat.shiftRight",
368 ];
369 for name in &binop_names {
370 env.add_constant(ConstantInfo::Axiom(AxiomVal {
371 common: ConstantVal {
372 name: Name::str(*name),
373 level_params: vec![],
374 ty: nat_binop.clone(),
375 },
376 is_unsafe: false,
377 }))
378 .map_err(|e| e.to_string())?;
379 }
380 let cmp_names = ["Nat.beq", "Nat.ble", "Nat.blt"];
381 for name in &cmp_names {
382 env.add_constant(ConstantInfo::Axiom(AxiomVal {
383 common: ConstantVal {
384 name: Name::str(*name),
385 level_params: vec![],
386 ty: nat_cmp.clone(),
387 },
388 is_unsafe: false,
389 }))
390 .map_err(|e| e.to_string())?;
391 }
392 Ok(())
393}
394pub(super) fn add_string_type(env: &mut Environment) -> Result<(), String> {
396 let type1 = Expr::Sort(Level::succ(Level::zero()));
397 let str_ty = Expr::Const(Name::str("String"), vec![]);
398 let nat_ty = Expr::Const(Name::str("Nat"), vec![]);
399 let bool_ty = Expr::Const(Name::str("Bool"), vec![]);
400 env.add_constant(ConstantInfo::Axiom(AxiomVal {
401 common: ConstantVal {
402 name: Name::str("String"),
403 level_params: vec![],
404 ty: type1,
405 },
406 is_unsafe: false,
407 }))
408 .map_err(|e| e.to_string())?;
409 env.add_constant(ConstantInfo::Axiom(AxiomVal {
410 common: ConstantVal {
411 name: Name::str("String.length"),
412 level_params: vec![],
413 ty: Expr::Pi(
414 BinderInfo::Default,
415 Name::str("s"),
416 Box::new(str_ty.clone()),
417 Box::new(nat_ty),
418 ),
419 },
420 is_unsafe: false,
421 }))
422 .map_err(|e| e.to_string())?;
423 env.add_constant(ConstantInfo::Axiom(AxiomVal {
424 common: ConstantVal {
425 name: Name::str("String.append"),
426 level_params: vec![],
427 ty: Expr::Pi(
428 BinderInfo::Default,
429 Name::str("a"),
430 Box::new(str_ty.clone()),
431 Box::new(Expr::Pi(
432 BinderInfo::Default,
433 Name::str("b"),
434 Box::new(str_ty.clone()),
435 Box::new(str_ty.clone()),
436 )),
437 ),
438 },
439 is_unsafe: false,
440 }))
441 .map_err(|e| e.to_string())?;
442 env.add_constant(ConstantInfo::Axiom(AxiomVal {
443 common: ConstantVal {
444 name: Name::str("String.beq"),
445 level_params: vec![],
446 ty: Expr::Pi(
447 BinderInfo::Default,
448 Name::str("a"),
449 Box::new(str_ty.clone()),
450 Box::new(Expr::Pi(
451 BinderInfo::Default,
452 Name::str("b"),
453 Box::new(str_ty),
454 Box::new(bool_ty),
455 )),
456 ),
457 },
458 is_unsafe: false,
459 }))
460 .map_err(|e| e.to_string())?;
461 Ok(())
462}
463pub(super) fn add_core_axioms(env: &mut Environment) -> Result<(), String> {
465 let type0 = Expr::Sort(Level::zero());
466 let propext_ty = Expr::Pi(
467 BinderInfo::Implicit,
468 Name::str("a"),
469 Box::new(type0.clone()),
470 Box::new(Expr::Pi(
471 BinderInfo::Implicit,
472 Name::str("b"),
473 Box::new(type0.clone()),
474 Box::new(type0.clone()),
475 )),
476 );
477 env.add_constant(ConstantInfo::Axiom(AxiomVal {
478 common: ConstantVal {
479 name: Name::str("propext"),
480 level_params: vec![],
481 ty: propext_ty,
482 },
483 is_unsafe: false,
484 }))
485 .map_err(|e| e.to_string())?;
486 let quot_ty = Expr::Pi(
487 BinderInfo::Implicit,
488 Name::str("α"),
489 Box::new(Expr::Sort(Level::param(Name::str("u")))),
490 Box::new(Expr::Pi(
491 BinderInfo::Default,
492 Name::str("r"),
493 Box::new(type0.clone()),
494 Box::new(Expr::Sort(Level::param(Name::str("u")))),
495 )),
496 );
497 env.add_constant(ConstantInfo::Axiom(AxiomVal {
498 common: ConstantVal {
499 name: Name::str("Quot"),
500 level_params: vec![Name::str("u")],
501 ty: quot_ty,
502 },
503 is_unsafe: false,
504 }))
505 .map_err(|e| e.to_string())?;
506 let choice_ty = Expr::Pi(
507 BinderInfo::Implicit,
508 Name::str("α"),
509 Box::new(Expr::Sort(Level::param(Name::str("u")))),
510 Box::new(Expr::Pi(
511 BinderInfo::Default,
512 Name::str("_"),
513 Box::new(type0),
514 Box::new(Expr::BVar(1)),
515 )),
516 );
517 env.add_constant(ConstantInfo::Axiom(AxiomVal {
518 common: ConstantVal {
519 name: Name::str("Classical.choice"),
520 level_params: vec![Name::str("u")],
521 ty: choice_ty,
522 },
523 is_unsafe: false,
524 }))
525 .map_err(|e| e.to_string())?;
526 Ok(())
527}
528pub(super) fn add_decidable_eq(env: &mut Environment) -> Result<(), String> {
530 let type1 = Expr::Sort(Level::succ(Level::zero()));
531 let type0 = Expr::Sort(Level::zero());
532 let decidable_eq_ty = Expr::Pi(
533 BinderInfo::Default,
534 Name::str("α"),
535 Box::new(type1.clone()),
536 Box::new(type0),
537 );
538 env.add(Declaration::Axiom {
539 name: Name::str("DecidableEq"),
540 univ_params: vec![],
541 ty: decidable_eq_ty,
542 })
543 .map_err(|e| e.to_string())?;
544 let decide_ty = Expr::Pi(
545 BinderInfo::Implicit,
546 Name::str("α"),
547 Box::new(type1),
548 Box::new(Expr::Pi(
549 BinderInfo::InstImplicit,
550 Name::str("_"),
551 Box::new(Expr::App(
552 Box::new(Expr::Const(Name::str("DecidableEq"), vec![])),
553 Box::new(Expr::BVar(0)),
554 )),
555 Box::new(Expr::Pi(
556 BinderInfo::Default,
557 Name::str("a"),
558 Box::new(Expr::BVar(1)),
559 Box::new(Expr::Pi(
560 BinderInfo::Default,
561 Name::str("b"),
562 Box::new(Expr::BVar(2)),
563 Box::new(Expr::Const(Name::str("Bool"), vec![])),
564 )),
565 )),
566 )),
567 );
568 env.add(Declaration::Axiom {
569 name: Name::str("DecidableEq.decide"),
570 univ_params: vec![],
571 ty: decide_ty,
572 })
573 .map_err(|e| e.to_string())?;
574 Ok(())
575}
576pub(super) fn add_eq_inductive(env: &mut Environment) -> Result<(), String> {
583 let u = Level::param(Name::str("u"));
584 let prop = Expr::Sort(Level::zero());
585 let sort_u = Expr::Sort(u.clone());
586 let eq_ty = Expr::Pi(
587 BinderInfo::Implicit,
588 Name::str("α"),
589 Box::new(sort_u.clone()),
590 Box::new(Expr::Pi(
591 BinderInfo::Default,
592 Name::str("a"),
593 Box::new(Expr::BVar(0)),
594 Box::new(Expr::Pi(
595 BinderInfo::Default,
596 Name::str("b"),
597 Box::new(Expr::BVar(1)),
598 Box::new(prop.clone()),
599 )),
600 )),
601 );
602 let ind = ConstantInfo::Inductive(InductiveVal {
603 common: ConstantVal {
604 name: Name::str("Eq"),
605 level_params: vec![Name::str("u")],
606 ty: eq_ty,
607 },
608 num_params: 1,
609 num_indices: 2,
610 all: vec![Name::str("Eq")],
611 ctors: vec![Name::str("Eq.refl")],
612 num_nested: 0,
613 is_rec: false,
614 is_unsafe: false,
615 is_reflexive: false,
616 is_prop: true,
617 });
618 let eq_refl_ty = Expr::Pi(
619 BinderInfo::Implicit,
620 Name::str("α"),
621 Box::new(sort_u),
622 Box::new(Expr::Pi(
623 BinderInfo::Default,
624 Name::str("a"),
625 Box::new(Expr::BVar(0)),
626 Box::new(Expr::App(
627 Box::new(Expr::App(
628 Box::new(Expr::App(
629 Box::new(Expr::Const(Name::str("Eq"), vec![u.clone()])),
630 Box::new(Expr::BVar(1)),
631 )),
632 Box::new(Expr::BVar(0)),
633 )),
634 Box::new(Expr::BVar(0)),
635 )),
636 )),
637 );
638 let ctor_refl = ConstantInfo::Constructor(ConstructorVal {
639 common: ConstantVal {
640 name: Name::str("Eq.refl"),
641 level_params: vec![Name::str("u")],
642 ty: eq_refl_ty,
643 },
644 induct: Name::str("Eq"),
645 cidx: 0,
646 num_params: 1,
647 num_fields: 1,
648 is_unsafe: false,
649 });
650 let rec = ConstantInfo::Recursor(RecursorVal {
651 common: ConstantVal {
652 name: Name::str("Eq.rec"),
653 level_params: vec![Name::str("u"), Name::str("v")],
654 ty: prop.clone(),
655 },
656 all: vec![Name::str("Eq")],
657 num_params: 1,
658 num_indices: 2,
659 num_motives: 1,
660 num_minors: 1,
661 rules: vec![RecursorRule {
662 ctor: Name::str("Eq.refl"),
663 nfields: 1,
664 rhs: Expr::BVar(0),
665 }],
666 k: true,
667 is_unsafe: false,
668 });
669 env.add_constant(ind).map_err(|e| e.to_string())?;
670 env.add_constant(ctor_refl).map_err(|e| e.to_string())?;
671 env.add_constant(rec).map_err(|e| e.to_string())?;
672 Ok(())
673}
674pub(super) fn add_prod_inductive(env: &mut Environment) -> Result<(), String> {
681 let u = Level::param(Name::str("u"));
682 let v = Level::param(Name::str("v"));
683 let type_u = Expr::Sort(Level::succ(u.clone()));
684 let type_v = Expr::Sort(Level::succ(v.clone()));
685 let type_max = Expr::Sort(Level::succ(Level::max(u.clone(), v.clone())));
686 let prod_ty = Expr::Pi(
687 BinderInfo::Default,
688 Name::str("α"),
689 Box::new(type_u.clone()),
690 Box::new(Expr::Pi(
691 BinderInfo::Default,
692 Name::str("β"),
693 Box::new(type_v.clone()),
694 Box::new(type_max),
695 )),
696 );
697 let ind = ConstantInfo::Inductive(InductiveVal {
698 common: ConstantVal {
699 name: Name::str("Prod"),
700 level_params: vec![Name::str("u"), Name::str("v")],
701 ty: prod_ty,
702 },
703 num_params: 2,
704 num_indices: 0,
705 all: vec![Name::str("Prod")],
706 ctors: vec![Name::str("Prod.mk")],
707 num_nested: 0,
708 is_rec: false,
709 is_unsafe: false,
710 is_reflexive: false,
711 is_prop: false,
712 });
713 let prod_mk_ty = Expr::Pi(
714 BinderInfo::Implicit,
715 Name::str("α"),
716 Box::new(type_u),
717 Box::new(Expr::Pi(
718 BinderInfo::Implicit,
719 Name::str("β"),
720 Box::new(type_v),
721 Box::new(Expr::Pi(
722 BinderInfo::Default,
723 Name::str("fst"),
724 Box::new(Expr::BVar(1)),
725 Box::new(Expr::Pi(
726 BinderInfo::Default,
727 Name::str("snd"),
728 Box::new(Expr::BVar(1)),
729 Box::new(Expr::App(
730 Box::new(Expr::App(
731 Box::new(Expr::Const(Name::str("Prod"), vec![u.clone(), v.clone()])),
732 Box::new(Expr::BVar(3)),
733 )),
734 Box::new(Expr::BVar(2)),
735 )),
736 )),
737 )),
738 )),
739 );
740 let ctor_mk = ConstantInfo::Constructor(ConstructorVal {
741 common: ConstantVal {
742 name: Name::str("Prod.mk"),
743 level_params: vec![Name::str("u"), Name::str("v")],
744 ty: prod_mk_ty,
745 },
746 induct: Name::str("Prod"),
747 cidx: 0,
748 num_params: 2,
749 num_fields: 2,
750 is_unsafe: false,
751 });
752 let rec = ConstantInfo::Recursor(RecursorVal {
753 common: ConstantVal {
754 name: Name::str("Prod.rec"),
755 level_params: vec![Name::str("u"), Name::str("v"), Name::str("w")],
756 ty: Expr::Sort(Level::zero()),
757 },
758 all: vec![Name::str("Prod")],
759 num_params: 2,
760 num_indices: 0,
761 num_motives: 1,
762 num_minors: 1,
763 rules: vec![RecursorRule {
764 ctor: Name::str("Prod.mk"),
765 nfields: 2,
766 rhs: Expr::BVar(0),
767 }],
768 k: false,
769 is_unsafe: false,
770 });
771 env.add_constant(ind).map_err(|e| e.to_string())?;
772 env.add_constant(ctor_mk).map_err(|e| e.to_string())?;
773 env.add_constant(rec).map_err(|e| e.to_string())?;
774 Ok(())
775}
776pub(super) fn add_list_inductive(env: &mut Environment) -> Result<(), String> {
784 let u = Level::param(Name::str("u"));
785 let type_u = Expr::Sort(Level::succ(u.clone()));
786 let list_bvar0 = Expr::App(
787 Box::new(Expr::Const(Name::str("List"), vec![u.clone()])),
788 Box::new(Expr::BVar(0)),
789 );
790 let list_ty = Expr::Pi(
791 BinderInfo::Default,
792 Name::str("α"),
793 Box::new(type_u.clone()),
794 Box::new(type_u.clone()),
795 );
796 let ind = ConstantInfo::Inductive(InductiveVal {
797 common: ConstantVal {
798 name: Name::str("List"),
799 level_params: vec![Name::str("u")],
800 ty: list_ty,
801 },
802 num_params: 1,
803 num_indices: 0,
804 all: vec![Name::str("List")],
805 ctors: vec![Name::str("List.nil"), Name::str("List.cons")],
806 num_nested: 0,
807 is_rec: true,
808 is_unsafe: false,
809 is_reflexive: false,
810 is_prop: false,
811 });
812 let nil_ty = Expr::Pi(
813 BinderInfo::Implicit,
814 Name::str("α"),
815 Box::new(type_u.clone()),
816 Box::new(list_bvar0.clone()),
817 );
818 let ctor_nil = ConstantInfo::Constructor(ConstructorVal {
819 common: ConstantVal {
820 name: Name::str("List.nil"),
821 level_params: vec![Name::str("u")],
822 ty: nil_ty,
823 },
824 induct: Name::str("List"),
825 cidx: 0,
826 num_params: 1,
827 num_fields: 0,
828 is_unsafe: false,
829 });
830 let cons_ty = Expr::Pi(
831 BinderInfo::Implicit,
832 Name::str("α"),
833 Box::new(type_u),
834 Box::new(Expr::Pi(
835 BinderInfo::Default,
836 Name::str("head"),
837 Box::new(Expr::BVar(0)),
838 Box::new(Expr::Pi(
839 BinderInfo::Default,
840 Name::str("tail"),
841 Box::new(list_bvar0.clone()),
842 Box::new(list_bvar0),
843 )),
844 )),
845 );
846 let ctor_cons = ConstantInfo::Constructor(ConstructorVal {
847 common: ConstantVal {
848 name: Name::str("List.cons"),
849 level_params: vec![Name::str("u")],
850 ty: cons_ty,
851 },
852 induct: Name::str("List"),
853 cidx: 1,
854 num_params: 1,
855 num_fields: 2,
856 is_unsafe: false,
857 });
858 let rec = ConstantInfo::Recursor(RecursorVal {
859 common: ConstantVal {
860 name: Name::str("List.rec"),
861 level_params: vec![Name::str("u"), Name::str("v")],
862 ty: Expr::Sort(Level::zero()),
863 },
864 all: vec![Name::str("List")],
865 num_params: 1,
866 num_indices: 0,
867 num_motives: 1,
868 num_minors: 2,
869 rules: vec![
870 RecursorRule {
871 ctor: Name::str("List.nil"),
872 nfields: 0,
873 rhs: Expr::BVar(0),
874 },
875 RecursorRule {
876 ctor: Name::str("List.cons"),
877 nfields: 2,
878 rhs: Expr::BVar(0),
879 },
880 ],
881 k: false,
882 is_unsafe: false,
883 });
884 env.add_constant(ind).map_err(|e| e.to_string())?;
885 env.add_constant(ctor_nil).map_err(|e| e.to_string())?;
886 env.add_constant(ctor_cons).map_err(|e| e.to_string())?;
887 env.add_constant(rec).map_err(|e| e.to_string())?;
888 Ok(())
889}
890pub fn is_builtin(name: &Name) -> bool {
892 let s = name.to_string();
893 matches!(
894 s.as_str(),
895 "Bool"
896 | "Bool.ind"
897 | "Bool.true"
898 | "Bool.false"
899 | "Bool.rec"
900 | "true"
901 | "false"
902 | "Unit"
903 | "Unit.ind"
904 | "Unit.unit"
905 | "Unit.rec"
906 | "unit"
907 | "Empty"
908 | "Empty.ind"
909 | "Empty.rec"
910 | "Nat"
911 | "Nat.zero"
912 | "Nat.succ"
913 | "Nat.rec"
914 | "String"
915 | "DecidableEq"
916 | "DecidableEq.decide"
917 | "propext"
918 | "Quot"
919 | "Classical.choice"
920 )
921}
922pub fn is_nat_op(name: &Name) -> bool {
924 let s = name.to_string();
925 matches!(
926 s.as_str(),
927 "Nat.add"
928 | "Nat.sub"
929 | "Nat.mul"
930 | "Nat.div"
931 | "Nat.mod"
932 | "Nat.pow"
933 | "Nat.gcd"
934 | "Nat.beq"
935 | "Nat.ble"
936 | "Nat.blt"
937 | "Nat.land"
938 | "Nat.lor"
939 | "Nat.xor"
940 | "Nat.shiftLeft"
941 | "Nat.shiftRight"
942 )
943}
944pub fn is_string_op(name: &Name) -> bool {
946 let s = name.to_string();
947 matches!(s.as_str(), "String.length" | "String.append" | "String.beq")
948}
949#[cfg(test)]
950mod tests {
951 use super::*;
952 #[test]
953 fn test_init_builtin_env() {
954 let mut env = Environment::new();
955 assert!(init_builtin_env(&mut env).is_ok());
956 assert!(env.get(&Name::str("Bool")).is_some());
957 assert!(env.get(&Name::str("true")).is_some());
958 assert!(env.get(&Name::str("false")).is_some());
959 assert!(env.get(&Name::str("Unit")).is_some());
960 assert!(env.get(&Name::str("unit")).is_some());
961 assert!(env.get(&Name::str("Empty")).is_some());
962 }
963 #[test]
964 fn test_bool_axioms() {
965 let mut env = Environment::new();
966 init_builtin_env(&mut env).expect("value should be present");
967 let bool_decl = env
968 .get(&Name::str("Bool"))
969 .expect("bool_decl should be present");
970 assert!(matches!(bool_decl, Declaration::Axiom { .. }));
971 let true_decl = env
972 .get(&Name::str("true"))
973 .expect("true_decl should be present");
974 assert!(matches!(true_decl, Declaration::Axiom { .. }));
975 }
976 #[test]
977 fn test_unit_axioms() {
978 let mut env = Environment::new();
979 init_builtin_env(&mut env).expect("value should be present");
980 let unit_decl = env
981 .get(&Name::str("Unit"))
982 .expect("unit_decl should be present");
983 assert!(matches!(unit_decl, Declaration::Axiom { .. }));
984 let unit_val = env
985 .get(&Name::str("unit"))
986 .expect("unit_val should be present");
987 assert!(matches!(unit_val, Declaration::Axiom { .. }));
988 }
989 #[test]
990 fn test_empty_axioms() {
991 let mut env = Environment::new();
992 init_builtin_env(&mut env).expect("value should be present");
993 let empty_decl = env
994 .get(&Name::str("Empty"))
995 .expect("empty_decl should be present");
996 assert!(matches!(empty_decl, Declaration::Axiom { .. }));
997 let rec_decl = env
998 .get(&Name::str("Empty.rec"))
999 .expect("rec_decl should be present");
1000 assert!(matches!(rec_decl, Declaration::Axiom { .. }));
1001 }
1002 #[test]
1003 fn test_decidable_eq() {
1004 let mut env = Environment::new();
1005 init_builtin_env(&mut env).expect("value should be present");
1006 let dec_eq = env
1007 .get(&Name::str("DecidableEq"))
1008 .expect("dec_eq should be present");
1009 assert!(matches!(dec_eq, Declaration::Axiom { .. }));
1010 let decide = env
1011 .get(&Name::str("DecidableEq.decide"))
1012 .expect("decide should be present");
1013 assert!(matches!(decide, Declaration::Axiom { .. }));
1014 }
1015 #[test]
1016 fn test_is_builtin() {
1017 assert!(is_builtin(&Name::str("Bool")));
1018 assert!(is_builtin(&Name::str("true")));
1019 assert!(is_builtin(&Name::str("Unit")));
1020 assert!(is_builtin(&Name::str("Nat")));
1021 assert!(is_builtin(&Name::str("String")));
1022 assert!(!is_builtin(&Name::str("CustomType")));
1023 }
1024 #[test]
1025 fn test_bool_inductive() {
1026 let mut env = Environment::new();
1027 init_builtin_env(&mut env).expect("value should be present");
1028 assert!(env.is_constructor(&Name::str("Bool.true")));
1029 assert!(env.is_constructor(&Name::str("Bool.false")));
1030 assert!(env.is_recursor(&Name::str("Bool.rec")));
1031 }
1032 #[test]
1033 fn test_nat_inductive() {
1034 let mut env = Environment::new();
1035 init_builtin_env(&mut env).expect("value should be present");
1036 assert!(env.is_inductive(&Name::str("Nat")));
1037 assert!(env.is_constructor(&Name::str("Nat.zero")));
1038 assert!(env.is_constructor(&Name::str("Nat.succ")));
1039 assert!(env.is_recursor(&Name::str("Nat.rec")));
1040 }
1041 #[test]
1042 fn test_nat_ops_registered() {
1043 let mut env = Environment::new();
1044 init_builtin_env(&mut env).expect("value should be present");
1045 assert!(env.find(&Name::str("Nat.add")).is_some());
1046 assert!(env.find(&Name::str("Nat.mul")).is_some());
1047 assert!(env.find(&Name::str("Nat.sub")).is_some());
1048 assert!(env.find(&Name::str("Nat.div")).is_some());
1049 assert!(env.find(&Name::str("Nat.beq")).is_some());
1050 }
1051 #[test]
1052 fn test_string_ops_registered() {
1053 let mut env = Environment::new();
1054 init_builtin_env(&mut env).expect("value should be present");
1055 assert!(env.find(&Name::str("String")).is_some());
1056 assert!(env.find(&Name::str("String.length")).is_some());
1057 assert!(env.find(&Name::str("String.append")).is_some());
1058 assert!(env.find(&Name::str("String.beq")).is_some());
1059 }
1060 #[test]
1061 fn test_core_axioms_registered() {
1062 let mut env = Environment::new();
1063 init_builtin_env(&mut env).expect("value should be present");
1064 assert!(env.find(&Name::str("propext")).is_some());
1065 assert!(env.find(&Name::str("Quot")).is_some());
1066 assert!(env.find(&Name::str("Classical.choice")).is_some());
1067 }
1068 #[test]
1069 fn test_is_nat_op() {
1070 assert!(is_nat_op(&Name::str("Nat.add")));
1071 assert!(is_nat_op(&Name::str("Nat.mul")));
1072 assert!(is_nat_op(&Name::str("Nat.gcd")));
1073 assert!(!is_nat_op(&Name::str("Nat.zero")));
1074 }
1075 #[test]
1076 fn test_is_string_op() {
1077 assert!(is_string_op(&Name::str("String.length")));
1078 assert!(is_string_op(&Name::str("String.append")));
1079 assert!(!is_string_op(&Name::str("String")));
1080 }
1081}
1082#[allow(dead_code)]
1084pub fn classify_builtin(name: &Name) -> BuiltinKind {
1085 let s = name.to_string();
1086 if is_nat_op(name) {
1087 return BuiltinKind::ArithOp;
1088 }
1089 if is_string_op(name) {
1090 return BuiltinKind::StringOp;
1091 }
1092 match s.as_str() {
1093 "Bool" | "Unit" | "Empty" | "Nat" | "String" => BuiltinKind::Type,
1094 "Bool.true" | "Bool.false" | "Unit.unit" | "Nat.zero" | "Nat.succ" | "true" | "false"
1095 | "unit" => BuiltinKind::Constructor,
1096 "Bool.rec" | "Unit.rec" | "Nat.rec" | "Empty.rec" => BuiltinKind::Recursor,
1097 "propext" | "Quot" | "Classical.choice" => BuiltinKind::Axiom,
1098 "Nat.beq" | "Nat.ble" | "Nat.blt" => BuiltinKind::CmpOp,
1099 "DecidableEq" | "DecidableEq.decide" => BuiltinKind::TypeClass,
1100 _ => BuiltinKind::Unknown,
1101 }
1102}
1103#[allow(dead_code)]
1105pub fn is_logical_connective(name: &Name) -> bool {
1106 let s = name.to_string();
1107 matches!(
1108 s.as_str(),
1109 "And" | "Or" | "Not" | "Iff" | "True" | "False" | "Exists"
1110 )
1111}
1112#[allow(dead_code)]
1114pub fn is_primitive_value(name: &Name) -> bool {
1115 let s = name.to_string();
1116 matches!(
1117 s.as_str(),
1118 "true" | "false" | "unit" | "Bool.true" | "Bool.false" | "Unit.unit" | "Nat.zero"
1119 )
1120}
1121#[allow(dead_code)]
1123pub fn builtin_universe_level(name: &Name) -> Option<u32> {
1124 let s = name.to_string();
1125 match s.as_str() {
1126 "Empty" => Some(0),
1127 "Bool" | "Unit" | "Nat" | "String" => Some(1),
1128 _ => None,
1129 }
1130}
1131#[allow(dead_code)]
1133pub fn builtin_ctor_count(name: &Name) -> Option<usize> {
1134 let s = name.to_string();
1135 match s.as_str() {
1136 "Bool" => Some(2),
1137 "Unit" => Some(1),
1138 "Empty" => Some(0),
1139 "Nat" => Some(2),
1140 _ => None,
1141 }
1142}
1143#[allow(dead_code)]
1145pub fn builtin_is_recursive(name: &Name) -> bool {
1146 name.to_string() == "Nat"
1147}
1148#[allow(dead_code)]
1150pub fn builtin_is_prop(name: &Name) -> bool {
1151 let s = name.to_string();
1152 matches!(s.as_str(), "Empty" | "True" | "False")
1153}
1154#[allow(dead_code)]
1156pub fn all_builtin_names() -> Vec<&'static str> {
1157 vec![
1158 "Bool",
1159 "Bool.ind",
1160 "Bool.true",
1161 "Bool.false",
1162 "Bool.rec",
1163 "true",
1164 "false",
1165 "Unit",
1166 "Unit.ind",
1167 "Unit.unit",
1168 "Unit.rec",
1169 "unit",
1170 "Empty",
1171 "Empty.ind",
1172 "Empty.rec",
1173 "Nat",
1174 "Nat.zero",
1175 "Nat.succ",
1176 "Nat.rec",
1177 "Nat.add",
1178 "Nat.sub",
1179 "Nat.mul",
1180 "Nat.div",
1181 "Nat.mod",
1182 "Nat.pow",
1183 "Nat.gcd",
1184 "Nat.beq",
1185 "Nat.ble",
1186 "Nat.blt",
1187 "Nat.land",
1188 "Nat.lor",
1189 "Nat.xor",
1190 "Nat.shiftLeft",
1191 "Nat.shiftRight",
1192 "String",
1193 "String.length",
1194 "String.append",
1195 "String.beq",
1196 "propext",
1197 "Quot",
1198 "Classical.choice",
1199 "DecidableEq",
1200 "DecidableEq.decide",
1201 ]
1202}
1203#[allow(dead_code)]
1205pub fn builtin_count() -> usize {
1206 all_builtin_names().len()
1207}
1208#[allow(dead_code)]
1210pub fn verify_builtins(env: &Environment) -> Vec<&'static str> {
1211 all_builtin_names()
1212 .into_iter()
1213 .filter(|n| env.find(&Name::str(*n)).is_none() && env.get(&Name::str(*n)).is_none())
1214 .collect()
1215}
1216#[allow(dead_code)]
1218pub fn lean4_name(name: &Name) -> Option<&'static str> {
1219 let s = name.to_string();
1220 match s.as_str() {
1221 "Bool.true" => Some("Bool.true"),
1222 "Bool.false" => Some("Bool.false"),
1223 "true" => Some("Bool.true"),
1224 "false" => Some("Bool.false"),
1225 "unit" => Some("Unit.unit"),
1226 "Nat.zero" => Some("Nat.zero"),
1227 "Nat.succ" => Some("Nat.succ"),
1228 _ => None,
1229 }
1230}
1231#[allow(dead_code)]
1233pub fn core_builtin_infos() -> Vec<BuiltinInfo> {
1234 vec![
1235 BuiltinInfo {
1236 name: "Bool",
1237 kind: BuiltinKind::Type,
1238 description: "Boolean type",
1239 },
1240 BuiltinInfo {
1241 name: "Unit",
1242 kind: BuiltinKind::Type,
1243 description: "Unit type (single-element)",
1244 },
1245 BuiltinInfo {
1246 name: "Empty",
1247 kind: BuiltinKind::Type,
1248 description: "Empty type (no elements)",
1249 },
1250 BuiltinInfo {
1251 name: "Nat",
1252 kind: BuiltinKind::Type,
1253 description: "Natural numbers",
1254 },
1255 BuiltinInfo {
1256 name: "String",
1257 kind: BuiltinKind::Type,
1258 description: "Unicode string type",
1259 },
1260 BuiltinInfo {
1261 name: "propext",
1262 kind: BuiltinKind::Axiom,
1263 description: "Propositional extensionality",
1264 },
1265 BuiltinInfo {
1266 name: "Quot",
1267 kind: BuiltinKind::Axiom,
1268 description: "Quotient type constructor",
1269 },
1270 BuiltinInfo {
1271 name: "Classical.choice",
1272 kind: BuiltinKind::Axiom,
1273 description: "Classical choice axiom",
1274 },
1275 ]
1276}
1277#[cfg(test)]
1278mod extended_builtin_tests {
1279 use super::*;
1280 #[test]
1281 fn test_classify_builtin_type() {
1282 assert_eq!(classify_builtin(&Name::str("Bool")), BuiltinKind::Type);
1283 assert_eq!(classify_builtin(&Name::str("Nat")), BuiltinKind::Type);
1284 }
1285 #[test]
1286 fn test_classify_builtin_ctor() {
1287 assert_eq!(
1288 classify_builtin(&Name::str("Bool.true")),
1289 BuiltinKind::Constructor
1290 );
1291 assert_eq!(
1292 classify_builtin(&Name::str("Nat.zero")),
1293 BuiltinKind::Constructor
1294 );
1295 }
1296 #[test]
1297 fn test_classify_builtin_arith() {
1298 assert_eq!(
1299 classify_builtin(&Name::str("Nat.add")),
1300 BuiltinKind::ArithOp
1301 );
1302 assert_eq!(
1303 classify_builtin(&Name::str("Nat.mul")),
1304 BuiltinKind::ArithOp
1305 );
1306 }
1307 #[test]
1308 fn test_classify_builtin_axiom() {
1309 assert_eq!(classify_builtin(&Name::str("propext")), BuiltinKind::Axiom);
1310 assert_eq!(
1311 classify_builtin(&Name::str("Classical.choice")),
1312 BuiltinKind::Axiom
1313 );
1314 }
1315 #[test]
1316 fn test_classify_builtin_unknown() {
1317 assert_eq!(
1318 classify_builtin(&Name::str("CustomThing")),
1319 BuiltinKind::Unknown
1320 );
1321 }
1322 #[test]
1323 fn test_is_primitive_value() {
1324 assert!(is_primitive_value(&Name::str("true")));
1325 assert!(is_primitive_value(&Name::str("false")));
1326 assert!(is_primitive_value(&Name::str("unit")));
1327 assert!(!is_primitive_value(&Name::str("Nat")));
1328 }
1329 #[test]
1330 fn test_builtin_universe_level() {
1331 assert_eq!(builtin_universe_level(&Name::str("Empty")), Some(0));
1332 assert_eq!(builtin_universe_level(&Name::str("Bool")), Some(1));
1333 assert_eq!(builtin_universe_level(&Name::str("CustomType")), None);
1334 }
1335 #[test]
1336 fn test_builtin_ctor_count() {
1337 assert_eq!(builtin_ctor_count(&Name::str("Bool")), Some(2));
1338 assert_eq!(builtin_ctor_count(&Name::str("Empty")), Some(0));
1339 assert_eq!(builtin_ctor_count(&Name::str("Unit")), Some(1));
1340 }
1341 #[test]
1342 fn test_builtin_is_recursive() {
1343 assert!(builtin_is_recursive(&Name::str("Nat")));
1344 assert!(!builtin_is_recursive(&Name::str("Bool")));
1345 }
1346 #[test]
1347 fn test_builtin_is_prop() {
1348 assert!(builtin_is_prop(&Name::str("Empty")));
1349 assert!(!builtin_is_prop(&Name::str("Nat")));
1350 }
1351 #[test]
1352 fn test_all_builtin_names_nonempty() {
1353 assert!(!all_builtin_names().is_empty());
1354 assert!(builtin_count() > 20);
1355 }
1356 #[test]
1357 fn test_core_builtin_infos() {
1358 let infos = core_builtin_infos();
1359 assert!(!infos.is_empty());
1360 assert!(infos.iter().any(|i| i.name == "Bool"));
1361 }
1362 #[test]
1363 fn test_builtin_kind_description() {
1364 assert_eq!(BuiltinKind::Type.description(), "primitive type");
1365 assert_eq!(BuiltinKind::Axiom.description(), "logical axiom");
1366 assert_eq!(BuiltinKind::Unknown.description(), "not a builtin");
1367 }
1368 #[test]
1369 fn test_lean4_name() {
1370 assert_eq!(lean4_name(&Name::str("true")), Some("Bool.true"));
1371 assert_eq!(lean4_name(&Name::str("unit")), Some("Unit.unit"));
1372 assert_eq!(lean4_name(&Name::str("CustomFn")), None);
1373 }
1374 #[test]
1375 fn test_verify_builtins() {
1376 let mut env = Environment::new();
1377 init_builtin_env(&mut env).expect("value should be present");
1378 let missing = verify_builtins(&env);
1379 assert!(missing.len() < 15);
1380 }
1381 #[test]
1382 fn test_is_logical_connective() {
1383 assert!(is_logical_connective(&Name::str("And")));
1384 assert!(is_logical_connective(&Name::str("Or")));
1385 assert!(is_logical_connective(&Name::str("Iff")));
1386 assert!(!is_logical_connective(&Name::str("Nat")));
1387 }
1388}
1389#[cfg(test)]
1390mod tests_padding_infra {
1391 use super::*;
1392 #[test]
1393 fn test_stat_summary() {
1394 let mut ss = StatSummary::new();
1395 ss.record(10.0);
1396 ss.record(20.0);
1397 ss.record(30.0);
1398 assert_eq!(ss.count(), 3);
1399 assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
1400 assert_eq!(ss.min().expect("min should succeed") as i64, 10);
1401 assert_eq!(ss.max().expect("max should succeed") as i64, 30);
1402 }
1403 #[test]
1404 fn test_transform_stat() {
1405 let mut ts = TransformStat::new();
1406 ts.record_before(100.0);
1407 ts.record_after(80.0);
1408 let ratio = ts.mean_ratio().expect("ratio should be present");
1409 assert!((ratio - 0.8).abs() < 1e-9);
1410 }
1411 #[test]
1412 fn test_small_map() {
1413 let mut m: SmallMap<u32, &str> = SmallMap::new();
1414 m.insert(3, "three");
1415 m.insert(1, "one");
1416 m.insert(2, "two");
1417 assert_eq!(m.get(&2), Some(&"two"));
1418 assert_eq!(m.len(), 3);
1419 let keys = m.keys();
1420 assert_eq!(*keys[0], 1);
1421 assert_eq!(*keys[2], 3);
1422 }
1423 #[test]
1424 fn test_label_set() {
1425 let mut ls = LabelSet::new();
1426 ls.add("foo");
1427 ls.add("bar");
1428 ls.add("foo");
1429 assert_eq!(ls.count(), 2);
1430 assert!(ls.has("bar"));
1431 assert!(!ls.has("baz"));
1432 }
1433 #[test]
1434 fn test_config_node() {
1435 let mut root = ConfigNode::section("root");
1436 let child = ConfigNode::leaf("key", "value");
1437 root.add_child(child);
1438 assert_eq!(root.num_children(), 1);
1439 }
1440 #[test]
1441 fn test_versioned_record() {
1442 let mut vr = VersionedRecord::new(0u32);
1443 vr.update(1);
1444 vr.update(2);
1445 assert_eq!(*vr.current(), 2);
1446 assert_eq!(vr.version(), 2);
1447 assert!(vr.has_history());
1448 assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
1449 }
1450 #[test]
1451 fn test_simple_dag() {
1452 let mut dag = SimpleDag::new(4);
1453 dag.add_edge(0, 1);
1454 dag.add_edge(1, 2);
1455 dag.add_edge(2, 3);
1456 assert!(dag.can_reach(0, 3));
1457 assert!(!dag.can_reach(3, 0));
1458 let order = dag.topological_sort().expect("order should be present");
1459 assert_eq!(order, vec![0, 1, 2, 3]);
1460 }
1461 #[test]
1462 fn test_focus_stack() {
1463 let mut fs: FocusStack<&str> = FocusStack::new();
1464 fs.focus("a");
1465 fs.focus("b");
1466 assert_eq!(fs.current(), Some(&"b"));
1467 assert_eq!(fs.depth(), 2);
1468 fs.blur();
1469 assert_eq!(fs.current(), Some(&"a"));
1470 }
1471}
1472#[cfg(test)]
1473mod tests_extra_iterators {
1474 use super::*;
1475 #[test]
1476 fn test_window_iterator() {
1477 let data = vec![1u32, 2, 3, 4, 5];
1478 let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
1479 assert_eq!(windows.len(), 3);
1480 assert_eq!(windows[0], &[1, 2, 3]);
1481 assert_eq!(windows[2], &[3, 4, 5]);
1482 }
1483 #[test]
1484 fn test_non_empty_vec() {
1485 let mut nev = NonEmptyVec::singleton(10u32);
1486 nev.push(20);
1487 nev.push(30);
1488 assert_eq!(nev.len(), 3);
1489 assert_eq!(*nev.first(), 10);
1490 assert_eq!(*nev.last(), 30);
1491 }
1492}
1493#[cfg(test)]
1494mod tests_padding2 {
1495 use super::*;
1496 #[test]
1497 fn test_sliding_sum() {
1498 let mut ss = SlidingSum::new(3);
1499 ss.push(1.0);
1500 ss.push(2.0);
1501 ss.push(3.0);
1502 assert!((ss.sum() - 6.0).abs() < 1e-9);
1503 ss.push(4.0);
1504 assert!((ss.sum() - 9.0).abs() < 1e-9);
1505 assert_eq!(ss.count(), 3);
1506 }
1507 #[test]
1508 fn test_path_buf() {
1509 let mut pb = PathBuf::new();
1510 pb.push("src");
1511 pb.push("main");
1512 assert_eq!(pb.as_str(), "src/main");
1513 assert_eq!(pb.depth(), 2);
1514 pb.pop();
1515 assert_eq!(pb.as_str(), "src");
1516 }
1517 #[test]
1518 fn test_string_pool() {
1519 let mut pool = StringPool::new();
1520 let s = pool.take();
1521 assert!(s.is_empty());
1522 pool.give("hello".to_string());
1523 let s2 = pool.take();
1524 assert!(s2.is_empty());
1525 assert_eq!(pool.free_count(), 0);
1526 }
1527 #[test]
1528 fn test_transitive_closure() {
1529 let mut tc = TransitiveClosure::new(4);
1530 tc.add_edge(0, 1);
1531 tc.add_edge(1, 2);
1532 tc.add_edge(2, 3);
1533 assert!(tc.can_reach(0, 3));
1534 assert!(!tc.can_reach(3, 0));
1535 let r = tc.reachable_from(0);
1536 assert_eq!(r.len(), 4);
1537 }
1538 #[test]
1539 fn test_token_bucket() {
1540 let mut tb = TokenBucket::new(100, 10);
1541 assert_eq!(tb.available(), 100);
1542 assert!(tb.try_consume(50));
1543 assert_eq!(tb.available(), 50);
1544 assert!(!tb.try_consume(60));
1545 assert_eq!(tb.capacity(), 100);
1546 }
1547 #[test]
1548 fn test_rewrite_rule_set() {
1549 let mut rrs = RewriteRuleSet::new();
1550 rrs.add(RewriteRule::unconditional(
1551 "beta",
1552 "App(Lam(x, b), v)",
1553 "b[x:=v]",
1554 ));
1555 rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
1556 assert_eq!(rrs.len(), 2);
1557 assert_eq!(rrs.unconditional_rules().len(), 1);
1558 assert_eq!(rrs.conditional_rules().len(), 1);
1559 assert!(rrs.get("beta").is_some());
1560 let disp = rrs
1561 .get("beta")
1562 .expect("element at \'beta\' should exist")
1563 .display();
1564 assert!(disp.contains("→"));
1565 }
1566}
1567#[cfg(test)]
1568mod tests_padding3 {
1569 use super::*;
1570 #[test]
1571 fn test_decision_node() {
1572 let tree = DecisionNode::Branch {
1573 key: "x".into(),
1574 val: "1".into(),
1575 yes_branch: Box::new(DecisionNode::Leaf("yes".into())),
1576 no_branch: Box::new(DecisionNode::Leaf("no".into())),
1577 };
1578 let mut ctx = std::collections::HashMap::new();
1579 ctx.insert("x".into(), "1".into());
1580 assert_eq!(tree.evaluate(&ctx), "yes");
1581 ctx.insert("x".into(), "2".into());
1582 assert_eq!(tree.evaluate(&ctx), "no");
1583 assert_eq!(tree.depth(), 1);
1584 }
1585 #[test]
1586 fn test_flat_substitution() {
1587 let mut sub = FlatSubstitution::new();
1588 sub.add("foo", "bar");
1589 sub.add("baz", "qux");
1590 assert_eq!(sub.apply("foo and baz"), "bar and qux");
1591 assert_eq!(sub.len(), 2);
1592 }
1593 #[test]
1594 fn test_stopwatch() {
1595 let mut sw = Stopwatch::start();
1596 sw.split();
1597 sw.split();
1598 assert_eq!(sw.num_splits(), 2);
1599 assert!(sw.elapsed_ms() >= 0.0);
1600 for &s in sw.splits() {
1601 assert!(s >= 0.0);
1602 }
1603 }
1604 #[test]
1605 fn test_either2() {
1606 let e: Either2<i32, &str> = Either2::First(42);
1607 assert!(e.is_first());
1608 let mapped = e.map_first(|x| x * 2);
1609 assert_eq!(mapped.first(), Some(84));
1610 let e2: Either2<i32, &str> = Either2::Second("hello");
1611 assert!(e2.is_second());
1612 assert_eq!(e2.second(), Some("hello"));
1613 }
1614 #[test]
1615 fn test_write_once() {
1616 let wo: WriteOnce<u32> = WriteOnce::new();
1617 assert!(!wo.is_written());
1618 assert!(wo.write(42));
1619 assert!(!wo.write(99));
1620 assert_eq!(wo.read(), Some(42));
1621 }
1622 #[test]
1623 fn test_sparse_vec() {
1624 let mut sv: SparseVec<i32> = SparseVec::new(100);
1625 sv.set(5, 10);
1626 sv.set(50, 20);
1627 assert_eq!(*sv.get(5), 10);
1628 assert_eq!(*sv.get(50), 20);
1629 assert_eq!(*sv.get(0), 0);
1630 assert_eq!(sv.nnz(), 2);
1631 sv.set(5, 0);
1632 assert_eq!(sv.nnz(), 1);
1633 }
1634 #[test]
1635 fn test_stack_calc() {
1636 let mut calc = StackCalc::new();
1637 calc.push(3);
1638 calc.push(4);
1639 calc.add();
1640 assert_eq!(calc.peek(), Some(7));
1641 calc.push(2);
1642 calc.mul();
1643 assert_eq!(calc.peek(), Some(14));
1644 }
1645}