Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
par_incr.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271type 'a var = { mutable value : 'a; mutable cutoff : 'a Types.cutoff; mutable to_string : 'a -> string; readers : Reader_list.t; } type ctx = Rsp.t type comp_stat = Types.counter type executor = Types.executor = { run : 'a. (unit -> 'a) -> 'a; par_do : 'a 'b. (unit -> 'a) -> (unit -> 'b) -> 'a * 'b; } type 'a t = ctx -> executor -> 'a var type 'a computation = {var : 'a var; mutable root : Rsp.t; e : executor} module RNode = Rsp.RNode module Cutoff = struct type 'a t = 'a Types.cutoff = | Never (*Represented as 0, can be optimized to have no branch when we match on this and check equality. We check is_same in Var.set, which would have to be false if you don't want the computation to be cut-off. So we have to return false*) | Always (*Represented as 1, can be optimized to have no branch when we match on this and check equality. This means things are always equal and hence we should have is_same be true.*) | Phys_equal | Eq of ('a -> 'a -> bool) | F of (oldval:'a -> newval:'a -> bool) let[@inline] attach cutoff t ctx e = let tvar = t ctx e in tvar.cutoff <- cutoff; tvar end module Var = struct type 'a t = 'a var let null = Obj.magic (ref ()) let[@inline] create ?(cutoff = Cutoff.Phys_equal) ?(to_s = Utils.undefined) x = let v = {value = x; cutoff; to_string = to_s; readers = Reader_list.empty ()} in v let[@inline] empty ~(cutoff : 'a Cutoff.t) ~(to_s : 'a -> string) () = {value = null; cutoff; to_string = to_s; readers = Reader_list.empty ()} let[@inline] set ({cutoff; value; readers; _} as t) x = if value == null then t.value <- x else let is_same = match cutoff with | Never -> false | Always -> true (*Compiler can optimize Always and Never cases by just returning it directly because of the way they are defined. Always will be represented as 1(same as true) and Never will be represented as 0(same as false) *) | Phys_equal -> x == value | Eq f -> f value x | F f -> f ~oldval:value ~newval:x in if not is_same then ( t.value <- x; Reader_list.iter readers Rsp.RNode.mark_dirty) let[@inline] value t = if t.value == null then failwith "Something is wrong, trying to access uninitialized value" else t.value let[@inline] cutoff {cutoff; _} = cutoff let[@inline] attach_cutoff (t : 'a t) cutoff = if t.cutoff != cutoff then t.cutoff <- cutoff let[@inline] attach_to_string (t : 'a t) f = if t.to_string != f then t.to_string <- f else () let[@inline] add_reader {readers; _} r = Reader_list.add_reader readers r let[@inline] remove_reader {readers; _} r = Reader_list.remove_reader readers r let[@inline] num_readers {readers; _} = Reader_list.length readers let[@inline] to_s t = t |> value |> t.to_string let[@inline] get_to_string {to_string; _} = to_string let[@inline] watch x _ _ = x module Syntax = struct let ( := ) = set let ( ! ) = value end end let return x _ _ = Var.create x let map ?(cutoff = Cutoff.Phys_equal) ~(fn : 'a -> 'b) (t : 'a t) (ctx : ctx) (e : executor) = let open Types in let left = Rsp.make_empty `S in let x = t left e in let y = Var.empty ~cutoff ~to_s:Utils.undefined () in let read_fn (type a) : a action -> a = function | Update -> Var.set y (Var.value x |> fn) | Remove self -> Var.remove_reader x self | Show -> "map: " ^ Var.to_s y | Count cntr -> cntr.map <- cntr.map + 1 in let read_x = RNode.make ~fn:RNode.{fn = read_fn} in Var.add_reader x read_x; Rsp.set_exn ctx `Left (Rsp.prune left); Rsp.set_exn ctx `Right read_x; read_x.fn Update; y let combine (a : 'a t) (b : 'b t) ctx e = let open Types in let ll = Rsp.make_empty `S in let lr = Rsp.make_empty `S in let x = a ll e in let y = b lr e in let xy = Var.empty ~cutoff:Phys_equal ~to_s:(Utils.combine_to_s (Var.get_to_string x) (Var.get_to_string y)) () in let read_fn_xy (type a) : a action -> a = function | Update -> Var.set xy (Var.value x, Var.value y) | Remove self -> Var.remove_reader x self; Var.remove_reader y self | Show -> "combine: " ^ Var.to_s xy | Count cntr -> cntr.combine <- cntr.combine + 1 in let read_xy = RNode.make ~fn:RNode.{fn = read_fn_xy} in Var.add_reader x read_xy; Var.add_reader y read_xy; let left = Rsp.make_node `S ~l:(Rsp.prune ll) ~r:(Rsp.prune lr) in Rsp.set_exn ctx `Left left; Rsp.set_exn ctx `Right read_xy; read_xy.fn Update; xy let par ~left ~right ctx e = let open Types in let (lres, ll), (rres, lr) = e.par_do (fun () -> let ll = Rsp.make_empty `S in let lres = left ll e in (lres, Rsp.prune ll)) (fun () -> let lr = Rsp.make_empty `S in let rres = right lr e in (rres, Rsp.prune lr)) in let lr_comb = Var.empty ~cutoff:Phys_equal ~to_s: (Utils.combine_to_s (Var.get_to_string lres) (Var.get_to_string rres)) () in let read_fn_lr_comb (type a) : a action -> a = function | Update -> Var.set lr_comb (Var.value lres, Var.value rres) | Remove self -> Var.remove_reader lres self; Var.remove_reader rres self | Show -> "par: " ^ Var.to_s lr_comb | Count cntr -> cntr.par_do <- cntr.par_do + 1 in let read_lr = RNode.make ~fn:RNode.{fn = read_fn_lr_comb} in Var.add_reader lres read_lr; Var.add_reader rres read_lr; let left = Rsp.make_node `P ~l:ll ~r:lr in Rsp.set_exn ctx `Left left; Rsp.set_exn ctx `Right read_lr; read_lr.fn Update; lr_comb let map2 ?(cutoff = Types.Phys_equal) ?(mode = `Seq) ~fn x y ctx e = let xy = match mode with `Seq -> combine x y | `Par -> par ~left:x ~right:y in map ~cutoff ~fn:(fun (x, y) -> fn x y) xy ctx e let value comp = Var.value comp.var let dump_tree file c = Out_channel.with_open_text file (fun oc -> Rsp.to_d2 oc c.root |> ignore) let destroy_comp comp = let root = comp.root in comp.root <- Types.nil_tree; Rsp.destroy root let[@inline] delay f c e = f () c e module Debug = struct let attach ~fn t c e = let tvar = t c e in Var.attach_to_string tvar fn; tvar end let bind ~fn x ctx e = let open Types in let r = Rsp.set_and_get_exn ctx `Right (Rsp.make_empty `S) in let ll = Rsp.make_empty `S in let xvar = x ll e in let y = Var.empty ~cutoff:Phys_equal ~to_s:Utils.undefined () in let read_fn_xvar (type a) : a action -> a = function | Update -> begin let y' = fn (Var.value xvar) in let rl = Rsp.make_empty `S in let yvar' = y' rl e in let () = Rsp.set_exn r `Left (Rsp.prune rl) in let read_fn_yvar' (type a) : a action -> a = function | Update -> Var.set y (Var.value yvar'); Var.attach_cutoff y (Var.cutoff yvar'); Var.attach_to_string y (Var.get_to_string yvar') | Remove self -> Var.remove_reader yvar' self | Show -> "inner-bind: " ^ Var.to_s y | Count _ -> () (*Not going to count this*) in let read_yvar' = RNode.make ~fn:RNode.{fn = read_fn_yvar'} in Var.add_reader yvar' read_yvar'; Rsp.set_exn r `Right read_yvar'; read_yvar'.fn Update end | Remove self -> Var.remove_reader xvar self | Show -> "outer-bind: " ^ Var.to_s xvar | Count cntr -> cntr.bind <- cntr.bind + 1 in let read_xvar = RNode.make ~fn:RNode.{fn = read_fn_xvar} in Var.add_reader xvar read_xvar; let l = Rsp.make_node `S ~l:(Rsp.prune ll) ~r:read_xvar in Rsp.set_exn ctx `Left l; read_xvar.fn Update; y let run ~(executor : executor) f = let root = Rsp.make_root () in let run' = executor.run in let f' () = f root executor in let var = run' f' in {root; var; e = executor} let propagate comp = Rsp.propagate_root comp.root comp.e let get_stat comp = Rsp.get_stats comp.root module Syntax = struct let ( let+ ) v f = map ~fn:f v let ( and+ ) x y = combine x y let ( let* ) v f = bind ~fn:f v let ( and* ) = ( and+ ) let ( let& ) v f = map ~fn:f v let ( and& ) left right = par ~left ~right end