mirror of
https://github.com/CatalaLang/catala.git
synced 2024-11-08 07:51:43 +03:00
OCaml runtime: register fallback exception printers
This was a pending TODO: now the Catala program compiled into OCaml should return better messages and a little more information about uncaught exceptions. Note that this also concerns, at the moment, compiled modules called from the Catala interpreter: in this case, it's already better than nothing, but what we need is proper interoperation between the runtime exceptions and the interpreter handling (`EmptyError` should already be handled properly since it is critical to the computation flow, but "error" exceptions are left uncaught and will kill the interpreter). This may be part of a bigger task on unifying the output of the runtime and toplevel, which also concerns computation traces. Note 2: All runtime exceptions don't have a position available, which is quite unfortunate when your program hits an error. With `OCAMLRUNPARAM=b` and if compiled with `-g` (which should normally be the case), you can get an OCaml backtrace but that's not very friendly. Ideas for improvement: - The runtime could force-enable backtrace recording (`Printexc.record_backtrace true`) to supersede the need for `OCAMLRUNPARAM`. We can also record our own handler to print the file position and/or backtrace in the way we see fit - The printer of OCaml code in Catala could insert line directives so that the positions in the backtrace actually trace automatically back to the Catala code - If we don't want to leverage any OCaml machinery in this way, the compiler should add position information to any operator that might fail (e.g. divisions, date comparisons, etc.). Note that running in trace mode might already help pinpoint the location of the error ?
This commit is contained in:
parent
c8e529dd9f
commit
5d432d6bb9
@ -129,7 +129,7 @@ let rec evaluate_operator
|
||||
| _ -> assert false
|
||||
in
|
||||
try f x y with
|
||||
| Division_by_zero ->
|
||||
| Runtime.Division_by_zero ->
|
||||
Message.error
|
||||
~extra_pos:
|
||||
[
|
||||
|
@ -53,9 +53,34 @@ exception IndivisibleDurations
|
||||
exception ImpossibleDate
|
||||
exception NoValueProvided of source_position
|
||||
exception NotSameLength
|
||||
exception Division_by_zero (* Shadows the stdlib definition *)
|
||||
|
||||
(* TODO: register exception printers for the above
|
||||
(Printexc.register_printer) *)
|
||||
(* Register exceptions printers *)
|
||||
let () =
|
||||
let pos () p =
|
||||
Printf.sprintf "%s:%d.%d-%d.%d" p.filename p.start_line p.start_column
|
||||
p.end_line p.end_column
|
||||
in
|
||||
let pr fmt = Printf.ksprintf (fun s -> Some s) fmt in
|
||||
Printexc.register_printer
|
||||
@@ function
|
||||
| EmptyError -> pr "A variable couldn't be resolved"
|
||||
| AssertionFailed p -> pr "At %a: Assertion failed" pos p
|
||||
| ConflictError p -> pr "At %a: Conflicting exceptions" pos p
|
||||
| UncomparableDurations -> pr "Ambiguous comparison between durations"
|
||||
| IndivisibleDurations -> pr "Ambiguous division between durations"
|
||||
| ImpossibleDate -> pr "Invalid date"
|
||||
| NoValueProvided p ->
|
||||
pr "At %a: No definition applied to this variable" pos p
|
||||
| NotSameLength -> pr "Attempt to traverse lists of different lengths"
|
||||
| Division_by_zero -> pr "Division by zero"
|
||||
| _ -> None
|
||||
|
||||
let () =
|
||||
Printexc.set_uncaught_exception_handler
|
||||
@@ fun exc bt ->
|
||||
Printf.eprintf "[ERROR] %s\n%!" (Printexc.to_string exc);
|
||||
if Printexc.backtrace_status () then Printexc.print_raw_backtrace stderr bt
|
||||
|
||||
let round (q : Q.t) : Z.t =
|
||||
(* The mathematical formula is [round(q) = sgn(q) * floor(abs(q) + 0.5)].
|
||||
|
@ -76,6 +76,7 @@ exception UncomparableDurations
|
||||
exception IndivisibleDurations
|
||||
exception ImpossibleDate
|
||||
exception NoValueProvided of source_position
|
||||
exception Division_by_zero (* Shadows the stdlib definition *)
|
||||
|
||||
(** {1 Value Embedding} *)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user