|
| 1 | +# Reactive Graph Reachability |
| 2 | + |
| 3 | +This directory hosts two minimal OCaml implementations for computing the set of |
| 4 | +nodes that are unreachable from all marked nodes in a graph assembled from |
| 5 | +multiple per-file fragments: |
| 6 | + |
| 7 | +1. `traditional_analysis/` contains a plain OCaml executable plus unit tests that parse |
| 8 | + `.graph` files, build the global graph, and print unreachable nodes. |
| 9 | +2. `reactive_analysis/` reuses the same parser/graph logic but runs the pipeline through |
| 10 | + the Skip reactive runtime (vendored under `reactive_graph/vendor/skip-ocaml`) |
| 11 | + so that file |
| 12 | + parsing and reachability recompute incrementally. |
| 13 | + |
| 14 | +The implementations share `graph_lib/`, which knows how to parse graph files and |
| 15 | +compute reachability. |
| 16 | + |
| 17 | +## Input format |
| 18 | + |
| 19 | +Each `.graph` file can contain `node` and `edge` directives: |
| 20 | + |
| 21 | +``` |
| 22 | +node <id> [marked] |
| 23 | +edge <src> <dst> |
| 24 | +``` |
| 25 | + |
| 26 | +* Node identifiers are integers and must be unique globally. |
| 27 | +* Adding the literal `marked` after a node ID makes it one of the starting |
| 28 | + points for reachability. |
| 29 | +* Edge sources must be defined in the same file; edge destinations must exist in |
| 30 | + some file. |
| 31 | + |
| 32 | +Sample files live under `data/`. |
| 33 | + |
| 34 | +## Traditional build & tests |
| 35 | + |
| 36 | +``` |
| 37 | +cd /Users/cristianocalcagno/GitHub/rescript |
| 38 | +dune runtest --root reactive_graph # runs unit tests |
| 39 | +dune exec --root reactive_graph reactive_graph/traditional_analysis/bin/traditional_main.exe -- reactive_graph/data |
| 40 | +``` |
| 41 | + |
| 42 | +The executable prints either `All nodes are reachable...` or the sorted list of |
| 43 | +unreachable nodes. |
| 44 | + |
| 45 | +## Reactive build & usage |
| 46 | + |
| 47 | +`reactive_graph/vendor/skip-ocaml/` vendors the Skip runtime sources copied from |
| 48 | +[`skip-ocaml`](https://github.com/skiplang/skip-ocaml) at commit |
| 49 | +`0a8ddbf29970869d9396d7e860e3b48bb3df8695`. The snapshot includes only the |
| 50 | +pieces required to build `libskip_reactive.a` (runtime C/C++ glue plus the LLVM |
| 51 | +module `external/skip.ll`). If you want libbacktrace support, build |
| 52 | +`external/libbacktrace.a` for your platform and drop it into the vendor tree |
| 53 | +before compiling. Otherwise, build the static library once: |
| 54 | + |
| 55 | +``` |
| 56 | +cd /Users/cristianocalcagno/GitHub/rescript/reactive_graph/vendor/skip-ocaml |
| 57 | +make build/libskip_reactive.a |
| 58 | +``` |
| 59 | + |
| 60 | +(Re-run the command whenever you clean the vendor build directory.) |
| 61 | + |
| 62 | +1. Build the reactive binary from the ReScript repo: |
| 63 | + |
| 64 | + ``` |
| 65 | + cd /Users/cristianocalcagno/GitHub/rescript |
| 66 | + dune build --root reactive_graph reactive_analysis/bin/reactive_main.exe |
| 67 | + ``` |
| 68 | + |
| 69 | +2. Run it by pointing to the directory with `.graph` files. The executable |
| 70 | + creates `graph.rheap` by default; pass a custom heap path as the first |
| 71 | + argument if you need to override it (macOS users should delete heaps between |
| 72 | + runs, but the CLI now removes the default automatically): |
| 73 | + |
| 74 | +``` |
| 75 | +./_build/default/reactive_analysis/bin/reactive_main.exe reactive_graph/data |
| 76 | +``` |
| 77 | + |
| 78 | + The first run parses all files and caches the intermediate representations. |
| 79 | + Subsequent runs only re-parse and recompute for the files that change. |
| 80 | + (Any heap filename works; `graph.rheap` is just a short example.) |
| 81 | + After each run the CLI now prints the reactive heap usage using the |
| 82 | + `Reactive.heap_usage()` API, so you can see how many bytes of the `.rheap` |
| 83 | + file are currently occupied. |
| 84 | + |
| 85 | +### Makefile shortcuts |
| 86 | + |
| 87 | +From `reactive_graph/` you can use the tiny Makefile: |
| 88 | + |
| 89 | +``` |
| 90 | +make traditional-run # build + run the non-reactive analysis |
| 91 | +make reactive-run # build runtime + reactive binary + run |
| 92 | +make clean |
| 93 | +``` |
| 94 | + |
| 95 | +`make reactive-run` builds the vendored runtime automatically (via |
| 96 | +`make -C vendor/skip-ocaml ...`) before invoking the executable. |
| 97 | + |
| 98 | +### macOS note |
| 99 | + |
| 100 | +Because ASLR prevents reusing heaps across fresh processes, macOS users must |
| 101 | +delete the `.rheap` file before every new invocation of the reactive binary. |
| 102 | +The runtime now exits immediately with an explanatory error if it detects an |
| 103 | +existing heap file on macOS. |
| 104 | + |
| 105 | +## Directory layout |
| 106 | + |
| 107 | +``` |
| 108 | +graph_lib/ Shared parser and reachability logic |
| 109 | +traditional_analysis/ Non-reactive CLI + tests |
| 110 | +reactive_analysis/ Reactive CLI + vendored Skip runtime bindings |
| 111 | +data/ Example input fragments |
| 112 | +``` |
| 113 | + |
| 114 | +Both executables accept a directory path; they enumerate all `*.graph` files |
| 115 | +inside that directory and report unreachable nodes in ascending order. |
0 commit comments