package frenetic

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file DynGraph.ml

1
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
open Core
open Async

type 'a consumer = 'a -> unit

type 'a producer = unit -> 'a

type cannot_receive

type ('b, 'a) t = {
  mutable now : 'a; (* the value at this node *)
  producer : unit -> 'a; (* produces the value at this node *)
  mutable to_list : ('a consumer) list; (* push updates to these consumers *)
  mutable from_list : ('b producer) list; (* combine the values from these producers *)
  receive : 'b -> unit (* recalculate at this node when this function is applied *)
}

let propagate (node: ('b, 'a) t) : unit =
  let v = node.now in
  List.iter node.to_list ~f:(fun f -> f v)

let create (init: 'a) (f: 'b list -> 'a) : ('b, 'a) t =
  let rec node = {
    now = init;
    producer = (fun () -> node.now);
    to_list = [];
    from_list = [];
    receive = (fun b ->
      node.now <- f (List.map node.from_list ~f:(fun f -> f ()));
      propagate node)
  } in
  node

let create_source (init: 'a) : (cannot_receive, 'a) t =
  let rec node = {
    now = init;
    producer = (fun () -> node.now);
    to_list = [];
    from_list = [];
    receive = (fun _ -> failwith "impossible: create_source node received a value")
  } in
  node

let push (x: 'a) (node : ('b, 'a) t) : unit =
    node.now <- x;
    propagate node

let attach (src : ('a, 'b) t) (dst : ('b, 'c) t) : unit =
  src.to_list <- dst.receive :: src.to_list;
  dst.from_list <- src.producer :: dst.from_list

let to_pipe (node : ('b, 'a) t) : 'a * 'a Pipe.Reader.t  =
  let (r, w) = Pipe.create () in
  let consume b = Pipe.write_without_pushback w b in
  node.to_list <- consume :: node.to_list;
  (node.producer (), r)

let from_pipe (init : 'a) (reader : 'a Pipe.Reader.t) : (cannot_receive, 'a) t =
  let rec node = {
    now = init;
    producer = (fun () -> node.now);
    to_list = [];
    from_list = [];
    receive = (fun _ -> failwith "impossible: from_pipe node received a value")
  } in
  let _ = Pipe.iter_without_pushback reader ~f:(fun x ->
    node.now <- x;
    List.iter node.to_list ~f:(fun f -> f x)) in
  node
OCaml

Innovation. Community. Security.