123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173open!Importtypet=exn[@@deriving_inlinesexp_of]letsexp_of_t=(sexp_of_exn:t->Sexplib0.Sexp.t)[@@@end]letexit=Caml.exitexceptionFinallyoft*t[@@deriving_inlinesexp]let()=Sexplib0.Sexp_conv.Exn_converter.add[%extension_constructorFinally](function|Finally(arg0__001_,arg1__002_)->letres0__003_=sexp_of_targ0__001_andres1__004_=sexp_of_targ1__002_inSexplib0.Sexp.List[Sexplib0.Sexp.Atom"exn.ml.Finally";res0__003_;res1__004_]|_->assertfalse);;[@@@end]exceptionReraisedofstring*t[@@deriving_inlinesexp]let()=Sexplib0.Sexp_conv.Exn_converter.add[%extension_constructorReraised](function|Reraised(arg0__005_,arg1__006_)->letres0__007_=sexp_of_stringarg0__005_andres1__008_=sexp_of_targ1__006_inSexplib0.Sexp.List[Sexplib0.Sexp.Atom"exn.ml.Reraised";res0__007_;res1__008_]|_->assertfalse);;[@@@end]exceptionSexpofSexp.t(* We install a custom exn-converter rather than use:
{[
exception Sexp of Sexp.t [@@deriving_inline sexp]
(* ... *)
[@@@end]
]}
to eliminate the extra wrapping of [(Sexp ...)]. *)let()=Sexplib0.Sexp_conv.Exn_converter.add[%extension_constructorSexp](function|Sexpt->t|_->(* Reaching this branch indicates a bug in sexplib. *)assertfalse);;letcreate_ssexp=Sexpsexpletraise_with_original_backtracetbacktrace=Caml.Printexc.raise_with_backtracetbacktrace;;externalis_phys_equal_most_recent:t->bool="Base_caml_exn_is_most_recent_exn"letreraiseexnstr=letexn'=Reraised(str,exn)inifis_phys_equal_most_recentexnthen(letbt=Caml.Printexc.get_raw_backtrace()inraise_with_original_backtraceexn'bt)elseraiseexn';;letreraisefexcformat=Printf.ksprintf(funstr()->reraiseexcstr)formatletto_stringexc=Sexp.to_string_hum~indent:2(sexp_of_exnexc)letto_string_machexc=Sexp.to_string_mach(sexp_of_exnexc)letsexp_of_t=sexp_of_exnletprotectx~fx~(finally:_->unit)=matchfxwith|res->finallyx;res|exceptionexn->letbt=Caml.Printexc.get_raw_backtrace()in(matchfinallyxwith|()->raise_with_original_backtraceexnbt|exceptionfinal_exn->(* Unfortunately, the backtrace of the [final_exn] is discarded here. *)raise_with_original_backtrace(Finally(exn,final_exn))bt);;letprotect~f~finally=protectx~f()~finallyletdoes_raise(typea)(f:unit->a)=tryignore(f():a);falsewith|_->true;;includePretty_printer.Register_pp(structtypet=exnletppppft=matchsexp_of_exn_opttwith|Somesexp->Sexp.pp_humppfsexp|None->Caml.Format.pp_print_stringppf(Caml.Printexc.to_stringt);;letmodule_name="Base.Exn"end)letprint_with_backtraceexcraw_backtrace=Caml.Format.eprintf"@[<2>Uncaught exception:@\n@\n@[%a@]@]@\n@."ppexc;ifCaml.Printexc.backtrace_status()thenCaml.Printexc.print_raw_backtraceCaml.stderrraw_backtrace;Caml.flushCaml.stderr;;letset_uncaught_exception_handler()=Caml.Printexc.set_uncaught_exception_handlerprint_with_backtrace;;lethandle_uncaught_aux~do_at_exit~exitf=tryf()with|exc->letraw_backtrace=Caml.Printexc.get_raw_backtrace()in(* One reason to run [do_at_exit] handlers before printing out the error message is
that it helps curses applications bring the terminal in a good state, otherwise the
error message might get corrupted. Also, the OCaml top-level uncaught exception
handler does the same. *)ifdo_at_exitthen(tryCaml.do_at_exit()with|_->());(tryprint_with_backtraceexcraw_backtracewith|_->(tryCaml.Printf.eprintf"Exn.handle_uncaught could not print; exiting anyway\n%!"with|_->()));exit1;;lethandle_uncaught_and_exitf=handle_uncaught_auxf~exit~do_at_exit:truelethandle_uncaught~exit:must_exitf=handle_uncaught_auxf~exit:(ifmust_exitthenexitelseignore)~do_at_exit:must_exit;;letreraise_uncaughtstrfunc=tryfunc()with|exn->letbt=Caml.Printexc.get_raw_backtrace()inraise_with_original_backtrace(Reraised(str,exn))bt;;externalclear_backtrace:unit->unit="Base_clear_caml_backtrace_pos"[@@noalloc]letraise_without_backtracee=(* We clear the backtrace to reduce confusion, so that people don't think whatever
is stored corresponds to this raise. *)clear_backtrace();Caml.raise_notracee;;letinitialize_module()=set_uncaught_exception_handler()modulePrivate=structletclear_backtrace=clear_backtraceend