1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6use std::collections::{BTreeMap, HashMap, HashSet};
7
8use super::types::{
9 ApproximateVerification, Assertion, Command, ConcurrentSeparationLogicExt, EffectSystem,
10 FractionalPerm, GhostHeap, Heap, HeapPred, HoareTriple, Namespace, NumericalDomain,
11 ProbabilisticHoareLogic, RelyCondition, RelyGuaranteeLogic, Transition, TypeAndEffect,
12 VerificationCondition, LTS,
13};
14
15pub fn app(f: Expr, a: Expr) -> Expr {
16 Expr::App(Box::new(f), Box::new(a))
17}
18pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
19 app(app(f, a), b)
20}
21pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
22 app(app2(f, a, b), c)
23}
24pub fn cst(s: &str) -> Expr {
25 Expr::Const(Name::str(s), vec![])
26}
27pub fn prop() -> Expr {
28 Expr::Sort(Level::zero())
29}
30pub fn type0() -> Expr {
31 Expr::Sort(Level::succ(Level::zero()))
32}
33pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
34 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
35}
36pub fn arrow(a: Expr, b: Expr) -> Expr {
37 pi(BinderInfo::Default, "_", a, b)
38}
39pub fn bvar(n: u32) -> Expr {
40 Expr::BVar(n)
41}
42pub fn nat_ty() -> Expr {
43 cst("Nat")
44}
45pub fn bool_ty() -> Expr {
46 cst("Bool")
47}
48pub fn string_ty() -> Expr {
49 cst("String")
50}
51pub fn list_ty(elem: Expr) -> Expr {
52 app(cst("List"), elem)
53}
54pub fn option_ty(a: Expr) -> Expr {
55 app(cst("Option"), a)
56}
57pub fn assertion_ty() -> Expr {
60 arrow(type0(), prop())
61}
62pub fn hoare_triple_ty() -> Expr {
65 arrow(prop(), arrow(type0(), arrow(prop(), prop())))
66}
67pub fn total_hoare_triple_ty() -> Expr {
70 arrow(prop(), arrow(type0(), arrow(prop(), prop())))
71}
72pub fn skip_rule_ty() -> Expr {
75 pi(BinderInfo::Default, "P", prop(), prop())
76}
77pub fn assign_rule_ty() -> Expr {
80 prop()
81}
82pub fn seq_rule_ty() -> Expr {
85 arrow(prop(), arrow(prop(), arrow(prop(), prop())))
86}
87pub fn while_rule_ty() -> Expr {
90 arrow(prop(), arrow(prop(), prop()))
91}
92pub fn consequence_rule_ty() -> Expr {
95 prop()
96}
97pub fn verification_condition_ty() -> Expr {
100 prop()
101}
102pub fn wp_ty() -> Expr {
105 arrow(type0(), arrow(prop(), prop()))
106}
107pub fn wlp_ty() -> Expr {
110 arrow(type0(), arrow(prop(), prop()))
111}
112pub fn sp_ty() -> Expr {
115 arrow(prop(), arrow(type0(), prop()))
116}
117pub fn wp_soundness_ty() -> Expr {
120 pi(
121 BinderInfo::Default,
122 "C",
123 type0(),
124 pi(BinderInfo::Default, "Q", prop(), prop()),
125 )
126}
127pub fn wp_completeness_ty() -> Expr {
130 pi(
131 BinderInfo::Default,
132 "P",
133 prop(),
134 pi(
135 BinderInfo::Default,
136 "Q",
137 prop(),
138 pi(BinderInfo::Default, "C", type0(), arrow(prop(), prop())),
139 ),
140 )
141}
142pub fn predicate_transformer_ty() -> Expr {
145 arrow(prop(), prop())
146}
147pub fn angelic_pt_ty() -> Expr {
150 arrow(type0(), arrow(prop(), prop()))
151}
152pub fn demonic_pt_ty() -> Expr {
155 arrow(type0(), arrow(prop(), prop()))
156}
157pub fn heap_predicate_ty() -> Expr {
160 arrow(type0(), prop())
161}
162pub fn sep_star_ty() -> Expr {
165 arrow(
166 arrow(type0(), prop()),
167 arrow(arrow(type0(), prop()), arrow(type0(), prop())),
168 )
169}
170pub fn sep_wand_ty() -> Expr {
173 arrow(
174 arrow(type0(), prop()),
175 arrow(arrow(type0(), prop()), arrow(type0(), prop())),
176 )
177}
178pub fn points_to_ty() -> Expr {
181 arrow(nat_ty(), arrow(nat_ty(), arrow(type0(), prop())))
182}
183pub fn emp_predicate_ty() -> Expr {
186 arrow(type0(), prop())
187}
188pub fn frame_rule_ty() -> Expr {
191 arrow(prop(), arrow(prop(), arrow(prop(), prop())))
192}
193pub fn sep_logic_triple_ty() -> Expr {
196 arrow(
197 arrow(type0(), prop()),
198 arrow(type0(), arrow(arrow(type0(), prop()), prop())),
199 )
200}
201pub fn bi_abduction_ty() -> Expr {
204 arrow(
205 arrow(type0(), prop()),
206 arrow(arrow(type0(), prop()), option_ty(type0())),
207 )
208}
209pub fn spatially_disjoint_ty() -> Expr {
212 arrow(
213 arrow(type0(), prop()),
214 arrow(arrow(type0(), prop()), prop()),
215 )
216}
217pub fn concurrent_triple_ty() -> Expr {
220 arrow(
221 arrow(type0(), prop()),
222 arrow(type0(), arrow(arrow(type0(), prop()), prop())),
223 )
224}
225pub fn parallel_composition_rule_ty() -> Expr {
228 prop()
229}
230pub fn critical_section_rule_ty() -> Expr {
233 arrow(prop(), arrow(prop(), prop()))
234}
235pub fn thread_local_ty() -> Expr {
238 arrow(type0(), prop())
239}
240pub fn shared_invariant_ty() -> Expr {
243 arrow(arrow(type0(), prop()), prop())
244}
245pub fn ownership_transfer_ty() -> Expr {
248 arrow(
249 arrow(type0(), prop()),
250 arrow(arrow(type0(), prop()), prop()),
251 )
252}
253pub fn atomic_triple_ty() -> Expr {
256 arrow(prop(), arrow(type0(), arrow(prop(), prop())))
257}
258pub fn rely_condition_ty() -> Expr {
261 arrow(type0(), arrow(type0(), prop()))
262}
263pub fn guarantee_condition_ty() -> Expr {
266 arrow(type0(), arrow(type0(), prop()))
267}
268pub fn rely_guarantee_triple_ty() -> Expr {
271 arrow(
272 arrow(type0(), arrow(type0(), prop())),
273 arrow(
274 arrow(type0(), arrow(type0(), prop())),
275 arrow(prop(), arrow(type0(), arrow(prop(), prop()))),
276 ),
277 )
278}
279pub fn rely_guarantee_parallel_ty() -> Expr {
282 prop()
283}
284pub fn stability_condition_ty() -> Expr {
287 arrow(
288 arrow(type0(), prop()),
289 arrow(arrow(type0(), arrow(type0(), prop())), prop()),
290 )
291}
292pub fn rely_guarantee_consequence_ty() -> Expr {
295 prop()
296}
297pub fn iris_prop_ty() -> Expr {
300 type0()
301}
302pub fn iris_entails_ty() -> Expr {
305 arrow(type0(), arrow(type0(), prop()))
306}
307pub fn iris_sep_star_ty() -> Expr {
310 arrow(type0(), arrow(type0(), type0()))
311}
312pub fn iris_wand_ty() -> Expr {
315 arrow(type0(), arrow(type0(), type0()))
316}
317pub fn iris_later_ty() -> Expr {
320 arrow(type0(), type0())
321}
322pub fn iris_always_ty() -> Expr {
325 arrow(type0(), type0())
326}
327pub fn iris_excl_ty() -> Expr {
330 pi(BinderInfo::Default, "V", type0(), arrow(bvar(0), type0()))
331}
332pub fn iris_agree_ty() -> Expr {
335 pi(BinderInfo::Default, "V", type0(), arrow(bvar(0), type0()))
336}
337pub fn iris_auth_ty() -> Expr {
340 pi(BinderInfo::Default, "A", type0(), arrow(bvar(0), type0()))
341}
342pub fn iris_fragment_ty() -> Expr {
345 pi(BinderInfo::Default, "A", type0(), arrow(bvar(0), type0()))
346}
347pub fn resource_algebra_ty() -> Expr {
351 arrow(type0(), prop())
352}
353pub fn ghost_state_ty() -> Expr {
356 pi(BinderInfo::Default, "A", type0(), arrow(prop(), type0()))
357}
358pub fn ghost_update_ty() -> Expr {
361 arrow(type0(), type0())
362}
363pub fn frame_preserving_update_ty() -> Expr {
367 pi(
368 BinderInfo::Default,
369 "A",
370 type0(),
371 arrow(bvar(0), arrow(bvar(1), prop())),
372 )
373}
374pub fn cmra_ty() -> Expr {
377 arrow(type0(), prop())
378}
379pub fn cmra_op_ty() -> Expr {
382 pi(
383 BinderInfo::Default,
384 "A",
385 type0(),
386 arrow(bvar(0), arrow(bvar(1), option_ty(bvar(2)))),
387 )
388}
389pub fn cmra_valid_ty() -> Expr {
392 pi(BinderInfo::Default, "A", type0(), arrow(bvar(0), prop()))
393}
394pub fn cmra_core_ty() -> Expr {
397 pi(
398 BinderInfo::Default,
399 "A",
400 type0(),
401 arrow(bvar(0), option_ty(bvar(1))),
402 )
403}
404pub fn invariant_ty() -> Expr {
407 arrow(nat_ty(), arrow(type0(), type0()))
408}
409pub fn invariant_alloc_ty() -> Expr {
412 pi(BinderInfo::Default, "P", type0(), prop())
413}
414pub fn invariant_open_ty() -> Expr {
417 pi(
418 BinderInfo::Default,
419 "N",
420 nat_ty(),
421 pi(
422 BinderInfo::Default,
423 "P",
424 type0(),
425 pi(BinderInfo::Default, "Q", type0(), prop()),
426 ),
427 )
428}
429pub fn namespace_mask_ty() -> Expr {
432 type0()
433}
434pub fn mask_subset_ty() -> Expr {
437 arrow(type0(), arrow(type0(), prop()))
438}
439pub fn fancy_update_ty() -> Expr {
442 arrow(type0(), arrow(type0(), arrow(type0(), type0())))
443}
444pub fn fractional_permission_ty() -> Expr {
447 type0()
448}
449pub fn fractional_points_to_ty() -> Expr {
452 arrow(
453 nat_ty(),
454 arrow(nat_ty(), arrow(type0(), arrow(type0(), prop()))),
455 )
456}
457pub fn permission_split_ty() -> Expr {
460 prop()
461}
462pub fn permission_combine_ty() -> Expr {
465 prop()
466}
467pub fn counting_permission_ty() -> Expr {
470 type0()
471}
472pub fn write_permission_ty() -> Expr {
475 type0()
476}
477pub fn read_permission_ty() -> Expr {
480 type0()
481}
482pub fn ranking_function_ty() -> Expr {
486 pi(
487 BinderInfo::Default,
488 "S",
489 type0(),
490 arrow(arrow(bvar(0), nat_ty()), arrow(type0(), prop())),
491 )
492}
493pub fn termination_proof_ty() -> Expr {
496 arrow(prop(), arrow(type0(), prop()))
497}
498pub fn total_correctness_rule_ty() -> Expr {
501 prop()
502}
503pub fn loop_variant_ty() -> Expr {
506 type0()
507}
508pub fn loop_invariant_ty() -> Expr {
511 arrow(type0(), prop())
512}
513pub fn well_founded_order_ty() -> Expr {
516 pi(
517 BinderInfo::Default,
518 "A",
519 type0(),
520 arrow(arrow(bvar(0), arrow(bvar(1), prop())), prop()),
521 )
522}
523pub fn abstract_spec_ty() -> Expr {
526 type0()
527}
528pub fn concrete_impl_ty() -> Expr {
531 type0()
532}
533pub fn data_refinement_ty() -> Expr {
536 arrow(type0(), arrow(type0(), prop()))
537}
538pub fn simulation_relation_ty() -> Expr {
541 pi(
542 BinderInfo::Default,
543 "A",
544 type0(),
545 pi(
546 BinderInfo::Default,
547 "C",
548 type0(),
549 arrow(arrow(bvar(1), arrow(bvar(1), prop())), prop()),
550 ),
551 )
552}
553pub fn backward_simulation_ty() -> Expr {
556 pi(
557 BinderInfo::Default,
558 "A",
559 type0(),
560 pi(
561 BinderInfo::Default,
562 "C",
563 type0(),
564 arrow(arrow(bvar(1), arrow(bvar(2), prop())), prop()),
565 ),
566 )
567}
568pub fn refinement_mapping_ty() -> Expr {
571 pi(
572 BinderInfo::Default,
573 "A",
574 type0(),
575 pi(
576 BinderInfo::Default,
577 "C",
578 type0(),
579 arrow(arrow(bvar(1), bvar(2)), prop()),
580 ),
581 )
582}
583pub fn abadi_lamport_ty() -> Expr {
586 prop()
587}
588pub fn build_program_logics_env() -> Environment {
590 let mut env = Environment::new();
591 let axioms: &[(&str, Expr)] = &[
592 ("Assertion", assertion_ty()),
593 ("HoareTriple", hoare_triple_ty()),
594 ("TotalHoareTriple", total_hoare_triple_ty()),
595 ("SkipRule", skip_rule_ty()),
596 ("AssignRule", assign_rule_ty()),
597 ("SeqRule", seq_rule_ty()),
598 ("WhileRule", while_rule_ty()),
599 ("ConsequenceRule", consequence_rule_ty()),
600 ("VerificationCondition", verification_condition_ty()),
601 ("WP", wp_ty()),
602 ("WLP", wlp_ty()),
603 ("SP", sp_ty()),
604 ("WPSoundness", wp_soundness_ty()),
605 ("WPCompleteness", wp_completeness_ty()),
606 ("PredicateTransformer", predicate_transformer_ty()),
607 ("AngelicPT", angelic_pt_ty()),
608 ("DemonicPT", demonic_pt_ty()),
609 ("HeapPredicate", heap_predicate_ty()),
610 ("SepStar", sep_star_ty()),
611 ("SepWand", sep_wand_ty()),
612 ("PointsTo", points_to_ty()),
613 ("EmpPredicate", emp_predicate_ty()),
614 ("FrameRule", frame_rule_ty()),
615 ("SepLogicTriple", sep_logic_triple_ty()),
616 ("BiAbduction", bi_abduction_ty()),
617 ("SpatiallyDisjoint", spatially_disjoint_ty()),
618 ("ConcurrentTriple", concurrent_triple_ty()),
619 ("ParallelCompositionRule", parallel_composition_rule_ty()),
620 ("CriticalSectionRule", critical_section_rule_ty()),
621 ("ThreadLocal", thread_local_ty()),
622 ("SharedInvariant", shared_invariant_ty()),
623 ("OwnershipTransfer", ownership_transfer_ty()),
624 ("AtomicTriple", atomic_triple_ty()),
625 ("RelyCondition", rely_condition_ty()),
626 ("GuaranteeCondition", guarantee_condition_ty()),
627 ("RelyGuaranteeTriple", rely_guarantee_triple_ty()),
628 ("RelyGuaranteeParallel", rely_guarantee_parallel_ty()),
629 ("StabilityCondition", stability_condition_ty()),
630 ("RelyGuaranteeConsequence", rely_guarantee_consequence_ty()),
631 ("IrisProp", iris_prop_ty()),
632 ("IrisEntails", iris_entails_ty()),
633 ("IrisSepStar", iris_sep_star_ty()),
634 ("IrisWand", iris_wand_ty()),
635 ("IrisLater", iris_later_ty()),
636 ("IrisAlways", iris_always_ty()),
637 ("IrisExcl", iris_excl_ty()),
638 ("IrisAgree", iris_agree_ty()),
639 ("IrisAuth", iris_auth_ty()),
640 ("IrisFragment", iris_fragment_ty()),
641 ("ResourceAlgebra", resource_algebra_ty()),
642 ("GhostState", ghost_state_ty()),
643 ("GhostUpdate", ghost_update_ty()),
644 ("FramePreservingUpdate", frame_preserving_update_ty()),
645 ("CMRA", cmra_ty()),
646 ("CMRAOp", cmra_op_ty()),
647 ("CMRAValid", cmra_valid_ty()),
648 ("CMRACore", cmra_core_ty()),
649 ("Invariant", invariant_ty()),
650 ("InvariantAlloc", invariant_alloc_ty()),
651 ("InvariantOpen", invariant_open_ty()),
652 ("NamespaceMask", namespace_mask_ty()),
653 ("MaskSubset", mask_subset_ty()),
654 ("FancyUpdate", fancy_update_ty()),
655 ("FractionalPermission", fractional_permission_ty()),
656 ("FractionalPointsTo", fractional_points_to_ty()),
657 ("PermissionSplit", permission_split_ty()),
658 ("PermissionCombine", permission_combine_ty()),
659 ("CountingPermission", counting_permission_ty()),
660 ("WritePermission", write_permission_ty()),
661 ("ReadPermission", read_permission_ty()),
662 ("RankingFunction", ranking_function_ty()),
663 ("TerminationProof", termination_proof_ty()),
664 ("TotalCorrectnessRule", total_correctness_rule_ty()),
665 ("LoopVariant", loop_variant_ty()),
666 ("LoopInvariant", loop_invariant_ty()),
667 ("WellFoundedOrder", well_founded_order_ty()),
668 ("AbstractSpec", abstract_spec_ty()),
669 ("ConcreteImpl", concrete_impl_ty()),
670 ("DataRefinement", data_refinement_ty()),
671 ("SimulationRelation", simulation_relation_ty()),
672 ("BackwardSimulation", backward_simulation_ty()),
673 ("RefinementMapping", refinement_mapping_ty()),
674 ("AbadiLamport", abadi_lamport_ty()),
675 ];
676 for (name, ty) in axioms {
677 env.add(Declaration::Axiom {
678 name: Name::str(*name),
679 univ_params: vec![],
680 ty: ty.clone(),
681 })
682 .ok();
683 }
684 env
685}
686pub type GuaranteeCondition<S> = RelyCondition<S>;
688pub fn is_stable<S: Clone + Eq + std::hash::Hash>(
691 predicate: &HashSet<S>,
692 rely: &RelyCondition<S>,
693) -> bool {
694 rely.transitions.iter().all(|t| {
695 if predicate.contains(&t.before) {
696 predicate.contains(&t.after)
697 } else {
698 true
699 }
700 })
701}
702pub fn trace_inclusion_holds<S>(concrete: <S<S>, abstract_lts: <S<S>) -> bool
705where
706 S: Clone + Eq + std::hash::Hash + std::fmt::Debug,
707{
708 let abstract_labels: HashSet<String> = abstract_lts
709 .transitions
710 .values()
711 .flat_map(|v| v.iter().map(|(l, _)| l.clone()))
712 .collect();
713 concrete.labels_subset_of(&abstract_labels)
714}
715pub fn hoare_logic_rules() -> Vec<(&'static str, &'static str)> {
724 vec![
725 ("Skip", "{P} skip {P}"), ("Assign", "{P[e/x]} x := e {P}"), ("Seq",
726 "{P} C1 {R} {R} C2 {Q}\nāāāāāāāāāāāāāāāāāāāāāā\n{P} C1; C2 {Q}"),
727 ("If",
728 "{P ā§ b} C1 {Q} {P ⧠¬b} C2 {Q}\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n{P} if b then C1 else C2 {Q}"),
729 ("While",
730 "{I ā§ b} C {I}\nāāāāāāāāāāāāāāāāāāāāāāāā\n{I} while b do C {I ⧠¬b}"),
731 ("Consequence",
732 "P ⢠P' {P'} C {Q'} Q' ⢠Q\nāāāāāāāāāāāāāāāāāāāāāāāāāā\n{P} C {Q}"),
733 ("Frame",
734 "{P} C {Q} mod(C) # fv(R) = ā
\nāāāāāāāāāāāāāāāāāāāāāāāāāā\n{P ā R} C {Q ā R}"),
735 ("Parallel",
736 "{P1} C1 {Q1} {P2} C2 {Q2}\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n{P1 ā P2} C1 ā C2 {Q1 ā Q2}"),
737 ]
738}
739pub fn wp_rules() -> Vec<(&'static str, &'static str)> {
747 vec![
748 ("WP-Skip", "wp(skip, Q) = Q"),
749 ("WP-Assign", "wp(x := e, Q) = Q[e/x]"),
750 ("WP-Seq", "wp(C1; C2, Q) = wp(C1, wp(C2, Q))"),
751 (
752 "WP-If",
753 "wp(if b then C1 else C2, Q) = (b ā wp(C1,Q)) ā§ (¬b ā wp(C2,Q))",
754 ),
755 (
756 "WP-While",
757 "wp(while b do C, Q) = lfp(Ī»X. (¬b ā Q) ā§ (b ā wp(C, X)))",
758 ),
759 ("WP-Sound", "{wp(C,Q)} C {Q}"),
760 ("WP-Complete", "{P} C {Q} ⢠P ā wp(C,Q)"),
761 ]
762}
763pub fn iris_invariant_rules() -> Vec<(&'static str, &'static str)> {
771 vec![
772 ("Inv-Alloc", "ā·P ⢠|={E}=> ā N ā E, inv(N, P)"),
773 (
774 "Inv-Open",
775 "inv(N, P) ā (ā·P -ā |={E}=> ā·P ā Q) ⢠|={EāŖ{N},E}=> Q",
776 ),
777 ("Inv-Pers", "ā” inv(N, P)"),
778 ("GhostAlloc", "⢠|==> ā γ, own(γ, a)"),
779 ("GhostUpdate", "own(γ, a) ⢠|==> own(γ, b) (when a ~~> b)"),
780 ("Frame-Iris", "E ā E' ā |={E}=> P ⢠|={E'}=> P"),
781 ]
782}
783#[cfg(test)]
784mod tests {
785 use super::*;
786 #[test]
787 fn test_build_program_logics_env() {
788 let env = build_program_logics_env();
789 assert!(env.get(&Name::str("HoareTriple")).is_some());
790 assert!(env.get(&Name::str("WP")).is_some());
791 assert!(env.get(&Name::str("FrameRule")).is_some());
792 assert!(env.get(&Name::str("IrisProp")).is_some());
793 assert!(env.get(&Name::str("CMRA")).is_some());
794 assert!(env.get(&Name::str("Invariant")).is_some());
795 assert!(env.get(&Name::str("FractionalPermission")).is_some());
796 assert!(env.get(&Name::str("DataRefinement")).is_some());
797 }
798 #[test]
799 fn test_assertion_operations() {
800 let p = Assertion::new("x > 0");
801 let q = Assertion::new("y < 10");
802 let pq = p.and(&q);
803 assert!(pq.formula.contains("x > 0"));
804 assert!(pq.formula.contains("y < 10"));
805 let neg = p.negate();
806 assert!(neg.formula.contains("¬"));
807 let s = p.subst("x", "x + 1");
808 assert_eq!(s.formula, "x + 1 > 0");
809 }
810 #[test]
811 fn test_wp_skip() {
812 let c = Command::Skip;
813 let q = Assertion::new("x >= 0");
814 let wp = c.wp(&q);
815 assert_eq!(wp.formula, "x >= 0");
816 }
817 #[test]
818 fn test_wp_assign() {
819 let c = Command::Assign("x".to_string(), "x + 1".to_string());
820 let q = Assertion::new("x > 5");
821 let wp = c.wp(&q);
822 assert_eq!(wp.formula, "x + 1 > 5");
823 }
824 #[test]
825 fn test_wp_seq() {
826 let c = Command::Seq(
827 Box::new(Command::Assign("x".to_string(), "x + 1".to_string())),
828 Box::new(Command::Skip),
829 );
830 let q = Assertion::new("x > 5");
831 let wp = c.wp(&q);
832 assert_eq!(wp.formula, "x + 1 > 5");
833 }
834 #[test]
835 fn test_heap_disjoint_union() {
836 let mut h1 = Heap::empty();
837 h1.write(0, 42);
838 let mut h2 = Heap::empty();
839 h2.write(1, 99);
840 assert!(h1.is_disjoint(&h2));
841 let h3 = h1.disjoint_union(&h2);
842 assert_eq!(h3.size(), 2);
843 assert_eq!(h3.read(0), Some(42));
844 assert_eq!(h3.read(1), Some(99));
845 }
846 #[test]
847 fn test_fractional_permissions() {
848 let wp = FractionalPerm::write();
849 assert!(wp.is_write());
850 let (h1, h2) = wp.split_half();
851 assert!(!h1.is_write());
852 assert!(!h2.is_write());
853 let combined = h1.combine(&h2).expect("combine should succeed");
854 assert!(combined.is_write());
855 assert!(combined.combine(&h1).is_none());
856 }
857 #[test]
858 fn test_ghost_heap() {
859 let mut gh: GhostHeap<u64> = GhostHeap::empty();
860 gh.alloc("counter", 0u64);
861 assert_eq!(gh.read("counter"), Some(&0u64));
862 let ok = gh.update("counter", 42u64);
863 assert!(ok);
864 assert_eq!(gh.read("counter"), Some(&42u64));
865 }
866 #[test]
867 fn test_stability() {
868 use std::collections::HashSet;
869 let mut pred: HashSet<u32> = HashSet::new();
870 pred.insert(1);
871 pred.insert(2);
872 let mut rely: RelyCondition<u32> = RelyCondition::empty();
873 rely.add(Transition::new(1u32, 2u32));
874 assert!(is_stable(&pred, &rely));
875 rely.add(Transition::new(2u32, 3u32));
876 assert!(!is_stable(&pred, &rely));
877 }
878 #[test]
879 fn test_hoare_logic_rules() {
880 let rules = hoare_logic_rules();
881 assert!(!rules.is_empty());
882 assert!(rules.iter().any(|(n, _)| *n == "Frame"));
883 assert!(rules.iter().any(|(n, _)| *n == "While"));
884 }
885}
886pub fn build_env() -> Result<Environment, String> {
889 Ok(build_program_logics_env())
890}
891#[cfg(test)]
892mod tests_proglogics_ext {
893 use super::*;
894 use std::fmt;
895 #[test]
896 fn test_concurrent_separation_logic() {
897 let iris = ConcurrentSeparationLogicExt::iris();
898 assert!(iris.fractional_permissions);
899 assert!(iris.supports_rely_guarantee);
900 let triple = iris.concurrent_triple("emp", "x := 0", "x = 0");
901 assert!(triple.contains("emp"));
902 assert!(iris.race_condition_freedom());
903 }
904 #[test]
905 fn test_rely_guarantee() {
906 let rg = RelyGuaranteeLogic::new("y=0", "xā„0", "x=0", "xā„0");
907 let triple = rg.rg_triple("x := x + 1");
908 assert!(triple.contains("R:"));
909 let stab = rg.stability_check();
910 assert!(stab.contains("stable"));
911 }
912 #[test]
913 fn test_effect_system() {
914 let ae = EffectSystem::algebraic_effects();
915 assert!(ae.is_algebraic);
916 assert!(!ae.monad_based);
917 let desc = ae.effect_handling_description();
918 assert!(desc.contains("algebraically"));
919 let free = ae.free_monad_presentation();
920 assert!(free.contains("IO"));
921 }
922 #[test]
923 fn test_type_and_effect() {
924 let pure_te = TypeAndEffect::pure_type("Int");
925 assert!(pure_te.is_pure());
926 let judge = pure_te.type_and_effect_judgment();
927 assert!(judge.contains("ā
"));
928 let eff = TypeAndEffect::effectful("Unit", vec!["IO".to_string()]);
929 assert!(!eff.is_pure());
930 }
931 #[test]
932 fn test_probabilistic_hoare_logic() {
933 let phl = ProbabilisticHoareLogic::phl("μ_init", "flip", "p(heads)=0.5");
934 let wpt = phl.expectation_transformer();
935 assert!(wpt.contains("wp(flip"));
936 let mm = phl.mciver_morgan_rule();
937 assert!(mm.contains("McIver-Morgan"));
938 }
939 #[test]
940 fn test_approximate_verification() {
941 let av = ApproximateVerification::pac_verification(0.01, 0.05, "safety");
942 assert!((av.confidence - 0.95).abs() < 1e-10);
943 let samples = av.sample_complexity();
944 assert!(samples > 0);
945 let stmt = av.soundness_statement();
946 assert!(stmt.contains("safety"));
947 }
948 #[test]
949 fn test_numerical_domain() {
950 let intervals = NumericalDomain::intervals();
951 assert!(!intervals.is_relational);
952 let cost = intervals.precision_cost_tradeoff();
953 assert!(cost.contains("O(n)"));
954 let oct = NumericalDomain::octagons();
955 assert!(oct.is_relational);
956 assert!(oct.is_more_precise_than_intervals());
957 let poly = NumericalDomain::polyhedra();
958 assert!(poly.is_relational);
959 }
960}