Skip to main content

oxilean_std/session_types/
functions.rs

1//! Auto-generated module
2//!
3//! šŸ¤– Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use 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}
55/// `SType : Type`
56/// The type of binary session types.
57pub fn stype_ty() -> Expr {
58    type0()
59}
60/// `Send : Type → SType → SType`
61/// `!T.S` — send a value of type T, then continue as S.
62pub fn send_ty() -> Expr {
63    arrow(type0(), arrow(cst("SType"), cst("SType")))
64}
65/// `Recv : Type → SType → SType`
66/// `?T.S` — receive a value of type T, then continue as S.
67pub fn recv_ty() -> Expr {
68    arrow(type0(), arrow(cst("SType"), cst("SType")))
69}
70/// `End : SType`
71/// Session termination — the session has ended.
72pub fn end_ty() -> Expr {
73    cst("SType")
74}
75/// `SChoice : SType → SType → SType`
76/// Internal choice: `S₁ āŠ• Sā‚‚` — select one branch to send.
77pub fn schoice_ty() -> Expr {
78    arrow(cst("SType"), arrow(cst("SType"), cst("SType")))
79}
80/// `SBranch : SType → SType → SType`
81/// External choice: `S₁ & Sā‚‚` — offer both branches, peer selects.
82pub fn sbranch_ty() -> Expr {
83    arrow(cst("SType"), arrow(cst("SType"), cst("SType")))
84}
85/// `SRec : (SType → SType) → SType`
86/// Iso-recursive session type: `μX.S(X)`.
87pub fn srec_ty() -> Expr {
88    arrow(arrow(cst("SType"), cst("SType")), cst("SType"))
89}
90/// `SVar : Nat → SType`
91/// Session type variable (de Bruijn index).
92pub fn svar_ty() -> Expr {
93    arrow(nat_ty(), cst("SType"))
94}
95/// `dual : SType → SType`
96/// Duality: swaps `Send` and `Recv`, swaps `SChoice` and `SBranch`.
97pub fn dual_ty() -> Expr {
98    arrow(cst("SType"), cst("SType"))
99}
100/// `dual_involutive : āˆ€ (S : SType), dual (dual S) = S`
101pub 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}
113/// `dual_send : āˆ€ (T : Type) (S : SType), dual (Send T S) = Recv T (dual S)`
114pub 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}
131/// `dual_end : dual End = End`
132pub fn dual_end_ty() -> Expr {
133    app2(cst("Eq"), app(cst("dual"), cst("End")), cst("End"))
134}
135/// `Channel : SType → Type`
136/// A typed channel: `Chan S` is a channel whose protocol is `S`.
137pub fn channel_ty() -> Expr {
138    arrow(cst("SType"), type0())
139}
140/// `send_msg : {T : Type} → {S : SType} → Chan (Send T S) → T → Chan S`
141/// Send a message along a channel.
142pub 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}
156/// `recv_msg : {T : Type} → {S : SType} → Chan (Recv T S) → (T Ɨ Chan S)`
157/// Receive a message from a channel.
158pub 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}
172/// `close : Chan End → Unit`
173/// Close a finished channel.
174pub fn close_ty() -> Expr {
175    arrow(app(cst("Channel"), cst("End")), cst("Unit"))
176}
177/// `LinearType : Type → Prop`
178/// Predicate asserting a type is linear (used exactly once).
179pub fn linear_type_ty() -> Expr {
180    arrow(type0(), prop())
181}
182/// `LinearCtx : Type`
183/// A linear typing context: a finite map from names to (linear) types.
184pub fn linear_ctx_ty() -> Expr {
185    type0()
186}
187/// `CtxSplit : LinearCtx → LinearCtx → LinearCtx → Prop`
188/// Context splitting: the left context is the disjoint union of the right two.
189pub fn ctx_split_ty() -> Expr {
190    arrow(
191        cst("LinearCtx"),
192        arrow(cst("LinearCtx"), arrow(cst("LinearCtx"), prop())),
193    )
194}
195/// `LinearWellTyped : LinearCtx → Process → SType → Prop`
196/// Typing judgment for linear processes.
197pub fn linear_well_typed_ty() -> Expr {
198    arrow(
199        cst("LinearCtx"),
200        arrow(type0(), arrow(cst("SType"), prop())),
201    )
202}
203/// `LinearSafety : Process → Prop`
204/// A process is safe if channels are used linearly (exactly once).
205pub fn linear_safety_ty() -> Expr {
206    arrow(type0(), prop())
207}
208/// `AffineType : Type → Prop`
209/// Predicate for affine types (used at most once).
210pub fn affine_type_ty() -> Expr {
211    arrow(type0(), prop())
212}
213/// `UnrestrictedType : Type → Prop`
214/// Predicate for unrestricted (reusable) types.
215pub fn unrestricted_type_ty() -> Expr {
216    arrow(type0(), prop())
217}
218/// `Role : Type`
219/// A participant role in a multiparty session.
220pub fn role_ty() -> Expr {
221    type0()
222}
223/// `GType : Type`
224/// A global session type (the overall protocol from a bird's-eye view).
225pub fn gtype_ty() -> Expr {
226    type0()
227}
228/// `GComm : Role → Role → Type → GType → GType`
229/// `p → q : T. G` — role p sends a value of type T to role q, then continues as G.
230pub 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}
239/// `GChoice : Role → Role → GType → GType → GType`
240/// `p + q { G₁, Gā‚‚ }` — role p makes a choice communicated to q.
241pub 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}
250/// `GEnd : GType`
251/// The end of the global protocol.
252pub fn gend_ty() -> Expr {
253    cst("GType")
254}
255/// `GRec : (GType → GType) → GType`
256/// Recursive global type: `μX.G(X)`.
257pub fn grec_ty() -> Expr {
258    arrow(arrow(cst("GType"), cst("GType")), cst("GType"))
259}
260/// `WellFormed : GType → Prop`
261/// A global type is well-formed if all roles are consistent and the protocol terminates.
262pub fn well_formed_ty() -> Expr {
263    arrow(cst("GType"), prop())
264}
265/// `Participants : GType → List Role`
266/// Extract the set of roles participating in a global type.
267pub fn participants_ty() -> Expr {
268    arrow(cst("GType"), list_ty(cst("Role")))
269}
270/// `LType : Type`
271/// A local session type: the protocol from one participant's perspective.
272pub fn ltype_ty() -> Expr {
273    type0()
274}
275/// `LSend : Role → Type → LType → LType`
276/// `!q(T).L` — send T to role q, continue as L.
277pub fn lsend_ty() -> Expr {
278    arrow(
279        cst("Role"),
280        arrow(type0(), arrow(cst("LType"), cst("LType"))),
281    )
282}
283/// `LRecv : Role → Type → LType → LType`
284/// `?p(T).L` — receive T from role p, continue as L.
285pub fn lrecv_ty() -> Expr {
286    arrow(
287        cst("Role"),
288        arrow(type0(), arrow(cst("LType"), cst("LType"))),
289    )
290}
291/// `LChoice : Role → LType → LType → LType`
292/// Internal choice offered to role `r`.
293pub fn lchoice_ty() -> Expr {
294    arrow(
295        cst("Role"),
296        arrow(cst("LType"), arrow(cst("LType"), cst("LType"))),
297    )
298}
299/// `LBranch : Role → LType → LType → LType`
300/// External choice from role `r`.
301pub fn lbranch_ty() -> Expr {
302    arrow(
303        cst("Role"),
304        arrow(cst("LType"), arrow(cst("LType"), cst("LType"))),
305    )
306}
307/// `LEnd : LType`
308/// Session end from one participant's perspective.
309pub fn lend_ty() -> Expr {
310    cst("LType")
311}
312/// `project : GType → Role → LType`
313/// Project a global type onto a specific role's local type.
314pub fn project_ty() -> Expr {
315    arrow(cst("GType"), arrow(cst("Role"), cst("LType")))
316}
317/// `ProjectionSound : āˆ€ (G : GType) (p : Role), WellFormed G →
318///   LocallyConsistent (project G p)`
319/// Soundness of projection: projections of well-formed globals are locally consistent.
320pub 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}
339/// `LocallyConsistent : LType → Prop`
340pub fn locally_consistent_ty() -> Expr {
341    arrow(cst("LType"), prop())
342}
343/// `Mergeability : LType → LType → Prop`
344/// Two local types can be merged (for projection of choices not involving a role).
345pub fn mergeability_ty() -> Expr {
346    arrow(cst("LType"), arrow(cst("LType"), prop()))
347}
348/// `Process : Type`
349/// The type of processes in the session calculus.
350pub fn process_ty() -> Expr {
351    type0()
352}
353/// `Reduces : Process → Process → Prop`
354/// One-step reduction relation.
355pub fn reduces_ty() -> Expr {
356    arrow(type0(), arrow(type0(), prop()))
357}
358/// `Stuck : Process → Prop`
359/// A process is stuck if it cannot reduce and is not a value.
360pub fn stuck_ty() -> Expr {
361    arrow(type0(), prop())
362}
363/// `DeadlockFree : Process → Prop`
364/// A process is deadlock-free if all reachable states are not stuck.
365pub fn deadlock_free_ty() -> Expr {
366    arrow(type0(), prop())
367}
368/// `Progress : Process → SType → Prop`
369/// Progress: a well-typed process either terminates or can take a step.
370pub fn progress_ty() -> Expr {
371    arrow(type0(), arrow(cst("SType"), prop()))
372}
373/// `SubjectReduction : Prop`
374/// Subject reduction: typing is preserved by reduction.
375pub fn subject_reduction_ty() -> Expr {
376    prop()
377}
378/// `TypeSafety : Prop`
379/// Type safety: well-typed processes do not go wrong.
380pub fn type_safety_ty() -> Expr {
381    prop()
382}
383/// `DeadlockFreedomThm : āˆ€ (P : Process) (S : SType), WellTyped P S → DeadlockFree P`
384/// Deadlock freedom from type well-typedness.
385pub 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}
401/// `WellTypedProcess : Process → SType → Prop`
402pub fn well_typed_process_ty() -> Expr {
403    arrow(type0(), arrow(cst("SType"), prop()))
404}
405/// `ProgressThm : āˆ€ (P : Process) (S : SType), WellTyped P S →
406///   IsValue P ∨ ∃ P', Reduces P P'`
407pub 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}
427/// `IsValue : Process → Prop`
428pub fn is_value_ty() -> Expr {
429    arrow(type0(), prop())
430}
431/// `InferSType : Process → SType → Prop`
432/// Session type inference judgment.
433pub fn infer_stype_ty() -> Expr {
434    arrow(type0(), arrow(cst("SType"), prop()))
435}
436/// `PrincipalSType : Process → SType → Prop`
437/// The principal (most general) session type of a process.
438pub fn principal_stype_ty() -> Expr {
439    arrow(type0(), arrow(cst("SType"), prop()))
440}
441/// `STypeUnify : SType → SType → STypeSubst → Prop`
442/// Unification of session types under a substitution.
443pub fn stype_unify_ty() -> Expr {
444    arrow(cst("SType"), arrow(cst("SType"), arrow(type0(), prop())))
445}
446/// `STypeSubst : Type`
447/// A session type substitution.
448pub fn stype_subst_ty() -> Expr {
449    type0()
450}
451/// `InferenceComplete : Prop`
452/// Completeness of session type inference.
453pub fn inference_complete_ty() -> Expr {
454    prop()
455}
456/// `InferenceSound : Prop`
457/// Soundness of session type inference.
458pub fn inference_sound_ty() -> Expr {
459    prop()
460}
461/// `DepSType : Type`
462/// Dependent session types: the continuation type can depend on communicated values.
463pub fn dep_stype_ty() -> Expr {
464    type0()
465}
466/// `DepSend : {T : Type} → (T → DepSType) → DepSType`
467/// `!x : T. S(x)` — send x of type T, continuation depends on x.
468pub fn dep_send_ty() -> Expr {
469    impl_pi(
470        "T",
471        type0(),
472        arrow(arrow(bvar(0), cst("DepSType")), cst("DepSType")),
473    )
474}
475/// `DepRecv : {T : Type} → (T → DepSType) → DepSType`
476/// `?x : T. S(x)` — receive x of type T, continuation depends on x.
477pub fn dep_recv_ty() -> Expr {
478    impl_pi(
479        "T",
480        type0(),
481        arrow(arrow(bvar(0), cst("DepSType")), cst("DepSType")),
482    )
483}
484/// `DepEnd : DepSType`
485pub fn dep_end_ty() -> Expr {
486    cst("DepSType")
487}
488/// `DepDual : DepSType → DepSType`
489pub fn dep_dual_ty() -> Expr {
490    arrow(cst("DepSType"), cst("DepSType"))
491}
492/// `DepChannel : DepSType → Type`
493pub fn dep_channel_ty() -> Expr {
494    arrow(cst("DepSType"), type0())
495}
496/// `DepSendMsg : {T : Type} → {S : T → DepSType} → DepChan (DepSend S) → (x : T) → DepChan (S x)`
497pub fn dep_send_msg_ty() -> Expr {
498    arrow(cst("DepSType"), arrow(type0(), arrow(type0(), type0())))
499}
500/// `Unfold : SType → SType`
501/// Unfold one step of a recursive session type: `μX.S(X) ↦ S(μX.S(X))`.
502pub fn unfold_ty() -> Expr {
503    arrow(cst("SType"), cst("SType"))
504}
505/// `Fold : SType → SType`
506/// Fold back a session type into a recursive form.
507pub fn fold_ty() -> Expr {
508    arrow(cst("SType"), cst("SType"))
509}
510/// `IsoRecursive : SType → Prop`
511/// Predicate for iso-recursive session types (explicit fold/unfold).
512pub fn iso_recursive_ty() -> Expr {
513    arrow(cst("SType"), prop())
514}
515/// `EquiRecursive : SType → Prop`
516/// Predicate for equi-recursive session types (implicit fold/unfold).
517pub fn equi_recursive_ty() -> Expr {
518    arrow(cst("SType"), prop())
519}
520/// `Coinductive : SType → Prop`
521/// Coinductive (possibly infinite) session type.
522pub fn coinductive_ty() -> Expr {
523    arrow(cst("SType"), prop())
524}
525/// `STypeEquiv : SType → SType → Prop`
526/// Bisimilarity / coinductive equality of session types.
527pub fn stype_equiv_ty() -> Expr {
528    arrow(cst("SType"), arrow(cst("SType"), prop()))
529}
530/// `UnfoldPreservesDual : āˆ€ S, dual (Unfold S) = Unfold (dual S)`
531pub 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}
543/// `AsyncSType : Type`
544/// Asynchronous session type with buffered channels.
545pub fn async_stype_ty() -> Expr {
546    type0()
547}
548/// `AsyncSend : Type → AsyncSType → AsyncSType`
549/// Asynchronous send: message is placed in a buffer; continuation does not wait.
550pub fn async_send_ty() -> Expr {
551    arrow(type0(), arrow(cst("AsyncSType"), cst("AsyncSType")))
552}
553/// `AsyncRecv : Type → AsyncSType → AsyncSType`
554/// Asynchronous receive: eventually retrieve from buffer; continuation after receipt.
555pub fn async_recv_ty() -> Expr {
556    arrow(type0(), arrow(cst("AsyncSType"), cst("AsyncSType")))
557}
558/// `EventualDelivery : AsyncSType → Prop`
559/// Every message sent is eventually delivered (liveness guarantee).
560pub fn eventual_delivery_ty() -> Expr {
561    arrow(cst("AsyncSType"), prop())
562}
563/// `BufferBound : AsyncSType → Nat → Prop`
564/// The buffer size is bounded by `n`; prevents unbounded queuing.
565pub fn buffer_bound_ty() -> Expr {
566    arrow(cst("AsyncSType"), arrow(nat_ty(), prop()))
567}
568/// `AsyncDual : AsyncSType → AsyncSType`
569/// Dual of an asynchronous session type.
570pub fn async_dual_ty() -> Expr {
571    arrow(cst("AsyncSType"), cst("AsyncSType"))
572}
573/// `AsyncEnd : AsyncSType`
574/// Termination of an asynchronous session.
575pub fn async_end_ty() -> Expr {
576    cst("AsyncSType")
577}
578/// `LLProp : Type`
579/// Propositions in multiplicative intuitionistic linear logic (MILL).
580pub fn ll_prop_ty() -> Expr {
581    type0()
582}
583/// `Tensor : LLProp → LLProp → LLProp`
584/// Multiplicative conjunction: `A āŠ— B`.
585pub fn tensor_ty() -> Expr {
586    arrow(cst("LLProp"), arrow(cst("LLProp"), cst("LLProp")))
587}
588/// `Lolli : LLProp → LLProp → LLProp`
589/// Linear implication: `A ⊸ B`.
590pub fn lolli_ty() -> Expr {
591    arrow(cst("LLProp"), arrow(cst("LLProp"), cst("LLProp")))
592}
593/// `Par : LLProp → LLProp → LLProp`
594/// Multiplicative disjunction: `A ā…‹ B`.
595pub fn par_ty() -> Expr {
596    arrow(cst("LLProp"), arrow(cst("LLProp"), cst("LLProp")))
597}
598/// `Bang : LLProp → LLProp`
599/// Exponential modality: `!A` — unrestricted use.
600pub fn bang_ty() -> Expr {
601    arrow(cst("LLProp"), cst("LLProp"))
602}
603/// `WhyNot : LLProp → LLProp`
604/// Exponential modality: `?A` — potential use.
605pub fn why_not_ty() -> Expr {
606    arrow(cst("LLProp"), cst("LLProp"))
607}
608/// `CutElim : Prop`
609/// Cut elimination theorem for MILL: every proof can be made cut-free.
610pub fn cut_elim_ty() -> Expr {
611    prop()
612}
613/// `CurryHowardLL : LLProp → SType → Prop`
614/// The Curry-Howard correspondence between MILL propositions and session types.
615pub fn curry_howard_ll_ty() -> Expr {
616    arrow(cst("LLProp"), arrow(cst("SType"), prop()))
617}
618/// `SSubtype : SType → SType → Prop`
619/// Behavioral subtyping: `S₁ <: Sā‚‚` means S₁ can be used where Sā‚‚ is expected.
620pub fn ssubtype_ty() -> Expr {
621    arrow(cst("SType"), arrow(cst("SType"), prop()))
622}
623/// `SSubtypeRefl : āˆ€ S, SSubtype S S`
624pub 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}
632/// `SSubtypeTrans : āˆ€ S₁ Sā‚‚ Sā‚ƒ, SSubtype S₁ Sā‚‚ → SSubtype Sā‚‚ Sā‚ƒ → SSubtype S₁ Sā‚ƒ`
633pub 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}
657/// `SendCovariant : āˆ€ T S₁ Sā‚‚, SSubtype S₁ Sā‚‚ → SSubtype (Send T S₁) (Send T Sā‚‚)`
658/// Send is covariant in the continuation.
659pub 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}
684/// `RecvContravariant : āˆ€ T S₁ Sā‚‚, SSubtype S₁ Sā‚‚ → SSubtype (Recv T Sā‚‚) (Recv T S₁)`
685/// Receive is contravariant in the continuation (dual direction).
686pub 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}
711/// `HOSType : Type`
712/// Higher-order session types: channels can carry session channels.
713pub fn ho_stype_ty() -> Expr {
714    type0()
715}
716/// `SendChan : SType → HOSType → HOSType`
717/// `!Chan(S).T` — send a channel of type S, then continue as T.
718pub fn send_chan_ty() -> Expr {
719    arrow(cst("SType"), arrow(cst("HOSType"), cst("HOSType")))
720}
721/// `RecvChan : SType → HOSType → HOSType`
722/// `?Chan(S).T` — receive a channel of type S, then continue as T.
723pub fn recv_chan_ty() -> Expr {
724    arrow(cst("SType"), arrow(cst("HOSType"), cst("HOSType")))
725}
726/// `SessionPassing : HOSType → Prop`
727/// A higher-order session type that involves session-passing.
728pub fn session_passing_ty() -> Expr {
729    arrow(cst("HOSType"), prop())
730}
731/// `HODual : HOSType → HOSType`
732/// Dual of a higher-order session type.
733pub fn ho_dual_ty() -> Expr {
734    arrow(cst("HOSType"), cst("HOSType"))
735}
736/// `ExSType : Type`
737/// Session types extended with exceptions and failure handling.
738pub fn ex_stype_ty() -> Expr {
739    type0()
740}
741/// `Throw : Type → ExSType`
742/// Raise an exception of the given type, terminating the session.
743pub fn throw_ty() -> Expr {
744    arrow(type0(), cst("ExSType"))
745}
746/// `Catch : ExSType → ExSType → ExSType`
747/// `try S catch H` — run S, if exception H is raised, switch to handler.
748pub fn catch_ty() -> Expr {
749    arrow(cst("ExSType"), arrow(cst("ExSType"), cst("ExSType")))
750}
751/// `ExceptionSafe : ExSType → Prop`
752/// A session type is exception-safe if all exceptions are handled.
753pub fn exception_safe_ty() -> Expr {
754    arrow(cst("ExSType"), prop())
755}
756/// `FaultTolerant : ExSType → Prop`
757/// A process is fault-tolerant if it can recover from any exception.
758pub fn fault_tolerant_ty() -> Expr {
759    arrow(cst("ExSType"), prop())
760}
761/// `GSType : Type`
762/// Gradual session types: mixing static and dynamic checking.
763pub fn g_stype_ty() -> Expr {
764    type0()
765}
766/// `GradualSend : Type → GSType → GSType`
767/// Gradual send: partially statically checked.
768pub fn gradual_send_ty() -> Expr {
769    arrow(type0(), arrow(cst("GSType"), cst("GSType")))
770}
771/// `GradualRecv : Type → GSType → GSType`
772/// Gradual receive: partially statically checked.
773pub fn gradual_recv_ty() -> Expr {
774    arrow(type0(), arrow(cst("GSType"), cst("GSType")))
775}
776/// `DynSType : GSType`
777/// The dynamic session type `?` — completely unchecked at compile time.
778pub fn dyn_stype_ty() -> Expr {
779    cst("GSType")
780}
781/// `CastInsertion : GSType → SType → GSType → Prop`
782/// Cast insertion: convert between gradual and static session types.
783pub fn cast_insertion_ty() -> Expr {
784    arrow(
785        cst("GSType"),
786        arrow(cst("SType"), arrow(cst("GSType"), prop())),
787    )
788}
789/// `DynamicMonitor : GSType → Prop`
790/// A session type that must be monitored at runtime.
791pub fn dynamic_monitor_ty() -> Expr {
792    arrow(cst("GSType"), prop())
793}
794/// `GradualConsistency : GSType → GSType → Prop`
795/// Gradual consistency: two session types agree on their static parts.
796pub fn gradual_consistency_ty() -> Expr {
797    arrow(cst("GSType"), arrow(cst("GSType"), prop()))
798}
799/// `ProbSType : Type`
800/// Probabilistic session type with Markov-chain semantics.
801pub fn prob_stype_ty() -> Expr {
802    type0()
803}
804/// `ProbChoice : SType → SType → Expr`
805/// `S₁ āŠ•[p] Sā‚‚` — choose S₁ with probability p, Sā‚‚ with probability 1-p.
806pub fn prob_choice_ty() -> Expr {
807    arrow(
808        cst("SType"),
809        arrow(cst("SType"), arrow(cst("Real"), cst("ProbSType"))),
810    )
811}
812/// `ExpectedCost : ProbSType → Nat → Prop`
813/// Expected number of communication steps is bounded by n.
814pub fn expected_cost_ty() -> Expr {
815    arrow(cst("ProbSType"), arrow(nat_ty(), prop()))
816}
817/// `MarkovChainProtocol : ProbSType → Prop`
818/// The probabilistic session type has a finite-state Markov chain interpretation.
819pub fn markov_chain_protocol_ty() -> Expr {
820    arrow(cst("ProbSType"), prop())
821}
822/// `Termination : ProbSType → Prop`
823/// The probabilistic session terminates with probability 1 (almost-sure termination).
824pub fn prob_termination_ty() -> Expr {
825    arrow(cst("ProbSType"), prop())
826}
827/// `Choreography : Type`
828/// A global choreography: the global view of a multiparty protocol.
829pub fn choreography_ty() -> Expr {
830    type0()
831}
832/// `Realization : Choreography → GType → Prop`
833/// A choreography is realized by a global type.
834pub fn realization_ty() -> Expr {
835    arrow(cst("Choreography"), arrow(cst("GType"), prop()))
836}
837/// `GlobalView : GType → Choreography`
838/// Extract the global view (choreography) from a global type.
839pub fn global_view_ty() -> Expr {
840    arrow(cst("GType"), cst("Choreography"))
841}
842/// `EndpointProjection : Choreography → Role → LType`
843/// Project a choreography onto a role's local type.
844pub fn endpoint_projection_ty() -> Expr {
845    arrow(cst("Choreography"), arrow(cst("Role"), cst("LType")))
846}
847/// `ChoreographyConsistency : Choreography → Prop`
848/// A choreography is consistent if all endpoint projections are compatible.
849pub fn choreography_consistency_ty() -> Expr {
850    arrow(cst("Choreography"), prop())
851}
852/// `AmbienceCompatibility : Choreography → GType → Prop`
853/// The choreography is compatible with the ambient global type.
854pub fn ambience_compatibility_ty() -> Expr {
855    arrow(cst("Choreography"), arrow(cst("GType"), prop()))
856}
857/// `SharedMemType : Type`
858/// Session types for shared memory concurrency.
859pub fn shared_mem_type_ty() -> Expr {
860    type0()
861}
862/// `Mutex : Type → SharedMemType`
863/// A mutex protecting a resource of type T.
864pub fn mutex_ty() -> Expr {
865    arrow(type0(), cst("SharedMemType"))
866}
867/// `Acquire : SharedMemType → SType → SType`
868/// Acquire a lock, then continue with a typed session.
869pub fn acquire_ty() -> Expr {
870    arrow(cst("SharedMemType"), arrow(cst("SType"), cst("SType")))
871}
872/// `Release : SharedMemType → SType → SType`
873/// Release a lock, then continue.
874pub fn release_ty() -> Expr {
875    arrow(cst("SharedMemType"), arrow(cst("SType"), cst("SType")))
876}
877/// `DataRaceFree : SharedMemType → Prop`
878/// A shared memory protocol is data-race free by type structure.
879pub fn data_race_free_ty() -> Expr {
880    arrow(cst("SharedMemType"), prop())
881}
882/// Build the session types environment.
883pub 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}