sequence/lib/trampoline.ml

64 lines
1.6 KiB
OCaml

open Step
type thunk = unit -> result
type trace_entry = {
pc : int;
stack_len : int;
cont_depth : int;
}
type config = {
max_steps : int option;
trace : bool;
trace_entries : trace_entry list ref;
}
let default_config = {
max_steps = None;
trace = false;
trace_entries = ref [];
}
let rec run ?(config = default_config) thunk =
match config.max_steps with
| Some max when max <= 0 -> None
| Some max -> run_with_limit ~config max thunk
| None -> run_unlimited ~config thunk
and run_unlimited ~config thunk =
match thunk () with
| Continue { state; cont } ->
(if config.trace then
config.trace_entries := {
pc = state.pc;
stack_len = List.length state.stack;
cont_depth = Cont.depth cont;
} :: !(config.trace_entries));
run_unlimited ~config (fun () -> step state cont)
| Halted v -> Some v
| Error e -> None
and run_with_limit ~config max_steps thunk =
let rec aux steps thunk =
if steps >= max_steps then
None
else
match thunk () with
| Continue { state; cont } ->
(if config.trace then
config.trace_entries := {
pc = state.pc;
stack_len = List.length state.stack;
cont_depth = Cont.depth cont;
} :: !(config.trace_entries));
aux (steps + 1) (fun () -> step state cont)
| Halted v -> Some v
| Error e -> None
in
aux 0 thunk
let get_trace config = List.rev !(config.trace_entries)
let clear_trace config = config.trace_entries := []