0 | module System.Concurrency.Session
2 | import Control.Linear.LIO
4 | import Data.List.AtIndex
7 | import Data.OpenUnion
10 | import System.Concurrency as Threads
11 | import System.Concurrency.Linear
13 | import Language.Reflection
26 | data Session : Type where
27 | Send : (ty : Type) -> (s : Session) -> Session
28 | Recv : (ty : Type) -> (s : Session) -> Session
34 | Dual : Session -> Session
35 | Dual (Send ty s) = Recv ty (Dual s)
36 | Dual (Recv ty s) = Send ty (Dual s)
41 | dualInvolutive : (s : Session) -> Dual (Dual s) === s
42 | dualInvolutive (Send ty s) = cong (Send ty) (dualInvolutive s)
43 | dualInvolutive (Recv ty s) = cong (Recv ty) (dualInvolutive s)
44 | dualInvolutive End = Refl
50 | SendTypes : Session -> List Type
51 | SendTypes (Send ty s) = ty :: SendTypes s
52 | SendTypes (Recv ty s) = SendTypes s
59 | RecvTypes : Session -> List Type
60 | RecvTypes (Send ty s) = RecvTypes s
61 | RecvTypes (Recv ty s) = ty :: RecvTypes s
67 | RecvDualTypes : (s : Session) -> RecvTypes (Dual s) === SendTypes s
68 | RecvDualTypes (Send ty s) = cong (ty ::) (RecvDualTypes s)
69 | RecvDualTypes (Recv ty s) = RecvDualTypes s
70 | RecvDualTypes End = Refl
75 | SendDualTypes : (s : Session) -> SendTypes (Dual s) === RecvTypes s
76 | SendDualTypes (Send ty s) = SendDualTypes s
77 | SendDualTypes (Recv ty s) = cong (ty ::) (SendDualTypes s)
78 | SendDualTypes End = Refl
86 | data Seen : Nat -> Nat -> (Session -> Session) -> Type where
87 | None : Seen 0 0 Prelude.id
88 | Recv : (ty : Type) -> Seen m n f -> Seen (S m) n (f . Recv ty)
89 | Send : (ty : Type) -> Seen m n f -> Seen m (S n) (f . Send ty)
94 | atRecvIndex : Seen m _ f ->
96 | AtIndex ty (RecvTypes s) n ->
97 | AtIndex ty (RecvTypes (f s)) (m + n)
98 | atRecvIndex None accS accAt = accAt
99 | atRecvIndex (Recv ty s) accS accAt
100 | = rewrite plusSuccRightSucc (pred m) n in
101 | atRecvIndex s (Recv ty accS) (S accAt)
102 | atRecvIndex (Send ty s) accS accAt
103 | = atRecvIndex s (Send ty accS) accAt
108 | atSendIndex : Seen _ m f ->
110 | AtIndex ty (SendTypes s) n ->
111 | AtIndex ty (SendTypes (f s)) (m + n)
112 | atSendIndex None accS accAt = accAt
113 | atSendIndex (Recv ty s) accS accAt
114 | = atSendIndex s (Recv ty accS) accAt
115 | atSendIndex (Send ty s) accS accAt
116 | = rewrite plusSuccRightSucc (pred m) n in
117 | atSendIndex s (Send ty accS) (S accAt)
142 | record Channel (s : Session) where
143 | constructor MkChannel
146 | {0 seenPrefix : Session -> Session}
147 | 0 seen : Seen recvStep sendStep seenPrefix
149 | sendChan : Threads.Channel (Union (SendTypes (seenPrefix s)))
150 | recvChan : Threads.Channel (Union (RecvTypes (seenPrefix s)))
156 | recv : LinearIO io =>
157 | Channel (Recv ty s) -@
158 | L1 io (Res ty (const (Channel s)))
159 | recv (MkChannel {recvStep} seen sendCh recvCh) = do
160 | x@(Element k prf val) <- channelGet recvCh
164 | let Just val = prj (recvStep + 0) (atRecvIndex seen (Recv ty s) Z) x
165 | | Nothing => die1 "Error: invalid recv expected \{show recvStep} but got \{show k}"
166 | pure1 (val # MkChannel (Recv ty seen) sendCh recvCh)
173 | send : LinearIO io =>
174 | (1 _ : Channel (Send ty s)) ->
177 | send (MkChannel {sendStep} seen sendCh recvCh) x = do
178 | let val = inj (sendStep + 0) (atSendIndex seen (Send ty s) Z) x
179 | channelPut sendCh val
180 | pure1 (MkChannel (Send ty seen) sendCh recvCh)
184 | end : LinearIO io => Channel End -@ L io ()
185 | end (MkChannel _ _ _) = do
194 | L1 io (LPair (Channel s) (Channel (Dual s)))
196 | sendChan <- Threads.makeChannel
197 | recvChan <- Threads.makeChannel
198 | let 1 posCh : Channel s
199 | := MkChannel None sendChan recvChan
200 | let 1 negCh : Channel (Dual s)
202 | (rewrite SendDualTypes s in recvChan)
203 | (rewrite RecvDualTypes s in sendChan)
204 | pure1 (posCh # negCh)
210 | fork : (0 s : Session) ->
211 | (Channel s -@ L IO a) -@
212 | (Channel (Dual s) -@ L IO b) -@
215 | let 1 io = makeChannel s
216 | (posCh # negCh) <- io
217 | par (kA posCh) (kB negCh)