Guest User

Untitled

a guest
Apr 20th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.33 KB | None | 0 0
  1. module Dataflow
  2.  
  3. open Microsoft.FSharp.Math
  4. open System.Collections
  5. open System.Collections.Generic
  6.  
  7. module Guts =
  8. open System
  9. open System.Collections.Generic
  10.  
  11. [<Interface>]
  12. type ICell =
  13. abstract Invalidate : unit -> bool
  14. abstract NotifyCalled : ICell -> unit
  15. abstract NotifyRemoved : ICell -> unit
  16. abstract WeakReference : WeakReference<ICell>
  17. abstract AfterInvalidate : unit -> unit
  18. abstract InvalidateIf : unit -> bool
  19. abstract BarfOnCycle : bool
  20. abstract Compute : unit -> unit
  21. and Integrity() =
  22. let mutable stack : ICell list = []
  23. let mutable toBe : ICell list = []
  24. let mutable thunks : (unit -> unit) list = []
  25. member o.Push (callee : ICell) =
  26. //match List.tryFind (fun x -> Object.ReferenceEquals(x, callee)) stack with
  27. if 1 < List.sumBy (fun x -> if Object.ReferenceEquals(x, callee) then 1 else 0) stack
  28. then match callee.BarfOnCycle with
  29. | true -> sprintf "cycle detected on cell %A" callee |> failwith
  30. | false -> false
  31. else stack <- callee :: stack
  32. true
  33. member o.DetermineCaller callee =
  34. let getFirst xs =
  35. match xs with
  36. | x :: xs -> Some x
  37. | [] -> None
  38. let rec fn rest =
  39. match rest with
  40. | [] -> failwith "corrupt stack!"
  41. | x :: xs when Object.ReferenceEquals(callee, x) -> xs, getFirst xs
  42. | _ :: xs -> fn xs
  43. let stack', caller = fn stack
  44. stack <- stack'
  45. caller
  46. member o.DetermineCallerSingle() =
  47. match stack with
  48. | x :: _ -> Some x
  49. | [] -> None
  50. member o.EvalLater c =
  51. toBe <- c :: toBe
  52. member o.MakeBe() =
  53. o.EvalCells()
  54. o.EvalThunks()
  55. member private o.EvalCells() =
  56. match toBe with
  57. | [] -> ()
  58. | x::xs -> x.Compute(); toBe <- xs; o.EvalCells()
  59. member private o.EvalThunks() =
  60. match thunks with
  61. | [] -> ()
  62. | x :: xs -> x(); thunks <- xs; o.EvalThunks()
  63.  
  64. member o.EvalThunkLater fn =
  65. thunks <- fn :: thunks
  66.  
  67. [<AbstractClass>]
  68. type 'T BaseCell(isLazy : bool, integrity : Integrity) as o =
  69. let inner : ICell HashSet = HashSet()
  70. let callers : ICell WeakReference HashSet = HashSet(WeakReferenceComparer.Singleton : IEqualityComparer<WeakReference<ICell>>)
  71. do if not isLazy then integrity.EvalLater o
  72. abstract BarfOnCycle : bool
  73. member val Handlers : ('T -> unit) ResizeArray = ResizeArray()
  74. member o.RecomputeCallers() =
  75. for i in callers do
  76. match i.TryGetTarget() with
  77. | true, c -> if c.Invalidate() then c.AfterInvalidate()
  78. | _, _ -> ()
  79. abstract IsForcing : bool
  80. default o.IsForcing = false
  81. interface ICell with
  82. member o.Invalidate () =
  83. let ret = (o :> ICell).InvalidateIf()
  84. if ret then
  85. o.IsCached <- false
  86. for i in callers do
  87. match i.TryGetTarget() with
  88. | true, v -> v.Invalidate () |> ignore
  89. | _, _ -> ()
  90. ret
  91. member o.AfterInvalidate () =
  92. if not isLazy
  93. then o.GetValue () |> ignore
  94. for i in callers |> Seq.toList do
  95. match i.TryGetTarget() with
  96. | true, v -> v.AfterInvalidate (); if o.IsForcing then v.Compute()
  97. | _, _ -> ()
  98. member o.NotifyCalled c =
  99. inner.Add c |> ignore
  100. member o.NotifyRemoved c =
  101. inner.Remove c |> ignore
  102. member o.WeakReference = WeakReference<ICell>(o)
  103. member o.InvalidateIf () = true
  104. member o.BarfOnCycle = o.BarfOnCycle
  105. member o.Compute () = o.GetValue() |> ignore
  106. abstract ComputeValue : unit -> 'T
  107. member o.IsLazy with get () = isLazy
  108. member o.CacheValue () =
  109. let oldInner = HashSet(inner)
  110. inner.Clear()
  111. o.CachedValue <- o.ComputeValue ()
  112. o.IsCached <- true
  113. let removed = HashSet(inner)
  114. removed.ExceptWith(oldInner)
  115. for i in removed do
  116. i.NotifyRemoved o
  117. let predicate (x : WeakReference<ICell>) = match x.TryGetTarget() with
  118. | true, d -> removed.Contains(d)
  119. | _, _ -> true
  120. Predicate predicate |> callers.RemoveWhere |> ignore
  121. let cnt = o.Handlers.Count
  122. let value = o.CachedValue
  123. for i in 0 .. cnt - 1 do
  124. let handler = o.Handlers.[i]
  125. integrity.EvalThunkLater <| fun () -> handler value
  126. member val IsCached = false with get, set
  127. member val CachedValue = Unchecked.defaultof<'T> with get, set
  128. member o.NotifyCaller (caller : ICell) =
  129. caller.NotifyCalled o
  130. caller.WeakReference |> callers.Add |> ignore
  131. member o.GetValue () =
  132. if not o.IsCached
  133. then match (if integrity.Push o
  134. then o.CacheValue ()
  135. true
  136. else false) with
  137. | true -> match integrity.DetermineCaller o with
  138. | Some x -> o.NotifyCaller x
  139. | None -> ()
  140. | false -> ()
  141. else match integrity.DetermineCallerSingle() with
  142. | Some x -> o.NotifyCaller x
  143. | None -> ()
  144. o.CachedValue
  145. override o.Finalize() =
  146. for i in inner do
  147. i.NotifyRemoved o
  148. and WeakReferenceComparer private() =
  149. interface IEqualityComparer<WeakReference<ICell>> with
  150. member o.Equals(x, y) =
  151. match x.TryGetTarget(), y.TryGetTarget() with
  152. | (true, x), (true, y) when Object.ReferenceEquals(x, y) -> true
  153. | _, _ -> false
  154. member o.GetHashCode(x) =
  155. match x.TryGetTarget() with
  156. | true, x -> x.GetHashCode()
  157. | false, _ -> 0
  158. static member val Singleton = WeakReferenceComparer() :> IEqualityComparer<WeakReference<ICell>>
  159.  
  160. type 'T InputCell(integrity, initialValue : 'T) as o =
  161. inherit BaseCell<'T>(true, integrity)
  162. do o.CachedValue <- initialValue
  163. o.IsCached <- true
  164. override o.ComputeValue () = o.CachedValue
  165. member o.SetValue value =
  166. if not <| Object.Equals(value, o.CachedValue) then
  167. o.CachedValue <- value
  168. if (o :> ICell).Invalidate ()
  169. then (o :> ICell).AfterInvalidate ()
  170. override o.BarfOnCycle = false
  171.  
  172. type 'T Event(integrity, initialValue) =
  173. inherit BaseCell<'T>(false, integrity)
  174. let mutable resetValue = initialValue
  175. override o.ComputeValue () = resetValue
  176. override o.IsForcing = true
  177. member o.Fire value =
  178. resetValue <- value
  179. try if (o :> ICell).Invalidate ()
  180. then (o :> ICell).AfterInvalidate ()
  181. finally resetValue <- initialValue
  182. override o.BarfOnCycle = true
  183.  
  184. type Filter<'T, 'C, 'S>(cell : 'C BaseCell, initialState : 'S, filter : 'S -> 'S * bool, map : 'S -> 'T, integrity : Integrity) =
  185. inherit BaseCell<'T>(false, integrity)
  186. let mutable state = initialState
  187. let mutable didFire = true
  188. override o.ComputeValue () =
  189. let c = cell.GetValue()
  190. let state', didFire' = filter state
  191. state <- state'
  192. map state
  193. interface ICell with
  194. override o.InvalidateIf () =
  195. let c = cell.CachedValue
  196. let state', didFire' = filter state
  197. state <- state'
  198. didFire <- didFire'
  199. didFire
  200. override o.BarfOnCycle = true
  201.  
  202. type 'U Container(cell : 'U BaseCell) =
  203. member val Cell = cell with get, set
  204. and 'T M =
  205. | Return of 'T BaseCell
  206. | Done of 'T
  207. | Delay of (unit -> 'T M)
  208. | Wrapper of 'T Container
  209. member o.eval () =
  210. match o with
  211. | Return c -> c.GetValue ()
  212. | Done v -> v
  213. | Delay k -> (k()).eval()
  214. | Wrapper w -> w.Cell.GetValue()
  215. member o.value = o.eval()
  216. member private o._set1 c value =
  217. match c with
  218. | Return w -> o._set2 w value
  219. | Wrapper w -> o._set2 w.Cell value
  220. | _ -> failwith "can't happen"
  221. member private o._set2 c value =
  222. match c with
  223. | :? InputCell<'T> as c -> c.SetValue value
  224. | :? Event<'T> as c -> c.Fire value
  225. | _ -> failwith "can't happen"
  226. member o.set (value : 'T) =
  227. o._set1 o value
  228. member o.cell
  229. with get () =
  230. match o with
  231. | Wrapper w -> w.Cell
  232. | Return c -> c
  233. | _ -> failwith "can't happen"
  234. member o.force() =
  235. match o with
  236. | Wrapper w -> if (w.Cell :> ICell).Invalidate()
  237. then (w.Cell :> ICell).AfterInvalidate()
  238. | Return c -> if (c :> ICell).Invalidate()
  239. then (c :> ICell).AfterInvalidate()
  240. | _ -> failwith "can't happen"
  241. member o.replace (cell : 'T M) =
  242. match o with
  243. | Wrapper w -> let old = w.Cell in w.Cell <- cell.cell; old.RecomputeCallers()
  244. | _ -> failwith "not a wrapper"
  245. member o.Handlers =
  246. o.cell.Handlers
  247.  
  248. type 'T Formula(isLazy : bool, fn : unit -> 'T, integrity) =
  249. inherit BaseCell<'T>(isLazy, integrity)
  250. override o.ComputeValue () = fn ()
  251. override o.BarfOnCycle = true
  252.  
  253. type BaseFormulaBuilder(integrity, isLazy) =
  254. let bind (k : 'a -> 'b M) (v : 'a M) : 'b M =
  255. v.eval () |> k
  256. member o.Bind(v, k) = bind k v
  257. member o.Return (v : 'a) = Done v
  258. member o.Zero () = Done ()
  259. member o.Combine (a : 'a M, b : 'b M) = a.eval () |> ignore; b
  260. member o.Delay (k : unit -> 'a M) : 'a M = Delay k
  261. member o.ReturnFrom (m : 'a M) : 'a M = m
  262. member o.While (cond : unit -> bool, body : unit M) : unit M =
  263. while cond () do
  264. body.eval ()
  265. Done ()
  266. member o.For(seq : 'a seq, f : 'a -> unit M) : unit M =
  267. for i in seq do
  268. (f i).eval() |> ignore
  269. Done ()
  270. member o.TryWith (f : 'a M, p : exn -> 'a M) : 'a M =
  271. try f.eval () |> Done
  272. with | ex -> p ex
  273. member o.TryFinally (f : 'a M, p : unit -> unit) : 'a M =
  274. try f.eval () |> Done
  275. finally p ()
  276. member o.Using (v : 'a, f : 'a -> 'b M) : 'b M when 'U :> IDisposable =
  277. using v f
  278. member o.Run (m : 'a M) : 'a M =
  279. Wrapper(Container(Formula(isLazy, (fun () -> m.eval ()), integrity)))
  280.  
  281. type FormulaBuilder(integrity) =
  282. inherit BaseFormulaBuilder(integrity, true)
  283.  
  284. type StrictFormulaBuiler(integrity) =
  285. inherit BaseFormulaBuilder(integrity, false)
  286.  
  287. type 'T XList =
  288. inherit IList<'T>
  289. abstract AddRange : 'T seq -> unit
  290.  
  291. type 'T ListWrapper(sequence : 'T ResizeArray, cell : 'T SequenceCell) =
  292. let update() =
  293. if (cell :> ICell).Invalidate()
  294. then (cell :> ICell).AfterInvalidate()
  295. interface IList<'T> with
  296. member o.Count = sequence.Count
  297. member o.IsReadOnly = false
  298. member o.Item
  299. with get i = sequence.[i]
  300. and set i v = sequence.[i] <- v; update()
  301. member o.Add value = sequence.Add value;
  302. member o.Clear () = sequence.Clear (); update()
  303. member o.Contains value = sequence.Contains value
  304. member o.CopyTo(ary, int) = sequence.CopyTo(ary, int)
  305. member o.GetEnumerator () = (sequence :> 'T IList).GetEnumerator ()
  306. member o.RemoveAt i = sequence.RemoveAt i; update()
  307. member o.Remove v = let ret = sequence.Remove v in update(); ret
  308. member o.Insert(i, v) = sequence.Insert(i, v); update()
  309. member o.IndexOf v = sequence.IndexOf v
  310. interface IEnumerable with
  311. member o.GetEnumerator () = (sequence :> IEnumerable).GetEnumerator ()
  312. interface XList<'T> with
  313. member o.AddRange xs = sequence.AddRange xs; update()
  314. and 'T SequenceCell(integrity) as self =
  315. inherit BaseCell<'T XList>(true, integrity)
  316. let wrapper = ListWrapper(ResizeArray<'T>(), self)
  317. override o.ComputeValue () = (wrapper :> 'T XList)
  318. override o.BarfOnCycle = true
  319.  
  320. type 'T Cell = 'T Guts.M
  321. type 'T ListCell = 'T Guts.XList Guts.M
  322.  
  323. type Sheet() =
  324. let integrity = Guts.Integrity()
  325. let wrap (cell : 'T Guts.BaseCell) =
  326. Guts.Wrapper(Guts.Container(cell))
  327. member o.Input x = Guts.InputCell(integrity, x) |> wrap
  328. member o.Formula = Guts.FormulaBuilder(integrity)
  329. member o.StrictFormula = Guts.StrictFormulaBuiler(integrity)
  330. member o.Event x = Guts.Event(integrity, x) |> wrap
  331. member o.Filter c state filter map = Guts.Filter(c, state, filter, map, integrity) |> wrap
  332. member o.Delta (delta : 'a) (c : 'a Guts.M) =
  333. let ops = GlobalAssociations.GetNumericAssociation<'a>()
  334. let cell = c.cell
  335. o.Filter cell
  336. ops.Zero
  337. (fun state -> let value = cell.GetValue()
  338. if ops.Abs(ops.Subtract(value, state)) >= delta
  339. then value, true
  340. else state, false)
  341. (fun x -> x)
  342. member o.List () : 'T Guts.XList Guts.M = Guts.SequenceCell(integrity) |> wrap
  343. member o.MakeBe() = integrity.MakeBe()
Add Comment
Please, Sign In to add comment