Skip to content

Commit c76eace

Browse files
committed
v0.13-preview.120.27+112
1 parent 6bf0991 commit c76eace

23 files changed

+178
-61
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
_build
22
*.install
33
*.merlin
4+
_opam
45

hash_types/README.org

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#+TITLE: Base_internalhash_types
2+
3+
This micro-library allows hash states, seeds, and values to be type-equal
4+
between ~Base~ and ~Base_boot~.
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(** [state] is defined as a subtype of [int] using the [private] keyword. This makes it an
2+
opaque type for most purposes, and tells the compiler that the type is immediate. *)
3+
type state = private int
4+
type seed = int
5+
type hash_value = int
6+
7+
external create_seeded : seed -> state = "%identity" [@@noalloc]
8+
external fold_int64 : state -> int64 -> state = "Base_internalhash_fold_int64" [@@noalloc]
9+
external fold_int : state -> int -> state = "Base_internalhash_fold_int" [@@noalloc]
10+
external fold_float : state -> float -> state = "Base_internalhash_fold_float" [@@noalloc]
11+
external fold_string : state -> string -> state = "Base_internalhash_fold_string" [@@noalloc]
12+
external get_hash_value : state -> hash_value = "Base_internalhash_get_hash_value" [@@noalloc]

hash_types/src/dune

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(library (name base_internalhash_types)
2+
(public_name base.base_internalhash_types) (libraries)
3+
(preprocess no_preprocessing) (js_of_ocaml (javascript_files runtime.js))
4+
(c_names internalhash_stubs) (install_c_headers internalhash))
File renamed without changes.
File renamed without changes.

hash_types/src/runtime.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//Provides: Base_internalhash_fold_int64
2+
//Requires: caml_hash_mix_int64
3+
var Base_internalhash_fold_int64 = caml_hash_mix_int64;
4+
//Provides: Base_internalhash_fold_int
5+
//Requires: caml_hash_mix_int
6+
var Base_internalhash_fold_int = caml_hash_mix_int;
7+
//Provides: Base_internalhash_fold_float
8+
//Requires: caml_hash_mix_float
9+
var Base_internalhash_fold_float = caml_hash_mix_float;
10+
//Provides: Base_internalhash_fold_string
11+
//Requires: caml_hash_mix_string
12+
var Base_internalhash_fold_string = caml_hash_mix_string;
13+
//Provides: Base_internalhash_get_hash_value
14+
//Requires: caml_hash_mix_final
15+
function Base_internalhash_get_hash_value(seed) {
16+
var h = caml_hash_mix_final(seed);
17+
return h & 0x3FFFFFFF;
18+
}

hash_types/test/dune

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(library (name base_internalhash_types_test)
2+
(libraries base base_boot expect_test_helpers_kernel
3+
replace_caml_modify_for_testing stdio)
4+
(preprocess (pps ppx_jane)))

hash_types/test/import.ml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include Stdio
2+
include Expect_test_helpers_kernel

hash_types/test/test_immediate.ml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
open! Base
2+
open! Import
3+
4+
let%expect_test "[Base.Hash.state] is still immediate" =
5+
require_no_allocation [%here] (fun () ->
6+
ignore (Sys.opaque_identity (Base.Hash.create ())));
7+
[%expect {| |}]
8+
9+
let%expect_test "[Base_boot.Hash.state] is still immediate" =
10+
require_no_allocation [%here] (fun () ->
11+
ignore (Sys.opaque_identity (Base_boot.Hash.create ())));
12+
[%expect {| |}]
13+
14+
type t = { mutable state : Base.Hash.state; mutable list : unit list }
15+
16+
let%expect_test _ =
17+
let count_caml_modify f =
18+
Replace_caml_modify_for_testing.reset ();
19+
f ();
20+
print_s [%sexp (Replace_caml_modify_for_testing.count () : int)];
21+
in
22+
let t = { state = Base.Hash.create ~seed:1 (); list = [] } in
23+
let list = [ (); () ] (* not an immediate type, requires caml_modify *) in
24+
count_caml_modify (fun () -> t.list <- list);
25+
[%expect {| 1 |}];
26+
let state = Base.Hash.create ~seed:2 () (* immediate, I hope *) in
27+
count_caml_modify (fun () -> t.state <- state);
28+
[%expect {| 0 |}];
29+
;;

hash_types/test/test_immediate.mli

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(*_ This signature is deliberately empty. *)

hash_types/test/test_unification.ml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
open! Base
2+
open! Import
3+
4+
let%expect_test "[Base.Hash.state] unifies with [Base_boot.Hash.state]" =
5+
let _f (state : Base.Hash.state) : Base_boot.Hash.state = state in
6+
[%expect {| |}]
7+
;;

hash_types/test/test_unification.mli

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(*_ This signature is deliberately empty. *)

src/bytes.ml

+24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
open! Import
22

3+
module Array = Array0
34
let stage = Staged.stage
45

56
module T = struct
@@ -68,6 +69,29 @@ let to_list t =
6869
in
6970
loop t (length t - 1) []
7071

72+
let to_array t = Array.init (length t) ~f:(fun i -> (unsafe_get t i))
73+
74+
let map t ~f = map t ~f
75+
let mapi t ~f = mapi t ~f
76+
77+
let fold =
78+
let rec loop t ~f ~len ~pos acc =
79+
if Int_replace_polymorphic_compare.equal pos len
80+
then acc
81+
else loop t ~f ~len ~pos:(pos + 1) (f acc (unsafe_get t pos))
82+
in
83+
fun t ~init ~f ->
84+
loop t ~f ~len:(length t) ~pos:0 init
85+
86+
let foldi =
87+
let rec loop t ~f ~len ~pos acc =
88+
if Int_replace_polymorphic_compare.equal pos len
89+
then acc
90+
else loop t ~f ~len ~pos:(pos + 1) (f pos acc (unsafe_get t pos))
91+
in
92+
fun t ~init ~f ->
93+
loop t ~f ~len:(length t) ~pos:0 init
94+
7195
let tr ~target ~replacement s =
7296
for i = 0 to length s - 1 do
7397
if Char.equal (unsafe_get s i) target

src/bytes.mli

+17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ val create : int -> t
4242
with the byte [c]. *)
4343
val make : int -> char -> t
4444

45+
(** [map f t] applies function [f] to every byte, in order, and builds the byte
46+
sequence with the results returned by [f]. *)
47+
val map : t -> f : (char -> char) -> t
48+
49+
(** Like [map], but passes each character's index to [f] along with the char. *)
50+
val mapi : t -> f : (int -> char -> char) -> t
51+
4552
(** [copy t] returns a newly-allocated byte sequence that contains the same
4653
bytes as [t]. *)
4754
val copy : t -> t
@@ -89,6 +96,16 @@ val tr_multi : target:string -> replacement:string -> (t -> unit) Staged.t
8996
(** [to_list t] returns the bytes in [t] as a list of chars. *)
9097
val to_list : t -> char list
9198

99+
(** [to_array t] returns the bytes in [t] as an array of chars. *)
100+
val to_array : t -> char array
101+
102+
(** [fold a ~f ~init:b] is [f a1 (f a2 (...))] *)
103+
val fold : t -> init : 'a -> f : ('a -> char -> 'a) -> 'a
104+
105+
(** [foldi] works similarly to [fold], but also passes the index of each character to
106+
[f]. *)
107+
val foldi : t -> init : 'a -> f : (int -> 'a -> char -> 'a) -> 'a
108+
92109
(** [contains ?pos ?len t c] returns [true] iff [c] appears in [t] between [pos]
93110
and [pos + len]. *)
94111
val contains : ?pos:int -> ?len:int -> t -> char -> bool

src/bytes0.ml

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ let copy = Caml.Bytes.copy
4545
let create = Caml.Bytes.create
4646
let fill = Caml.Bytes.fill
4747
let make = Caml.Bytes.make
48+
let map = Caml.Bytes.map
49+
let mapi = Caml.Bytes.mapi
4850
let sub = Caml.Bytes.sub
4951
let unsafe_blit = Caml.Bytes.unsafe_blit
5052

src/dune

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
(action (run %{first_dep} -atomic -o %{targets})) (mode fallback))
1616

1717
(library (name base) (public_name base)
18-
(libraries caml sexplib0 shadow_stdlib) (install_c_headers internalhash)
18+
(libraries base_internalhash_types caml sexplib0 shadow_stdlib)
1919
(c_flags :standard -D_LARGEFILE64_SOURCE (:include mpopcnt.sexp))
20-
(c_names exn_stubs int_math_stubs internalhash_stubs hash_stubs am_testing)
20+
(c_names exn_stubs int_math_stubs hash_stubs am_testing)
2121
(preprocess no_preprocessing)
2222
(lint
2323
(pps ppx_base ppx_base_lint -check-doc-comments -type-conv-keep-w32=impl

src/hash.ml

+9-15
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,12 @@ end
138138

139139
module Internalhash : sig
140140
include Hash_intf.S
141-
with type state = private int (* allow optimizations for immediate type *)
142-
and type seed = int
143-
and type hash_value = int
141+
with type state = Base_internalhash_types.state
142+
(* We give a concrete type for [state], albeit only partially exposed (see
143+
Base_internalhash_types), so that it unifies with the same type in [Base_boot],
144+
and to allow optimizations for the immediate type. *)
145+
and type seed = Base_internalhash_types.seed
146+
and type hash_value = Base_internalhash_types.hash_value
144147

145148
external fold_int64 : state -> int64 -> state = "Base_internalhash_fold_int64" [@@noalloc]
146149
external fold_int : state -> int -> state = "Base_internalhash_fold_int" [@@noalloc]
@@ -150,24 +153,15 @@ module Internalhash : sig
150153
end = struct
151154
let description = "internalhash"
152155

153-
type state = int
154-
type hash_value = int
155-
type seed = int
156-
157-
external create_seeded : seed -> state = "%identity" [@@noalloc]
158-
external fold_int64 : state -> int64 -> state = "Base_internalhash_fold_int64" [@@noalloc]
159-
external fold_int : state -> int -> state = "Base_internalhash_fold_int" [@@noalloc]
160-
external fold_float : state -> float -> state = "Base_internalhash_fold_float" [@@noalloc]
161-
external fold_string : state -> string -> state = "Base_internalhash_fold_string" [@@noalloc]
162-
external get_hash_value : state -> hash_value = "Base_internalhash_get_hash_value" [@@noalloc]
156+
include Base_internalhash_types
163157

164158
let alloc () = create_seeded 0
165159

166160
let reset ?(seed=0) _t = create_seeded seed
167161

168162
module For_tests = struct
169-
let compare_state = compare
170-
let state_to_string = Int.to_string
163+
let compare_state (a : state) (b : state) = compare (a :> int) (b :> int)
164+
let state_to_string (state : state) = Int.to_string (state :> int)
171165
end
172166
end
173167

src/hash_intf.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ module type Hash = sig
189189
tables and other structures. *)
190190

191191
include Full
192-
with type state = private int
193-
and type seed = int
192+
with type state = Base_internalhash_types.state
193+
and type seed = Base_internalhash_types.seed
194194

195-
and type hash_value = int (** @open *)
195+
and type hash_value = Base_internalhash_types.hash_value (** @open *)
196196
end

src/obj_array.mli

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
(** This module is deprecated for external use. Users should replace occurrences of
2-
[Obj_array.t] in their code with [Obj.t Uniform_array.t].
3-
4-
This module is here for the implementing [Uniform_array] internally, and exposed
5-
through [Not_exposed_properly] to ease the transition for users.
6-
*)
1+
(** This module is not exposed for external use, and is only here for the implementation
2+
of [Uniform_array] internally. [Obj.t Uniform_array.t] should be used in place of
3+
[Obj_array.t]. *)
74

85
open! Import
96

@@ -69,4 +66,3 @@ val unsafe_clear_if_pointer : t -> int -> unit
6966
(** [truncate t ~len] shortens [t]'s length to [len]. It is an error if [len <= 0] or
7067
[len > length t].*)
7168
val truncate : t -> len:int -> unit
72-

src/option.ml

+31-14
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,36 @@
11
open! Import
22

3-
type 'a t = 'a option [@@deriving_inline sexp, compare, hash]
4-
let t_of_sexp :
5-
'a . (Ppx_sexp_conv_lib.Sexp.t -> 'a) -> Ppx_sexp_conv_lib.Sexp.t -> 'a t =
6-
option_of_sexp
7-
let sexp_of_t :
8-
'a . ('a -> Ppx_sexp_conv_lib.Sexp.t) -> 'a t -> Ppx_sexp_conv_lib.Sexp.t =
9-
sexp_of_option
10-
let compare : 'a . ('a -> 'a -> int) -> 'a t -> 'a t -> int = compare_option
11-
let hash_fold_t :
12-
'a .
13-
(Ppx_hash_lib.Std.Hash.state -> 'a -> Ppx_hash_lib.Std.Hash.state) ->
14-
Ppx_hash_lib.Std.Hash.state -> 'a t -> Ppx_hash_lib.Std.Hash.state
15-
= hash_fold_option
16-
[@@@end]
3+
type 'a t = 'a option =
4+
| None
5+
| Some of 'a
6+
7+
include
8+
(struct type 'a t = 'a option [@@deriving_inline compare, hash, sexp]
9+
let compare : 'a . ('a -> 'a -> int) -> 'a t -> 'a t -> int = compare_option
10+
let hash_fold_t :
11+
'a .
12+
(Ppx_hash_lib.Std.Hash.state -> 'a -> Ppx_hash_lib.Std.Hash.state) ->
13+
Ppx_hash_lib.Std.Hash.state -> 'a t -> Ppx_hash_lib.Std.Hash.state
14+
= hash_fold_option
15+
let t_of_sexp :
16+
'a . (Ppx_sexp_conv_lib.Sexp.t -> 'a) -> Ppx_sexp_conv_lib.Sexp.t -> 'a t =
17+
option_of_sexp
18+
let sexp_of_t :
19+
'a . ('a -> Ppx_sexp_conv_lib.Sexp.t) -> 'a t -> Ppx_sexp_conv_lib.Sexp.t =
20+
sexp_of_option
21+
[@@@end] end
22+
: sig type 'a t = 'a option [@@deriving_inline compare, hash, sexp]
23+
include
24+
sig
25+
[@@@ocaml.warning "-32"]
26+
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
27+
val hash_fold_t :
28+
(Ppx_hash_lib.Std.Hash.state -> 'a -> Ppx_hash_lib.Std.Hash.state) ->
29+
Ppx_hash_lib.Std.Hash.state -> 'a t -> Ppx_hash_lib.Std.Hash.state
30+
include Ppx_sexp_conv_lib.Sexpable.S1 with type 'a t := 'a t
31+
end[@@ocaml.doc "@inline"]
32+
[@@@end] end
33+
with type 'a t := 'a t)
1734

1835
let is_none = function None -> true | _ -> false
1936

src/option.mli

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
open! Import
44

5-
type 'a t = 'a option [@@deriving_inline compare, hash, sexp]
5+
type 'a t = 'a option =
6+
| None
7+
| Some of 'a
8+
[@@deriving_inline compare, hash, sexp]
69
include
710
sig
811
[@@@ocaml.warning "-32"]

src/runtime.js

-19
Original file line numberDiff line numberDiff line change
@@ -81,25 +81,6 @@ function Base_int_math_int64_pow_stub(base, exponent) {
8181
return res;
8282
}
8383

84-
//Provides: Base_internalhash_fold_int64
85-
//Requires: caml_hash_mix_int64
86-
var Base_internalhash_fold_int64 = caml_hash_mix_int64;
87-
//Provides: Base_internalhash_fold_int
88-
//Requires: caml_hash_mix_int
89-
var Base_internalhash_fold_int = caml_hash_mix_int;
90-
//Provides: Base_internalhash_fold_float
91-
//Requires: caml_hash_mix_float
92-
var Base_internalhash_fold_float = caml_hash_mix_float;
93-
//Provides: Base_internalhash_fold_string
94-
//Requires: caml_hash_mix_string
95-
var Base_internalhash_fold_string = caml_hash_mix_string;
96-
//Provides: Base_internalhash_get_hash_value
97-
//Requires: caml_hash_mix_final
98-
function Base_internalhash_get_hash_value(seed) {
99-
var h = caml_hash_mix_final(seed);
100-
return h & 0x3FFFFFFF;
101-
}
102-
10384
//Provides: Base_hash_string mutable
10485
//Requires: caml_hash
10586
function Base_hash_string(s) {

0 commit comments

Comments
 (0)