1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 AsyncSessionEndpoint, BaseType, ChoreographyEngine, ChoreographyStep, DeadlockChecker, GType,
9 GradualSessionMonitor, LType, Message, MonitorResult, ProbBranch, ProbSessionScheduler, Role,
10 SType, SessionChecker, SessionEndpoint, SessionOp, SessionSubtypeChecker,
11};
12
13pub fn app(f: Expr, a: Expr) -> Expr {
14 Expr::App(Box::new(f), Box::new(a))
15}
16pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
17 app(app(f, a), b)
18}
19pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
20 app(app2(f, a, b), c)
21}
22pub fn cst(s: &str) -> Expr {
23 Expr::Const(Name::str(s), vec![])
24}
25pub fn prop() -> Expr {
26 Expr::Sort(Level::zero())
27}
28pub fn type0() -> Expr {
29 Expr::Sort(Level::succ(Level::zero()))
30}
31pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
32 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
33}
34pub fn arrow(a: Expr, b: Expr) -> Expr {
35 pi(BinderInfo::Default, "_", a, b)
36}
37pub fn impl_pi(name: &str, dom: Expr, body: Expr) -> Expr {
38 pi(BinderInfo::Implicit, name, dom, body)
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 list_ty(elem: Expr) -> Expr {
50 app(cst("List"), elem)
51}
52pub fn string_ty() -> Expr {
53 cst("String")
54}
55pub fn stype_ty() -> Expr {
58 type0()
59}
60pub fn send_ty() -> Expr {
63 arrow(type0(), arrow(cst("SType"), cst("SType")))
64}
65pub fn recv_ty() -> Expr {
68 arrow(type0(), arrow(cst("SType"), cst("SType")))
69}
70pub fn end_ty() -> Expr {
73 cst("SType")
74}
75pub fn schoice_ty() -> Expr {
78 arrow(cst("SType"), arrow(cst("SType"), cst("SType")))
79}
80pub fn sbranch_ty() -> Expr {
83 arrow(cst("SType"), arrow(cst("SType"), cst("SType")))
84}
85pub fn srec_ty() -> Expr {
88 arrow(arrow(cst("SType"), cst("SType")), cst("SType"))
89}
90pub fn svar_ty() -> Expr {
93 arrow(nat_ty(), cst("SType"))
94}
95pub fn dual_ty() -> Expr {
98 arrow(cst("SType"), cst("SType"))
99}
100pub fn dual_involutive_ty() -> Expr {
102 pi(
103 BinderInfo::Default,
104 "S",
105 cst("SType"),
106 app2(
107 cst("Eq"),
108 app(cst("dual"), app(cst("dual"), bvar(0))),
109 bvar(0),
110 ),
111 )
112}
113pub fn dual_send_ty() -> Expr {
115 pi(
116 BinderInfo::Default,
117 "T",
118 type0(),
119 pi(
120 BinderInfo::Default,
121 "S",
122 cst("SType"),
123 app2(
124 cst("Eq"),
125 app(cst("dual"), app2(cst("Send"), bvar(1), bvar(0))),
126 app2(cst("Recv"), bvar(1), app(cst("dual"), bvar(0))),
127 ),
128 ),
129 )
130}
131pub fn dual_end_ty() -> Expr {
133 app2(cst("Eq"), app(cst("dual"), cst("End")), cst("End"))
134}
135pub fn channel_ty() -> Expr {
138 arrow(cst("SType"), type0())
139}
140pub fn send_msg_ty() -> Expr {
143 impl_pi(
144 "T",
145 type0(),
146 impl_pi(
147 "S",
148 cst("SType"),
149 arrow(
150 app(cst("Channel"), app2(cst("Send"), bvar(1), bvar(0))),
151 arrow(bvar(2), app(cst("Channel"), bvar(1))),
152 ),
153 ),
154 )
155}
156pub fn recv_msg_ty() -> Expr {
159 impl_pi(
160 "T",
161 type0(),
162 impl_pi(
163 "S",
164 cst("SType"),
165 arrow(
166 app(cst("Channel"), app2(cst("Recv"), bvar(1), bvar(0))),
167 app2(cst("Prod"), bvar(2), app(cst("Channel"), bvar(1))),
168 ),
169 ),
170 )
171}
172pub fn close_ty() -> Expr {
175 arrow(app(cst("Channel"), cst("End")), cst("Unit"))
176}
177pub fn linear_type_ty() -> Expr {
180 arrow(type0(), prop())
181}
182pub fn linear_ctx_ty() -> Expr {
185 type0()
186}
187pub fn ctx_split_ty() -> Expr {
190 arrow(
191 cst("LinearCtx"),
192 arrow(cst("LinearCtx"), arrow(cst("LinearCtx"), prop())),
193 )
194}
195pub fn linear_well_typed_ty() -> Expr {
198 arrow(
199 cst("LinearCtx"),
200 arrow(type0(), arrow(cst("SType"), prop())),
201 )
202}
203pub fn linear_safety_ty() -> Expr {
206 arrow(type0(), prop())
207}
208pub fn affine_type_ty() -> Expr {
211 arrow(type0(), prop())
212}
213pub fn unrestricted_type_ty() -> Expr {
216 arrow(type0(), prop())
217}
218pub fn role_ty() -> Expr {
221 type0()
222}
223pub fn gtype_ty() -> Expr {
226 type0()
227}
228pub fn gcomm_ty() -> Expr {
231 arrow(
232 cst("Role"),
233 arrow(
234 cst("Role"),
235 arrow(type0(), arrow(cst("GType"), cst("GType"))),
236 ),
237 )
238}
239pub fn gchoice_ty() -> Expr {
242 arrow(
243 cst("Role"),
244 arrow(
245 cst("Role"),
246 arrow(cst("GType"), arrow(cst("GType"), cst("GType"))),
247 ),
248 )
249}
250pub fn gend_ty() -> Expr {
253 cst("GType")
254}
255pub fn grec_ty() -> Expr {
258 arrow(arrow(cst("GType"), cst("GType")), cst("GType"))
259}
260pub fn well_formed_ty() -> Expr {
263 arrow(cst("GType"), prop())
264}
265pub fn participants_ty() -> Expr {
268 arrow(cst("GType"), list_ty(cst("Role")))
269}
270pub fn ltype_ty() -> Expr {
273 type0()
274}
275pub fn lsend_ty() -> Expr {
278 arrow(
279 cst("Role"),
280 arrow(type0(), arrow(cst("LType"), cst("LType"))),
281 )
282}
283pub fn lrecv_ty() -> Expr {
286 arrow(
287 cst("Role"),
288 arrow(type0(), arrow(cst("LType"), cst("LType"))),
289 )
290}
291pub fn lchoice_ty() -> Expr {
294 arrow(
295 cst("Role"),
296 arrow(cst("LType"), arrow(cst("LType"), cst("LType"))),
297 )
298}
299pub fn lbranch_ty() -> Expr {
302 arrow(
303 cst("Role"),
304 arrow(cst("LType"), arrow(cst("LType"), cst("LType"))),
305 )
306}
307pub fn lend_ty() -> Expr {
310 cst("LType")
311}
312pub fn project_ty() -> Expr {
315 arrow(cst("GType"), arrow(cst("Role"), cst("LType")))
316}
317pub fn projection_sound_ty() -> Expr {
321 pi(
322 BinderInfo::Default,
323 "G",
324 cst("GType"),
325 pi(
326 BinderInfo::Default,
327 "p",
328 cst("Role"),
329 arrow(
330 app(cst("WellFormed"), bvar(1)),
331 app(
332 cst("LocallyConsistent"),
333 app2(cst("project"), bvar(2), bvar(1)),
334 ),
335 ),
336 ),
337 )
338}
339pub fn locally_consistent_ty() -> Expr {
341 arrow(cst("LType"), prop())
342}
343pub fn mergeability_ty() -> Expr {
346 arrow(cst("LType"), arrow(cst("LType"), prop()))
347}
348pub fn process_ty() -> Expr {
351 type0()
352}
353pub fn reduces_ty() -> Expr {
356 arrow(type0(), arrow(type0(), prop()))
357}
358pub fn stuck_ty() -> Expr {
361 arrow(type0(), prop())
362}
363pub fn deadlock_free_ty() -> Expr {
366 arrow(type0(), prop())
367}
368pub fn progress_ty() -> Expr {
371 arrow(type0(), arrow(cst("SType"), prop()))
372}
373pub fn subject_reduction_ty() -> Expr {
376 prop()
377}
378pub fn type_safety_ty() -> Expr {
381 prop()
382}
383pub fn deadlock_freedom_thm_ty() -> Expr {
386 pi(
387 BinderInfo::Default,
388 "P",
389 type0(),
390 pi(
391 BinderInfo::Default,
392 "S",
393 cst("SType"),
394 arrow(
395 app2(cst("WellTypedProcess"), bvar(1), bvar(0)),
396 app(cst("DeadlockFree"), bvar(2)),
397 ),
398 ),
399 )
400}
401pub fn well_typed_process_ty() -> Expr {
403 arrow(type0(), arrow(cst("SType"), prop()))
404}
405pub fn progress_thm_ty() -> Expr {
408 pi(
409 BinderInfo::Default,
410 "P",
411 type0(),
412 pi(
413 BinderInfo::Default,
414 "S",
415 cst("SType"),
416 arrow(
417 app2(cst("WellTypedProcess"), bvar(1), bvar(0)),
418 app2(
419 cst("Or"),
420 app(cst("IsValue"), bvar(2)),
421 app(cst("Exists"), app(cst("Reduces"), bvar(3))),
422 ),
423 ),
424 ),
425 )
426}
427pub fn is_value_ty() -> Expr {
429 arrow(type0(), prop())
430}
431pub fn infer_stype_ty() -> Expr {
434 arrow(type0(), arrow(cst("SType"), prop()))
435}
436pub fn principal_stype_ty() -> Expr {
439 arrow(type0(), arrow(cst("SType"), prop()))
440}
441pub fn stype_unify_ty() -> Expr {
444 arrow(cst("SType"), arrow(cst("SType"), arrow(type0(), prop())))
445}
446pub fn stype_subst_ty() -> Expr {
449 type0()
450}
451pub fn inference_complete_ty() -> Expr {
454 prop()
455}
456pub fn inference_sound_ty() -> Expr {
459 prop()
460}
461pub fn dep_stype_ty() -> Expr {
464 type0()
465}
466pub fn dep_send_ty() -> Expr {
469 impl_pi(
470 "T",
471 type0(),
472 arrow(arrow(bvar(0), cst("DepSType")), cst("DepSType")),
473 )
474}
475pub fn dep_recv_ty() -> Expr {
478 impl_pi(
479 "T",
480 type0(),
481 arrow(arrow(bvar(0), cst("DepSType")), cst("DepSType")),
482 )
483}
484pub fn dep_end_ty() -> Expr {
486 cst("DepSType")
487}
488pub fn dep_dual_ty() -> Expr {
490 arrow(cst("DepSType"), cst("DepSType"))
491}
492pub fn dep_channel_ty() -> Expr {
494 arrow(cst("DepSType"), type0())
495}
496pub fn dep_send_msg_ty() -> Expr {
498 arrow(cst("DepSType"), arrow(type0(), arrow(type0(), type0())))
499}
500pub fn unfold_ty() -> Expr {
503 arrow(cst("SType"), cst("SType"))
504}
505pub fn fold_ty() -> Expr {
508 arrow(cst("SType"), cst("SType"))
509}
510pub fn iso_recursive_ty() -> Expr {
513 arrow(cst("SType"), prop())
514}
515pub fn equi_recursive_ty() -> Expr {
518 arrow(cst("SType"), prop())
519}
520pub fn coinductive_ty() -> Expr {
523 arrow(cst("SType"), prop())
524}
525pub fn stype_equiv_ty() -> Expr {
528 arrow(cst("SType"), arrow(cst("SType"), prop()))
529}
530pub fn unfold_preserves_dual_ty() -> Expr {
532 pi(
533 BinderInfo::Default,
534 "S",
535 cst("SType"),
536 app2(
537 cst("Eq"),
538 app(cst("dual"), app(cst("Unfold"), bvar(0))),
539 app(cst("Unfold"), app(cst("dual"), bvar(0))),
540 ),
541 )
542}
543pub fn async_stype_ty() -> Expr {
546 type0()
547}
548pub fn async_send_ty() -> Expr {
551 arrow(type0(), arrow(cst("AsyncSType"), cst("AsyncSType")))
552}
553pub fn async_recv_ty() -> Expr {
556 arrow(type0(), arrow(cst("AsyncSType"), cst("AsyncSType")))
557}
558pub fn eventual_delivery_ty() -> Expr {
561 arrow(cst("AsyncSType"), prop())
562}
563pub fn buffer_bound_ty() -> Expr {
566 arrow(cst("AsyncSType"), arrow(nat_ty(), prop()))
567}
568pub fn async_dual_ty() -> Expr {
571 arrow(cst("AsyncSType"), cst("AsyncSType"))
572}
573pub fn async_end_ty() -> Expr {
576 cst("AsyncSType")
577}
578pub fn ll_prop_ty() -> Expr {
581 type0()
582}
583pub fn tensor_ty() -> Expr {
586 arrow(cst("LLProp"), arrow(cst("LLProp"), cst("LLProp")))
587}
588pub fn lolli_ty() -> Expr {
591 arrow(cst("LLProp"), arrow(cst("LLProp"), cst("LLProp")))
592}
593pub fn par_ty() -> Expr {
596 arrow(cst("LLProp"), arrow(cst("LLProp"), cst("LLProp")))
597}
598pub fn bang_ty() -> Expr {
601 arrow(cst("LLProp"), cst("LLProp"))
602}
603pub fn why_not_ty() -> Expr {
606 arrow(cst("LLProp"), cst("LLProp"))
607}
608pub fn cut_elim_ty() -> Expr {
611 prop()
612}
613pub fn curry_howard_ll_ty() -> Expr {
616 arrow(cst("LLProp"), arrow(cst("SType"), prop()))
617}
618pub fn ssubtype_ty() -> Expr {
621 arrow(cst("SType"), arrow(cst("SType"), prop()))
622}
623pub fn ssubtype_refl_ty() -> Expr {
625 pi(
626 BinderInfo::Default,
627 "S",
628 cst("SType"),
629 app2(cst("SSubtype"), bvar(0), bvar(0)),
630 )
631}
632pub fn ssubtype_trans_ty() -> Expr {
634 pi(
635 BinderInfo::Default,
636 "S1",
637 cst("SType"),
638 pi(
639 BinderInfo::Default,
640 "S2",
641 cst("SType"),
642 pi(
643 BinderInfo::Default,
644 "S3",
645 cst("SType"),
646 arrow(
647 app2(cst("SSubtype"), bvar(2), bvar(1)),
648 arrow(
649 app2(cst("SSubtype"), bvar(2), bvar(1)),
650 app2(cst("SSubtype"), bvar(4), bvar(2)),
651 ),
652 ),
653 ),
654 ),
655 )
656}
657pub fn send_covariant_ty() -> Expr {
660 pi(
661 BinderInfo::Default,
662 "T",
663 type0(),
664 pi(
665 BinderInfo::Default,
666 "S1",
667 cst("SType"),
668 pi(
669 BinderInfo::Default,
670 "S2",
671 cst("SType"),
672 arrow(
673 app2(cst("SSubtype"), bvar(1), bvar(0)),
674 app2(
675 cst("SSubtype"),
676 app2(cst("Send"), bvar(2), bvar(2)),
677 app2(cst("Send"), bvar(2), bvar(1)),
678 ),
679 ),
680 ),
681 ),
682 )
683}
684pub fn recv_contravariant_ty() -> Expr {
687 pi(
688 BinderInfo::Default,
689 "T",
690 type0(),
691 pi(
692 BinderInfo::Default,
693 "S1",
694 cst("SType"),
695 pi(
696 BinderInfo::Default,
697 "S2",
698 cst("SType"),
699 arrow(
700 app2(cst("SSubtype"), bvar(1), bvar(0)),
701 app2(
702 cst("SSubtype"),
703 app2(cst("Recv"), bvar(2), bvar(1)),
704 app2(cst("Recv"), bvar(2), bvar(2)),
705 ),
706 ),
707 ),
708 ),
709 )
710}
711pub fn ho_stype_ty() -> Expr {
714 type0()
715}
716pub fn send_chan_ty() -> Expr {
719 arrow(cst("SType"), arrow(cst("HOSType"), cst("HOSType")))
720}
721pub fn recv_chan_ty() -> Expr {
724 arrow(cst("SType"), arrow(cst("HOSType"), cst("HOSType")))
725}
726pub fn session_passing_ty() -> Expr {
729 arrow(cst("HOSType"), prop())
730}
731pub fn ho_dual_ty() -> Expr {
734 arrow(cst("HOSType"), cst("HOSType"))
735}
736pub fn ex_stype_ty() -> Expr {
739 type0()
740}
741pub fn throw_ty() -> Expr {
744 arrow(type0(), cst("ExSType"))
745}
746pub fn catch_ty() -> Expr {
749 arrow(cst("ExSType"), arrow(cst("ExSType"), cst("ExSType")))
750}
751pub fn exception_safe_ty() -> Expr {
754 arrow(cst("ExSType"), prop())
755}
756pub fn fault_tolerant_ty() -> Expr {
759 arrow(cst("ExSType"), prop())
760}
761pub fn g_stype_ty() -> Expr {
764 type0()
765}
766pub fn gradual_send_ty() -> Expr {
769 arrow(type0(), arrow(cst("GSType"), cst("GSType")))
770}
771pub fn gradual_recv_ty() -> Expr {
774 arrow(type0(), arrow(cst("GSType"), cst("GSType")))
775}
776pub fn dyn_stype_ty() -> Expr {
779 cst("GSType")
780}
781pub fn cast_insertion_ty() -> Expr {
784 arrow(
785 cst("GSType"),
786 arrow(cst("SType"), arrow(cst("GSType"), prop())),
787 )
788}
789pub fn dynamic_monitor_ty() -> Expr {
792 arrow(cst("GSType"), prop())
793}
794pub fn gradual_consistency_ty() -> Expr {
797 arrow(cst("GSType"), arrow(cst("GSType"), prop()))
798}
799pub fn prob_stype_ty() -> Expr {
802 type0()
803}
804pub fn prob_choice_ty() -> Expr {
807 arrow(
808 cst("SType"),
809 arrow(cst("SType"), arrow(cst("Real"), cst("ProbSType"))),
810 )
811}
812pub fn expected_cost_ty() -> Expr {
815 arrow(cst("ProbSType"), arrow(nat_ty(), prop()))
816}
817pub fn markov_chain_protocol_ty() -> Expr {
820 arrow(cst("ProbSType"), prop())
821}
822pub fn prob_termination_ty() -> Expr {
825 arrow(cst("ProbSType"), prop())
826}
827pub fn choreography_ty() -> Expr {
830 type0()
831}
832pub fn realization_ty() -> Expr {
835 arrow(cst("Choreography"), arrow(cst("GType"), prop()))
836}
837pub fn global_view_ty() -> Expr {
840 arrow(cst("GType"), cst("Choreography"))
841}
842pub fn endpoint_projection_ty() -> Expr {
845 arrow(cst("Choreography"), arrow(cst("Role"), cst("LType")))
846}
847pub fn choreography_consistency_ty() -> Expr {
850 arrow(cst("Choreography"), prop())
851}
852pub fn ambience_compatibility_ty() -> Expr {
855 arrow(cst("Choreography"), arrow(cst("GType"), prop()))
856}
857pub fn shared_mem_type_ty() -> Expr {
860 type0()
861}
862pub fn mutex_ty() -> Expr {
865 arrow(type0(), cst("SharedMemType"))
866}
867pub fn acquire_ty() -> Expr {
870 arrow(cst("SharedMemType"), arrow(cst("SType"), cst("SType")))
871}
872pub fn release_ty() -> Expr {
875 arrow(cst("SharedMemType"), arrow(cst("SType"), cst("SType")))
876}
877pub fn data_race_free_ty() -> Expr {
880 arrow(cst("SharedMemType"), prop())
881}
882pub fn build_session_types_env(env: &mut Environment) -> Result<(), String> {
884 let axioms: &[(&str, Expr)] = &[
885 ("SType", stype_ty()),
886 ("Send", send_ty()),
887 ("Recv", recv_ty()),
888 ("End", end_ty()),
889 ("SChoice", schoice_ty()),
890 ("SBranch", sbranch_ty()),
891 ("SRec", srec_ty()),
892 ("SVar", svar_ty()),
893 ("dual", dual_ty()),
894 ("dual_involutive", dual_involutive_ty()),
895 ("dual_send", dual_send_ty()),
896 ("dual_end", dual_end_ty()),
897 ("Channel", channel_ty()),
898 ("send_msg", send_msg_ty()),
899 ("recv_msg", recv_msg_ty()),
900 ("close", close_ty()),
901 ("LinearType", linear_type_ty()),
902 ("LinearCtx", linear_ctx_ty()),
903 ("CtxSplit", ctx_split_ty()),
904 ("LinearWellTyped", linear_well_typed_ty()),
905 ("LinearSafety", linear_safety_ty()),
906 ("AffineType", affine_type_ty()),
907 ("UnrestrictedType", unrestricted_type_ty()),
908 ("Role", role_ty()),
909 ("GType", gtype_ty()),
910 ("GComm", gcomm_ty()),
911 ("GChoice", gchoice_ty()),
912 ("GEnd", gend_ty()),
913 ("GRec", grec_ty()),
914 ("WellFormed", well_formed_ty()),
915 ("Participants", participants_ty()),
916 ("LType", ltype_ty()),
917 ("LSend", lsend_ty()),
918 ("LRecv", lrecv_ty()),
919 ("LChoice", lchoice_ty()),
920 ("LBranch", lbranch_ty()),
921 ("LEnd", lend_ty()),
922 ("project", project_ty()),
923 ("LocallyConsistent", locally_consistent_ty()),
924 ("Mergeability", mergeability_ty()),
925 ("ProjectionSound", projection_sound_ty()),
926 ("Process", process_ty()),
927 ("Reduces", reduces_ty()),
928 ("Stuck", stuck_ty()),
929 ("DeadlockFree", deadlock_free_ty()),
930 ("Progress", progress_ty()),
931 ("SubjectReduction", subject_reduction_ty()),
932 ("TypeSafety", type_safety_ty()),
933 ("WellTypedProcess", well_typed_process_ty()),
934 ("DeadlockFreedomThm", deadlock_freedom_thm_ty()),
935 ("ProgressThm", progress_thm_ty()),
936 ("IsValue", is_value_ty()),
937 ("InferSType", infer_stype_ty()),
938 ("PrincipalSType", principal_stype_ty()),
939 ("STypeUnify", stype_unify_ty()),
940 ("STypeSubst", stype_subst_ty()),
941 ("InferenceComplete", inference_complete_ty()),
942 ("InferenceSound", inference_sound_ty()),
943 ("DepSType", dep_stype_ty()),
944 ("DepSend", dep_send_ty()),
945 ("DepRecv", dep_recv_ty()),
946 ("DepEnd", dep_end_ty()),
947 ("DepDual", dep_dual_ty()),
948 ("DepChannel", dep_channel_ty()),
949 ("DepSendMsg", dep_send_msg_ty()),
950 ("Unfold", unfold_ty()),
951 ("Fold", fold_ty()),
952 ("IsoRecursive", iso_recursive_ty()),
953 ("EquiRecursive", equi_recursive_ty()),
954 ("Coinductive", coinductive_ty()),
955 ("STypeEquiv", stype_equiv_ty()),
956 ("UnfoldPreservesDual", unfold_preserves_dual_ty()),
957 ("AsyncSType", async_stype_ty()),
958 ("AsyncSend", async_send_ty()),
959 ("AsyncRecv", async_recv_ty()),
960 ("EventualDelivery", eventual_delivery_ty()),
961 ("BufferBound", buffer_bound_ty()),
962 ("AsyncDual", async_dual_ty()),
963 ("AsyncEnd", async_end_ty()),
964 ("LLProp", ll_prop_ty()),
965 ("Tensor", tensor_ty()),
966 ("Lolli", lolli_ty()),
967 ("Par", par_ty()),
968 ("Bang", bang_ty()),
969 ("WhyNot", why_not_ty()),
970 ("CutElim", cut_elim_ty()),
971 ("CurryHowardLL", curry_howard_ll_ty()),
972 ("SSubtype", ssubtype_ty()),
973 ("SSubtypeRefl", ssubtype_refl_ty()),
974 ("SSubtypeTrans", ssubtype_trans_ty()),
975 ("SendCovariant", send_covariant_ty()),
976 ("RecvContravariant", recv_contravariant_ty()),
977 ("HOSType", ho_stype_ty()),
978 ("SendChan", send_chan_ty()),
979 ("RecvChan", recv_chan_ty()),
980 ("SessionPassing", session_passing_ty()),
981 ("HODual", ho_dual_ty()),
982 ("ExSType", ex_stype_ty()),
983 ("Throw", throw_ty()),
984 ("Catch", catch_ty()),
985 ("ExceptionSafe", exception_safe_ty()),
986 ("FaultTolerant", fault_tolerant_ty()),
987 ("GSType", g_stype_ty()),
988 ("GradualSend", gradual_send_ty()),
989 ("GradualRecv", gradual_recv_ty()),
990 ("DynSType", dyn_stype_ty()),
991 ("CastInsertion", cast_insertion_ty()),
992 ("DynamicMonitor", dynamic_monitor_ty()),
993 ("GradualConsistency", gradual_consistency_ty()),
994 ("ProbSType", prob_stype_ty()),
995 ("ProbChoice", prob_choice_ty()),
996 ("ExpectedCost", expected_cost_ty()),
997 ("MarkovChainProtocol", markov_chain_protocol_ty()),
998 ("ProbTermination", prob_termination_ty()),
999 ("Choreography", choreography_ty()),
1000 ("Realization", realization_ty()),
1001 ("GlobalView", global_view_ty()),
1002 ("EndpointProjection", endpoint_projection_ty()),
1003 ("ChoreographyConsistency", choreography_consistency_ty()),
1004 ("AmbienceCompatibility", ambience_compatibility_ty()),
1005 ("SharedMemType", shared_mem_type_ty()),
1006 ("Mutex", mutex_ty()),
1007 ("Acquire", acquire_ty()),
1008 ("Release", release_ty()),
1009 ("DataRaceFree", data_race_free_ty()),
1010 ];
1011 for (name, ty) in axioms {
1012 env.add(Declaration::Axiom {
1013 name: Name::str(*name),
1014 univ_params: vec![],
1015 ty: ty.clone(),
1016 })
1017 .ok();
1018 }
1019 Ok(())
1020}
1021#[cfg(test)]
1022mod tests {
1023 use super::*;
1024 use oxilean_kernel::{Environment, Name};
1025 #[test]
1026 fn test_build_env_registers_axioms() {
1027 let mut env = Environment::new();
1028 build_session_types_env(&mut env).expect("build should succeed");
1029 assert!(env.get(&Name::str("SType")).is_some(), "SType missing");
1030 assert!(env.get(&Name::str("Send")).is_some(), "Send missing");
1031 assert!(env.get(&Name::str("Recv")).is_some(), "Recv missing");
1032 assert!(env.get(&Name::str("dual")).is_some(), "dual missing");
1033 assert!(env.get(&Name::str("GType")).is_some(), "GType missing");
1034 assert!(env.get(&Name::str("project")).is_some(), "project missing");
1035 assert!(
1036 env.get(&Name::str("DeadlockFree")).is_some(),
1037 "DeadlockFree missing"
1038 );
1039 assert!(
1040 env.get(&Name::str("DepSType")).is_some(),
1041 "DepSType missing"
1042 );
1043 }
1044 #[test]
1045 fn test_dual_involutive() {
1046 let st = SType::Send(
1047 Box::new(BaseType::Nat),
1048 Box::new(SType::Recv(Box::new(BaseType::Bool), Box::new(SType::End))),
1049 );
1050 let d = st.dual();
1051 let dd = d.dual();
1052 assert_eq!(st, dd, "dual should be involutive");
1053 }
1054 #[test]
1055 fn test_dual_swaps_send_recv() {
1056 let send = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1057 assert!(matches!(send.dual(), SType::Recv(_, _)));
1058 let recv = SType::Recv(Box::new(BaseType::Bool), Box::new(SType::End));
1059 assert!(matches!(recv.dual(), SType::Send(_, _)));
1060 }
1061 #[test]
1062 fn test_dual_choice() {
1063 let choice = SType::Choice(Box::new(SType::End), Box::new(SType::End));
1064 let d = choice.dual();
1065 assert!(matches!(d, SType::Branch(_, _)));
1066 let branch = SType::Branch(Box::new(SType::End), Box::new(SType::End));
1067 assert!(matches!(branch.dual(), SType::Choice(_, _)));
1068 }
1069 #[test]
1070 fn test_session_endpoint_send_recv() {
1071 let st = SType::Send(
1072 Box::new(BaseType::Nat),
1073 Box::new(SType::Recv(Box::new(BaseType::Nat), Box::new(SType::End))),
1074 );
1075 let mut ep = SessionEndpoint::new(st);
1076 ep.send(Message::Nat(42)).expect("send should succeed");
1077 assert!(ep.remaining.is_recv());
1078 }
1079 #[test]
1080 fn test_session_type_checker() {
1081 let st = SType::Send(
1082 Box::new(BaseType::Nat),
1083 Box::new(SType::Recv(Box::new(BaseType::Bool), Box::new(SType::End))),
1084 );
1085 let mut checker = SessionChecker::new();
1086 checker.register_channel("ch", st);
1087 let ops = vec![
1088 SessionOp::Send(BaseType::Nat),
1089 SessionOp::Recv(BaseType::Bool),
1090 SessionOp::Close,
1091 ];
1092 let result = checker.check_usage("ch", &ops);
1093 assert!(
1094 result.is_ok(),
1095 "Well-typed usage should type check: {:?}",
1096 result
1097 );
1098 assert_eq!(result.expect("result should be valid"), SType::End);
1099 }
1100 #[test]
1101 fn test_global_type_projection() {
1102 let alice = Role::new("Alice");
1103 let bob = Role::new("Bob");
1104 let global = GType::Comm {
1105 sender: alice.clone(),
1106 receiver: bob.clone(),
1107 msg_ty: BaseType::Nat,
1108 cont: Box::new(GType::End),
1109 };
1110 let alice_proj = global.project(&alice);
1111 let bob_proj = global.project(&bob);
1112 assert!(
1113 matches!(alice_proj, LType::Send(_, _, _)),
1114 "Alice should have LSend"
1115 );
1116 assert!(
1117 matches!(bob_proj, LType::Recv(_, _, _)),
1118 "Bob should have LRecv"
1119 );
1120 }
1121 #[test]
1122 fn test_deadlock_checker() {
1123 let mut checker = DeadlockChecker::new();
1124 checker.add_wait("ch1", "A", "B");
1125 checker.add_wait("ch2", "B", "C");
1126 assert!(checker.is_deadlock_free(), "Should be deadlock-free");
1127 checker.add_wait("ch3", "C", "A");
1128 assert!(
1129 !checker.is_deadlock_free(),
1130 "Cycle: should NOT be deadlock-free"
1131 );
1132 }
1133 #[test]
1134 fn test_recursive_session_unfold() {
1135 let nat_stream = SType::Rec(
1136 "X".to_string(),
1137 Box::new(SType::Send(
1138 Box::new(BaseType::Nat),
1139 Box::new(SType::Var("X".to_string())),
1140 )),
1141 );
1142 let unfolded = nat_stream.unfold();
1143 assert!(unfolded.is_send());
1144 }
1145 #[test]
1146 fn test_new_axioms_registered() {
1147 let mut env = Environment::new();
1148 build_session_types_env(&mut env).expect("build should succeed");
1149 assert!(env.get(&Name::str("AsyncSType")).is_some());
1150 assert!(env.get(&Name::str("AsyncSend")).is_some());
1151 assert!(env.get(&Name::str("EventualDelivery")).is_some());
1152 assert!(env.get(&Name::str("BufferBound")).is_some());
1153 assert!(env.get(&Name::str("AsyncDual")).is_some());
1154 assert!(env.get(&Name::str("LLProp")).is_some());
1155 assert!(env.get(&Name::str("Tensor")).is_some());
1156 assert!(env.get(&Name::str("Lolli")).is_some());
1157 assert!(env.get(&Name::str("Bang")).is_some());
1158 assert!(env.get(&Name::str("CutElim")).is_some());
1159 assert!(env.get(&Name::str("CurryHowardLL")).is_some());
1160 assert!(env.get(&Name::str("SSubtype")).is_some());
1161 assert!(env.get(&Name::str("SSubtypeRefl")).is_some());
1162 assert!(env.get(&Name::str("SendCovariant")).is_some());
1163 assert!(env.get(&Name::str("RecvContravariant")).is_some());
1164 assert!(env.get(&Name::str("HOSType")).is_some());
1165 assert!(env.get(&Name::str("SendChan")).is_some());
1166 assert!(env.get(&Name::str("SessionPassing")).is_some());
1167 assert!(env.get(&Name::str("ExSType")).is_some());
1168 assert!(env.get(&Name::str("Throw")).is_some());
1169 assert!(env.get(&Name::str("Catch")).is_some());
1170 assert!(env.get(&Name::str("FaultTolerant")).is_some());
1171 assert!(env.get(&Name::str("GSType")).is_some());
1172 assert!(env.get(&Name::str("DynSType")).is_some());
1173 assert!(env.get(&Name::str("CastInsertion")).is_some());
1174 assert!(env.get(&Name::str("GradualConsistency")).is_some());
1175 assert!(env.get(&Name::str("ProbSType")).is_some());
1176 assert!(env.get(&Name::str("ProbChoice")).is_some());
1177 assert!(env.get(&Name::str("MarkovChainProtocol")).is_some());
1178 assert!(env.get(&Name::str("ProbTermination")).is_some());
1179 assert!(env.get(&Name::str("Choreography")).is_some());
1180 assert!(env.get(&Name::str("Realization")).is_some());
1181 assert!(env.get(&Name::str("EndpointProjection")).is_some());
1182 assert!(env.get(&Name::str("ChoreographyConsistency")).is_some());
1183 assert!(env.get(&Name::str("SharedMemType")).is_some());
1184 assert!(env.get(&Name::str("Mutex")).is_some());
1185 assert!(env.get(&Name::str("Acquire")).is_some());
1186 assert!(env.get(&Name::str("DataRaceFree")).is_some());
1187 }
1188 #[test]
1189 fn test_async_endpoint_send_buffered() {
1190 let st = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1191 let mut ep = AsyncSessionEndpoint::new(st);
1192 ep.async_send(Message::Nat(7))
1193 .expect("async_send should succeed");
1194 assert_eq!(ep.outbox_len(), 1, "message should be in outbox");
1195 assert!(
1196 ep.remaining == SType::End,
1197 "remaining should advance to End"
1198 );
1199 }
1200 #[test]
1201 fn test_async_endpoint_flush_and_recv() {
1202 let sender_st = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1203 let recv_st = SType::Recv(Box::new(BaseType::Nat), Box::new(SType::End));
1204 let mut sender = AsyncSessionEndpoint::new(sender_st);
1205 let mut receiver = AsyncSessionEndpoint::new(recv_st);
1206 sender.async_send(Message::Nat(42)).expect("send ok");
1207 let flushed = sender.flush_to(&mut receiver);
1208 assert_eq!(flushed, 1);
1209 assert_eq!(receiver.inbox_len(), 1);
1210 let msg = receiver.async_recv().expect("recv ok");
1211 assert!(matches!(msg, Message::Nat(42)));
1212 }
1213 #[test]
1214 fn test_subtype_reflexivity() {
1215 let mut checker = SessionSubtypeChecker::new();
1216 let st = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1217 assert!(
1218 checker.is_subtype(&st, &st),
1219 "every type is a subtype of itself"
1220 );
1221 }
1222 #[test]
1223 fn test_subtype_end() {
1224 let mut checker = SessionSubtypeChecker::new();
1225 assert!(checker.is_subtype(&SType::End, &SType::End));
1226 }
1227 #[test]
1228 fn test_subtype_incompatible() {
1229 let mut checker = SessionSubtypeChecker::new();
1230 let send = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1231 let recv = SType::Recv(Box::new(BaseType::Nat), Box::new(SType::End));
1232 assert!(
1233 !checker.is_subtype(&send, &recv),
1234 "Send is not subtype of Recv"
1235 );
1236 }
1237 #[test]
1238 fn test_prob_scheduler_probabilities_sum_to_one() {
1239 let branches = vec![
1240 ProbBranch {
1241 label: "A".into(),
1242 weight: 1.0,
1243 cont: SType::End,
1244 },
1245 ProbBranch {
1246 label: "B".into(),
1247 weight: 3.0,
1248 cont: SType::End,
1249 },
1250 ];
1251 let sched = ProbSessionScheduler::new(branches);
1252 let probs = sched.probabilities();
1253 let sum: f64 = probs.iter().sum();
1254 assert!((sum - 1.0).abs() < 1e-9, "probabilities should sum to 1");
1255 }
1256 #[test]
1257 fn test_prob_scheduler_greedy_choice() {
1258 let branches = vec![
1259 ProbBranch {
1260 label: "low".into(),
1261 weight: 1.0,
1262 cont: SType::End,
1263 },
1264 ProbBranch {
1265 label: "high".into(),
1266 weight: 9.0,
1267 cont: SType::End,
1268 },
1269 ];
1270 let sched = ProbSessionScheduler::new(branches);
1271 assert_eq!(
1272 sched.greedy_choice(),
1273 Some(1),
1274 "highest weight branch is index 1"
1275 );
1276 }
1277 #[test]
1278 fn test_choreography_engine_simple() {
1279 let alice = Role::new("Alice");
1280 let bob = Role::new("Bob");
1281 let global = GType::Comm {
1282 sender: alice.clone(),
1283 receiver: bob.clone(),
1284 msg_ty: BaseType::Nat,
1285 cont: Box::new(GType::End),
1286 };
1287 let mut engine = ChoreographyEngine::new();
1288 engine.execute(&global).expect("execution should succeed");
1289 assert_eq!(engine.comm_count(), 1, "one communication step");
1290 assert!(matches!(engine.trace[0], ChoreographyStep::Comm { .. }));
1291 assert!(matches!(engine.trace[1], ChoreographyStep::End));
1292 }
1293 #[test]
1294 fn test_monitor_exact_match() {
1295 let st = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1296 let mut monitor = GradualSessionMonitor::new(st);
1297 let result = monitor.check_send(&BaseType::Nat);
1298 assert_eq!(result, MonitorResult::Ok);
1299 assert!(monitor.is_safe());
1300 assert!(monitor.casts.is_empty());
1301 }
1302 #[test]
1303 fn test_monitor_type_mismatch_inserts_cast() {
1304 let st = SType::Send(Box::new(BaseType::Nat), Box::new(SType::End));
1305 let mut monitor = GradualSessionMonitor::new(st);
1306 let result = monitor.check_send(&BaseType::Bool);
1307 assert!(matches!(result, MonitorResult::CastInserted(_)));
1308 assert!(!monitor.casts.is_empty());
1309 }
1310 #[test]
1311 fn test_monitor_wrong_direction_failure() {
1312 let st = SType::Recv(Box::new(BaseType::Nat), Box::new(SType::End));
1313 let mut monitor = GradualSessionMonitor::new(st);
1314 let result = monitor.check_send(&BaseType::Nat);
1315 assert!(matches!(result, MonitorResult::Failure(_)));
1316 assert!(!monitor.is_safe());
1317 }
1318}