Skip to content

Commit f0e7b37

Browse files
committed
wip: add hashset
1 parent 398aaf5 commit f0e7b37

30 files changed

+2450
-142
lines changed

jscomp/others/.depend

+10
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,16 @@ bs_internalMutableAVLSet.cmj : bs_internalAVLset.cmj
2323
bs_Hash.cmj : bs_Hash.cmi
2424
bs_Queue.cmj : bs_Array.cmj bs_Queue.cmi
2525
bs_internalBucketsType.cmj : bs_Array.cmj
26+
bs_internalSetBuckets.cmj : bs_internalBucketsType.cmj bs_Array.cmj
2627
bs_internalBuckets.cmj : bs_internalBucketsType.cmj bs_Array.cmj
2728
bs_HashMap.cmj : bs_internalBucketsType.cmj bs_internalBuckets.cmj \
2829
bs_Hash.cmj bs_Bag.cmj bs_Array.cmj bs_HashMap.cmi
30+
bs_HashSet.cmj : bs_internalSetBuckets.cmj bs_internalBucketsType.cmj \
31+
bs_Hash.cmj bs_Bag.cmj bs_Array.cmj bs_HashSet.cmi
32+
bs_HashSetString.cmj : bs_internalSetBuckets.cmj bs_internalBucketsType.cmj \
33+
bs_Array.cmj bs_HashSetString.cmi
34+
bs_HashSetInt.cmj : bs_internalSetBuckets.cmj bs_internalBucketsType.cmj \
35+
bs_Array.cmj bs_HashSetInt.cmi
2936
bs_Bag.cmj :
3037
bs_Cmp.cmj : bs_Cmp.cmi
3138
bs_Map.cmj : bs_internalAVLtree.cmj bs_Cmp.cmj bs_Bag.cmj bs_Array.cmj \
@@ -62,6 +69,9 @@ bs_Array.cmi :
6269
bs_Hash.cmi :
6370
bs_Queue.cmi :
6471
bs_HashMap.cmi : bs_Hash.cmi bs_Bag.cmj
72+
bs_HashSet.cmi : bs_Hash.cmi bs_Bag.cmj
73+
bs_HashSetString.cmi :
74+
bs_HashSetInt.cmi :
6575
bs_Cmp.cmi :
6676
bs_Map.cmi : bs_Cmp.cmi bs_Bag.cmj
6777
bs_Set.cmi : bs_Cmp.cmi bs_Bag.cmj

jscomp/others/Makefile

+12
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ SOURCE_LIST= node_path node_fs node_process dict node_module js_array js_string
1818
bs_Hash\
1919
bs_Queue\
2020
bs_internalBucketsType\
21+
bs_internalSetBuckets\
2122
bs_internalBuckets\
2223
bs_HashMap\
24+
bs_HashSet\
25+
bs_HashSetString\
26+
bs_HashSetInt\
2327
bs_Bag\
2428
bs_Cmp\
2529
bs_Map\
@@ -61,6 +65,14 @@ clean::
6165
rm -f *.rawlambda *.lam *.lambda *.map
6266

6367
ifndef BS_RELEASE_BUILD
68+
bs_HashSetString.ml: hashset.cppo.ml
69+
cppo -D TYPE_STRING $^ > $@
70+
bs_HashSetInt.ml: hashset.cppo.ml
71+
cppo -D TYPE_INT $^ > $@
72+
bs_HashSetString.mli: hashset.cppo.mli
73+
cppo -D TYPE_STRING $^ > $@
74+
bs_HashSetInt.mli: hashset.cppo.mli
75+
cppo -D TYPE_INT $^ > $@
6476
bs_HashMapString.ml: hashmap.cppo.ml
6577
cppo -D TYPE_STRING $^ > $@
6678
bs_HashMapInt.ml: hashmap.cppo.ml

jscomp/others/bs.ml

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ module Hash = Bs_Hash
3232
module Array = Bs_Array
3333
module Queue = Bs_Queue
3434
module HashMap = Bs_HashMap
35+
module HashSet = Bs_HashSet
36+
module HashSetInt = Bs_HashSetInt
37+
module HashSetString = Bs_HashSetInt
3538
module HashMapString = Bs_HashMapString
3639
module HashMapInt = Bs_HashMapInt
3740
module Map = Bs_Map

jscomp/others/bs_HashMap.ml

+10-7
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,22 @@ let replace0 ~hash ~eq h key info =
188188
(* TODO: duplicate bucklets ? *)
189189
end
190190

191-
let rec mem_in_bucket ~eq key buckets =
192-
match C.toOpt buckets with
193-
| None ->
194-
false
195-
| Some cell ->
191+
let rec mem_in_bucket ~eq key cell =
196192
(Bs_Hash.getEq eq)
197193
(N.key cell) key [@bs] ||
198-
mem_in_bucket ~eq key (N.next cell)
194+
(match C.toOpt (N.next cell) with
195+
| None -> false
196+
| Some nextCell ->
197+
mem_in_bucket ~eq key nextCell)
199198

200199
let mem0 ~hash ~eq h key =
201200
let h_buckets = C.buckets h in
202201
let nid = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
203-
mem_in_bucket ~eq key (Bs_Array.unsafe_get h_buckets nid)
202+
let bucket = (Bs_Array.unsafe_get h_buckets nid) in
203+
match C.toOpt bucket with
204+
| None -> false
205+
| Some bucket ->
206+
mem_in_bucket ~eq key bucket
204207

205208

206209
let create0 = C.create0

jscomp/others/bs_HashSet.ml

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
(* Copyright (C) 2017 Authors of BuckleScript
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU Lesser General Public License as published by
5+
* the Free Software Foundation, either version 3 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* In addition to the permissions granted to you by the LGPL, you may combine
9+
* or link a "work that uses the Library" with a publicly distributed version
10+
* of this file to produce a combined library or application, then distribute
11+
* that combined work under the terms of your choosing, with no requirement
12+
* to comply with the obligations normally placed on you by section 4 of the
13+
* LGPL version 3 (or the corresponding section of a later version of the LGPL
14+
* should you choose to use a later version).
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License
22+
* along with this program; if not, write to the Free Software
23+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
24+
25+
26+
module N = Bs_internalSetBuckets
27+
module C = Bs_internalBucketsType
28+
module B = Bs_Bag
29+
type ('a,'id) t0 = 'a N.t0
30+
31+
32+
type 'a bucket = 'a N.bucket
33+
34+
type ('a,'id) t =
35+
(('a, 'id) Bs_Hash.t,
36+
('a,'id) t0) B.bag
37+
38+
39+
40+
let rec insert_bucket ~hash ~h_buckets ~ndata_tail h old_bucket =
41+
match C.toOpt old_bucket with
42+
| None -> ()
43+
| Some cell ->
44+
let nidx = (Bs_Hash.getHash hash) (N.key cell) [@bs] land (Array.length h_buckets - 1) in
45+
let v = C.return cell in
46+
begin match C.toOpt (Bs_Array.unsafe_get ndata_tail nidx) with
47+
| None ->
48+
Bs_Array.unsafe_set h_buckets nidx v
49+
| Some tail ->
50+
N.nextSet tail v (* cell put at the end *)
51+
end;
52+
Bs_Array.unsafe_set ndata_tail nidx v;
53+
insert_bucket ~hash ~h_buckets ~ndata_tail h (N.next cell)
54+
55+
56+
let resize ~hash h =
57+
let odata = C.buckets h in
58+
let osize = Array.length odata in
59+
let nsize = osize * 2 in
60+
if nsize >= osize then begin (* no overflow *)
61+
let h_buckets = C.makeSize nsize in
62+
let ndata_tail = C.makeSize nsize in (* keep track of tail *)
63+
C.bucketsSet h h_buckets; (* so that indexfun sees the new bucket count *)
64+
for i = 0 to osize - 1 do
65+
insert_bucket ~hash ~h_buckets ~ndata_tail h (Bs_Array.unsafe_get odata i)
66+
done;
67+
for i = 0 to nsize - 1 do
68+
match C.toOpt (Bs_Array.unsafe_get ndata_tail i) with
69+
| None -> ()
70+
| Some tail -> N.nextSet tail C.emptyOpt
71+
done
72+
end
73+
74+
75+
76+
let rec remove_bucket ~eq h h_buckets i key prec cell =
77+
let cell_next = N.next cell in
78+
if (Bs_Hash.getEq eq) (N.key cell) key [@bs]
79+
then
80+
begin
81+
N.nextSet prec cell_next;
82+
C.sizeSet h (C.size h - 1);
83+
end
84+
else
85+
match C.toOpt cell_next with
86+
| None ->
87+
()
88+
| Some cell_next ->
89+
remove_bucket ~eq h h_buckets i key cell cell_next
90+
91+
let remove0 ~hash ~eq h key =
92+
let h_buckets = C.buckets h in
93+
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
94+
let l = (Bs_Array.unsafe_get h_buckets i) in
95+
match C.toOpt l with
96+
| None -> ()
97+
| Some cell ->
98+
let next_cell = (N.next cell) in
99+
if (Bs_Hash.getEq eq) (N.key cell) key [@bs] then
100+
begin
101+
C.sizeSet h (C.size h - 1) ;
102+
Bs_Array.unsafe_set h_buckets i next_cell
103+
end
104+
else
105+
match C.toOpt next_cell with
106+
| None -> ()
107+
| Some next_cell ->
108+
remove_bucket ~eq h h_buckets i key cell next_cell
109+
110+
111+
112+
113+
let rec addBucket ~eq h key cell =
114+
if (Bs_Hash.getEq eq) (N.key cell) key [@bs]
115+
then
116+
N.keySet cell key
117+
else
118+
let n = N.next cell in
119+
match C.toOpt n with
120+
| None ->
121+
C.sizeSet h (C.size h + 1);
122+
N.nextSet cell (C.return @@ N.bucket ~key ~next:n)
123+
| Some n -> addBucket ~eq h key n
124+
125+
let add0
126+
~hash:(hash:(_,'id)Bs_Hash.hash)
127+
~eq:(eq:(_,'id) Bs_Hash.eq) (h : (_,'id) t0) key =
128+
let h_buckets = C.buckets h in
129+
let i = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
130+
let l = Array.unsafe_get h_buckets i in
131+
(match C.toOpt l with
132+
| None ->
133+
C.sizeSet h (C.size h + 1);
134+
Bs_Array.unsafe_set h_buckets i
135+
(C.return @@ N.bucket ~key ~next:C.emptyOpt)
136+
| Some cell ->
137+
addBucket ~eq h key cell);
138+
if C.size h > Array.length (C.buckets h) lsl 1 then resize ~hash h
139+
140+
141+
let rec mem_in_bucket ~eq key cell =
142+
(Bs_Hash.getEq eq)
143+
(N.key cell) key [@bs] ||
144+
(match C.toOpt (N.next cell) with
145+
| None -> false
146+
| Some nextCell ->
147+
mem_in_bucket ~eq key nextCell)
148+
149+
let mem0 ~hash ~eq h key =
150+
let h_buckets = C.buckets h in
151+
let nid = (Bs_Hash.getHash hash) key [@bs] land (Array.length h_buckets - 1) in
152+
let bucket = (Bs_Array.unsafe_get h_buckets nid) in
153+
match C.toOpt bucket with
154+
| None -> false
155+
| Some bucket ->
156+
mem_in_bucket ~eq key bucket
157+
158+
159+
let create0 = C.create0
160+
let clear0 = C.clear0
161+
let reset0 = C.reset0
162+
let length0 = C.length0
163+
let iter0 = N.iter0
164+
let fold0 = N.fold0
165+
let logStats0 = N.logStats0
166+
167+
168+
(* Wrapper *)
169+
let create dict initialize_size =
170+
B.bag ~data:(create0 initialize_size)
171+
~dict
172+
let clear h = clear0 (B.data h)
173+
let reset h = reset0 (B.data h)
174+
let length h = length0 (B.data h)
175+
let iter f h = iter0 f (B.data h)
176+
let fold f h init = fold0 f (B.data h) init
177+
let logStats h = logStats0 (B.data h)
178+
179+
let add (type a) (type id) (h : (a,id) t) (key:a) =
180+
let dict,data = B.(dict h, data h) in
181+
let module M = (val dict) in
182+
add0 ~hash:M.hash ~eq:M.eq data key
183+
184+
let remove (type a) (type id) (h : (a,id) t) (key : a) =
185+
let dict,data = B.(dict h, data h) in
186+
let module M = (val dict) in
187+
remove0 ~hash:M.hash ~eq:M.eq data key
188+
189+
190+
let replace (type a)(type id) (h : (a,id) t) (key : a) =
191+
let dict,data = B.(dict h, data h) in
192+
let module M = (val dict) in
193+
add0 ~hash:M.hash ~eq:M.eq data key
194+
195+
let mem (type a) (type id) (h : (a,id) t) (key : a) =
196+
let dict,data = B.(dict h, data h) in
197+
let module M = (val dict) in
198+
mem0 ~hash:M.hash ~eq:M.eq data key
199+

0 commit comments

Comments
 (0)