123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272(** [Info] is a library for lazily constructing human-readable information as a string or
sexp, with a primary use being error messages.
Using [Info] is often preferable to [sprintf] or manually constructing strings because
you don't have to eagerly construct the string -- you only need to pay when you
actually want to display the info, which for many applications is rare. Using [Info]
is also better than creating custom exceptions because you have more control over the
format.
Info is intended to be constructed in the following style; for simple info, you write:
{[
Info.of_string "Unable to find file"
]}
Or for a more descriptive [Info] without attaching any content (but evaluating the
result eagerly):
{[
Info.createf "Process %s exited with code %d" process exit_code
]}
For info where you want to attach some content, you would write:
{[
Info.create "Unable to find file" filename [%sexp_of: string]
]}
Or even,
{[
Info.create
"price too big"
(price, [ `Max max_price ])
[%sexp_of: float * [ `Max of float ]]
]}
Note that an [Info.t] can be created from any arbitrary sexp with [Info.t_of_sexp]. *)open!ImportmoduleInvariant=Invariant_intf.DefinitionsmoduleSexp=Sexp0moduleDefinitions=structmoduletypeInternal_repr=sigtypeinfo(** The internal representation. It is exposed so that we can write efficient
serializers outside of this module. *)typet=|Could_not_constructofSexp.t|Stringofstring|ExnofexnModes.Global.t|SexpofSexp.t|Tag_sexpofstring*Sexp.t*Source_code_position0.toption|Tag_tofstring*t|Tag_argofstring*Sexp.t*t|Of_listofintoption*tlist|With_backtraceoft*string(** The second argument is the backtrace *)[@@derivingsexp_of~stackify]valof_info:local_info->tval%templateto_info:t@p->info@p[@@modep=(portable,nonportable)]end(** [Info.t Modes.Portable.t] with some common ppxes derived on it. It also re-exports
some functions of [Info] so users don't need to frequently wrap and unwrap
[Modes.Portable.t] just to manipulate the underlying info. *)moduletypePortable=sigtypeinfotypet=infoModes.Portable.t[@@derivingcompare~localize,equal~localize,globalize,hash,sexp~stackify,sexp_grammar]valcreate_s:Sexp.t->tvalof_string:string->tvalof_list:tlist->tvalof_portable_lazy:stringPortable_lazy.t->tvalof_portable_lazy_sexp:Sexp.tPortable_lazy.t->tvalof_portable_lazy_t:tPortable_lazy.t->tval%templatecreate:('a:kmodcontended).?here:Source_code_position0.t->?strict:unit->string->'a@portable->('a->Sexp.t)@portable->t[@@kindk=(bits64,float64,value_or_null)]valtag_s:t->tag:Sexp.t->tvaltag:t->tag:string->tvaltag_arg:('a:value_or_nullmodcontended).t->string->'a@portable->('a->Sexp.t)@portable->tvalof_thunk:(unit->string)@portable->tvalcreatef:('a,unit,string,t)format4->'aendmoduletypeS0=sig@@portable(** Serialization and comparison force the lazy message. *)typet:valuemodcontendedglobal[@@derivingcompare~localize,equal~localize,globalize,hash,sexp~stackify,sexp_grammar]typeinfo:=t(** Explicitly indicate that [t_of_sexp] produces a portable [t]. This is nicer for
the user: you can do more things with a portable [t], e.g. move it between
domains. *)valt_of_sexp:Sexp.t->t@portableincludeInvariant.Swithtypet:=t(** [to_string_hum] forces the lazy message, which might be an expensive operation.
[to_string_hum] usually produces a sexp; however, it is guaranteed that
[to_string_hum (of_string s) = s].
If this string is going to go into a log file, you may find it useful to ensure
that the string is only one line long. To do this, use [to_string_mach t]. *)valto_string_hum:t->string(** [to_string_mach t] outputs [t] as a sexp on a single line. *)valto_string_mach:t->stringvalof_string:string->t@portable(** Be careful that the body of the lazy or thunk does not access mutable data, since
it will only be called at an undetermined later point. *)valof_lazy:stringLazy.t->tvalof_lazy_sexp:Sexp.tLazy.t->tvalof_lazy_t:tLazy.t->tval%templateof_thunk:(unit->string)@p->t@p[@@modep=(portable,nonportable)]valof_portable_lazy:stringPortable_lazy.t->t@portablevalof_portable_lazy_sexp:Sexp.tPortable_lazy.t->t@portablevalof_portable_lazy_t:tPortable_lazy.t->t@portable(** For [create message a sexp_of_a], [sexp_of_a a] is lazily computed, when the info
is converted to a sexp. So if [a] is mutated in the time between the call to
[create] and the sexp conversion, those mutations will be reflected in the sexp.
Use [~strict:()] to force [sexp_of_a a] to be computed immediately. *)val%templatecreate:('a:k).?here:Source_code_position0.t->?strict:unit->string->'a@p->('a@c->Sexp.t)@p->t@p[@@kindk=(bits64,float64,value_or_null)][@@mode(p,c)=((nonportable,uncontended),(portable,contended))]valcreate_s:Sexp.t->t@portable(** Constructs a [t] containing only a string from a format. This eagerly constructs
the string. *)valcreatef:('a,unit,string,t)format4->'a(** [createf_portable format arg1 arg2 ... ()] is like [createf format arg1 arg2 ...],
except creating a portable error. *)valcreatef_portable:('a,unit,string,unit->t@portable)format4->'a(** Adds a string to the front. *)val%templatetag:t@p->tag:string->t@p[@@modep=(portable,nonportable)](** Adds a sexp to the front. *)val%templatetag_s:t@p->tag:Sexp.t->t@p[@@modep=(portable,nonportable)](** Adds a lazy string to the front. *)valtag_lazy:t->tag:stringLazy.t->t(** Adds a portable lazy string to the front. *)val%templatetag_portable_lazy:t@p->tag:stringPortable_lazy.t->t@p[@@modep=(portable,nonportable)](** Adds a lazy sexp to the front. *)valtag_s_lazy:t->tag:Sexp.tLazy.t->t(** Adds a portable lazy sexp to the front. *)val%templatetag_s_portable_lazy:t@p->tag:Sexp.tPortable_lazy.t->t@p[@@modep=(portable,nonportable)](** Adds a string and some other data in the form of an s-expression at the front. *)val%templatetag_arg:('a:value_or_null).t@p->string->'a@p->('a@c->Sexp.t)@p->t@p[@@mode(p,c)=((nonportable,uncontended),(portable,contended))](** Combines multiple infos into one. *)val%templateof_list:tlist@p->t@p[@@modep=(portable,nonportable)](** [of_exn] and [to_exn] are primarily used with [Error], but their definitions have
to be here because they refer to the underlying representation.
[~backtrace:`Get] attaches the backtrace for the most recent exception. The same
caveats as for [Printexc.print_backtrace] apply. [~backtrace:(`This s)] attaches
the backtrace [s]. The default is no backtrace. *)valof_exn:?backtrace:[`Get|`Thisofstring]->exn->t@portablevalto_exn:t->exnvalpp:Formatter.t->t->unitmoduleInternal_repr:Internal_reprwithtypeinfo:=tmodulePortable:Portablewithtypeinfo:=infovalof_portable:Portable.t->t@portablevalto_portable:t@portable->Portable.t(** Constructs a portable info out of a possibly non-portable info. This operation is
less expensive than [err |> sexp_of_t |> create_s], but it's not a no-op.
It's not a no-op because it needs to force any non-portable computation of the
input info. *)valportabilize:t->t@portable(** Convert to [Portable.t] via [portabilize]. *)valto_portable_portabilize:t->Portable.tendmoduletypeS=sig@@portableincludeS0(** Unlike the standard [to_string_*] functions under [S], these encode any [t] that's
represented by a sexp [1] using [Sexp.Utf8.to_string_*], ensuring that valid UTF-8
sexp atoms get printed as-is. Standard [to_string_*] functions, by contrast,
encode sexps using [Sexp.to_string_*], encoding UTF-8 / other non-ASCII characters
using escape sequences.
[1] this will be true in most cases except when created out of [of_string], which
simply gets stored as a string, not a sexp. *)moduleUtf8:sig(** [to_string_hum] forces the lazy message, which might be an expensive operation.
[to_string_hum] usually produces a sexp; however, it is guaranteed that
[to_string_hum (of_string s) = s].
If this string is going to go into a log file, you may find it useful to ensure
that the string is only one line long. To do this, use [to_string_mach t]. *)valto_string_hum:t->string(** [to_string_mach t] outputs [t] as a sexp on a single line. *)valto_string_mach:t->stringendendendmoduletypeInfo0=sig@@portableincludemoduletypeofstructincludeDefinitionsendincludeS0(** @inline *)endmoduletypeInfo=sig@@portableincludeInfo0(** @inline *)includeSwithtypet:=t(** @inline *)end