97 lines
3.5 KiB
OCaml
97 lines
3.5 KiB
OCaml
(** HTML Renderer
|
|
|
|
Renders the output of computations on a given program as an HTML webpage.
|
|
*)
|
|
|
|
(** Generates a fresh unique identifier *)
|
|
let fresh_uuid =
|
|
let next = ref 0 in
|
|
fun () ->
|
|
let out = !next in
|
|
incr next ; out
|
|
|
|
(** Checks whether a submethod is relevant to show, or whether it should be
|
|
hidden by default. *)
|
|
let is_sub_relevant sub = Renderer.AnnotAsm.(
|
|
List.exists
|
|
(fun instr -> instr.instr_annot.Renderer.events <> [])
|
|
sub.sub_asm
|
|
)
|
|
|
|
|
|
(** Box `AnnotAsm.asm_info_t` as a Jingoo tvalue *)
|
|
let render_prog_box annotated_prog = Jingoo.Jg_types.(Renderer.AnnotAsm.(
|
|
let render_addr addr = (Format.sprintf "%04x" addr) in
|
|
List.map (fun render_sub ->
|
|
[
|
|
("sub_section", box_string render_sub.sub_section);
|
|
("sub_name", box_string render_sub.sub_name);
|
|
("sub_addr", box_string (Format.sprintf "%016x" render_sub.sub_addr));
|
|
("sub_uuid", box_int @@ fresh_uuid ());
|
|
("sub_relevant", box_int @@ (match is_sub_relevant render_sub with
|
|
| true -> 1
|
|
| false -> 0));
|
|
("sub_asm", List.map (fun row -> [
|
|
("instr_addr", box_string (render_addr row.instr_addr));
|
|
("instr_bytes", box_string (
|
|
Format.asprintf "%a" Asm_acquire.pp_hex_bytes row.instr_bytes
|
|
));
|
|
("instr_asm", box_string row.instr_asm);
|
|
("instr_events", (List.map (fun event ->
|
|
let typ, id, bound, data = Renderer.(match event with
|
|
| BoxStart(id, bound, data) -> "start", id, bound, data
|
|
| BoxEnd(id, bound, data) -> "end", id, bound, data
|
|
) in
|
|
[
|
|
("typ", box_string typ);
|
|
("id", box_int id);
|
|
("bound", box_string @@ render_addr bound);
|
|
("data", box_string @@ Format.sprintf "[%d] File %s, %d:%d"
|
|
data.box_class_id data.box_file data.box_line data.box_col);
|
|
("box_eq", box_int data.box_class_id);
|
|
|
|
] |> box_obj)
|
|
row.instr_annot.Renderer.events)
|
|
|> box_list);
|
|
] |> box_obj) render_sub.sub_asm
|
|
|> box_list;
|
|
)] |> box_obj
|
|
) annotated_prog
|
|
|> box_list
|
|
))
|
|
|
|
let render_progs_box annotated_progs = Jingoo.Jg_types.(
|
|
List.map (fun (prog_path, annotated_prog) ->
|
|
[
|
|
("path", box_string prog_path);
|
|
("prog", render_prog_box annotated_prog)
|
|
] |> box_obj)
|
|
annotated_progs
|
|
|> box_list
|
|
)
|
|
|
|
module IntSet = Set.Make(struct type t = int let compare = compare end)
|
|
|
|
let prog_box_classes render_data = Jingoo.Jg_types.(
|
|
List.fold_left (fun accu prog ->
|
|
List.fold_left (fun accu (Renderer.TaggedRange(_, _, box)) ->
|
|
IntSet.add box.box_class_id accu)
|
|
accu prog.Renderer.render_boxes)
|
|
IntSet.empty render_data
|
|
|> IntSet.elements
|
|
|> List.map box_int
|
|
|> box_list
|
|
)
|
|
|
|
(** [render multi_render_data] renders the given [render_data] to a string. *)
|
|
let render multi_render_data = Jingoo.(
|
|
let annotated_progs = List.map (fun render_data ->
|
|
render_data.Renderer.render_prog_path,
|
|
Renderer.render_data_to_annotated_asm render_data) multi_render_data in
|
|
let models = [
|
|
("progs", render_progs_box annotated_progs);
|
|
("box_classes", prog_box_classes multi_render_data);
|
|
] in
|
|
Jg_template.from_file "src/render_html.jingoo" ~models:models
|
|
)
|