12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576(** Warnings and errors. *)openLplibopenBase(** [err_fmt] warning/error output formatter. *)leterr_fmt=Stdlib.refFormat.err_formatter(** [no_wrn] disables warnings when set to [true]. *)letno_wrn=Stdlib.reffalse(** [wrn popt fmt] prints a yellow warning message with [Format] format [fmt].
Note that the output buffer is flushed by the function, and that output is
prefixed with the position [popt] if given. A newline is automatically put
at the end of the message as well. *)letwrn:Pos.popt->'aoutfmt->'a=funposfmt->Color.update_with_color!err_fmt;letopenStdlibinletfprintf=if!no_wrnthenFormat.ifprintfelseoutinmatchposwith|None->fprintf!err_fmt(Color.yelfmt^^"@.")|Some_->fprintf!err_fmt(Color.yel("[%a]@ "^^fmt)^^"@.")Pos.pppos(** [with_no_wrn f x] disables warnings before executing [f x] and then
restores the initial state of warnings. The result of [f x] is returned.
*)letwith_no_wrn:('a->'b)->'a->'b=funfx->letopenStdlibinletw=!no_wrninno_wrn:=true;letres=fxinno_wrn:=w;res(** Exception raised in case of failure. Note that we use an optional optional
source position. [None] is used on errors that are independant from source
code position (e.g., errors related to command-line arguments parsing). In
cases where positions are expected [Some None] may be used to indicate the
abscence of a position. This may happen when terms are generated (e.g., by
a form of desugaring). *)exceptionFatalofPos.poptoption*string(** [fatal_str fmt] may be called an arbitrary number of times to build up the
error message of the [fatal] or [fatal_no_pos] functions prior to calling
them. Note that the messages are stored in a buffer that is flushed by the
[fatal] or [fatal_no_pos] function. Hence, they must be called. *)letfatal_msg:'aoutfmt->'a=funfmt->outFormat.str_formatterfmt(** [fatal popt fmt] raises the [Fatal(popt,msg)] exception, in which [msg] is
built from the format [fmt] (provided the necessary arguments). *)letfatal:Pos.popt->('a,'b)koutfmt->'a=funposfmt->letcont_=raise(Fatal(Some(pos),Format.flush_str_formatter()))inFormat.kfprintfcontFormat.str_formatterfmt(** [fatal_no_pos fmt] is similar to [fatal _ fmt], but it is used to raise an
error that has no precise attached source code position. *)letfatal_no_pos:('a,'b)koutfmt->'a=funfmt->letcont_=raise(Fatal(None,Format.flush_str_formatter()))inFormat.kfprintfcontFormat.str_formatterfmt(** [handle_exceptions f] runs [f ()] in an exception handler and handles both
expected and unexpected exceptions by displaying a graceful error message.
In case of an error, the program is (irrecoverably) stopped with exit code
[1] (indicating failure). Hence, [handle_exceptions] should only be called
by the main program logic, not by the internals. *)lethandle_exceptions:(unit->unit)->unit=funf->letexit_with:typeab.(a,b)koutfmt->a=funfmt->Color.update_with_colorFormat.err_formatter;Format.kfprintf(fun_->exit1)Format.err_formatter(Color.red(fmt^^"@."))intryf()with|Fatal(None,msg)->exit_with"%s"msg|Fatal(Some(p),msg)->exit_with"[%a] %s"Pos.pppmsg|e->exit_with"Uncaught [%s]."(Printexc.to_stringe)