Skip to content

Commit

Permalink
🚧 Pluggable recorder module for the interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeta611 committed Nov 27, 2024
1 parent 813d881 commit 69f7535
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 45 deletions.
6 changes: 6 additions & 0 deletions bin/js/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(executable
(name main)
(modes js)
(preprocess
(pps ppx_jane js_of_ocaml-ppx))
(libraries react_trace base logs logs.fmt fmt fmt.tty js_of_ocaml))
39 changes: 39 additions & 0 deletions bin/js/main.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
open! Core
open React_trace

let position (lexbuf : Lexing.lexbuf) : string =
let open Lexing in
let pos = lexbuf.lex_curr_p in
sprintf "%s:%d:%d" pos.pos_fname pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1)

let parse_with_error (lexbuf : Lexing.lexbuf) : Syntax.Prog.t =
Parser.prog Lexer.read lexbuf

let parse_program_str (program_str : string) : (Syntax.Prog.t, string) result =
let lexbuf = Lexing.from_string program_str in
match parse_with_error lexbuf with
| prog -> Ok prog
| exception Parser.Error ->
Error (sprintf "%s: syntax error" (position lexbuf))

let () =
Fmt_tty.setup_std_outputs ();
Logs.set_reporter (Logs_fmt.reporter ());
Logs.set_level (Some Logs.Info);

let open Js_of_ocaml in
Js.export_all
(object%js
method run (fuel : int) program_str =
(let open Result.Let_syntax in
let%bind prog = parse_program_str program_str in
let Interp.{ recording; _ } =
Interp.run
?fuel:(if fuel < 1 then None else Some fuel)
~recorder:(module Recorder)
prog
in
if Logs.err_count () > 0 then Error "error" else Ok recording)
|> (function Ok s -> s | Error s -> s)
|> Js.string
end)
39 changes: 39 additions & 0 deletions bin/js/recorder.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
open Stdlib.Effect
open Stdlib.Effect.Deep
open React_trace
include Recorder_intf

(* TODO: Replace the dummy string with an actual recording type *)
type recording = string

let emp_recording = "empty recording"

let event_h =
{
retc = (fun v ~recording -> (v, recording));
exnc = raise;
effc =
(fun (type a) (eff : a t) ->
match eff with
| Evt_update_st (path, label, (v, q)) ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore (path, label, v, q);
continue k () ~recording)
| Evt_set_dec (path, dec) ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore (path, dec);
continue k () ~recording)
| Evt_enq_eff (path, clos) ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore (path, clos);
continue k () ~recording)
| Evt_alloc_pt path ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore path;
continue k () ~recording)
| _ -> None);
}
1 change: 1 addition & 0 deletions bin/js/recorder.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include React_trace.Recorder_intf.Intf with type recording = string
1 change: 0 additions & 1 deletion bin/dune → bin/native/dune
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
(executable
(public_name react_trace)
(name main)
(modes exe js)
(preprocess
(pps ppx_jane))
(libraries react_trace base logs logs.fmt fmt fmt.tty))
4 changes: 3 additions & 1 deletion bin/main.ml → bin/native/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ let () =
Sexp.pp_hum Stdlib.Format.std_formatter (Syntax.Prog.sexp_of_t prog)
else
let { Interp.steps; _ } =
Interp.run ?fuel:!opt_fuel ~report:!opt_report prog
Interp.run ?fuel:!opt_fuel ~report:!opt_report
~recorder:(module Default_recorder)
prog
in
printf "\nSteps: %d\n" steps;
Stdlib.exit (if Logs.err_count () > 0 then 1 else 0))
37 changes: 37 additions & 0 deletions lib/default_recorder.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
open Stdlib.Effect
open Stdlib.Effect.Deep
include Recorder_intf

type recording = unit

let emp_recording = ()

let event_h =
{
retc = (fun v ~recording -> (v, recording));
exnc = raise;
effc =
(fun (type a) (eff : a t) ->
match eff with
| Evt_update_st (path, label, (v, q)) ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore (path, label, v, q);
continue k () ~recording)
| Evt_set_dec (path, dec) ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore (path, dec);
continue k () ~recording)
| Evt_enq_eff (path, clos) ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore (path, clos);
continue k () ~recording)
| Evt_alloc_pt path ->
Some
(fun (k : (a, _) continuation) ~(recording : recording) ->
ignore path;
continue k () ~recording)
| _ -> None);
}
1 change: 1 addition & 0 deletions lib/default_recorder.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include Recorder_intf.Intf
24 changes: 18 additions & 6 deletions lib/interp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -572,10 +572,16 @@ let step_path (path : Path.t) : bool =

has_updates

type run_info = { steps : int; mem : Memory.t; treemem : Tree_mem.t }

let run ?(fuel : int option) ?(report : bool = false) (prog : Prog.t) : run_info
=
type 'recording run_info = {
steps : int;
mem : Memory.t;
treemem : Tree_mem.t;
recording : 'recording;
}

let run (type recording) ?(fuel : int option) ?(report : bool = false)
~(recorder : (module Recorder_intf.Intf with type recording = recording))
(prog : Prog.t) : recording run_info =
Logger.run prog;

let driver () =
Expand All @@ -592,9 +598,15 @@ let run ?(fuel : int option) ?(report : bool = false) (prog : Prog.t) : run_info
loop ();
!cnt
in

let driver () =
let open (val recorder) in
match_with driver () event_h ~recording:emp_recording
in
(* TODO: Integrate Report_box with (WIP) Recorder API *)
let driver () = try_with driver () (Report_box.log_h report) in

let driver () = match_with driver () treemem_h ~treemem:Tree_mem.empty in
let driver () = match_with driver () mem_h ~mem:Memory.empty in
let (steps, treemem), mem = driver () in
{ steps; mem; treemem }
let ((steps, recording), treemem), mem = driver () in
{ steps; mem; treemem; recording }
22 changes: 0 additions & 22 deletions lib/recorder.ml

This file was deleted.

15 changes: 0 additions & 15 deletions lib/recorder.mli

This file was deleted.

18 changes: 18 additions & 0 deletions lib/recorder_intf.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
open! Core
open Stdlib.Effect
open Stdlib.Effect.Deep
open Syntax
open Concrete_domains

type _ Stdlib.Effect.t +=
| Evt_update_st : (Path.t * Label.t * (value * Job_q.t)) -> unit t
| Evt_set_dec : (Path.t * decision) -> unit t
| Evt_enq_eff : (Path.t * clos) -> unit t
| Evt_alloc_pt : Path.t -> unit t

module type Intf = sig
type recording

val emp_recording : recording
val event_h : 'a. ('a, recording:recording -> 'a * recording) handler
end
6 changes: 6 additions & 0 deletions test/test_react_trace.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ open React_trace

let fuel = 100

module Interp = struct
include Interp

let run = Interp.run ~recorder:(module Default_recorder)
end

let parse_prog s =
let lexbuf = Lexing.from_string s in
Parser.prog Lexer.read lexbuf
Expand Down

0 comments on commit 69f7535

Please sign in to comment.