package codex
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
The Codex library for building static analysers based on abstract interpretation
Install
dune-project
Dependency
Authors
Maintainers
Sources
1.0-rc4.tar.gz
md5=bc7266a140c6886add673ede90e335d3
sha512=8da42c0ff2c1098c5f9cb2b5b43b306faf7ac93b8f5ae00c176918cee761f249ff45b29309f31a05bbcf6312304f86a0d5a000eb3f1094d3d3c2b9b4c7f5c386
doc/src/codex.tracelog/tracelog.ml.html
Source file tracelog.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406(**************************************************************************) (* This file is part of the Codex semantics library. *) (* *) (* Copyright (C) 2013-2025 *) (* CEA (Commissariat à l'énergie atomique et aux énergies *) (* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation, version 2.1. *) (* *) (* It is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) (* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file LICENSE). *) (* *) (**************************************************************************) (* -*- compile-command: "OCAMLRUNPARAM=\"b\" ocamlfind ocamlc common.ml terminal.mli terminal.ml tracelog.mli tracelog.ml -package unix -linkpkg && ./a.out" -*- *) include Common;; let log_binary_trace = ref false let print_backtraces = ref true let set_log_binary_trace bool = log_binary_trace := bool type 'a printf = ('a, Format.formatter, unit) format -> 'a;; type 'a log = 'a printf -> unit;; type location = .. module type S = sig val error : 'a log -> unit val warning : 'a log -> unit val notice : 'a log -> unit val info : 'a log -> unit val debug : 'a log -> unit val fatal : 'a log -> 'b val not_yet_implemented : 'a log -> unit val trace: 'a log -> ?loc:location -> ?bintrace:_ Syntax_tree.Location_identifier.t -> ?pp_ret:(Format.formatter -> 'b -> unit) -> (unit -> 'b) -> 'b val fatal_handler: ('a -> 'b) -> ('a -> 'b) end;; module Dummy: S = struct let error _ = () let warning _ = () let notice _ = () let info _ = () let debug _ = () let fatal _ = raise (Fatal "dummy") let not_yet_implemented = fatal let trace _ ?loc:_ ?bintrace:_ ?pp_ret:_ f = f () let fatal_handler f x = try f x with | Fatal _ -> exit 1 | _ -> exit 2 end (* TODO: Use standard log levels, liike syslog debug; debug-level messages. info; informational. Those are normally not displayed. notice; significant warning; error; critical; ;; traces occur on the info and debug levels. *) module Level = struct let critical = 2 (* Always printed: the reason why we use this program. *) let error = 3 (* The program does not run normally. *) let warning = 4 (* There is possibly a problem. *) let notice = 5 (* All messages above this level are displayed. *) let info = 6 (* Normally not displayed. *) let trace = info (* Tracing information is normally not displayed. *) let debug = 7 (* Normally not displayed; extra verbose. *) end;; let current_level = ref Level.warning;; (* Print warnings but not feedback messages by default. *) let set_verbosity_level x = let open Level in let vb = match x with | `Critical -> critical | `Error -> error | `Warning -> warning | `Info -> info | `Notice -> notice | `Debug -> debug in current_level := vb let get_verbosity_level() = let open Level in let current_level = !current_level in if current_level == error then `Error else if current_level == warning then `Warning else if current_level == info then `Info else if current_level == notice then `Notice else if current_level == debug then `Debug else assert false ;; let location_stack = ref [];; let reset_location_stack () = location_stack := [] let current_location() = match !location_stack with | [] -> None | hd::_ -> Some hd let current_location_stack() = !location_stack let r_pp_location_stack = ref (fun fmt locstack -> match locstack with | [] -> () | _ -> Format.fprintf fmt "<cannot print location>" ) ;; let set_pp_location_stack f = r_pp_location_stack := f;; let pp_location_stack fmt loc = (* If we already print trace information, do not reprint the position. *) if !current_level >= Level.trace then () else !r_pp_location_stack fmt loc ;; module MakeGeneric (V:sig val get_verbosity_level: unit -> int end) (Category:sig val category:string end) = struct let maybe_log_bintrace level log = if !log_binary_trace then begin (Binarytrace.add_trace_to_file (Category.category) (Single {category=Category.category; severity = level; content= Format.asprintf "%t" (fun fmt -> log (Format.fprintf fmt))})) end let print ?(last=false) f = f (Terminal.printf Category.category ~last) (* Note: reusing the buffer is not faster. *) let string_of_log: type a. a log -> string = fun log -> let buf = Buffer.create 150 in let ppf = Format.formatter_of_buffer buf in log (Format.fprintf ppf); Format.pp_print_flush ppf (); Buffer.contents buf ;; (* Not sure if this is useful. *) let log_of_string str : 'a log = fun m -> m (format_of_string "%s") str let log_concat (log1:'a log) (log2:'b log) : 'c log = fun (m:'c printf) -> m "%t%t" (fun fmt -> log1 (Format.fprintf fmt)) (fun fmt -> log2 (Format.fprintf fmt)) ;; let print_at_level level f = if V.get_verbosity_level() >= level then (maybe_log_bintrace level f; print f) ;; let notice f = print_at_level Level.notice f let info f = print_at_level Level.info f let generic_error level underlined_title log = if V.get_verbosity_level() >= Level.error then begin maybe_log_bintrace level log; let colored_log fmt = Format.pp_open_stag fmt (Weight Bold); Format.pp_open_stag fmt (Color Red); pp_location_stack fmt !location_stack; Format.pp_open_stag fmt (Underline true); Format.fprintf fmt underlined_title ; Format.pp_close_stag fmt (); Format.fprintf fmt ": %t" (fun fmt -> log (Format.fprintf fmt)); Format.pp_close_stag fmt (); Format.pp_close_stag fmt () in print (fun p -> p "%t" colored_log) end ;; let error log = generic_error Level.error "Error" log;; let warning log = if V.get_verbosity_level() >= Level.error then begin maybe_log_bintrace Level.warning log; let colored_log fmt = Format.pp_open_stag fmt (Color Red); pp_location_stack fmt !location_stack; Format.pp_open_stag fmt (Underline true); Format.fprintf fmt "Warning"; Format.pp_close_stag fmt (); Format.fprintf fmt ": %t" (fun fmt -> log (Format.fprintf fmt)); Format.pp_close_stag fmt (); in print (fun p -> p "%t" colored_log) end ;; let debug log = if V.get_verbosity_level() >= Level.debug then begin maybe_log_bintrace Level.debug log; let colored_log fmt = Format.pp_open_stag fmt (Weight Faint); Format.pp_open_stag fmt (Color Cyan); Format.pp_open_stag fmt (Italic true); log (Format.fprintf fmt); Format.pp_close_stag fmt (); Format.pp_close_stag fmt (); Format.pp_close_stag fmt () in print (fun p -> p "%t" colored_log) end ;; (** Fail, but reuse the message in the failwith argument. *) let fatal: type a. a log -> 'b = fun log -> generic_error Level.critical "Fatal Error" log; raise (Fatal (Format.asprintf "%s:%t" (Category.category) (fun fmt -> log (Format.fprintf fmt)))) let fatal_handler f x = try f x with | Fatal s -> (* The error message is already printed by fatal. *) let backtrace = (Printexc.get_backtrace()) in print (fun p -> p "%s" backtrace); exit 1 | e -> let exc_string = Printexc.to_string e in let backtrace = Printexc.get_backtrace() in generic_error Level.critical "Uncaught exception" (fun p -> p "%s" exc_string); print (fun p -> p "The full backtrace is:\n%s" backtrace); exit 2 ;; let not_yet_implemented log = fatal (log_concat (log_of_string "Not yet implemented: ") log) ;; (** - If [loc] is not None, push the loc on the stack of locations. - If printed: increase the nesting level. - - TODO: Add a log level; default would be info (or trace). *) (* TODO: Merge the two locations *) let trace log ?(loc:location option) ?(bintrace: _ Syntax_tree.Location_identifier.t option) ?pp_ret f = let open Binarytrace in if !log_binary_trace then begin (Binarytrace.add_trace_to_file (Category.category) (Node {loc=bintrace; category=Category.category; content= string_of_log log})) end; let pop_loc = match loc with | None -> fun () -> () | Some loc -> location_stack := loc::!location_stack; fun () -> location_stack := List.tl !location_stack in (* Note: we do the try with only with if for performance purposes. *) let display_trace = V.get_verbosity_level() >= Level.trace in begin try let with_color log = fun fmt -> Format.pp_open_stag fmt (Color Green); log (Format.fprintf fmt); Format.pp_close_stag fmt () in if display_trace then begin print ~last:false (fun p -> p "%t" @@ with_color log); Terminal.open_nesting (); end; (* Binarytrace.open_nesting (); *) let res = f() in if display_trace then begin (match pp_ret with | Some pp_ret -> print ~last:true (fun p -> p "%t" @@ with_color (fun p -> p "Result: %a" pp_ret res)); | None -> print ~last:true (fun p -> p "%t" @@ with_color (fun p -> p "Result: <not printed>"));); Terminal.close_nesting (); end; if !log_binary_trace then begin let result = match pp_ret with | Some pp_ret -> let resultstr = string_of_log (fun p -> p "%a" pp_ret res) in Result (Some resultstr) | None -> Result None in Binarytrace.add_trace_to_file (Category.category) result; (* Binarytrace.close_nesting (); *) end; pop_loc(); res with e -> (* close nesting without returning, and raise with the same backtrace. *) let bt = Printexc.get_raw_backtrace () in if display_trace then begin print ~last:(not !print_backtraces) (fun p -> p "No result (exception %s)" (Printexc.to_string e)); if !print_backtraces then begin print ~last:true (fun p -> p "%s" (Printexc.raw_backtrace_to_string bt)); print_backtraces := false (* avoid reprinting the same backtrace again *) end; Terminal.close_nesting (); end; pop_loc(); if !log_binary_trace then Binarytrace.add_trace_to_file (Category.category) (Result None); (* Binarytrace.close_nesting (); *) Printexc.raise_with_backtrace e bt end ;; end;; module Make = MakeGeneric[@inlined hint](struct let get_verbosity_level() = !current_level end) module MakeDebug = MakeGeneric(struct let get_verbosity_level() = Level.debug end) module MakeSilent = MakeGeneric(struct let get_verbosity_level() = 1 end) module Test() = struct module Logs=Make(struct let category = "test" end);; set_verbosity_level `Debug;; Logs.notice (fun m -> m "Test 0 message %s %a ads" "Hu" Format.pp_print_string "Ha");; Logs.notice (fun m -> m "Test simple message\n");; Logs.warning (fun m -> m "Test 1 warning with newline in middle %s %a@\nads" "Hu" Format.pp_print_string "Ha");; Logs.error (fun m -> m "Test 2 error with newline at the end %s %a@\n" "Hu" Format.pp_print_string "Ha");; (* Logs.output := false;; *) Logs.error (fun m -> m "Test 3 warning with newline in middle %s %a@\naaend" "Hu" Format.pp_print_string "Ha");; Logs.debug (fun m -> m "Test 4 debug output %s %a@\naaend" "Hu" Format.pp_print_string "Ha");; try Logs.not_yet_implemented (fun p -> p "FEATURE") with _ -> ();; try Logs.fatal (fun m -> m "Test 5 fatal %s %a@\nad" "Hu" Format.pp_print_string "Ha") with _ -> ();; let my_add a b = Logs.trace (fun p -> p "Evaluating %d + %d" a b) ~pp_ret:Format.pp_print_int (fun () -> a + b) ;; my_add (my_add 2 3) (my_add 4 5);; (* Flat. *) type expr = | Add of expr * expr | Cst of int let rec pp_expr fmt = function | Cst i -> Format.fprintf fmt "%d" i | Add(e1,e2) -> Format.fprintf fmt "(%a + %a)" pp_expr e1 pp_expr e2 let rec eval' = function | Cst i -> i | Add(e1,e2) -> Logs.debug (fun p -> p "Before\n e1"); let r1 = eval e1 in Logs.debug (fun p -> p "Middle"); let r2 = eval e2 in Logs.debug (fun p -> p "End"); r1 + r2 and eval e = Logs.trace (fun p -> p "Evaluating @\nexpression %a" pp_expr e) ~pp_ret:Format.pp_print_int (fun () -> eval' e);; eval (Add (Add(Cst 2,Cst 3),Add(Cst 4,Cst 5)));; exception Custom;; let rec eval' = function | Cst i when i == 5 -> raise Custom | Cst i -> i | Add(e1,e2) -> Logs.debug (fun p -> p "Before\n e1"); let r1 = eval e1 in Logs.debug (fun p -> p "Middle"); let r2 = eval e2 in Logs.debug (fun p -> p "End"); r1 + r2 and eval e = Logs.trace (fun p -> p "Evaluating @\nexpression %a" pp_expr e) ~pp_ret:Format.pp_print_int (fun () -> eval' e);; try eval (Add (Add(Cst 2,Cst 3),Add(Cst 4,Cst 5))) with Custom -> 3;; end;; (* module M = Test();; *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>