2 | import Control.Monad.Elin
4 | import Data.Linear.Deferred
5 | import Data.Linear.ELift1
6 | import Data.Linear.Ref1
7 | import Data.Linear.Traverse1
8 | import Data.Linear.Unique
12 | import Data.SortedMap
13 | import Data.SortedSet
23 | record Hook (f : List Type -> Type -> Type) where
26 | lease : f [] (f [] ())
28 | updCleanup, updUnlease : (Bool,Nat) -> ((Bool,Nat),Bool)
29 | updCleanup (False,b) = ((True,b),b == 0)
30 | updCleanup p = (p,False)
32 | updUnlease (b,1) = ((b,0),b)
33 | updUnlease (b,n) = ((b,pred n),False)
35 | updLease : (Bool,Nat) -> ((Bool,Nat),())
36 | updLease (b,n) = ((b,S n),())
38 | hook : ELift1 s f => f [] () -> F1 s (Hook f)
40 | let state # t := ref1 (False,Z) t
41 | in H (cl state) (ls state) # t
44 | cl : Ref s (Bool,Nat) -> f [] ()
45 | cl state = when !(update state updCleanup) act
47 | unlease : Ref s (Bool,Nat) -> f [] ()
48 | unlease state = when !(update state updUnlease) act
50 | ls : Ref s (Bool,Nat) -> f [] (f [] ())
51 | ls state = update state updLease $> unlease state
72 | data Interrupt : (f : List Type -> Type -> Type) -> Type where
74 | I : (def : Deferred World a) -> Interrupt (Async e)
92 | interface ELift1 s f => Target s f | f where
94 | combineInterrupts : (x,y : Interrupt f) -> F1 s (Interrupt f, List (f [] ()))
97 | isInterrupted : Interrupt f -> f [] Bool
100 | raceInterrupt : Interrupt f -> f es a -> f [] (Outcome es a)
103 | Target s (Elin s) where
104 | combineInterrupts None None t = (None, []) # t
105 | isInterrupted _ = pure False
106 | raceInterrupt _ = map toOutcome . attempt
109 | Target World (Async e) where
110 | combineInterrupts None x t = (x, []) # t
111 | combineInterrupts x None t = (x, []) # t
112 | combineInterrupts (I d1) (I d2) t =
113 | let d3 # t := deferredOf1 () t
114 | f1 # t := observeDeferred1 d1 (\_ => putDeferred1 d3 ()) t
115 | f2 # t := observeDeferred1 d2 (\_ => putDeferred1 d3 ()) t
116 | in (I d3, [lift1 f1, lift1 f2]) # t
118 | isInterrupted None = pure False
119 | isInterrupted (I d) = completed d
121 | raceInterrupt None act = toOutcome <$> attempt act
122 | raceInterrupt (I d) act =
123 | racePair {fs = []} act (await d) >>= \case
124 | Left (o,x) => cancel x $> o
125 | Right (x,_) => cancel x $> Canceled
136 | record ScopeID where
142 | SID x == SID y = x == y
146 | compare (SID x) (SID y) = compare x y
152 | scopeID : F1 s ScopeID
153 | scopeID t = let tok # t := token1 t in SID (unsafeVal tok) # t
156 | record Node (f : List Type -> Type -> Type)
160 | 0 ScopeST : (f : List Type -> Type -> Type) -> Type
161 | ScopeST f = SortedMap ScopeID (Node f)
164 | 0 STRef : (s : Type) -> (f : List Type -> Type -> Type) -> Type
165 | STRef s f = Ref s (ScopeST f)
187 | record Scope (f : List Type -> Type -> Type) where
198 | ancestors : List ScopeID
201 | interrupt : Interrupt f
203 | state : Ref tstate (ScopeST f)
205 | {auto tgt : Target tstate f}
209 | record Node (f : List
Type -> Type -> Type) where
215 | cleanup : List (Hook f)
218 | children : SortedSet ScopeID
226 | insertScope : Node f -> ScopeST f -> ScopeST f
227 | insertScope s = insert s.scope.id s
231 | getRoot : Target s f => STRef s f -> ScopeID -> ScopeST f -> Node f
232 | getRoot ref id = fromMaybe (N (S id id [] None ref) [] empty) . lookup id
238 | openAncestor : ScopeST f -> Scope f -> Node f
239 | openAncestor ss s@(S {}) = go s.ancestors
241 | go : List ScopeID -> Node f
242 | go [] = getRoot s.state s.root ss
243 | go (x :: xs) = fromMaybe (go xs) (lookup x ss)
249 | openSelfOrAncestor : ScopeST f -> Scope f -> Node f
250 | openSelfOrAncestor ss sc =
251 | fromMaybe (openAncestor ss sc) (lookup sc.id ss)
253 | removeChild : Bool -> Scope f -> ScopeST f -> ScopeST f
254 | removeChild False sc st = st
255 | removeChild True sc st =
256 | let par := openAncestor st sc
257 | in insertScope ({children $= delete sc.id} par) st
259 | deleteNode : ScopeST f -> Node f -> ScopeST f
260 | deleteNode m n = delete n.scope.id m
263 | root : Target s f => STRef s f -> F1 s (Scope f)
265 | let sid # t := scopeID t
266 | r := N (S sid sid [] None ref) [] empty
267 | _ # t := mod1 ref (insertScope r) t
276 | openScope : Target s f => STRef s f -> Interrupt f -> Scope f -> F1 s (Scope f)
277 | openScope ref int sc@(S i rt as ir _) t =
278 | let sid # t := scopeID t
279 | (sint, cncl) # t := combineInterrupts ir int t
280 | hooks # t := traverse1 hook cncl t
281 | in casupdate1 ref (\ss =>
282 | let par := openSelfOrAncestor ss sc
284 | node := N (Scope.S sid rt ancs sint ref) hooks empty
285 | par2 := {children $= insert sid} par
286 | in (insertScope par2 $
insertScope node ss, node.scope)) t
291 | addHook : Scope f -> f [] () -> f [] ()
292 | addHook sc@(S {}) act = do
293 | hk <- lift1 (hook act)
294 | Ref1.mod sc.state $
\ss =>
295 | let res := {cleanup $= (hk ::)} (openSelfOrAncestor ss sc)
296 | in insertScope res ss
298 | parameters (ref : STRef s f)
299 | findNode : ScopeID -> F1 s (Maybe $
Node f)
300 | findNode x t = let st # t := read1 ref t in lookup x st # t
302 | findNodes : List ScopeID -> F1 s (List $
Node f)
303 | findNodes xs t = let ms # t := traverse1 findNode xs t in catMaybes ms # t
305 | childNodesL : List (Node f) -> List (Node f) -> F1 s (List (Node f))
307 | childNodes : List (Node f) -> Node f -> F1 s (List (Node f))
308 | childNodes ns n t =
309 | let ns2 # t := findNodes (reverse $
Prelude.toList n.children) t
310 | in childNodesL (n::ns) ns2 t
312 | childNodesL ns [] t = ns # t
313 | childNodesL ns (c::cs) t =
315 | let ns2 # t := childNodes ns c t
316 | in childNodesL ns2 cs t
318 | parameters {auto tgt : Target s f}
325 | close : (remove : Bool) -> ScopeID -> f [] ()
327 | Just n <- lift1 (findNode ref id) | Nothing => pure ()
328 | cs <- lift1 (childNodes ref [] n)
329 | mod ref $
\m => removeChild b n.scope (foldl deleteNode m cs)
330 | traverse_ cleanup (cs >>= cleanup)
337 | lease : Scope f -> f [] (f [] ())
338 | lease sc@(S i r as is ref) = do
339 | Just nd <- lift1 (findNode ref i) | Nothing => pure (pure ())
340 | ns <- lift1 (findNodes ref as)
341 | all <- lift1 (childNodes ref ns nd)
342 | cs <- traverse lease (all >>= cleanup)
343 | pure (sequence_ cs)
348 | newScope : Target s f => f [] (Scope f)
350 | ref <- newref {a = ScopeST f} empty
351 | sc <- lift1 (FS.Scope.root ref)
359 | printScope : Scope f -> String
360 | printScope (S i _ as _ _) = fastConcat . intersperse " <- " . map show $
i::as
363 | Interpolation (Scope f) where interpolate = printScope
366 | logScope : HasIO (f es) => String -> Scope f -> f es ()
367 | logScope nm sc = putStrLn "Scope \{nm}: \{sc}"