(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2022 Nomadic Labs *) (* Copyright (c) 2023 TriliTech *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) (* to deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) (* and/or sell copies of the Software, and to permit persons to whom the *) (* Software is furnished to do so, subject to the following conditions: *) (* *) (* The above copyright notice and this permission notice shall be included *) (* in all copies or substantial portions of the Software. *) (* *) (* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) (* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) (* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) (* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) (* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) (* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) open Repl_helpers open Tezos_scoru_wasm open Custom_section (* Possible step kinds. *) type eval_step = | Tick (** Tick per tick *) | Result (** Up to Eval (Result (SK_Result _ | SK_Trap _)) *) | Kernel_run (** Up to the end of the current `kernel_run` *) | Inbox (** Until input requested *) type profile_options = {collapse : bool; with_time : bool; no_reboot : bool} (* Possible commands for the REPL. *) type commands = | Time of commands | Show_inbox | Show_outbox of int32 | Show_status | Show_durable_storage | Show_subkeys of string | Show_key of string * printable_value_kind | Show_memory of int32 * int * printable_value_kind | Dump_function_symbols | Step of eval_step | Load_inputs | Reveal_preimage of string option | Reveal_metadata | Profile of profile_options | Unknown of string | Help | Stop let parse_eval_step = function | "tick" -> Some Tick | "result" -> Some Result | "kernel_run" -> Some Kernel_run | "inbox" -> Some Inbox | _ -> None let parse_memory_commands = function | ["at"; address; "for"; length; "bytes"] -> ( match (Int32.of_string_opt address, int_of_string_opt length) with | Some address, Some length -> Some (Show_memory (address, length, `Hex)) | _, _ -> None) | ["at"; address; "for"; length; "bytes"; "as"; "string"] -> ( match (Int32.of_string_opt address, int_of_string_opt length) with | Some address, Some length -> Some (Show_memory (address, length, `String)) | _, _ -> None) | ["at"; address; "as"; kind] -> ( match (Int32.of_string_opt address, integer_value_kind_of_string kind) with | Some address, Some kind -> Some (Show_memory (address, value_kind_length kind, kind)) | _, _ -> None) | _ -> None let parse_profile_options = let set_option profile_options = function | "--collapsed" -> Option.map (fun opts -> {opts with collapse = true}) profile_options | "--without-time" -> Option.map (fun opts -> {opts with with_time = false}) profile_options | "--no-reboot" -> Option.map (fun opts -> {opts with no_reboot = true}) profile_options | _ -> None in List.fold_left set_option (Some {collapse = false; with_time = true; no_reboot = false}) (* Documentation for commands type *) type command_description = { parse : string list -> commands option; documentation : string; } (* Parsing and documentation of each possible command *) let rec commands_docs = [ { parse = (function | "time" :: rst -> try_parse rst |> Option.map (fun x -> Time x) | _ -> None); documentation = "time : Executes and returns the time required for \ its execution."; }; { parse = (function ["show"; "inbox"] -> Some Show_inbox | _ -> None); documentation = "show inbox: Prints the current input buffer and the number of \ messages it contains."; }; { parse = (function | ["show"; "outbox"; "at"; "level"; level] -> Int32.of_string_opt level |> Option.map (fun l -> Show_outbox l) | _ -> None); documentation = "show outbox at level : Prints the outbox messages for ."; }; { parse = (function ["show"; "status"] -> Some Show_status | _ -> None); documentation = "show status: Shows the state of the PVM."; }; { parse = (function | ["show"; "durable"; "storage"] -> Some Show_durable_storage | _ -> None); documentation = "show durable storage: Prints the durable storage from the root of the \ tree."; }; { parse = (function | ["show"; "subkeys"; path] | ["ls"; path] -> Some (Show_subkeys path) | ["show"; "subkeys"] | ["ls"] -> Some (Show_subkeys "/") | _ -> None); documentation = "show subkeys [] | ls []: Prints the direct subkeys under \ (default '/')"; }; { parse = (function | ["show"; "key"; key] -> Some (Show_key (key, `Hex)) | ["show"; "key"; key; "as"; kind] -> printable_value_kind_of_string kind |> Option.map (fun kind -> Show_key (key, kind)) | _ -> None); documentation = "show key [as ]: Looks for given in durable storage \ and prints its value in format. Prints errors if is \ invalid or not existing."; }; { parse = (function | ["dump"; "function"; "symbols"] -> Some Dump_function_symbols | _ -> None); documentation = "dump function symbols: Pretty-prints the parsed functions custom \ section. The result will be empty if the kernel is in `wast` format \ or has been stripped of its custom sections."; }; { parse = (function | ["step"; step] -> parse_eval_step step |> Option.map (fun s -> Step s) | _ -> None); documentation = "step : Depending on :\n\ \ - tick: Run for a tick.\n\ \ - result: Run up to the end of `kernel_run` but before \ rebooting of waiting for reboot, before the memory is flushed.\n\ \ - kernel_run: Run up to the end of the current `kernel_run` \ with padding up to the maximum ticks per reboot for the current \ version of the PVM.\n\ \ - inbox: Run until the next inbox level. Loads the next \ inbox if the interpreter is waiting for inputs."; }; { parse = (function ["load"; "inputs"] -> Some Load_inputs | _ -> None); documentation = "load inputs: If the kernel is waiting for inputs, go the the next \ level and load the next inbox."; }; { parse = (function | ["reveal"; "preimage"] -> Some (Reveal_preimage None) | ["reveal"; "preimage"; hex_encoded_preimage] -> Some (Reveal_preimage (Some hex_encoded_preimage)) | _ -> None); documentation = "reveal preimage []: Checks the current state is \ waiting for a preimage, parses as an \ hexadecimal representation of the data or uses the builtin if none is \ given, and does a reveal step."; }; { parse = (function ["reveal"; "metadata"] -> Some Reveal_metadata | _ -> None); documentation = "reveal metadata: While in a reveal step, print the current metadata \ from PVM."; }; { parse = (function ["stop"] -> Some Stop | _ -> None); documentation = "stop: Stops the execution of the current session."; }; { parse = (function | "profile" :: options -> parse_profile_options options |> Option.map (fun opts -> Profile opts) | _ -> None); documentation = "profile