sequence/lib/vm.ml

63 lines
1.7 KiB
OCaml

open Instr
open State
open Cont
open Step
open Trampoline
type t = {
code : Instr.t array;
initial_state : State.t;
}
type execution_result =
| Success of value option
| Failure of State.error
| Timeout
let create code =
let state = State.create code in
{ code; initial_state = state }
let execute ?(config = Trampoline.default_config) vm =
let state = vm.initial_state in
let cont = Cont.halt in
match Trampoline.run ~config (fun () -> step state cont) with
| Some v -> Success v
| None -> Failure NoExceptionHandler
let execute_with_limit vm max_steps =
let config = { Trampoline.default_config with max_steps = Some max_steps } in
execute ~config vm
let execute_program ?(config = Trampoline.default_config) code =
let vm = create code in
execute ~config vm
let execute_program_with_limit code max_steps =
let vm = create code in
execute_with_limit vm max_steps
let execute_with_trace code =
let config = { Trampoline.default_config with trace = true } in
let result = execute_program ~config code in
(result, Trampoline.get_trace config)
let disassemble code =
Array.mapi (fun i instr -> (i, Instr.show instr)) code
|> Array.to_list
let validate code =
let errors = ref [] in
Array.iteri (fun i instr ->
match instr with
| JMP offset | JMP_IF offset | JMP_IF_NOT offset | TRY offset ->
let target = i + 1 + offset - 1 in
if target < 0 || target >= Array.length code then
errors := (i, State.InvalidJump target) :: !errors
| MK_CLOSURE code_addr ->
if code_addr < 0 || code_addr >= Array.length code then
errors := (i, State.InvalidJump code_addr) :: !errors
| _ -> ())
code;
List.rev !errors