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