.TH "Misc" 3 2024-05-31 OCamldoc "OCaml library" .SH NAME Misc \- Miscellaneous useful types and functions .SH Module Module Misc .SH Documentation .sp Module .BI "Misc" : .B sig end .sp Miscellaneous useful types and functions .sp Warning: this module is unstable and part of .ft B Compiler_libs .ft R \&. .sp .sp .sp .PP .SS Reporting fatal errors .PP .I val fatal_error : .B string -> 'a .sp Raise the .ft B Fatal_error .ft R exception with the given string\&. .sp .I val fatal_errorf : .B ('a, Format.formatter, unit, 'b) format4 -> 'a .sp Format the arguments according to the given format string and raise .ft B Fatal_error .ft R with the resulting string\&. .sp .I exception Fatal_error .sp .sp .PP .SS Exceptions and finalization .PP .I val try_finally : .B ?always:(unit -> unit) -> ?exceptionally:(unit -> unit) -> (unit -> 'a) -> 'a .sp .ft B try_finally work ~always ~exceptionally .ft R is designed to run code in .ft B work .ft R that may fail with an exception, and has two kind of cleanup routines: .ft B always .ft R , that must be run after any execution of the function (typically, freeing system resources), and .ft B exceptionally .ft R , that should be run only if .ft B work .ft R or .ft B always .ft R failed with an exception (typically, undoing user\-visible state changes that would only make sense if the function completes correctly)\&. For example: .sp .EX .ft B .br \& let objfile = outputprefix ^ "\&.cmo" in .br \& let oc = open_out_bin objfile in .br \& Misc\&.try_finally .br \& (fun () \-> .br \& bytecode .br \& ++ Timings\&.(accumulate_time (Generate sourcefile)) .br \& (Emitcode\&.to_file oc modulename objfile); .br \& Warnings\&.check_fatal ()) .br \& ~always:(fun () \-> close_out oc) .br \& ~exceptionally:(fun _exn \-> remove_file objfile); .br \& .ft R .EE .sp If .ft B exceptionally .ft R fail with an exception, it is propagated as usual\&. .sp If .ft B always .ft R or .ft B exceptionally .ft R use exceptions internally for control\-flow but do not raise, then .ft B try_finally .ft R is careful to preserve any exception backtrace coming from .ft B work .ft R or .ft B always .ft R for easier debugging\&. .sp .I val reraise_preserving_backtrace : .B exn -> (unit -> unit) -> 'a .sp .ft B reraise_preserving_backtrace e f .ft R is (f (); raise e) except that the current backtrace is preserved, even if .ft B f .ft R uses exceptions internally\&. .sp .PP .SS List operations .PP .I val map_end : .B ('a -> 'b) -> 'a list -> 'b list -> 'b list .sp .ft B map_end f l t .ft R is .ft B map f l @ t .ft R , just more efficient\&. .sp .I val rev_map_end : .B ('a -> 'b) -> 'a list -> 'b list -> 'b list .sp .ft B map_end f l t .ft R is .ft B map f (rev l) @ t .ft R , just more efficient\&. .sp .I val map_left_right : .B ('a -> 'b) -> 'a list -> 'b list .sp Like .ft B List\&.map .ft R , with guaranteed left\-to\-right evaluation order .sp .I val for_all2 : .B ('a -> 'b -> bool) -> 'a list -> 'b list -> bool .sp Same as .ft B List\&.for_all .ft R but for a binary predicate\&. In addition, this .ft B for_all2 .ft R never fails: given two lists with different lengths, it returns false\&. .sp .I val replicate_list : .B 'a -> int -> 'a list .sp .ft B replicate_list elem n .ft R is the list with .ft B n .ft R elements all identical to .ft B elem .ft R \&. .sp .I val list_remove : .B 'a -> 'a list -> 'a list .sp .ft B list_remove x l .ft R returns a copy of .ft B l .ft R with the first element equal to .ft B x .ft R removed\&. .sp .I val split_last : .B 'a list -> 'a list * 'a .sp Return the last element and the other elements of the given list\&. .sp .PP .SS Hash table operations .PP .I val create_hashtable : .B int -> ('a * 'b) list -> ('a, 'b) Hashtbl.t .sp Create a hashtable with the given initial size and fills it with the given bindings\&. .sp .PP .SS Extensions to the standard library .PP .I module Stdlib : .B sig end .sp .sp .PP .SS Operations on files and file paths .PP .I val find_in_path : .B string list -> string -> string .sp Search a file in a list of directories\&. .sp .I val find_in_path_rel : .B string list -> string -> string .sp Search a relative file in a list of directories\&. .sp .I val normalized_unit_filename : .B string -> string .sp Normalize file name .ft B Foo\&.ml .ft R to .ft B foo\&.ml .ft R .sp .I val find_in_path_normalized : .B string list -> string -> string .sp Same as .ft B Misc\&.find_in_path_rel .ft R , but search also for normalized unit filename, i\&.e\&. if name is .ft B Foo\&.ml .ft R , allow .ft B /path/Foo\&.ml .ft R and .ft B /path/foo\&.ml .ft R to match\&. .sp .I val remove_file : .B string -> unit .sp Delete the given file if it exists and is a regular file\&. Does nothing for other kinds of files\&. Never raises an error\&. .sp .I val expand_directory : .B string -> string -> string .sp .ft B expand_directory alt file .ft R eventually expands a .ft B + .ft R at the beginning of file into .ft B alt .ft R (an alternate root directory) .sp .I val split_path_contents : .B ?sep:char -> string -> string list .sp .ft B split_path_contents ?sep s .ft R interprets .ft B s .ft R as the value of a "PATH"\-like variable and returns the corresponding list of directories\&. .ft B s .ft R is split using the platform\-specific delimiter, or .ft B ~sep .ft R if it is passed\&. .sp Returns the empty list if .ft B s .ft R is empty\&. .sp .I val copy_file : .B in_channel -> out_channel -> unit .sp .ft B copy_file ic oc .ft R reads the contents of file .ft B ic .ft R and copies them to .ft B oc .ft R \&. It stops when encountering EOF on .ft B ic .ft R \&. .sp .I val copy_file_chunk : .B in_channel -> out_channel -> int -> unit .sp .ft B copy_file_chunk ic oc n .ft R reads .ft B n .ft R bytes from .ft B ic .ft R and copies them to .ft B oc .ft R \&. It raises .ft B End_of_file .ft R when encountering EOF on .ft B ic .ft R \&. .sp .I val string_of_file : .B in_channel -> string .sp .ft B string_of_file ic .ft R reads the contents of file .ft B ic .ft R and copies them to a string\&. It stops when encountering EOF on .ft B ic .ft R \&. .sp .I val output_to_file_via_temporary : .B ?mode:open_flag list -> .B string -> (string -> out_channel -> 'a) -> 'a .sp Produce output in temporary file, then rename it (as atomically as possible) to the desired output file name\&. .ft B output_to_file_via_temporary filename fn .ft R opens a temporary file which is passed to .ft B fn .ft R (name + output channel)\&. When .ft B fn .ft R returns, the channel is closed and the temporary file is renamed to .ft B filename .ft R \&. .sp .I val protect_writing_to_file : .B filename:string -> f:(out_channel -> 'a) -> 'a .sp Open the given .ft B filename .ft R for writing (in binary mode), pass the .ft B out_channel .ft R to the given function, then close the channel\&. If the function raises an exception then .ft B filename .ft R will be removed\&. .sp .I val concat_null_terminated : .B string list -> string .sp .ft B concat_null_terminated [x1;x2; \&.\&.\&. xn] .ft R is .ft B x1 ^ "\(rs000" ^ x2 ^ "\(rs000" ^ \&.\&.\&. ^ xn ^ "\(rs000" .ft R .sp .I val split_null_terminated : .B string -> string list .sp .ft B split_null_terminated s .ft R is similar .ft B String\&.split_on_char \&'\(rs000\&' .ft R but ignores the trailing separator, if any .sp .I val chop_extensions : .B string -> string .sp Return the given file name without its extensions\&. The extensions is the longest suffix starting with a period and not including a directory separator, .ft B \&.xyz\&.uvw .ft R for instance\&. .sp Return the given name if it does not contain an extension\&. .sp .PP .SS Integer operations .PP .I val log2 : .B int -> int .sp .ft B log2 n .ft R returns .ft B s .ft R such that .ft B n = 1 lsl s .ft R if .ft B n .ft R is a power of 2 .sp .I val align : .B int -> int -> int .sp .ft B align n a .ft R rounds .ft B n .ft R upwards to a multiple of .ft B a .ft R (a power of 2)\&. .sp .I val no_overflow_add : .B int -> int -> bool .sp .ft B no_overflow_add n1 n2 .ft R returns .ft B true .ft R if the computation of .ft B n1 + n2 .ft R does not overflow\&. .sp .I val no_overflow_sub : .B int -> int -> bool .sp .ft B no_overflow_sub n1 n2 .ft R returns .ft B true .ft R if the computation of .ft B n1 \- n2 .ft R does not overflow\&. .sp .I val no_overflow_mul : .B int -> int -> bool .sp .ft B no_overflow_mul n1 n2 .ft R returns .ft B true .ft R if the computation of .ft B n1 * n2 .ft R does not overflow\&. .sp .I val no_overflow_lsl : .B int -> int -> bool .sp .ft B no_overflow_lsl n k .ft R returns .ft B true .ft R if the computation of .ft B n lsl k .ft R does not overflow\&. .sp .I val letter_of_int : .B int -> string .sp .sp .I module Int_literal_converter : .B sig end .sp .sp .I val find_first_mono : .B (int -> bool) -> int .sp .ft B find_first_mono p .ft R takes an integer predicate .ft B p : int \-> bool .ft R that we assume: 1\&. is monotonic on natural numbers: if .ft B a <= b .ft R then .ft B p a .ft R implies .ft B p b .ft R , 2\&. is satisfied for some natural numbers in range .ft B 0; max_int .ft R (this is equivalent to: .ft B p max_int = true .ft R )\&. .sp .ft B find_first_mono p .ft R is the smallest natural number N that satisfies .ft B p .ft R , computed in O(log(N)) calls to .ft B p .ft R \&. .sp Our implementation supports two cases where the preconditions on .ft B p .ft R are not respected: .sp \-If .ft B p .ft R is always .ft B false .ft R , we silently return .ft B max_int .ft R instead of looping or crashing\&. .sp \-If .ft B p .ft R is non\-monotonic but eventually true, we return some satisfying value\&. .sp .PP .SS String operations .PP .I val search_substring : .B string -> string -> int -> int .sp .ft B search_substring pat str start .ft R returns the position of the first occurrence of string .ft B pat .ft R in string .ft B str .ft R \&. Search starts at offset .ft B start .ft R in .ft B str .ft R \&. Raise .ft B Not_found .ft R if .ft B pat .ft R does not occur\&. .sp .I val replace_substring : .B before:string -> after:string -> string -> string .sp .ft B replace_substring ~before ~after str .ft R replaces all occurrences of .ft B before .ft R with .ft B after .ft R in .ft B str .ft R and returns the resulting string\&. .sp .I val rev_split_words : .B string -> string list .sp .ft B rev_split_words s .ft R splits .ft B s .ft R in blank\-separated words, and returns the list of words in reverse order\&. .sp .I val cut_at : .B string -> char -> string * string .sp .ft B String\&.cut_at s c .ft R returns a pair containing the sub\-string before the first occurrence of .ft B c .ft R in .ft B s .ft R , and the sub\-string after the first occurrence of .ft B c .ft R in .ft B s .ft R \&. .ft B let (before, after) = String\&.cut_at s c in .br \& before ^ String\&.make 1 c ^ after .ft R is the identity if .ft B s .ft R contains .ft B c .ft R \&. .sp Raise .ft B Not_found .ft R if the character does not appear in the string .sp .B "Since" 4.01 .sp .I val ordinal_suffix : .B int -> string .sp .ft B ordinal_suffix n .ft R is the appropriate suffix to append to the numeral .ft B n .ft R as an ordinal number: .ft B 1 .ft R \-> .ft B "st" .ft R , .ft B 2 .ft R \-> .ft B "nd" .ft R , .ft B 3 .ft R \-> .ft B "rd" .ft R , .ft B 4 .ft R \-> .ft B "th" .ft R , and so on\&. Handles larger numbers (e\&.g\&., .ft B 42 .ft R \-> .ft B "nd" .ft R ) and the numbers 11\-\-13 (which all get .ft B "th" .ft R ) correctly\&. .sp .I val normalise_eol : .B string -> string .sp .ft B normalise_eol s .ft R returns a fresh copy of .ft B s .ft R with any \&'\(rsr\&' characters removed\&. Intended for pre\-processing text which will subsequently be printed on a channel which performs EOL transformations (i\&.e\&. Windows) .sp .I val delete_eol_spaces : .B string -> string .sp .ft B delete_eol_spaces s .ft R returns a fresh copy of .ft B s .ft R with any end of line spaces removed\&. Intended to normalize the output of the toplevel for tests\&. .sp .PP .SS Operations on references .PP .I type ref_and_value = | R .B : .B 'a ref * 'a .B -> .B ref_and_value .sp .sp .I val protect_refs : .B ref_and_value list -> (unit -> 'a) -> 'a .sp .ft B protect_refs l f .ft R temporarily sets .ft B r .ft R to .ft B v .ft R for each .ft B R (r, v) .ft R in .ft B l .ft R while executing .ft B f .ft R \&. The previous contents of the references is restored even if .ft B f .ft R raises an exception, without altering the exception backtrace\&. .sp .I val get_ref : .B 'a list ref -> 'a list .sp .ft B get_ref lr .ft R returns the content of the list reference .ft B lr .ft R and reset its content to the empty list\&. .sp .I val set_or_ignore : .B ('a -> 'b option) -> 'b option ref -> 'a -> unit .sp .ft B set_or_ignore f opt x .ft R sets .ft B opt .ft R to .ft B f x .ft R if it returns .ft B Some _ .ft R , or leaves it unmodified if it returns .ft B None .ft R \&. .sp .PP .SS Operations on triples and quadruples .PP .I val fst3 : .B 'a * 'b * 'c -> 'a .sp .sp .I val snd3 : .B 'a * 'b * 'c -> 'b .sp .sp .I val thd3 : .B 'a * 'b * 'c -> 'c .sp .sp .I val fst4 : .B 'a * 'b * 'c * 'd -> 'a .sp .sp .I val snd4 : .B 'a * 'b * 'c * 'd -> 'b .sp .sp .I val thd4 : .B 'a * 'b * 'c * 'd -> 'c .sp .sp .I val for4 : .B 'a * 'b * 'c * 'd -> 'd .sp .sp .PP .SS Spell checking and ``did you mean'' suggestions .PP .I val edit_distance : .B string -> string -> int -> int option .sp .ft B edit_distance a b cutoff .ft R computes the edit distance between strings .ft B a .ft R and .ft B b .ft R \&. To help efficiency, it uses a cutoff: if the distance .ft B d .ft R is smaller than .ft B cutoff .ft R , it returns .ft B Some d .ft R , else .ft B None .ft R \&. .sp The distance algorithm currently used is Damerau\-Levenshtein: it computes the number of insertion, deletion, substitution of letters, or swapping of adjacent letters to go from one word to the other\&. The particular algorithm may change in the future\&. .sp .I val spellcheck : .B string list -> string -> string list .sp .ft B spellcheck env name .ft R takes a list of names .ft B env .ft R that exist in the current environment and an erroneous .ft B name .ft R , and returns a list of suggestions taken from .ft B env .ft R , that are close enough to .ft B name .ft R that it may be a typo for one of them\&. .sp .I val did_you_mean : .B Format.formatter -> (unit -> string list) -> unit .sp .ft B did_you_mean ppf get_choices .ft R hints that the user may have meant one of the option returned by calling .ft B get_choices .ft R \&. It does nothing if the returned list is empty\&. .sp The .ft B unit \-> \&.\&.\&. .ft R thunking is meant to delay any potentially\-slow computation (typically computing edit\-distance with many things from the current environment) to when the hint message is to be printed\&. You should print an understandable error message before calling .ft B did_you_mean .ft R , so that users get a clear notification of the failure even if producing the hint is slow\&. .sp .I module Color : .B sig end .sp .SS Color support detection .sp .PP .SS Styling handling for terminal output .PP .I module Style : .B sig end .sp .sp .I module Error_style : .B sig end .sp .sp .PP .SS Formatted output .PP .I val print_if : .B Format.formatter -> .B bool ref -> (Format.formatter -> 'a -> unit) -> 'a -> 'a .sp .ft B print_if ppf flag fmt x .ft R prints .ft B x .ft R with .ft B fmt .ft R on .ft B ppf .ft R if .ft B b .ft R is true\&. .sp .I val pp_two_columns : .B ?sep:string -> .B ?max_lines:int -> Format.formatter -> (string * string) list -> unit .sp .ft B pp_two_columns ?sep ?max_lines ppf l .ft R prints the lines in .ft B l .ft R as two columns separated by .ft B sep .ft R ("|" by default)\&. .ft B max_lines .ft R can be used to indicate a maximum number of lines to print \-\- an ellipsis gets inserted at the middle if the input has too many lines\&. .sp Example: .sp pp_two_columns ~max_lines:3 Format\&.std_formatter [ "abc", "hello"; "def", "zzz"; "a" , "bllbl"; "bb" , "dddddd"; ] .sp prints .sp abc | hello \&.\&.\&. bb | dddddd .sp .I val print_see_manual : .B Format.formatter -> int list -> unit .sp See manual section .sp .PP .SS Displaying configuration variables .PP .I val show_config_and_exit : .B unit -> unit .sp Display the values of all compiler configuration variables from module .ft B Config .ft R , then exit the program with code 0\&. .sp .I val show_config_variable_and_exit : .B string -> unit .sp Display the value of the given configuration variable, then exit the program with code 0\&. .sp .PP .SS Handling of build maps .PP .PP Build maps cause the compiler to normalize file names embedded in object files, thus leading to more reproducible builds\&. .PP .I val get_build_path_prefix_map : .B unit -> Build_path_prefix_map.map option .sp Returns the map encoded in the .ft B BUILD_PATH_PREFIX_MAP .ft R environment variable\&. .sp .I val debug_prefix_map_flags : .B unit -> string list .sp Returns the list of .ft B \-\-debug\-prefix\-map .ft R flags to be passed to the assembler, built from the .ft B BUILD_PATH_PREFIX_MAP .ft R environment variable\&. .sp .PP .SS Handling of magic numbers .PP .I module Magic_number : .B sig end .sp .sp .PP .SS Miscellaneous type aliases .PP .I type filepath = .B string .sp .sp .I type modname = .B string .sp .sp .I type crcs = .B (modname * Digest.t option) list .sp .sp .I type alerts = .B string Stdlib.String.Map.t .sp .sp