1116 lines
24 KiB
JavaScript
1116 lines
24 KiB
JavaScript
|
|
||
|
|
||
|
import * as Caml from "./caml.js";
|
||
|
import * as $$Array from "./array.js";
|
||
|
import * as Curry from "./curry.js";
|
||
|
import * as Random from "./random.js";
|
||
|
import * as Caml_obj from "./caml_obj.js";
|
||
|
import * as Caml_hash from "./caml_hash.js";
|
||
|
import * as Caml_array from "./caml_array.js";
|
||
|
import * as Pervasives from "./pervasives.js";
|
||
|
import * as Caml_option from "./caml_option.js";
|
||
|
import * as CamlinternalLazy from "./camlinternalLazy.js";
|
||
|
|
||
|
function hash(x) {
|
||
|
return Caml_hash.hash(10, 100, 0, x);
|
||
|
}
|
||
|
|
||
|
function hash_param(n1, n2, x) {
|
||
|
return Caml_hash.hash(n1, n2, 0, x);
|
||
|
}
|
||
|
|
||
|
function seeded_hash(seed, x) {
|
||
|
return Caml_hash.hash(10, 100, seed, x);
|
||
|
}
|
||
|
|
||
|
function flip_ongoing_traversal(h) {
|
||
|
h.initial_size = -h.initial_size | 0;
|
||
|
}
|
||
|
|
||
|
var randomized = {
|
||
|
contents: false
|
||
|
};
|
||
|
|
||
|
function randomize(param) {
|
||
|
randomized.contents = true;
|
||
|
}
|
||
|
|
||
|
function is_randomized(param) {
|
||
|
return randomized.contents;
|
||
|
}
|
||
|
|
||
|
var prng = {
|
||
|
LAZY_DONE: false,
|
||
|
VAL: (function () {
|
||
|
return Random.State.make_self_init(undefined);
|
||
|
})
|
||
|
};
|
||
|
|
||
|
function power_2_above(_x, n) {
|
||
|
while(true) {
|
||
|
var x = _x;
|
||
|
if (x >= n) {
|
||
|
return x;
|
||
|
}
|
||
|
if ((x << 1) < x) {
|
||
|
return x;
|
||
|
}
|
||
|
_x = (x << 1);
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function create(randomOpt, initial_size) {
|
||
|
var random = randomOpt !== undefined ? randomOpt : randomized.contents;
|
||
|
var s = power_2_above(16, initial_size);
|
||
|
var seed = random ? Random.State.bits(CamlinternalLazy.force(prng)) : 0;
|
||
|
return {
|
||
|
size: 0,
|
||
|
data: Caml_array.make(s, /* Empty */0),
|
||
|
seed: seed,
|
||
|
initial_size: s
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function clear(h) {
|
||
|
h.size = 0;
|
||
|
var len = h.data.length;
|
||
|
for(var i = 0; i < len; ++i){
|
||
|
Caml_array.set(h.data, i, /* Empty */0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function reset(h) {
|
||
|
var len = h.data.length;
|
||
|
if (len === Pervasives.abs(h.initial_size)) {
|
||
|
return clear(h);
|
||
|
} else {
|
||
|
h.size = 0;
|
||
|
h.data = Caml_array.make(Pervasives.abs(h.initial_size), /* Empty */0);
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function copy_bucketlist(param) {
|
||
|
if (!param) {
|
||
|
return /* Empty */0;
|
||
|
}
|
||
|
var key = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
var loop = function (_prec, _param) {
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
var prec = _prec;
|
||
|
if (!param) {
|
||
|
return ;
|
||
|
}
|
||
|
var key = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
var r = /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: next
|
||
|
};
|
||
|
if (prec) {
|
||
|
prec.next = r;
|
||
|
} else {
|
||
|
throw {
|
||
|
RE_EXN_ID: "Assert_failure",
|
||
|
_1: [
|
||
|
"hashtbl.ml",
|
||
|
104,
|
||
|
23
|
||
|
],
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
_param = next;
|
||
|
_prec = r;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var r = /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: next
|
||
|
};
|
||
|
loop(r, next);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function copy(h) {
|
||
|
return {
|
||
|
size: h.size,
|
||
|
data: $$Array.map(copy_bucketlist, h.data),
|
||
|
seed: h.seed,
|
||
|
initial_size: h.initial_size
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function length(h) {
|
||
|
return h.size;
|
||
|
}
|
||
|
|
||
|
function resize(indexfun, h) {
|
||
|
var odata = h.data;
|
||
|
var osize = odata.length;
|
||
|
var nsize = (osize << 1);
|
||
|
if (nsize < osize) {
|
||
|
return ;
|
||
|
}
|
||
|
var ndata = Caml_array.make(nsize, /* Empty */0);
|
||
|
var ndata_tail = Caml_array.make(nsize, /* Empty */0);
|
||
|
var inplace = h.initial_size >= 0;
|
||
|
h.data = ndata;
|
||
|
var insert_bucket = function (_cell) {
|
||
|
while(true) {
|
||
|
var cell = _cell;
|
||
|
if (!cell) {
|
||
|
return ;
|
||
|
}
|
||
|
var key = cell.key;
|
||
|
var data = cell.data;
|
||
|
var next = cell.next;
|
||
|
var cell$1 = inplace ? cell : /* Cons */({
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: /* Empty */0
|
||
|
});
|
||
|
var nidx = Curry._2(indexfun, h, key);
|
||
|
var tail = Caml_array.get(ndata_tail, nidx);
|
||
|
if (tail) {
|
||
|
tail.next = cell$1;
|
||
|
} else {
|
||
|
Caml_array.set(ndata, nidx, cell$1);
|
||
|
}
|
||
|
Caml_array.set(ndata_tail, nidx, cell$1);
|
||
|
_cell = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
for(var i = 0; i < osize; ++i){
|
||
|
insert_bucket(Caml_array.get(odata, i));
|
||
|
}
|
||
|
if (!inplace) {
|
||
|
return ;
|
||
|
}
|
||
|
for(var i$1 = 0; i$1 < nsize; ++i$1){
|
||
|
var tail = Caml_array.get(ndata_tail, i$1);
|
||
|
if (tail) {
|
||
|
tail.next = /* Empty */0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function key_index(h, key) {
|
||
|
return Caml_hash.hash(10, 100, h.seed, key) & (h.data.length - 1 | 0);
|
||
|
}
|
||
|
|
||
|
function add(h, key, data) {
|
||
|
var i = key_index(h, key);
|
||
|
var bucket = /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: Caml_array.get(h.data, i)
|
||
|
};
|
||
|
Caml_array.set(h.data, i, bucket);
|
||
|
h.size = h.size + 1 | 0;
|
||
|
if (h.size > (h.data.length << 1)) {
|
||
|
return resize(key_index, h);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function remove(h, key) {
|
||
|
var i = key_index(h, key);
|
||
|
var _prec = /* Empty */0;
|
||
|
var _c = Caml_array.get(h.data, i);
|
||
|
while(true) {
|
||
|
var c = _c;
|
||
|
var prec = _prec;
|
||
|
if (!c) {
|
||
|
return ;
|
||
|
}
|
||
|
var k = c.key;
|
||
|
var next = c.next;
|
||
|
if (Caml_obj.equal(k, key)) {
|
||
|
h.size = h.size - 1 | 0;
|
||
|
if (prec) {
|
||
|
prec.next = next;
|
||
|
return ;
|
||
|
} else {
|
||
|
return Caml_array.set(h.data, i, next);
|
||
|
}
|
||
|
}
|
||
|
_c = next;
|
||
|
_prec = c;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function find(h, key) {
|
||
|
var match = Caml_array.get(h.data, key_index(h, key));
|
||
|
if (match) {
|
||
|
var k1 = match.key;
|
||
|
var d1 = match.data;
|
||
|
var next1 = match.next;
|
||
|
if (Caml_obj.equal(key, k1)) {
|
||
|
return d1;
|
||
|
}
|
||
|
if (next1) {
|
||
|
var k2 = next1.key;
|
||
|
var d2 = next1.data;
|
||
|
var next2 = next1.next;
|
||
|
if (Caml_obj.equal(key, k2)) {
|
||
|
return d2;
|
||
|
}
|
||
|
if (next2) {
|
||
|
var k3 = next2.key;
|
||
|
var d3 = next2.data;
|
||
|
var next3 = next2.next;
|
||
|
if (Caml_obj.equal(key, k3)) {
|
||
|
return d3;
|
||
|
} else {
|
||
|
var _param = next3;
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (param) {
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Caml_obj.equal(key, k)) {
|
||
|
return data;
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function find_opt(h, key) {
|
||
|
var match = Caml_array.get(h.data, key_index(h, key));
|
||
|
if (!match) {
|
||
|
return ;
|
||
|
}
|
||
|
var k1 = match.key;
|
||
|
var d1 = match.data;
|
||
|
var next1 = match.next;
|
||
|
if (Caml_obj.equal(key, k1)) {
|
||
|
return Caml_option.some(d1);
|
||
|
}
|
||
|
if (!next1) {
|
||
|
return ;
|
||
|
}
|
||
|
var k2 = next1.key;
|
||
|
var d2 = next1.data;
|
||
|
var next2 = next1.next;
|
||
|
if (Caml_obj.equal(key, k2)) {
|
||
|
return Caml_option.some(d2);
|
||
|
}
|
||
|
if (!next2) {
|
||
|
return ;
|
||
|
}
|
||
|
var k3 = next2.key;
|
||
|
var d3 = next2.data;
|
||
|
var next3 = next2.next;
|
||
|
if (Caml_obj.equal(key, k3)) {
|
||
|
return Caml_option.some(d3);
|
||
|
} else {
|
||
|
var _param = next3;
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return ;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Caml_obj.equal(key, k)) {
|
||
|
return Caml_option.some(data);
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function find_all(h, key) {
|
||
|
var find_in_bucket = function (_param) {
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return /* [] */0;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Caml_obj.equal(k, key)) {
|
||
|
return {
|
||
|
hd: data,
|
||
|
tl: find_in_bucket(next)
|
||
|
};
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
return find_in_bucket(Caml_array.get(h.data, key_index(h, key)));
|
||
|
}
|
||
|
|
||
|
function replace_bucket(key, data, _slot) {
|
||
|
while(true) {
|
||
|
var slot = _slot;
|
||
|
if (!slot) {
|
||
|
return true;
|
||
|
}
|
||
|
var k = slot.key;
|
||
|
var next = slot.next;
|
||
|
if (Caml_obj.equal(k, key)) {
|
||
|
slot.key = key;
|
||
|
slot.data = data;
|
||
|
return false;
|
||
|
}
|
||
|
_slot = next;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function replace(h, key, data) {
|
||
|
var i = key_index(h, key);
|
||
|
var l = Caml_array.get(h.data, i);
|
||
|
if (replace_bucket(key, data, l)) {
|
||
|
Caml_array.set(h.data, i, /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: l
|
||
|
});
|
||
|
h.size = h.size + 1 | 0;
|
||
|
if (h.size > (h.data.length << 1)) {
|
||
|
return resize(key_index, h);
|
||
|
} else {
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function mem(h, key) {
|
||
|
var _param = Caml_array.get(h.data, key_index(h, key));
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return false;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var next = param.next;
|
||
|
if (Caml_obj.equal(k, key)) {
|
||
|
return true;
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function iter(f, h) {
|
||
|
var do_bucket = function (_param) {
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return ;
|
||
|
}
|
||
|
var key = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
Curry._2(f, key, data);
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var old_trav = h.initial_size < 0;
|
||
|
if (!old_trav) {
|
||
|
flip_ongoing_traversal(h);
|
||
|
}
|
||
|
try {
|
||
|
var d = h.data;
|
||
|
for(var i = 0 ,i_finish = d.length; i < i_finish; ++i){
|
||
|
do_bucket(Caml_array.get(d, i));
|
||
|
}
|
||
|
if (!old_trav) {
|
||
|
return flip_ongoing_traversal(h);
|
||
|
} else {
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
catch (exn){
|
||
|
if (old_trav) {
|
||
|
throw exn;
|
||
|
}
|
||
|
flip_ongoing_traversal(h);
|
||
|
throw exn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function filter_map_inplace_bucket(f, h, i, _prec, _slot) {
|
||
|
while(true) {
|
||
|
var slot = _slot;
|
||
|
var prec = _prec;
|
||
|
if (!slot) {
|
||
|
if (prec) {
|
||
|
prec.next = /* Empty */0;
|
||
|
return ;
|
||
|
} else {
|
||
|
return Caml_array.set(h.data, i, /* Empty */0);
|
||
|
}
|
||
|
}
|
||
|
var key = slot.key;
|
||
|
var data = slot.data;
|
||
|
var next = slot.next;
|
||
|
var data$1 = Curry._2(f, key, data);
|
||
|
if (data$1 !== undefined) {
|
||
|
if (prec) {
|
||
|
prec.next = slot;
|
||
|
} else {
|
||
|
Caml_array.set(h.data, i, slot);
|
||
|
}
|
||
|
slot.data = Caml_option.valFromOption(data$1);
|
||
|
_slot = next;
|
||
|
_prec = slot;
|
||
|
continue ;
|
||
|
}
|
||
|
h.size = h.size - 1 | 0;
|
||
|
_slot = next;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function filter_map_inplace(f, h) {
|
||
|
var d = h.data;
|
||
|
var old_trav = h.initial_size < 0;
|
||
|
if (!old_trav) {
|
||
|
flip_ongoing_traversal(h);
|
||
|
}
|
||
|
try {
|
||
|
for(var i = 0 ,i_finish = d.length; i < i_finish; ++i){
|
||
|
filter_map_inplace_bucket(f, h, i, /* Empty */0, Caml_array.get(h.data, i));
|
||
|
}
|
||
|
return ;
|
||
|
}
|
||
|
catch (exn){
|
||
|
if (old_trav) {
|
||
|
throw exn;
|
||
|
}
|
||
|
flip_ongoing_traversal(h);
|
||
|
throw exn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function fold(f, h, init) {
|
||
|
var do_bucket = function (_b, _accu) {
|
||
|
while(true) {
|
||
|
var accu = _accu;
|
||
|
var b = _b;
|
||
|
if (!b) {
|
||
|
return accu;
|
||
|
}
|
||
|
var key = b.key;
|
||
|
var data = b.data;
|
||
|
var next = b.next;
|
||
|
_accu = Curry._3(f, key, data, accu);
|
||
|
_b = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var old_trav = h.initial_size < 0;
|
||
|
if (!old_trav) {
|
||
|
flip_ongoing_traversal(h);
|
||
|
}
|
||
|
try {
|
||
|
var d = h.data;
|
||
|
var accu = init;
|
||
|
for(var i = 0 ,i_finish = d.length; i < i_finish; ++i){
|
||
|
accu = do_bucket(Caml_array.get(d, i), accu);
|
||
|
}
|
||
|
if (!old_trav) {
|
||
|
flip_ongoing_traversal(h);
|
||
|
}
|
||
|
return accu;
|
||
|
}
|
||
|
catch (exn){
|
||
|
if (old_trav) {
|
||
|
throw exn;
|
||
|
}
|
||
|
flip_ongoing_traversal(h);
|
||
|
throw exn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function bucket_length(_accu, _param) {
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
var accu = _accu;
|
||
|
if (!param) {
|
||
|
return accu;
|
||
|
}
|
||
|
var next = param.next;
|
||
|
_param = next;
|
||
|
_accu = accu + 1 | 0;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function stats(h) {
|
||
|
var mbl = $$Array.fold_left((function (m, b) {
|
||
|
return Caml.int_max(m, bucket_length(0, b));
|
||
|
}), 0, h.data);
|
||
|
var histo = Caml_array.make(mbl + 1 | 0, 0);
|
||
|
$$Array.iter((function (b) {
|
||
|
var l = bucket_length(0, b);
|
||
|
Caml_array.set(histo, l, Caml_array.get(histo, l) + 1 | 0);
|
||
|
}), h.data);
|
||
|
return {
|
||
|
num_bindings: h.size,
|
||
|
num_buckets: h.data.length,
|
||
|
max_bucket_length: mbl,
|
||
|
bucket_histogram: histo
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function MakeSeeded(H) {
|
||
|
var key_index = function (h, key) {
|
||
|
return Curry._2(H.hash, h.seed, key) & (h.data.length - 1 | 0);
|
||
|
};
|
||
|
var add = function (h, key, data) {
|
||
|
var i = key_index(h, key);
|
||
|
var bucket = /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: Caml_array.get(h.data, i)
|
||
|
};
|
||
|
Caml_array.set(h.data, i, bucket);
|
||
|
h.size = h.size + 1 | 0;
|
||
|
if (h.size > (h.data.length << 1)) {
|
||
|
return resize(key_index, h);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
var remove = function (h, key) {
|
||
|
var i = key_index(h, key);
|
||
|
var _prec = /* Empty */0;
|
||
|
var _c = Caml_array.get(h.data, i);
|
||
|
while(true) {
|
||
|
var c = _c;
|
||
|
var prec = _prec;
|
||
|
if (!c) {
|
||
|
return ;
|
||
|
}
|
||
|
var k = c.key;
|
||
|
var next = c.next;
|
||
|
if (Curry._2(H.equal, k, key)) {
|
||
|
h.size = h.size - 1 | 0;
|
||
|
if (prec) {
|
||
|
prec.next = next;
|
||
|
return ;
|
||
|
} else {
|
||
|
return Caml_array.set(h.data, i, next);
|
||
|
}
|
||
|
}
|
||
|
_c = next;
|
||
|
_prec = c;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var find = function (h, key) {
|
||
|
var match = Caml_array.get(h.data, key_index(h, key));
|
||
|
if (match) {
|
||
|
var k1 = match.key;
|
||
|
var d1 = match.data;
|
||
|
var next1 = match.next;
|
||
|
if (Curry._2(H.equal, key, k1)) {
|
||
|
return d1;
|
||
|
}
|
||
|
if (next1) {
|
||
|
var k2 = next1.key;
|
||
|
var d2 = next1.data;
|
||
|
var next2 = next1.next;
|
||
|
if (Curry._2(H.equal, key, k2)) {
|
||
|
return d2;
|
||
|
}
|
||
|
if (next2) {
|
||
|
var k3 = next2.key;
|
||
|
var d3 = next2.data;
|
||
|
var next3 = next2.next;
|
||
|
if (Curry._2(H.equal, key, k3)) {
|
||
|
return d3;
|
||
|
} else {
|
||
|
var _param = next3;
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (param) {
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(H.equal, key, k)) {
|
||
|
return data;
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
};
|
||
|
var find_opt = function (h, key) {
|
||
|
var match = Caml_array.get(h.data, key_index(h, key));
|
||
|
if (!match) {
|
||
|
return ;
|
||
|
}
|
||
|
var k1 = match.key;
|
||
|
var d1 = match.data;
|
||
|
var next1 = match.next;
|
||
|
if (Curry._2(H.equal, key, k1)) {
|
||
|
return Caml_option.some(d1);
|
||
|
}
|
||
|
if (!next1) {
|
||
|
return ;
|
||
|
}
|
||
|
var k2 = next1.key;
|
||
|
var d2 = next1.data;
|
||
|
var next2 = next1.next;
|
||
|
if (Curry._2(H.equal, key, k2)) {
|
||
|
return Caml_option.some(d2);
|
||
|
}
|
||
|
if (!next2) {
|
||
|
return ;
|
||
|
}
|
||
|
var k3 = next2.key;
|
||
|
var d3 = next2.data;
|
||
|
var next3 = next2.next;
|
||
|
if (Curry._2(H.equal, key, k3)) {
|
||
|
return Caml_option.some(d3);
|
||
|
} else {
|
||
|
var _param = next3;
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return ;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(H.equal, key, k)) {
|
||
|
return Caml_option.some(data);
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
var find_all = function (h, key) {
|
||
|
var find_in_bucket = function (_param) {
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return /* [] */0;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var d = param.data;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(H.equal, k, key)) {
|
||
|
return {
|
||
|
hd: d,
|
||
|
tl: find_in_bucket(next)
|
||
|
};
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
return find_in_bucket(Caml_array.get(h.data, key_index(h, key)));
|
||
|
};
|
||
|
var replace_bucket = function (key, data, _slot) {
|
||
|
while(true) {
|
||
|
var slot = _slot;
|
||
|
if (!slot) {
|
||
|
return true;
|
||
|
}
|
||
|
var k = slot.key;
|
||
|
var next = slot.next;
|
||
|
if (Curry._2(H.equal, k, key)) {
|
||
|
slot.key = key;
|
||
|
slot.data = data;
|
||
|
return false;
|
||
|
}
|
||
|
_slot = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var replace = function (h, key, data) {
|
||
|
var i = key_index(h, key);
|
||
|
var l = Caml_array.get(h.data, i);
|
||
|
if (replace_bucket(key, data, l)) {
|
||
|
Caml_array.set(h.data, i, /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: l
|
||
|
});
|
||
|
h.size = h.size + 1 | 0;
|
||
|
if (h.size > (h.data.length << 1)) {
|
||
|
return resize(key_index, h);
|
||
|
} else {
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
var mem = function (h, key) {
|
||
|
var _param = Caml_array.get(h.data, key_index(h, key));
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return false;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(H.equal, k, key)) {
|
||
|
return true;
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
return {
|
||
|
create: create,
|
||
|
clear: clear,
|
||
|
reset: reset,
|
||
|
copy: copy,
|
||
|
add: add,
|
||
|
remove: remove,
|
||
|
find: find,
|
||
|
find_opt: find_opt,
|
||
|
find_all: find_all,
|
||
|
replace: replace,
|
||
|
mem: mem,
|
||
|
iter: iter,
|
||
|
filter_map_inplace: filter_map_inplace,
|
||
|
fold: fold,
|
||
|
length: length,
|
||
|
stats: stats
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function Make(H) {
|
||
|
var equal = H.equal;
|
||
|
var key_index = function (h, key) {
|
||
|
return Curry._1(H.hash, key) & (h.data.length - 1 | 0);
|
||
|
};
|
||
|
var add = function (h, key, data) {
|
||
|
var i = key_index(h, key);
|
||
|
var bucket = /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: Caml_array.get(h.data, i)
|
||
|
};
|
||
|
Caml_array.set(h.data, i, bucket);
|
||
|
h.size = h.size + 1 | 0;
|
||
|
if (h.size > (h.data.length << 1)) {
|
||
|
return resize(key_index, h);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
var remove = function (h, key) {
|
||
|
var i = key_index(h, key);
|
||
|
var _prec = /* Empty */0;
|
||
|
var _c = Caml_array.get(h.data, i);
|
||
|
while(true) {
|
||
|
var c = _c;
|
||
|
var prec = _prec;
|
||
|
if (!c) {
|
||
|
return ;
|
||
|
}
|
||
|
var k = c.key;
|
||
|
var next = c.next;
|
||
|
if (Curry._2(equal, k, key)) {
|
||
|
h.size = h.size - 1 | 0;
|
||
|
if (prec) {
|
||
|
prec.next = next;
|
||
|
return ;
|
||
|
} else {
|
||
|
return Caml_array.set(h.data, i, next);
|
||
|
}
|
||
|
}
|
||
|
_c = next;
|
||
|
_prec = c;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var find = function (h, key) {
|
||
|
var match = Caml_array.get(h.data, key_index(h, key));
|
||
|
if (match) {
|
||
|
var k1 = match.key;
|
||
|
var d1 = match.data;
|
||
|
var next1 = match.next;
|
||
|
if (Curry._2(equal, key, k1)) {
|
||
|
return d1;
|
||
|
}
|
||
|
if (next1) {
|
||
|
var k2 = next1.key;
|
||
|
var d2 = next1.data;
|
||
|
var next2 = next1.next;
|
||
|
if (Curry._2(equal, key, k2)) {
|
||
|
return d2;
|
||
|
}
|
||
|
if (next2) {
|
||
|
var k3 = next2.key;
|
||
|
var d3 = next2.data;
|
||
|
var next3 = next2.next;
|
||
|
if (Curry._2(equal, key, k3)) {
|
||
|
return d3;
|
||
|
} else {
|
||
|
var _param = next3;
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (param) {
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(equal, key, k)) {
|
||
|
return data;
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
}
|
||
|
throw {
|
||
|
RE_EXN_ID: "Not_found",
|
||
|
Error: new Error()
|
||
|
};
|
||
|
};
|
||
|
var find_opt = function (h, key) {
|
||
|
var match = Caml_array.get(h.data, key_index(h, key));
|
||
|
if (!match) {
|
||
|
return ;
|
||
|
}
|
||
|
var k1 = match.key;
|
||
|
var d1 = match.data;
|
||
|
var next1 = match.next;
|
||
|
if (Curry._2(equal, key, k1)) {
|
||
|
return Caml_option.some(d1);
|
||
|
}
|
||
|
if (!next1) {
|
||
|
return ;
|
||
|
}
|
||
|
var k2 = next1.key;
|
||
|
var d2 = next1.data;
|
||
|
var next2 = next1.next;
|
||
|
if (Curry._2(equal, key, k2)) {
|
||
|
return Caml_option.some(d2);
|
||
|
}
|
||
|
if (!next2) {
|
||
|
return ;
|
||
|
}
|
||
|
var k3 = next2.key;
|
||
|
var d3 = next2.data;
|
||
|
var next3 = next2.next;
|
||
|
if (Curry._2(equal, key, k3)) {
|
||
|
return Caml_option.some(d3);
|
||
|
} else {
|
||
|
var _param = next3;
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return ;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var data = param.data;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(equal, key, k)) {
|
||
|
return Caml_option.some(data);
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
var find_all = function (h, key) {
|
||
|
var find_in_bucket = function (_param) {
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return /* [] */0;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var d = param.data;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(equal, k, key)) {
|
||
|
return {
|
||
|
hd: d,
|
||
|
tl: find_in_bucket(next)
|
||
|
};
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
return find_in_bucket(Caml_array.get(h.data, key_index(h, key)));
|
||
|
};
|
||
|
var replace_bucket = function (key, data, _slot) {
|
||
|
while(true) {
|
||
|
var slot = _slot;
|
||
|
if (!slot) {
|
||
|
return true;
|
||
|
}
|
||
|
var k = slot.key;
|
||
|
var next = slot.next;
|
||
|
if (Curry._2(equal, k, key)) {
|
||
|
slot.key = key;
|
||
|
slot.data = data;
|
||
|
return false;
|
||
|
}
|
||
|
_slot = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var replace = function (h, key, data) {
|
||
|
var i = key_index(h, key);
|
||
|
var l = Caml_array.get(h.data, i);
|
||
|
if (replace_bucket(key, data, l)) {
|
||
|
Caml_array.set(h.data, i, /* Cons */{
|
||
|
key: key,
|
||
|
data: data,
|
||
|
next: l
|
||
|
});
|
||
|
h.size = h.size + 1 | 0;
|
||
|
if (h.size > (h.data.length << 1)) {
|
||
|
return resize(key_index, h);
|
||
|
} else {
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
var mem = function (h, key) {
|
||
|
var _param = Caml_array.get(h.data, key_index(h, key));
|
||
|
while(true) {
|
||
|
var param = _param;
|
||
|
if (!param) {
|
||
|
return false;
|
||
|
}
|
||
|
var k = param.key;
|
||
|
var next = param.next;
|
||
|
if (Curry._2(equal, k, key)) {
|
||
|
return true;
|
||
|
}
|
||
|
_param = next;
|
||
|
continue ;
|
||
|
};
|
||
|
};
|
||
|
var create$1 = function (sz) {
|
||
|
return create(false, sz);
|
||
|
};
|
||
|
return {
|
||
|
create: create$1,
|
||
|
clear: clear,
|
||
|
reset: reset,
|
||
|
copy: copy,
|
||
|
add: add,
|
||
|
remove: remove,
|
||
|
find: find,
|
||
|
find_opt: find_opt,
|
||
|
find_all: find_all,
|
||
|
replace: replace,
|
||
|
mem: mem,
|
||
|
iter: iter,
|
||
|
filter_map_inplace: filter_map_inplace,
|
||
|
fold: fold,
|
||
|
length: length,
|
||
|
stats: stats
|
||
|
};
|
||
|
}
|
||
|
|
||
|
var seeded_hash_param = Caml_hash.hash;
|
||
|
|
||
|
export {
|
||
|
create ,
|
||
|
clear ,
|
||
|
reset ,
|
||
|
copy ,
|
||
|
add ,
|
||
|
find ,
|
||
|
find_opt ,
|
||
|
find_all ,
|
||
|
mem ,
|
||
|
remove ,
|
||
|
replace ,
|
||
|
iter ,
|
||
|
filter_map_inplace ,
|
||
|
fold ,
|
||
|
length ,
|
||
|
randomize ,
|
||
|
is_randomized ,
|
||
|
stats ,
|
||
|
Make ,
|
||
|
MakeSeeded ,
|
||
|
hash ,
|
||
|
seeded_hash ,
|
||
|
hash_param ,
|
||
|
seeded_hash_param ,
|
||
|
}
|
||
|
/* No side effect */
|