···7788### Runtime system:
991010+* #9391, #9424: Fix failed assertion in runtime due to ephemerons *set_* and
1111+ *blit_* function during Mark phase
1212+ (François Bobot, reported by Stephen Dolan, reviewed by Damien Doligez)
1313+1014### Code generation and optimizations:
11151216### Standard library:
···2024 are now provided by the camlp-streams library.
2125 (Xavier Leroy, review by Nicolás Ojeda Bär)
22262727+- #10526: add Random.bits32, Random.bits64, Random.nativebits
2828+ (Xavier Leroy, review by Gabriel Scherer and François Bobot)
2929+2330### Other libraries:
24312532- #10192: Add support for Unix domain sockets on Windows and use them
···3138- #3959, #7202, #10476: ocaml, in script mode, directive errors
3239 (`#use "missing_file";;`) use stderr and exit with an error.
3340 (Florian Angeletti, review by Gabriel Scherer)
4141+4242+- #10524: Directive argument type error now shows expected and received type.
4343+ (Wiktor Kuchta, review by Gabriel Scherer)
34443545### Manual and documentation:
3646
+1-2
lambda/lambda.ml
···375375 For that reason, they should not include cycles.
376376*)
377377378378-exception Not_simple
379379-380378let max_raw = 32
381379382380let make_key e =
381381+ let exception Not_simple in
383382 let count = ref 0 (* Used for controlling size *)
384383 and make_key = Ident.make_key_generator () in
385384 (* make_key is used for normalizing let-bound variables *)
-2
lambda/switch.ml
···2222 act_store : 'ctx -> 'a -> int ;
2323 act_store_shared : 'ctx -> 'a -> int ; }
24242525-exception Not_simple
2626-2725module type Stored = sig
2826 type t
2927 type key
-2
lambda/switch.mli
···3737 act_store : 'ctx -> 'a -> int ;
3838 act_store_shared : 'ctx -> 'a -> int ; }
39394040-exception Not_simple
4141-4240module type Stored = sig
4341 type t
4442 type key
+19-2
lambda/translcore.ml
···10861086 let x, y, z = List.fold_left rewrite_case ([], [], []) pat_expr_list in
10871087 List.rev x, List.rev y, List.rev z
10881088 in
10891089- let static_catch body val_ids handler =
10891089+ (* In presence of exception patterns, the code we generate for
10901090+10911091+ match <scrutinees> with
10921092+ | <val-patterns> -> <val-actions>
10931093+ | <exn-patterns> -> <exn-actions>
10941094+10951095+ looks like
10961096+10971097+ staticcatch
10981098+ (try (exit <val-exit> <scrutinees>)
10991099+ with <exn-patterns> -> <exn-actions>)
11001100+ with <val-exit> <val-ids> ->
11011101+ match <val-ids> with <val-patterns> -> <val-actions>
11021102+11031103+ In particular, the 'exit' in the value case ensures that the
11041104+ value actions run outside the try..with exception handler.
11051105+ *)
11061106+ let static_catch scrutinees val_ids handler =
10901107 let id = Typecore.name_pattern "exn" (List.map fst exn_cases) in
10911108 let static_exception_id = next_raise_count () in
10921109 Lstaticcatch
10931093- (Ltrywith (Lstaticraise (static_exception_id, body), id,
11101110+ (Ltrywith (Lstaticraise (static_exception_id, scrutinees), id,
10941111 Matching.for_trywith ~scopes e.exp_loc (Lvar id) exn_cases),
10951112 (static_exception_id, val_ids),
10961113 handler)
···11\documentclass[11pt]{book}
22-\usepackage{ae}
22+\usepackage{lmodern}% for T1 encoding and support of bold ttfamily
3344\usepackage[utf8]{inputenc}
55\usepackage[T1]{fontenc}
66+\usepackage{microtype}
67% HEVEA\@def@charset{UTF-8}%
78% Unicode character declarations
89\DeclareUnicodeCharacter{207A}{{}^{+}}
···2021% Package for code examples:
2122\usepackage{listings}
2223\usepackage{alltt}
2323-\usepackage{lmodern}% for supporting bold ttfamily in code examples
2424\usepackage[normalem]{ulem}% for underlining errors in code examples
2525\input{ifocamldoc}
2626\ifocamldoc\else
2727\usepackage{changepage}
2828\fi
2929\input{macros.tex}
3030+3131+% No ligatures in typewriter font
3232+\DisableLigatures{encoding = T1, family = tt* }
3333+3034% Listing environments
3135\lstnewenvironment{camloutput}{
3236 \lstset{
+19
stdlib/random.ml
···176176177177 let bool s = (bits s land 1 = 0)
178178179179+ let bits32 s =
180180+ let b1 = Int32.(shift_right_logical (of_int (bits s)) 14) in (* 16 bits *)
181181+ let b2 = Int32.(shift_right_logical (of_int (bits s)) 14) in (* 16 bits *)
182182+ Int32.(logor b1 (shift_left b2 16))
183183+184184+ let bits64 s =
185185+ let b1 = Int64.(shift_right_logical (of_int (bits s)) 9) in (* 21 bits *)
186186+ let b2 = Int64.(shift_right_logical (of_int (bits s)) 9) in (* 21 bits *)
187187+ let b3 = Int64.(shift_right_logical (of_int (bits s)) 8) in (* 22 bits *)
188188+ Int64.(logor b1 (logor (shift_left b2 21) (shift_left b3 42)))
189189+190190+ let nativebits =
191191+ if Nativeint.size = 32
192192+ then fun s -> Nativeint.of_int32 (bits32 s)
193193+ else fun s -> Int64.to_nativeint (bits64 s)
194194+179195end
180196181197(* This is the state you get with [init 27182818] and then applying
···206222let int64 bound = State.int64 (Domain.DLS.get random_key) bound
207223let float scale = State.float (Domain.DLS.get random_key) scale
208224let bool () = State.bool (Domain.DLS.get random_key)
225225+let bits32 () = State.bits32 (Domain.DLS.get random_key)
226226+let bits64 () = State.bits64 (Domain.DLS.get random_key)
227227+let nativebits () = State.nativebits (Domain.DLS.get random_key)
209228210229let full_init seed = State.full_init (Domain.DLS.get random_key) seed
211230let init seed = State.full_init (Domain.DLS.get random_key) [| seed |]
+18
stdlib/random.mli
···8282val bool : unit -> bool
8383(** [Random.bool ()] returns [true] or [false] with probability 0.5 each. *)
84848585+val bits32 : unit -> Int32.t
8686+(** [Random.bits32 ()] returns 32 random bits as an integer between
8787+ {!Int32.min_int} and {!Int32.max_int}.
8888+ @since 4.14.0 *)
8989+9090+val bits64 : unit -> Int64.t
9191+(** [Random.bits64 ()] returns 64 random bits as an integer between
9292+ {!Int64.min_int} and {!Int64.max_int}.
9393+ @since 4.14.0 *)
9494+9595+val nativebits : unit -> Nativeint.t
9696+(** [Random.nativebits ()] returns 32 or 64 random bits (depending on
9797+ the bit width of the platform) as an integer between
9898+ {!Nativeint.min_int} and {!Nativeint.max_int}.
9999+ @since 4.14.0 *)
8510086101(** {1 Advanced functions} *)
87102···114129 val int64 : t -> Int64.t -> Int64.t
115130 val float : t -> float -> float
116131 val bool : t -> bool
132132+ val bits32 : t -> Int32.t
133133+ val bits64 : t -> Int64.t
134134+ val nativebits : t -> Nativeint.t
117135 (** These functions are the same as the basic functions, except that they
118136 use (and update) the given PRNG state instead of the default one.
119137 *)
···11+(* TEST
22+*)
33+44+let debug = false
55+66+open Printf
77+open Ephemeron
88+99+let empty = ref 0
1010+let make_ra ~size = Array.init size (fun _ -> ref 1) [@@inline never]
1111+let make_ephes ~size = Array.init size (fun _ -> Ephemeron.K1.create ()) [@@inline never]
1212+1313+let test ~size ~slice =
1414+ let keys1 = make_ra ~size in
1515+ let keys2 = make_ra ~size in
1616+ let datas1 = make_ra ~size in
1717+ let datas2 = make_ra ~size in
1818+ let ephe1 = make_ephes ~size in
1919+ let ephe2 = make_ephes ~size in
2020+ if debug then Gc.set { (Gc.get ()) with Gc.verbose = 0x3 };
2121+ (** Fill ephe.(i )from key.(i) to data.(i) *)
2222+ for i=0 to size-1 do Ephemeron.K1.set_key ephe1.(i) keys1.(i); done;
2323+ for i=0 to size-1 do Ephemeron.K1.set_data ephe1.(i) datas1.(i); done;
2424+ for i=0 to size-1 do Ephemeron.K1.set_key ephe2.(i) keys2.(i); done;
2525+ for i=0 to size-1 do Ephemeron.K1.set_data ephe2.(i) datas2.(i); done;
2626+ (** Push everything in the major heap *)
2727+ if debug then Printf.eprintf "Start minor major\n%!";
2828+ Gc.minor ();
2929+ Gc.major ();
3030+ if debug then Printf.eprintf "start emptying\n%!";
3131+ for i=0 to size-1 do keys1.(i) <- empty; done;
3232+ for i=0 to size-1 do datas1.(i) <- empty; done;
3333+ (** The emptying is done during a major so keys and data are kept alive by the
3434+ assignments. Restart a new major *)
3535+ Gc.major ();
3636+ if debug then Printf.eprintf "Start checking state\n%!";
3737+ (** Fill the ephemeron with an alive key *)
3838+ if debug then Printf.eprintf "Start replacing dead key into alive one\n%!";
3939+ (* Printf.eprintf "put in set (2) %i\n%!" (Gc.major_slice (10*4*slice*6)); *)
4040+ for i=0 to size-1 do
4141+ ignore (Gc.major_slice (4));
4242+ if debug then Printf.eprintf "@%!";
4343+ Ephemeron.K1.blit_data ephe1.(i) ephe2.(i);
4444+ if debug && 0 = i mod (size / 10) then Printf.eprintf "done %5i/%i\n%!" i size;
4545+ done;
4646+ if debug then Printf.eprintf "end\n%!";
4747+ (** Finish all, assertion in clean phase should not find a dangling data *)
4848+ Gc.full_major ();
4949+ let r = ref 0 in
5050+ if debug then
5151+ for i=0 to size-1 do
5252+ if Ephemeron.K1.check_data ephe2.(size-1-i) then incr r;
5353+ if 0 = i mod (size / 10) then Printf.eprintf "done %5i/%i %i\n%!" i size !r;
5454+ done;
5555+ (* keep the arrays alive *)
5656+ assert (Array.length keys1 = size);
5757+ assert (Array.length keys2 = size);
5858+ assert (Array.length datas1 = size);
5959+ assert (Array.length datas2 = size);
6060+ assert (Array.length ephe1 = size);
6161+ assert (Array.length ephe2 = size)
6262+[@@inline never]
6363+6464+let () =
6565+ test ~size:1000 ~slice:5;
6666+ test ~size:1000 ~slice:10;
6767+ test ~size:1000 ~slice:15
+1-32
toplevel/byte/topeval.ml
···176176 toplevel_env := oldenv; raise x
177177 end
178178 | Ptop_dir {pdir_name = {Location.txt = dir_name}; pdir_arg } ->
179179- begin match Topcommon.get_directive dir_name with
180180- | None ->
181181- fprintf ppf "Unknown directive `%s'." dir_name;
182182- let directives = Topcommon.all_directive_names () in
183183- Misc.did_you_mean ppf
184184- (fun () -> Misc.spellcheck directives dir_name);
185185- fprintf ppf "@.";
186186- false
187187- | Some d ->
188188- match d, pdir_arg with
189189- | Directive_none f, None -> f (); true
190190- | Directive_string f, Some {pdira_desc = Pdir_string s} -> f s; true
191191- | Directive_int f, Some {pdira_desc = Pdir_int (n,None) } ->
192192- begin match Int_literal_converter.int n with
193193- | n -> f n; true
194194- | exception _ ->
195195- fprintf ppf "Integer literal exceeds the range of \
196196- representable integers for directive `%s'.@."
197197- dir_name;
198198- false
199199- end
200200- | Directive_int _, Some {pdira_desc = Pdir_int (_, Some _)} ->
201201- fprintf ppf "Wrong integer literal for directive `%s'.@."
202202- dir_name;
203203- false
204204- | Directive_ident f, Some {pdira_desc = Pdir_ident lid} -> f lid; true
205205- | Directive_bool f, Some {pdira_desc = Pdir_bool b} -> f b; true
206206- | _ ->
207207- fprintf ppf "Wrong type of argument for directive `%s'.@."
208208- dir_name;
209209- false
210210- end
179179+ try_run_directive ppf dir_name pdir_arg
211180212181let execute_phrase print_outcome ppf phr =
213182 try execute_phrase print_outcome ppf phr
+1-28
toplevel/native/topeval.ml
···279279 toplevel_env := oldenv; raise x
280280 end
281281 | Ptop_dir {pdir_name = {Location.txt = dir_name}; pdir_arg } ->
282282- begin match get_directive dir_name with
283283- | None ->
284284- fprintf ppf "Unknown directive `%s'.@." dir_name;
285285- false
286286- | Some d ->
287287- match d, pdir_arg with
288288- | Directive_none f, None -> f (); true
289289- | Directive_string f, Some {pdira_desc = Pdir_string s} -> f s; true
290290- | Directive_int f, Some {pdira_desc = Pdir_int (n,None)} ->
291291- begin match Int_literal_converter.int n with
292292- | n -> f n; true
293293- | exception _ ->
294294- fprintf ppf "Integer literal exceeds the range of \
295295- representable integers for directive `%s'.@."
296296- dir_name;
297297- false
298298- end
299299- | Directive_int _, Some {pdira_desc = Pdir_int (_, Some _)} ->
300300- fprintf ppf "Wrong integer literal for directive `%s'.@."
301301- dir_name;
302302- false
303303- | Directive_ident f, Some {pdira_desc = Pdir_ident lid} -> f lid; true
304304- | Directive_bool f, Some {pdira_desc = Pdir_bool b} -> f b; true
305305- | _ ->
306306- fprintf ppf "Wrong type of argument for directive `%s'.@."
307307- dir_name;
308308- false
309309- end
282282+ try_run_directive ppf dir_name pdir_arg
310283311284312285(* API compat *)
+48
toplevel/topcommon.ml
···308308309309let all_directive_names () =
310310 Hashtbl.fold (fun dir _ acc -> dir::acc) directive_table []
311311+312312+let try_run_directive ppf dir_name pdir_arg =
313313+ begin match get_directive dir_name with
314314+ | None ->
315315+ fprintf ppf "Unknown directive `%s'." dir_name;
316316+ let directives = all_directive_names () in
317317+ Misc.did_you_mean ppf
318318+ (fun () -> Misc.spellcheck directives dir_name);
319319+ fprintf ppf "@.";
320320+ false
321321+ | Some d ->
322322+ match d, pdir_arg with
323323+ | Directive_none f, None -> f (); true
324324+ | Directive_string f, Some {pdira_desc = Pdir_string s} -> f s; true
325325+ | Directive_int f, Some {pdira_desc = Pdir_int (n,None) } ->
326326+ begin match Misc.Int_literal_converter.int n with
327327+ | n -> f n; true
328328+ | exception _ ->
329329+ fprintf ppf "Integer literal exceeds the range of \
330330+ representable integers for directive `%s'.@."
331331+ dir_name;
332332+ false
333333+ end
334334+ | Directive_int _, Some {pdira_desc = Pdir_int (_, Some _)} ->
335335+ fprintf ppf "Wrong integer literal for directive `%s'.@."
336336+ dir_name;
337337+ false
338338+ | Directive_ident f, Some {pdira_desc = Pdir_ident lid} -> f lid; true
339339+ | Directive_bool f, Some {pdira_desc = Pdir_bool b} -> f b; true
340340+ | _ ->
341341+ let dir_type = match d with
342342+ | Directive_none _ -> "no argument"
343343+ | Directive_string _ -> "a `string' literal"
344344+ | Directive_int _ -> "an `int' literal"
345345+ | Directive_ident _ -> "an identifier"
346346+ | Directive_bool _ -> "a `bool' literal"
347347+ in
348348+ let arg_type = match pdir_arg with
349349+ | None -> "no argument"
350350+ | Some {pdira_desc = Pdir_string _} -> "a `string' literal"
351351+ | Some {pdira_desc = Pdir_int _} -> "an `int' literal"
352352+ | Some {pdira_desc = Pdir_ident _} -> "an identifier"
353353+ | Some {pdira_desc = Pdir_bool _} -> "a `bool' literal"
354354+ in
355355+ fprintf ppf "Directive `%s' expects %s, got %s.@."
356356+ dir_name dir_type arg_type;
357357+ false
358358+ end
+3
toplevel/topcommon.mli
···143143144144val all_directive_names : unit -> string list
145145146146+val try_run_directive :
147147+ formatter -> string -> Parsetree.directive_argument option -> bool
148148+146149val[@deprecated] directive_table : (string, directive_fun) Hashtbl.t
147150 (* @deprecated please use [add_directive] instead of inserting
148151 in this table directly. *)