63 lines
1.7 KiB
OCaml
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
|