Skip to content

Instantly share code, notes, and snippets.

@zerobias
Created January 20, 2019 09:31
Show Gist options
  • Save zerobias/fc692dfb897eda16e2cd9e1c5798a6eb to your computer and use it in GitHub Desktop.
Save zerobias/fc692dfb897eda16e2cd9e1c5798a6eb to your computer and use it in GitHub Desktop.
// Generated by BUCKLESCRIPT VERSION 4.0.6, PLEASE EDIT WITH CARE
'use strict';
var $$Map = require("./stdlib/map.js");
var Sys = require("./stdlib/sys.js");
var List = require("./stdlib/list.js");
var $$Array = require("./stdlib/array.js");
var Curry = require("./stdlib/curry.js");
var Caml_oo = require("./stdlib/caml_oo.js");
var Caml_obj = require("./stdlib/caml_obj.js");
var Caml_array = require("./stdlib/caml_array.js");
var Caml_int32 = require("./stdlib/caml_int32.js");
var Pervasives = require("./stdlib/pervasives.js");
var Caml_string = require("./stdlib/caml_string.js");
var Js_primitive = require("./stdlib/js_primitive.js");
var Caml_primitive = require("./stdlib/caml_primitive.js");
var Caml_exceptions = require("./stdlib/caml_exceptions.js");
var Caml_builtin_exceptions = require("./stdlib/caml_builtin_exceptions.js");
function is_block(a) {
return typeof a !== "number";
}
function extension_constructor(x) {
var slot = typeof x !== "number" && (x.tag | 0) !== 248 && x.length >= 1 ? x[0] : x;
var name = typeof slot !== "number" && slot.tag === 248 ? slot[0] : Pervasives.invalid_arg("Obj.extension_constructor");
if (name.tag === 252) {
return slot;
} else {
return Pervasives.invalid_arg("Obj.extension_constructor");
}
}
function extension_name(slot) {
return slot[0];
}
function extension_id(slot) {
return slot[1];
}
var Obj = /* module */[
/* is_block */is_block,
/* first_non_constant_constructor_tag */0,
/* last_non_constant_constructor_tag */245,
/* lazy_tag */246,
/* closure_tag */247,
/* object_tag */248,
/* infix_tag */249,
/* forward_tag */250,
/* no_scan_tag */251,
/* abstract_tag */251,
/* string_tag */252,
/* double_tag */253,
/* double_array_tag */254,
/* custom_tag */255,
/* final_tag */255,
/* int_tag */1000,
/* out_of_heap_tag */1001,
/* unaligned_tag */1002,
/* extension_constructor */extension_constructor,
/* extension_name */extension_name,
/* extension_id */extension_id
];
function copy(o) {
return Caml_exceptions.caml_set_oo_id(Caml_obj.caml_obj_dup(o));
}
var params = /* record */[
/* compact_table */true,
/* copy_parent */true,
/* clean_when_copying */true,
/* retry_count */3,
/* bucket_small_size */16
];
function public_method_label(s) {
var accu = 0;
for(var i = 0 ,i_finish = s.length - 1 | 0; i <= i_finish; ++i){
accu = Caml_int32.imul(223, accu) + Caml_string.get(s, i) | 0;
}
accu = accu & 2147483647;
if (accu > 1073741823) {
return accu - -2147483648 | 0;
} else {
return accu;
}
}
var compare = Caml_primitive.caml_string_compare;
var Vars = $$Map.Make(/* module */[/* compare */compare]);
var compare$1 = Caml_primitive.caml_string_compare;
var Meths = $$Map.Make(/* module */[/* compare */compare$1]);
var compare$2 = Caml_primitive.caml_int_compare;
var Labs = $$Map.Make(/* module */[/* compare */compare$2]);
var dummy_table = /* record */[
/* size */0,
/* methods : array */[/* () */0],
/* methods_by_name */Meths[/* empty */0],
/* methods_by_label */Labs[/* empty */0],
/* previous_states : [] */0,
/* hidden_meths : [] */0,
/* vars */Vars[/* empty */0],
/* initializers : [] */0
];
var table_count = /* record */[/* contents */0];
var dummy_met = [];
function fit_size(n) {
if (n <= 2) {
return n;
} else {
return (fit_size((n + 1 | 0) / 2 | 0) << 1);
}
}
function new_table(pub_labels) {
table_count[0] = table_count[0] + 1 | 0;
var len = pub_labels.length;
var methods = Caml_array.caml_make_vect((len << 1) + 2 | 0, dummy_met);
Caml_array.caml_array_set(methods, 0, len);
Caml_array.caml_array_set(methods, 1, (Caml_int32.imul(fit_size(len), Sys.word_size) / 8 | 0) - 1 | 0);
for(var i = 0 ,i_finish = len - 1 | 0; i <= i_finish; ++i){
Caml_array.caml_array_set(methods, (i << 1) + 3 | 0, Caml_array.caml_array_get(pub_labels, i));
}
return /* record */[
/* size */2,
/* methods */methods,
/* methods_by_name */Meths[/* empty */0],
/* methods_by_label */Labs[/* empty */0],
/* previous_states : [] */0,
/* hidden_meths : [] */0,
/* vars */Vars[/* empty */0],
/* initializers : [] */0
];
}
function resize(array, new_size) {
var old_size = array[/* methods */1].length;
if (new_size > old_size) {
var new_buck = Caml_array.caml_make_vect(new_size, dummy_met);
$$Array.blit(array[/* methods */1], 0, new_buck, 0, old_size);
array[/* methods */1] = new_buck;
return /* () */0;
} else {
return 0;
}
}
var method_count = /* record */[/* contents */0];
var inst_var_count = /* record */[/* contents */0];
function new_method(table) {
var index = table[/* methods */1].length;
resize(table, index + 1 | 0);
return index;
}
function get_method_label(table, name) {
try {
return Curry._2(Meths[/* find */21], name, table[/* methods_by_name */2]);
}
catch (exn){
if (exn === Caml_builtin_exceptions.not_found) {
var label = new_method(table);
table[/* methods_by_name */2] = Curry._3(Meths[/* add */3], name, label, table[/* methods_by_name */2]);
table[/* methods_by_label */3] = Curry._3(Labs[/* add */3], label, true, table[/* methods_by_label */3]);
return label;
} else {
throw exn;
}
}
}
function get_method_labels(table, names) {
return $$Array.map((function (param) {
return get_method_label(table, param);
}), names);
}
function set_method(table, label, element) {
method_count[0] = method_count[0] + 1 | 0;
if (Curry._2(Labs[/* find */21], label, table[/* methods_by_label */3])) {
var array = table;
var label$1 = label;
var element$1 = element;
resize(array, label$1 + 1 | 0);
return Caml_array.caml_array_set(array[/* methods */1], label$1, element$1);
} else {
table[/* hidden_meths */5] = /* :: */[
/* tuple */[
label,
element
],
table[/* hidden_meths */5]
];
return /* () */0;
}
}
function get_method(table, label) {
try {
return List.assoc(label, table[/* hidden_meths */5]);
}
catch (exn){
if (exn === Caml_builtin_exceptions.not_found) {
return Caml_array.caml_array_get(table[/* methods */1], label);
} else {
throw exn;
}
}
}
function to_list(arr) {
if (arr === 0) {
return /* [] */0;
} else {
return $$Array.to_list(arr);
}
}
function narrow(table, vars, virt_meths, concr_meths) {
var vars$1 = to_list(vars);
var virt_meths$1 = to_list(virt_meths);
var concr_meths$1 = to_list(concr_meths);
var virt_meth_labs = List.map((function (param) {
return get_method_label(table, param);
}), virt_meths$1);
var concr_meth_labs = List.map((function (param) {
return get_method_label(table, param);
}), concr_meths$1);
table[/* previous_states */4] = /* :: */[
/* tuple */[
table[/* methods_by_name */2],
table[/* methods_by_label */3],
table[/* hidden_meths */5],
table[/* vars */6],
virt_meth_labs,
vars$1
],
table[/* previous_states */4]
];
table[/* vars */6] = Curry._3(Vars[/* fold */10], (function (lab, info, tvars) {
if (List.mem(lab, vars$1)) {
return Curry._3(Vars[/* add */3], lab, info, tvars);
} else {
return tvars;
}
}), table[/* vars */6], Vars[/* empty */0]);
var by_name = /* record */[/* contents */Meths[/* empty */0]];
var by_label = /* record */[/* contents */Labs[/* empty */0]];
List.iter2((function (met, label) {
by_name[0] = Curry._3(Meths[/* add */3], met, label, by_name[0]);
var tmp;
try {
tmp = Curry._2(Labs[/* find */21], label, table[/* methods_by_label */3]);
}
catch (exn){
if (exn === Caml_builtin_exceptions.not_found) {
tmp = true;
} else {
throw exn;
}
}
by_label[0] = Curry._3(Labs[/* add */3], label, tmp, by_label[0]);
return /* () */0;
}), concr_meths$1, concr_meth_labs);
List.iter2((function (met, label) {
by_name[0] = Curry._3(Meths[/* add */3], met, label, by_name[0]);
by_label[0] = Curry._3(Labs[/* add */3], label, false, by_label[0]);
return /* () */0;
}), virt_meths$1, virt_meth_labs);
table[/* methods_by_name */2] = by_name[0];
table[/* methods_by_label */3] = by_label[0];
table[/* hidden_meths */5] = List.fold_right((function (met, hm) {
if (List.mem(met[0], virt_meth_labs)) {
return hm;
} else {
return /* :: */[
met,
hm
];
}
}), table[/* hidden_meths */5], /* [] */0);
return /* () */0;
}
function widen(table) {
var match = List.hd(table[/* previous_states */4]);
var virt_meths = match[4];
table[/* previous_states */4] = List.tl(table[/* previous_states */4]);
table[/* vars */6] = List.fold_left((function (s, v) {
return Curry._3(Vars[/* add */3], v, Curry._2(Vars[/* find */21], v, table[/* vars */6]), s);
}), match[3], match[5]);
table[/* methods_by_name */2] = match[0];
table[/* methods_by_label */3] = match[1];
table[/* hidden_meths */5] = List.fold_right((function (met, hm) {
if (List.mem(met[0], virt_meths)) {
return hm;
} else {
return /* :: */[
met,
hm
];
}
}), table[/* hidden_meths */5], match[2]);
return /* () */0;
}
function new_slot(table) {
var index = table[/* size */0];
table[/* size */0] = index + 1 | 0;
return index;
}
function new_variable(table, name) {
try {
return Curry._2(Vars[/* find */21], name, table[/* vars */6]);
}
catch (exn){
if (exn === Caml_builtin_exceptions.not_found) {
var index = new_slot(table);
if (name !== "") {
table[/* vars */6] = Curry._3(Vars[/* add */3], name, index, table[/* vars */6]);
}
return index;
} else {
throw exn;
}
}
}
function to_array(arr) {
if (Caml_obj.caml_equal(arr, 0)) {
return /* array */[];
} else {
return arr;
}
}
function new_methods_variables(table, meths, vals) {
var meths$1 = to_array(meths);
var nmeths = meths$1.length;
var nvals = vals.length;
var res = Caml_array.caml_make_vect(nmeths + nvals | 0, 0);
for(var i = 0 ,i_finish = nmeths - 1 | 0; i <= i_finish; ++i){
Caml_array.caml_array_set(res, i, get_method_label(table, Caml_array.caml_array_get(meths$1, i)));
}
for(var i$1 = 0 ,i_finish$1 = nvals - 1 | 0; i$1 <= i_finish$1; ++i$1){
Caml_array.caml_array_set(res, i$1 + nmeths | 0, new_variable(table, Caml_array.caml_array_get(vals, i$1)));
}
return res;
}
function get_variable(table, name) {
try {
return Curry._2(Vars[/* find */21], name, table[/* vars */6]);
}
catch (exn){
if (exn === Caml_builtin_exceptions.not_found) {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
453,
57
]
];
} else {
throw exn;
}
}
}
function get_variables(table, names) {
return $$Array.map((function (param) {
return get_variable(table, param);
}), names);
}
function add_initializer(table, f) {
table[/* initializers */7] = /* :: */[
f,
table[/* initializers */7]
];
return /* () */0;
}
function create_table(public_methods) {
if (public_methods === 0) {
return new_table(/* array */[]);
} else {
var tags = $$Array.map(public_method_label, public_methods);
var table = new_table(tags);
$$Array.iteri((function (i, met) {
var lab = (i << 1) + 2 | 0;
table[/* methods_by_name */2] = Curry._3(Meths[/* add */3], met, lab, table[/* methods_by_name */2]);
table[/* methods_by_label */3] = Curry._3(Labs[/* add */3], lab, true, table[/* methods_by_label */3]);
return /* () */0;
}), public_methods);
return table;
}
}
function init_class(table) {
inst_var_count[0] = (inst_var_count[0] + table[/* size */0] | 0) - 1 | 0;
table[/* initializers */7] = List.rev(table[/* initializers */7]);
return resize(table, 3 + Caml_int32.div((Caml_array.caml_array_get(table[/* methods */1], 1) << 4), Sys.word_size) | 0);
}
function inherits(cla, vals, virt_meths, concr_meths, param, top) {
var $$super = param[1];
narrow(cla, vals, virt_meths, concr_meths);
var init = top ? Curry._2($$super, cla, param[3]) : Curry._1($$super, cla);
widen(cla);
return $$Array.concat(/* :: */[
/* array */[init],
/* :: */[
$$Array.map((function (param) {
return get_variable(cla, param);
}), to_array(vals)),
/* :: */[
$$Array.map((function (nm) {
return get_method(cla, get_method_label(cla, nm));
}), to_array(concr_meths)),
/* [] */0
]
]
]);
}
function make_class(pub_meths, class_init) {
var table = create_table(pub_meths);
var env_init = Curry._1(class_init, table);
init_class(table);
return /* tuple */[
Curry._1(env_init, 0),
class_init,
env_init,
0
];
}
function make_class_store(pub_meths, class_init, init_table) {
var table = create_table(pub_meths);
var env_init = Curry._1(class_init, table);
init_class(table);
init_table[/* class_init */1] = class_init;
init_table[/* env_init */0] = env_init;
return /* () */0;
}
function dummy_class(loc) {
var undef = function () {
throw [
Caml_builtin_exceptions.undefined_recursive_module,
loc
];
};
return /* tuple */[
undef,
undef,
undef,
0
];
}
function create_object(table) {
var obj = Caml_obj.caml_obj_block(248, table[/* size */0]);
obj[0] = table[/* methods */1];
return Caml_exceptions.caml_set_oo_id(obj);
}
function create_object_opt(obj_0, table) {
if (obj_0) {
return obj_0;
} else {
var obj = Caml_obj.caml_obj_block(248, table[/* size */0]);
obj[0] = table[/* methods */1];
return Caml_exceptions.caml_set_oo_id(obj);
}
}
function iter_f(obj, _param) {
while(true) {
var param = _param;
if (param) {
Curry._1(param[0], obj);
_param = param[1];
continue ;
} else {
return /* () */0;
}
};
}
function run_initializers(obj, table) {
var inits = table[/* initializers */7];
if (inits !== /* [] */0) {
return iter_f(obj, inits);
} else {
return 0;
}
}
function run_initializers_opt(obj_0, obj, table) {
if (obj_0) {
return obj;
} else {
var inits = table[/* initializers */7];
if (inits !== /* [] */0) {
iter_f(obj, inits);
}
return obj;
}
}
function create_object_and_run_initializers(obj_0, table) {
if (obj_0) {
return obj_0;
} else {
var obj = create_object(table);
run_initializers(obj, table);
return obj;
}
}
function set_data(tables, v) {
if (tables) {
tables[0][/* data */1] = v;
return /* () */0;
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
542,
18
]
];
}
}
function set_next(tables, v) {
if (tables) {
tables[0][/* next */2] = v;
return /* () */0;
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
546,
18
]
];
}
}
function get_key(param) {
if (param) {
return param[0][/* key */0];
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
550,
18
]
];
}
}
function get_data(param) {
if (param) {
return param[0][/* data */1];
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
554,
18
]
];
}
}
function get_next(param) {
if (param) {
return param[0][/* next */2];
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
558,
18
]
];
}
}
function build_path(n, keys, tables) {
var res = /* Cons */[/* record */[
/* key */0,
/* data : Empty */0,
/* next : Empty */0
]];
var r = res;
for(var i = 0; i <= n; ++i){
r = /* Cons */[/* record */[
/* key */Caml_array.caml_array_get(keys, i),
/* data */r,
/* next : Empty */0
]];
}
set_data(tables, r);
return res;
}
function lookup_keys(i, keys, tables) {
if (i < 0) {
return tables;
} else {
var key = Caml_array.caml_array_get(keys, i);
var _tables = tables;
while(true) {
var tables$1 = _tables;
if (get_key(tables$1) === key) {
var tables_data = get_data(tables$1);
if (tables_data) {
return lookup_keys(i - 1 | 0, keys, tables_data);
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
581,
25
]
];
}
} else {
var next = get_next(tables$1);
if (next) {
_tables = next;
continue ;
} else {
var next$1 = /* Cons */[/* record */[
/* key */key,
/* data : Empty */0,
/* next : Empty */0
]];
set_next(tables$1, next$1);
return build_path(i - 1 | 0, keys, next$1);
}
}
};
}
}
function lookup_tables(root, keys) {
var root_data = get_data(root);
if (root_data) {
return lookup_keys(keys.length - 1 | 0, keys, root_data);
} else {
return build_path(keys.length - 1 | 0, keys, root);
}
}
function get_const(x) {
return (function () {
return x;
});
}
function get_var(n) {
return (function (obj) {
return obj[n];
});
}
function get_env(e, n) {
return (function (obj) {
return obj[e][n];
});
}
function get_meth(n) {
return (function (obj) {
return Curry._1(obj[0][n], obj);
});
}
function set_var(n) {
return (function (obj, x) {
obj[n] = x;
return /* () */0;
});
}
function app_const(f, x) {
return (function () {
return Curry._1(f, x);
});
}
function app_var(f, n) {
return (function (obj) {
return Curry._1(f, obj[n]);
});
}
function app_env(f, e, n) {
return (function (obj) {
return Curry._1(f, obj[e][n]);
});
}
function app_meth(f, n) {
return (function (obj) {
return Curry._1(f, Curry._1(obj[0][n], obj));
});
}
function app_const_const(f, x, y) {
return (function () {
return Curry._2(f, x, y);
});
}
function app_const_var(f, x, n) {
return (function (obj) {
return Curry._2(f, x, obj[n]);
});
}
function app_const_meth(f, x, n) {
return (function (obj) {
return Curry._2(f, x, Curry._1(obj[0][n], obj));
});
}
function app_var_const(f, n, x) {
return (function (obj) {
return Curry._2(f, obj[n], x);
});
}
function app_meth_const(f, n, x) {
return (function (obj) {
return Curry._2(f, Curry._1(obj[0][n], obj), x);
});
}
function app_const_env(f, x, e, n) {
return (function (obj) {
return Curry._2(f, x, obj[e][n]);
});
}
function app_env_const(f, e, n, x) {
return (function (obj) {
return Curry._2(f, obj[e][n], x);
});
}
function meth_app_const(n, x) {
return (function (obj) {
return Curry._2(obj[0][n], obj, x);
});
}
function meth_app_var(n, m) {
return (function (obj) {
return Curry._2(obj[0][n], obj, obj[m]);
});
}
function meth_app_env(n, e, m) {
return (function (obj) {
return Curry._2(obj[0][n], obj, obj[e][m]);
});
}
function meth_app_meth(n, m) {
return (function (obj) {
return Curry._2(obj[0][n], obj, Curry._1(obj[0][m], obj));
});
}
function send_const(m, x, _) {
return (function () {
return Curry._1(Curry._3(Caml_oo.caml_get_public_method, x, m, 13), x);
});
}
function send_var(m, n, _) {
return (function (obj) {
var tmp = obj[n];
return Curry._1(Curry._3(Caml_oo.caml_get_public_method, tmp, m, 14), tmp);
});
}
function send_env(m, e, n, _) {
return (function (obj) {
var tmp = obj[e][n];
return Curry._1(Curry._3(Caml_oo.caml_get_public_method, tmp, m, 15), tmp);
});
}
function send_meth(m, n, _) {
return (function (obj) {
var tmp = Curry._1(obj[0][n], obj);
return Curry._1(Curry._3(Caml_oo.caml_get_public_method, tmp, m, 16), tmp);
});
}
function new_cache(table) {
var n = new_method(table);
var n$1 = n % 2 === 0 || n > (2 + Caml_int32.div((Caml_array.caml_array_get(table[/* methods */1], 1) << 4), Sys.word_size) | 0) ? n : new_method(table);
Caml_array.caml_array_set(table[/* methods */1], n$1, 0);
return n$1;
}
function method_impl(table, i, arr) {
var next = function () {
i[0] = i[0] + 1 | 0;
return Caml_array.caml_array_get(arr, i[0]);
};
var clo = next(/* () */0);
if (typeof clo === "number") {
switch (clo) {
case 0 :
var x = next(/* () */0);
return (function () {
return x;
});
case 1 :
var n = next(/* () */0);
return (function (obj) {
return obj[n];
});
case 2 :
var e = next(/* () */0);
var n$1 = next(/* () */0);
return get_env(e, n$1);
case 3 :
return get_meth(next(/* () */0));
case 4 :
var n$2 = next(/* () */0);
return (function (obj, x) {
obj[n$2] = x;
return /* () */0;
});
case 5 :
var f = next(/* () */0);
var x$1 = next(/* () */0);
return (function () {
return Curry._1(f, x$1);
});
case 6 :
var f$1 = next(/* () */0);
var n$3 = next(/* () */0);
return (function (obj) {
return Curry._1(f$1, obj[n$3]);
});
case 7 :
var f$2 = next(/* () */0);
var e$1 = next(/* () */0);
var n$4 = next(/* () */0);
return app_env(f$2, e$1, n$4);
case 8 :
var f$3 = next(/* () */0);
var n$5 = next(/* () */0);
return app_meth(f$3, n$5);
case 9 :
var f$4 = next(/* () */0);
var x$2 = next(/* () */0);
var y = next(/* () */0);
return (function () {
return Curry._2(f$4, x$2, y);
});
case 10 :
var f$5 = next(/* () */0);
var x$3 = next(/* () */0);
var n$6 = next(/* () */0);
return app_const_var(f$5, x$3, n$6);
case 11 :
var f$6 = next(/* () */0);
var x$4 = next(/* () */0);
var e$2 = next(/* () */0);
var n$7 = next(/* () */0);
return app_const_env(f$6, x$4, e$2, n$7);
case 12 :
var f$7 = next(/* () */0);
var x$5 = next(/* () */0);
var n$8 = next(/* () */0);
return app_const_meth(f$7, x$5, n$8);
case 13 :
var f$8 = next(/* () */0);
var n$9 = next(/* () */0);
var x$6 = next(/* () */0);
return app_var_const(f$8, n$9, x$6);
case 14 :
var f$9 = next(/* () */0);
var e$3 = next(/* () */0);
var n$10 = next(/* () */0);
var x$7 = next(/* () */0);
return app_env_const(f$9, e$3, n$10, x$7);
case 15 :
var f$10 = next(/* () */0);
var n$11 = next(/* () */0);
var x$8 = next(/* () */0);
return app_meth_const(f$10, n$11, x$8);
case 16 :
var n$12 = next(/* () */0);
var x$9 = next(/* () */0);
return meth_app_const(n$12, x$9);
case 17 :
var n$13 = next(/* () */0);
var m = next(/* () */0);
return meth_app_var(n$13, m);
case 18 :
var n$14 = next(/* () */0);
var e$4 = next(/* () */0);
var m$1 = next(/* () */0);
return meth_app_env(n$14, e$4, m$1);
case 19 :
var n$15 = next(/* () */0);
var m$2 = next(/* () */0);
return meth_app_meth(n$15, m$2);
case 20 :
var m$3 = next(/* () */0);
var x$10 = next(/* () */0);
return send_const(m$3, x$10, new_cache(table));
case 21 :
var m$4 = next(/* () */0);
var n$16 = next(/* () */0);
return send_var(m$4, n$16, new_cache(table));
case 22 :
var m$5 = next(/* () */0);
var e$5 = next(/* () */0);
var n$17 = next(/* () */0);
return send_env(m$5, e$5, n$17, new_cache(table));
case 23 :
var m$6 = next(/* () */0);
var n$18 = next(/* () */0);
return send_meth(m$6, n$18, new_cache(table));
}
} else {
return clo;
}
}
function set_methods(table, methods) {
var len = methods.length;
var i = /* record */[/* contents */0];
while(i[0] < len) {
var label = Caml_array.caml_array_get(methods, i[0]);
var clo = method_impl(table, i, methods);
set_method(table, label, clo);
i[0] = i[0] + 1 | 0;
};
return /* () */0;
}
function stats() {
return /* record */[
/* classes */table_count[0],
/* methods */method_count[0],
/* inst_vars */inst_var_count[0]
];
}
var Coo = /* module */[
/* public_method_label */public_method_label,
/* new_method */new_method,
/* new_variable */new_variable,
/* new_methods_variables */new_methods_variables,
/* get_variable */get_variable,
/* get_variables */get_variables,
/* get_method_label */get_method_label,
/* get_method_labels */get_method_labels,
/* get_method */get_method,
/* set_method */set_method,
/* set_methods */set_methods,
/* narrow */narrow,
/* widen */widen,
/* add_initializer */add_initializer,
/* dummy_table */dummy_table,
/* create_table */create_table,
/* init_class */init_class,
/* inherits */inherits,
/* make_class */make_class,
/* make_class_store */make_class_store,
/* dummy_class */dummy_class,
/* copy */copy,
/* create_object */create_object,
/* create_object_opt */create_object_opt,
/* run_initializers */run_initializers,
/* run_initializers_opt */run_initializers_opt,
/* create_object_and_run_initializers */create_object_and_run_initializers,
/* lookup_tables */lookup_tables,
/* get_const */get_const,
/* get_var */get_var,
/* get_env */get_env,
/* get_meth */get_meth,
/* set_var */set_var,
/* app_const */app_const,
/* app_var */app_var,
/* app_env */app_env,
/* app_meth */app_meth,
/* app_const_const */app_const_const,
/* app_const_var */app_const_var,
/* app_const_env */app_const_env,
/* app_const_meth */app_const_meth,
/* app_var_const */app_var_const,
/* app_env_const */app_env_const,
/* app_meth_const */app_meth_const,
/* meth_app_const */meth_app_const,
/* meth_app_var */meth_app_var,
/* meth_app_env */meth_app_env,
/* meth_app_meth */meth_app_meth,
/* send_const */send_const,
/* send_var */send_var,
/* send_env */send_env,
/* send_meth */send_meth,
/* params */params,
/* stats */stats
];
function Make(Ord) {
var height = function (param) {
if (param) {
return param[0][/* h */3];
} else {
return 0;
}
};
var create = function (l, v, r) {
var hl = l ? l[0][/* h */3] : 0;
var hr = r ? r[0][/* h */3] : 0;
return /* Node */[/* record */[
/* l */l,
/* v */v,
/* r */r,
/* h */hl >= hr ? hl + 1 | 0 : hr + 1 | 0
]];
};
var bal = function (l, v, r) {
var hl = l ? l[0][/* h */3] : 0;
var hr = r ? r[0][/* h */3] : 0;
if (hl > (hr + 2 | 0)) {
if (l) {
var match = l[0];
var lr = match[/* r */2];
var lv = match[/* v */1];
var ll = match[/* l */0];
if (height(ll) >= height(lr)) {
return create(ll, lv, create(lr, v, r));
} else if (lr) {
var match$1 = lr[0];
return create(create(ll, lv, match$1[/* l */0]), match$1[/* v */1], create(match$1[/* r */2], v, r));
} else {
return Pervasives.invalid_arg("Set.bal");
}
} else {
return Pervasives.invalid_arg("Set.bal");
}
} else if (hr > (hl + 2 | 0)) {
if (r) {
var match$2 = r[0];
var rr = match$2[/* r */2];
var rv = match$2[/* v */1];
var rl = match$2[/* l */0];
if (height(rr) >= height(rl)) {
return create(create(l, v, rl), rv, rr);
} else if (rl) {
var match$3 = rl[0];
return create(create(l, v, match$3[/* l */0]), match$3[/* v */1], create(match$3[/* r */2], rv, rr));
} else {
return Pervasives.invalid_arg("Set.bal");
}
} else {
return Pervasives.invalid_arg("Set.bal");
}
} else {
return /* Node */[/* record */[
/* l */l,
/* v */v,
/* r */r,
/* h */hl >= hr ? hl + 1 | 0 : hr + 1 | 0
]];
}
};
var add = function (x, t) {
if (t) {
var match = t[0];
var r = match[/* r */2];
var v = match[/* v */1];
var l = match[/* l */0];
var c = Curry._2(Ord[/* compare */0], x, v);
if (c === 0) {
return t;
} else if (c < 0) {
var ll = add(x, l);
if (l === ll) {
return t;
} else {
return bal(ll, v, r);
}
} else {
var rr = add(x, r);
if (r === rr) {
return t;
} else {
return bal(l, v, rr);
}
}
} else {
return /* Node */[/* record */[
/* l : Empty */0,
/* v */x,
/* r : Empty */0,
/* h */1
]];
}
};
var singleton = function (x) {
return /* Node */[/* record */[
/* l : Empty */0,
/* v */x,
/* r : Empty */0,
/* h */1
]];
};
var add_min_element = function (x, param) {
if (param) {
var match = param[0];
return bal(add_min_element(x, match[/* l */0]), match[/* v */1], match[/* r */2]);
} else {
return singleton(x);
}
};
var add_max_element = function (x, param) {
if (param) {
var match = param[0];
return bal(match[/* l */0], match[/* v */1], add_max_element(x, match[/* r */2]));
} else {
return singleton(x);
}
};
var join = function (l, v, r) {
if (l) {
if (r) {
var match = r[0];
var rh = match[/* h */3];
var match$1 = l[0];
var lh = match$1[/* h */3];
if (lh > (rh + 2 | 0)) {
return bal(match$1[/* l */0], match$1[/* v */1], join(match$1[/* r */2], v, r));
} else if (rh > (lh + 2 | 0)) {
return bal(join(l, v, match[/* l */0]), match[/* v */1], match[/* r */2]);
} else {
return create(l, v, r);
}
} else {
return add_max_element(v, l);
}
} else {
return add_min_element(v, r);
}
};
var min_elt = function (_param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var l = match[/* l */0];
if (l) {
_param = l;
continue ;
} else {
return match[/* v */1];
}
} else {
throw Caml_builtin_exceptions.not_found;
}
};
};
var min_elt_opt = function (_param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var l = match[/* l */0];
if (l) {
_param = l;
continue ;
} else {
return Js_primitive.some(match[/* v */1]);
}
} else {
return undefined;
}
};
};
var max_elt = function (_param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var r = match[/* r */2];
if (r) {
_param = r;
continue ;
} else {
return match[/* v */1];
}
} else {
throw Caml_builtin_exceptions.not_found;
}
};
};
var max_elt_opt = function (_param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var r = match[/* r */2];
if (r) {
_param = r;
continue ;
} else {
return Js_primitive.some(match[/* v */1]);
}
} else {
return undefined;
}
};
};
var remove_min_elt = function (param) {
if (param) {
var match = param[0];
var l = match[/* l */0];
if (l) {
return bal(remove_min_elt(l), match[/* v */1], match[/* r */2]);
} else {
return match[/* r */2];
}
} else {
return Pervasives.invalid_arg("Set.remove_min_elt");
}
};
var concat = function (t1, t2) {
if (t1) {
if (t2) {
return join(t1, min_elt(t2), remove_min_elt(t2));
} else {
return t1;
}
} else {
return t2;
}
};
var split = function (x, param) {
if (param) {
var match = param[0];
var r = match[/* r */2];
var v = match[/* v */1];
var l = match[/* l */0];
var c = Curry._2(Ord[/* compare */0], x, v);
if (c === 0) {
return /* tuple */[
l,
true,
r
];
} else if (c < 0) {
var match$1 = split(x, l);
return /* tuple */[
match$1[0],
match$1[1],
join(match$1[2], v, r)
];
} else {
var match$2 = split(x, r);
return /* tuple */[
join(l, v, match$2[0]),
match$2[1],
match$2[2]
];
}
} else {
return /* tuple */[
/* Empty */0,
false,
/* Empty */0
];
}
};
var is_empty = function (param) {
if (param) {
return false;
} else {
return true;
}
};
var mem = function (x, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var c = Curry._2(Ord[/* compare */0], x, match[/* v */1]);
if (c === 0) {
return true;
} else {
_param = c < 0 ? match[/* l */0] : match[/* r */2];
continue ;
}
} else {
return false;
}
};
};
var remove = function (x, t) {
if (t) {
var match = t[0];
var r = match[/* r */2];
var v = match[/* v */1];
var l = match[/* l */0];
var c = Curry._2(Ord[/* compare */0], x, v);
if (c === 0) {
var t1 = l;
var t2 = r;
if (t1) {
if (t2) {
return bal(t1, min_elt(t2), remove_min_elt(t2));
} else {
return t1;
}
} else {
return t2;
}
} else if (c < 0) {
var ll = remove(x, l);
if (l === ll) {
return t;
} else {
return bal(ll, v, r);
}
} else {
var rr = remove(x, r);
if (r === rr) {
return t;
} else {
return bal(l, v, rr);
}
}
} else {
return /* Empty */0;
}
};
var union = function (s1, s2) {
if (s1) {
if (s2) {
var match = s2[0];
var h2 = match[/* h */3];
var v2 = match[/* v */1];
var match$1 = s1[0];
var h1 = match$1[/* h */3];
var v1 = match$1[/* v */1];
if (h1 >= h2) {
if (h2 === 1) {
return add(v2, s1);
} else {
var match$2 = split(v1, s2);
return join(union(match$1[/* l */0], match$2[0]), v1, union(match$1[/* r */2], match$2[2]));
}
} else if (h1 === 1) {
return add(v1, s2);
} else {
var match$3 = split(v2, s1);
return join(union(match$3[0], match[/* l */0]), v2, union(match$3[2], match[/* r */2]));
}
} else {
return s1;
}
} else {
return s2;
}
};
var inter = function (s1, s2) {
if (s1 && s2) {
var match = s1[0];
var r1 = match[/* r */2];
var v1 = match[/* v */1];
var l1 = match[/* l */0];
var match$1 = split(v1, s2);
var l2 = match$1[0];
if (match$1[1]) {
return join(inter(l1, l2), v1, inter(r1, match$1[2]));
} else {
return concat(inter(l1, l2), inter(r1, match$1[2]));
}
} else {
return /* Empty */0;
}
};
var diff = function (s1, s2) {
if (s1) {
if (s2) {
var match = s1[0];
var r1 = match[/* r */2];
var v1 = match[/* v */1];
var l1 = match[/* l */0];
var match$1 = split(v1, s2);
var l2 = match$1[0];
if (match$1[1]) {
return concat(diff(l1, l2), diff(r1, match$1[2]));
} else {
return join(diff(l1, l2), v1, diff(r1, match$1[2]));
}
} else {
return s1;
}
} else {
return /* Empty */0;
}
};
var cons_enum = function (_s, _e) {
while(true) {
var e = _e;
var s = _s;
if (s) {
var match = s[0];
_e = /* More */[
match[/* v */1],
match[/* r */2],
e
];
_s = match[/* l */0];
continue ;
} else {
return e;
}
};
};
var compare = function (s1, s2) {
var _e1 = cons_enum(s1, /* End */0);
var _e2 = cons_enum(s2, /* End */0);
while(true) {
var e2 = _e2;
var e1 = _e1;
if (e1) {
if (e2) {
var c = Curry._2(Ord[/* compare */0], e1[0], e2[0]);
if (c !== 0) {
return c;
} else {
_e2 = cons_enum(e2[1], e2[2]);
_e1 = cons_enum(e1[1], e1[2]);
continue ;
}
} else {
return 1;
}
} else if (e2) {
return -1;
} else {
return 0;
}
};
};
var equal = function (s1, s2) {
return compare(s1, s2) === 0;
};
var subset = function (_s1, _s2) {
while(true) {
var s2 = _s2;
var s1 = _s1;
if (s1) {
if (s2) {
var match = s2[0];
var r2 = match[/* r */2];
var l2 = match[/* l */0];
var match$1 = s1[0];
var r1 = match$1[/* r */2];
var v1 = match$1[/* v */1];
var l1 = match$1[/* l */0];
var c = Curry._2(Ord[/* compare */0], v1, match[/* v */1]);
if (c === 0) {
if (subset(l1, l2)) {
_s2 = r2;
_s1 = r1;
continue ;
} else {
return false;
}
} else if (c < 0) {
if (subset(/* Node */[/* record */[
/* l */l1,
/* v */v1,
/* r : Empty */0,
/* h */0
]], l2)) {
_s1 = r1;
continue ;
} else {
return false;
}
} else if (subset(/* Node */[/* record */[
/* l : Empty */0,
/* v */v1,
/* r */r1,
/* h */0
]], r2)) {
_s1 = l1;
continue ;
} else {
return false;
}
} else {
return false;
}
} else {
return true;
}
};
};
var iter = function (f, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
iter(f, match[/* l */0]);
Curry._1(f, match[/* v */1]);
_param = match[/* r */2];
continue ;
} else {
return /* () */0;
}
};
};
var fold = function (f, _s, _accu) {
while(true) {
var accu = _accu;
var s = _s;
if (s) {
var match = s[0];
_accu = Curry._2(f, match[/* v */1], fold(f, match[/* l */0], accu));
_s = match[/* r */2];
continue ;
} else {
return accu;
}
};
};
var for_all = function (p, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
if (Curry._1(p, match[/* v */1]) && for_all(p, match[/* l */0])) {
_param = match[/* r */2];
continue ;
} else {
return false;
}
} else {
return true;
}
};
};
var exists = function (p, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
if (Curry._1(p, match[/* v */1]) || exists(p, match[/* l */0])) {
return true;
} else {
_param = match[/* r */2];
continue ;
}
} else {
return false;
}
};
};
var filter = function (p, t) {
if (t) {
var match = t[0];
var r = match[/* r */2];
var v = match[/* v */1];
var l = match[/* l */0];
var l$prime = filter(p, l);
var pv = Curry._1(p, v);
var r$prime = filter(p, r);
if (pv) {
if (l === l$prime && r === r$prime) {
return t;
} else {
return join(l$prime, v, r$prime);
}
} else {
return concat(l$prime, r$prime);
}
} else {
return /* Empty */0;
}
};
var partition = function (p, param) {
if (param) {
var match = param[0];
var v = match[/* v */1];
var match$1 = partition(p, match[/* l */0]);
var lf = match$1[1];
var lt = match$1[0];
var pv = Curry._1(p, v);
var match$2 = partition(p, match[/* r */2]);
var rf = match$2[1];
var rt = match$2[0];
if (pv) {
return /* tuple */[
join(lt, v, rt),
concat(lf, rf)
];
} else {
return /* tuple */[
concat(lt, rt),
join(lf, v, rf)
];
}
} else {
return /* tuple */[
/* Empty */0,
/* Empty */0
];
}
};
var cardinal = function (param) {
if (param) {
var match = param[0];
return (cardinal(match[/* l */0]) + 1 | 0) + cardinal(match[/* r */2]) | 0;
} else {
return 0;
}
};
var elements_aux = function (_accu, _param) {
while(true) {
var param = _param;
var accu = _accu;
if (param) {
var match = param[0];
_param = match[/* l */0];
_accu = /* :: */[
match[/* v */1],
elements_aux(accu, match[/* r */2])
];
continue ;
} else {
return accu;
}
};
};
var elements = function (s) {
return elements_aux(/* [] */0, s);
};
var find = function (x, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var v = match[/* v */1];
var c = Curry._2(Ord[/* compare */0], x, v);
if (c === 0) {
return v;
} else {
_param = c < 0 ? match[/* l */0] : match[/* r */2];
continue ;
}
} else {
throw Caml_builtin_exceptions.not_found;
}
};
};
var find_first = function (f, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var v = match[/* v */1];
if (Curry._1(f, v)) {
var _v0 = v;
var f$1 = f;
var _param$1 = match[/* l */0];
while(true) {
var param$1 = _param$1;
var v0 = _v0;
if (param$1) {
var match$1 = param$1[0];
var v$1 = match$1[/* v */1];
if (Curry._1(f$1, v$1)) {
_param$1 = match$1[/* l */0];
_v0 = v$1;
continue ;
} else {
_param$1 = match$1[/* r */2];
continue ;
}
} else {
return v0;
}
};
} else {
_param = match[/* r */2];
continue ;
}
} else {
throw Caml_builtin_exceptions.not_found;
}
};
};
var find_first_opt = function (f, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var v = match[/* v */1];
if (Curry._1(f, v)) {
var _v0 = v;
var f$1 = f;
var _param$1 = match[/* l */0];
while(true) {
var param$1 = _param$1;
var v0 = _v0;
if (param$1) {
var match$1 = param$1[0];
var v$1 = match$1[/* v */1];
if (Curry._1(f$1, v$1)) {
_param$1 = match$1[/* l */0];
_v0 = v$1;
continue ;
} else {
_param$1 = match$1[/* r */2];
continue ;
}
} else {
return Js_primitive.some(v0);
}
};
} else {
_param = match[/* r */2];
continue ;
}
} else {
return undefined;
}
};
};
var find_last = function (f, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var v = match[/* v */1];
if (Curry._1(f, v)) {
var _v0 = v;
var f$1 = f;
var _param$1 = match[/* r */2];
while(true) {
var param$1 = _param$1;
var v0 = _v0;
if (param$1) {
var match$1 = param$1[0];
var v$1 = match$1[/* v */1];
if (Curry._1(f$1, v$1)) {
_param$1 = match$1[/* r */2];
_v0 = v$1;
continue ;
} else {
_param$1 = match$1[/* l */0];
continue ;
}
} else {
return v0;
}
};
} else {
_param = match[/* l */0];
continue ;
}
} else {
throw Caml_builtin_exceptions.not_found;
}
};
};
var find_last_opt = function (f, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var v = match[/* v */1];
if (Curry._1(f, v)) {
var _v0 = v;
var f$1 = f;
var _param$1 = match[/* r */2];
while(true) {
var param$1 = _param$1;
var v0 = _v0;
if (param$1) {
var match$1 = param$1[0];
var v$1 = match$1[/* v */1];
if (Curry._1(f$1, v$1)) {
_param$1 = match$1[/* r */2];
_v0 = v$1;
continue ;
} else {
_param$1 = match$1[/* l */0];
continue ;
}
} else {
return Js_primitive.some(v0);
}
};
} else {
_param = match[/* l */0];
continue ;
}
} else {
return undefined;
}
};
};
var find_opt = function (x, _param) {
while(true) {
var param = _param;
if (param) {
var match = param[0];
var v = match[/* v */1];
var c = Curry._2(Ord[/* compare */0], x, v);
if (c === 0) {
return Js_primitive.some(v);
} else {
_param = c < 0 ? match[/* l */0] : match[/* r */2];
continue ;
}
} else {
return undefined;
}
};
};
var map = function (f, t) {
if (t) {
var match = t[0];
var r = match[/* r */2];
var v = match[/* v */1];
var l = match[/* l */0];
var l$prime = map(f, l);
var v$prime = Curry._1(f, v);
var r$prime = map(f, r);
if (l === l$prime && v === v$prime && r === r$prime) {
return t;
} else {
var l$1 = l$prime;
var v$1 = v$prime;
var r$1 = r$prime;
if ((l$1 === /* Empty */0 || Curry._2(Ord[/* compare */0], max_elt(l$1), v$1) < 0) && (r$1 === /* Empty */0 || Curry._2(Ord[/* compare */0], v$1, min_elt(r$1)) < 0)) {
return join(l$1, v$1, r$1);
} else {
return union(l$1, add(v$1, r$1));
}
}
} else {
return /* Empty */0;
}
};
var of_list = function (l) {
if (l) {
var match = l[1];
var x0 = l[0];
if (match) {
var match$1 = match[1];
var x1 = match[0];
if (match$1) {
var match$2 = match$1[1];
var x2 = match$1[0];
if (match$2) {
var match$3 = match$2[1];
var x3 = match$2[0];
if (match$3) {
if (match$3[1]) {
var l$1 = List.sort_uniq(Ord[/* compare */0], l);
var sub = function (n, l) {
var exit = 0;
if (n > 3 || n < 0) {
exit = 1;
} else {
switch (n) {
case 0 :
return /* tuple */[
/* Empty */0,
l
];
case 1 :
if (l) {
return /* tuple */[
/* Node */[/* record */[
/* l : Empty */0,
/* v */l[0],
/* r : Empty */0,
/* h */1
]],
l[1]
];
} else {
exit = 1;
}
break;
case 2 :
if (l) {
var match = l[1];
if (match) {
return /* tuple */[
/* Node */[/* record */[
/* l : Node */[/* record */[
/* l : Empty */0,
/* v */l[0],
/* r : Empty */0,
/* h */1
]],
/* v */match[0],
/* r : Empty */0,
/* h */2
]],
match[1]
];
} else {
exit = 1;
}
} else {
exit = 1;
}
break;
case 3 :
if (l) {
var match$1 = l[1];
if (match$1) {
var match$2 = match$1[1];
if (match$2) {
return /* tuple */[
/* Node */[/* record */[
/* l : Node */[/* record */[
/* l : Empty */0,
/* v */l[0],
/* r : Empty */0,
/* h */1
]],
/* v */match$1[0],
/* r : Node */[/* record */[
/* l : Empty */0,
/* v */match$2[0],
/* r : Empty */0,
/* h */1
]],
/* h */2
]],
match$2[1]
];
} else {
exit = 1;
}
} else {
exit = 1;
}
} else {
exit = 1;
}
break;
}
}
if (exit === 1) {
var nl = n / 2 | 0;
var match$3 = sub(nl, l);
var l$1 = match$3[1];
if (l$1) {
var match$4 = sub((n - nl | 0) - 1 | 0, l$1[1]);
return /* tuple */[
create(match$3[0], l$1[0], match$4[0]),
match$4[1]
];
} else {
throw [
Caml_builtin_exceptions.assert_failure,
/* tuple */[
".",
1251,
22
]
];
}
}
};
return sub(List.length(l$1), l$1)[0];
} else {
return add(match$3[0], add(x3, add(x2, add(x1, singleton(x0)))));
}
} else {
return add(x3, add(x2, add(x1, singleton(x0))));
}
} else {
return add(x2, add(x1, singleton(x0)));
}
} else {
return add(x1, singleton(x0));
}
} else {
return singleton(x0);
}
} else {
return /* Empty */0;
}
};
return /* module */[
/* empty : Empty */0,
/* is_empty */is_empty,
/* mem */mem,
/* add */add,
/* singleton */singleton,
/* remove */remove,
/* union */union,
/* inter */inter,
/* diff */diff,
/* compare */compare,
/* equal */equal,
/* subset */subset,
/* iter */iter,
/* map */map,
/* fold */fold,
/* for_all */for_all,
/* exists */exists,
/* filter */filter,
/* partition */partition,
/* cardinal */cardinal,
/* elements */elements,
/* min_elt */min_elt,
/* min_elt_opt */min_elt_opt,
/* max_elt */max_elt,
/* max_elt_opt */max_elt_opt,
/* choose */min_elt,
/* choose_opt */min_elt_opt,
/* split */split,
/* find */find,
/* find_opt */find_opt,
/* find_first */find_first,
/* find_first_opt */find_first_opt,
/* find_last */find_last,
/* find_last_opt */find_last_opt,
/* of_list */of_list
];
}
var Empty = Caml_exceptions.create("Test.Stack.Empty");
function create() {
return /* record */[
/* c : [] */0,
/* len */0
];
}
function clear(s) {
s[/* c */0] = /* [] */0;
s[/* len */1] = 0;
return /* () */0;
}
function copy$1(s) {
return /* record */[
/* c */s[/* c */0],
/* len */s[/* len */1]
];
}
function push(x, s) {
s[/* c */0] = /* :: */[
x,
s[/* c */0]
];
s[/* len */1] = s[/* len */1] + 1 | 0;
return /* () */0;
}
function pop(s) {
var match = s[/* c */0];
if (match) {
s[/* c */0] = match[1];
s[/* len */1] = s[/* len */1] - 1 | 0;
return match[0];
} else {
throw Empty;
}
}
function top(s) {
var match = s[/* c */0];
if (match) {
return match[0];
} else {
throw Empty;
}
}
function is_empty(s) {
return s[/* c */0] === /* [] */0;
}
function length(s) {
return s[/* len */1];
}
function iter(f, s) {
return List.iter(f, s[/* c */0]);
}
function fold(f, acc, s) {
return List.fold_left(f, acc, s[/* c */0]);
}
var Stack = /* module */[
/* Empty */Empty,
/* create */create,
/* push */push,
/* pop */pop,
/* top */top,
/* clear */clear,
/* copy */copy$1,
/* is_empty */is_empty,
/* length */length,
/* iter */iter,
/* fold */fold
];
exports.Obj = Obj;
exports.Coo = Coo;
exports.Make = Make;
exports.Stack = Stack;
/* Vars Not a pure module */

https://reasonml.github.io/en/try?rrjsx=true&reason=LYewJgrgNgpgBAFwJ4Ad4HkBCApOBeOAbwCg44B6AKkrnTQCcBDBASxADsBnODuF9hDHrtGUOPRgoJnGAOZsuPAGZwAbqIgxOAOlJkAciARwlIeogAW8AMaNOEUXAgz6uyuQDce5GkReyMAAegsKOElIAXHAA5Iz4AHyI+HAARACkLGCyrMgp-nBBISJiIABGAFZRxniJscnpmdksufmFQsVwwIwA5izWUXU1MaX1GVkCzUh5erDGLJwA+qVQINYA1lUJcKUgIFCtwe2O8wv8CJtDO3ujZeWni2fTAYehYgg9F4ln9bbAUAu3BbvbpPAovDqcFgALxgnz4AhuFQWkJh0z0VEoejIcAAwiBgCgIIJuAgrIgjI4UfAABT8OAAdzMYE4ABp4dYoBAwPxupZ4FZGFl6JwAJTKOCiKBYsgClDbFbrbiMazWLSQ5bwJT0fF8iX0boQYDZbRkADK71YtigUCQ0ol1tWzBgYHlqzWSokYI5XOdumxZAAAqb+Kq4AAWbQABjDencejar3EMGVFkYGoWjPozLh3wIKV+-0BEhTadgGaZnFBCY6ShYMCgYCi1IQbLOYqG1VSaUBtfrYFBGLgAHUrOwnJD2LylFBGMBSmBGBFpQBtGQIBa9hsAXTgAFkAKqmgAqcH06BPpRskudPDHLGAwCJpfgyzdOjI1MwCvd9oVTrA0p0jicCcAgEClKyPDmPSzQWHAy7sDA9JLN+O6Xis9JsownqiPSjBINw1gcJCQo3o+7watoIrSkeZKcLO8DdCAWgmGY8FrkCPRbiacAABIgPSMCqEIbKmPQK4ccCW6tmOpJXjI4r3uRz6uoqDJWJ6cmdJkYCwAAtLILogCgrDANCQicNKiHCeYMg2OA8CkswcDcpw1j0Pe-BOtwvBySw5jAnA1JiWCs4oLASZEVmopsnJ0rGUI8i8JwFggNALqXiBjBKDAPGmhA1hwc4LHYfA7AcDAcmwJw3CuUREBMN0vrSgAYmxQQMAgPnsDaS7+qulUbnW24FMYji2GOmVdFkWU5dsSAmP5oEMkwKAoDyuqvus8LSoQACEpoEdoxmMAAjpopzjDkSAAL5spwIASuwC38GJXSsLwaZpXMXVwERAjZNwMHWnA5UINKmVSCd3T-m45DxuClKDZujZBS28Lowg7aJBA7DNIidwcSjVaI2IkkfGjMlY1suP43mBYAki5MggcRSOIhyFbRsQVnFT2NJPTs6FkiXMk2zYiQCgcKdvmQuM3ckti0cbz0LjtiCE26NtjTeMywzgIIKr7DqzASuJoKYAAkoShrprbIAJICAAzAATNo1Mdj8cuAhbVs25VoKzItwrruV7ALP9oGMAIEfEYbBUIGYnHdFEZz5EHM6gQsYex1w7wx5H8fWIn9DJ6nAjp5VcAzlCSBlxjlfGByID2BI9dpzMVe3DAxftxXndzOwtaBH3CCN6x9B4Vmo-j+VyITTPA8ShBhvKuuwLl2PS+gR5k6L2QQdgGl6Ybw3S9H+BZbYUwdenx3B9V9YziJ8A+-wQGjp-NoWRSD3-6pAAJUkDOVUGUFpP1AviZO2gUhbiXrWYob8g5nCQV3IkVsFiylQcYXGogWDdEQpbO+-cyA+HgG0LgChc47wTmYfIy4Az8CgPweAuF8KcC3OPChkIODUKLiXAYcQhjcKoYXVWxc6FLxEbwkQRoojSPDmI2h5ghg7x5Fww4lDeGZHkZonhii47iJLlsDuN0vCgEgBFdAFQohYFwAQEgpDUCOVZsrJMkQYhCMSDLMYTQWgI3FjwGxAtahCK7I0CY-jniBK6L0fonitjRBGHmXxkSpiuMTCcM4cIrhiBSYCLJAhA5VxOFzZIXi4B7UKQgakjARQZI6KfaoXwESCz+PLZOZsISDVPs2PmOs6apH1kzHpPQumUnMjmVpXZARUnGWIYshVnzlmilMvW3skSLNTOmTMzJ5mLT7HbDG-MfE9mGv2BpSN1woyObzRA-NaanJGdc85+yOYoTdE2O52tPZtOFncUWlyJYQCliEgWQyNkKxBfs+OxsnS3IEA83WXt2kGyNibfZvsQDW1tpTOAjsECu3diclF-yFhYpxQHcetYQ7Z14YXaO64lESNLoFAgkZx6Z1DvSuOjK+FGKTmyuALswwAFZOWMFrsnZIIqABs49m6txgNKggIqADs49u69yFSKgAHOPV6LAR46rDAATmpWYKeRCegytFRypec83LRxVcK0VABGceaYd5rxdS7d1481F7x1aKl248L4nxtaq0VTsw3HyvvQG+vrRVhgVc-KBwbxXwK8v8IVECX7JwNTHIVbrIyls1eg7FmDkwoBdSWyMHql64OYQQ50tbS2hu8M4sEggtEGLzgK+gGie36P5co5IgQtiOOxEHCdBBwj0GpIEep0og6cBWNUO0fAVC0kWFzRdYoABkB7EA9H3ZUggWr142qPSBcyZ74gEDdWKKd-oyAo0XWySMy7X1wBugUKACkX2vsCPkf0ZiV1V1kfAPAm6WDbtKd+aka6jCHuPcCJD672wXoqD3K93Rn2brfecjDRhP3ftfX++sgHCPwnUMwy22FujUhSNY8o2gFGjpZSkcjYHQNbrRqeqDWGQKGx5MnAjP7qS3BI1jXRw7RGGOUTx39-7qM-v4HRzI5L9TMdY+xvRCn+3KO43x8DZAzPVyrhxqDyQZNydkCO5lJcRRREDbyGo8UKjBWI-OmTIoyPkaDhxzItnkPnG7Q5wzNCWUuYxgkTz5RvN9mpL5sL-m4BPuXeBix0BHJdpxOgdAyQp2DgAbjPSpl4D2DWmYYwIVL1KnYC6DkdgZA6GlAAQRBkoNWH1FB0lJPMTo4Bct6k1GxTgBFBDAHHPADgNo2RgwnnyaUth7COGKq4OA7h8iDkIG63Emc2t-p2523wwJ8hkOrmmesl2u0UVgHd3wRpSRPZcWdubFQ3t-RWEq8ehJlh9AWC91KlsZzoVc6JycWwLsOqQsDyqoOqgqSGOD27cPkLqA8s+TWz57pQ-wyYkhlnjDvJB+ARYWOWDPk4H1bEzY8d6hvkhgn6Xr74RZ7vfD-N2dIGpGjqAgWq5NXXFTnHAmNT465-ze+JO4Ai4WGLjUtOJewCwgmjnbmRQ8413zts48Ffk7BzdqAuPJciel1sAXBvBpG4WALlXDPze885zybXWwXcC6F8YQ3iPwBm7V9d9C-MQcBtt371GTvA8C7ZCDpFzQw-riN47h7MB1fM69-HreD9SfXwEgHtPTPNes-T8X6Xpe+da6z+PGC4xkcagGdnuXvt+DNGp8wmE9AC9sluI36v59DTAFvuL1PCriyCE4hqKILutcw+fIW5oEcjv14ikMR5haNLNFp9Kakm7U8sk3TPkvh-deu8nP5k-zOtcH8k+jKPhfbj8z05jHvFQL8-tydKbG0oXfP+950RgNYZVFrGqOnD8I-cvVXQvP-GHb-f0PpKAtkGAjsJAiod2GHVAtjLGb7VvK9DUceLoIApfVrZEEuWEIKCAt3WKFHbxGSRfVPfvHPFyQfOuEA7feAs-boKmPmfmBA+-TA4lDA2gNA5pRAAQ7A9EagIgA7VjXDTgE7TwJeIiFAJAJsQgbQbQP9OwTxfmWIMfZMCfS9FfaDRIW4fQp0eWXDAEEyJsW4agjUfmMwpeI2U4XWdvcyYUWwioew2ARguXFw3A9wzvRYYycLKTbwoJcoHwmARwr7JQ8fZVS9clJrBYAItwvBYIrwqIk9BwrYJw6JNxGQJrLI6gwnX5LsIoi5AJQowyWwQqcg8I7I4EWKfpco9ISouoqwfZSomQKAJQEooPesElFJHo+sJQUEBhcqSUVYOBAoxMBXAHZhawBHUkf3IKOwk9MoxIRVBqaDCFdpBYy+IHI3AcKQ-bOAI8FSTomABQ77VPTgTlXYNYEFSfaqAvSCF3HYiQd3DsGnXbM4g7TACAFgKAVgRQROJMSAUMIiGaKkW4peBXQuOEL4mAG3UXbCTeLYFEtEhYWQVQL5AQVo7Y37XYnEkHKIAXLEkkiQRPRXDEuLIYbEpeRgNaPhTWIQj2YkluUk5k1krHdklA45Kk7kmk3kmtPEgU2gjGIkn7EU1EsUlYiwSUsQwYwXYUv7BUwuNkoKBAzklUzGfmJkpglkmtLU-knUg0jkmUo05vVkrUiUi02KE5Fo6UoUxk6k+U40u0uORUpsXU50lUr3dUnkr0mtLHbU6kf0oQu5PUm0oOE03E9gVQCMqMwU75Qk+5YM0U0MxUlMy0wUmPTM90uUggxHclb0vOJsQs2Mj00s0kcssM+k-nE3a02speEHBsxM-EoKQs9Mmsks9ssshM8knsls1Uw0tspgyoiM5oyI1sgcqcwyOkrvATLg10n5LkjUxclIh0hnNcvs+crcuXackcvctkXsxFLMz0xALte8cKfAaUAAHzgAAHFKo8Q84nzXzKoAA1bCL8t8hAAAUSTIAsql3ERy-NNF-P-P9GfI6zWg-NAi-IQpQD-PEjgrgFQpAtUBQrWggtJDwpQCQoQBIqIpIvQvIrjhwqorzgIosCIvQrIswuwqTOYuxHgvwsR3YrIGfPotQp4rgD4sR1Qsoswv4rWhovEpEq4sIswugqa0EufIUrADEo4rgBUqkvUpUvoq-JxA9OpBRPIz2wOwAAVsIGIQh5DttFCnFfAUALLgBuAHFpRlIG8iICQfVU8ohckb9sQ3KIplC64HKJABAfLdgoA-KyAAqbBYBnV6RRxY4VCeRwq9gorOgnwG8JBDZWC0owrpTXLMqIpSgCogD1xOAuhrRkRJkCrzN-tHKVcQrZwHjJCaBzjzR5BQI+hrLTs7KqsLRnKiBVsjstBN50rk8xrAI85lyVdeY9ALNV0BqohHktgo4uovBssRsIo8QQAogCsisXKyAEoxxWMvBWqpDZDi53FpBsgkoxxqBqB4Y9BJiQBpjrAdxqwrlLpBFEkwlZZ2kOJdhLo0QyAMQLqcMrqgrtsHqnqmCoaL1J0INjBHoCA9NpM9NJZqQ9NfMQBtdlMOJMgpNyNwNzqaA8QCRpB9EeATIFBuAHq4xQaaBzKmAXsLIbKPs4AmqnLitCrU8-p8QHLtVxdfLearjjJgrSp8qRb-QYqftkxw4ErZAkqkAUrtgIrxqir4Bsr6BcrcZws5qZbNbthSrBoKrJRqqYRJq6riAl4ubBqgMPLBa8DYAqhVY09VtxaFgQrshXbNB0qOR5aMxEqgrVb453b-Rtbdb8qnZ0qSr1hTbKr-gqQog3VZU-KSbGaHq4BmbLK2b6bYa5dAjRBLDe4qQZUzrM6pD7Zps6aYaba+q+BpsHzMKAARFgjrL8tuh8JATATulgnEWkRFehLuofDrNkEenu8e-u6kL9ThCgGgCExgVQEAELKePGScOmguw+Fg04abVOJuggWJPoakZdUmi45xWux6+um887Hob7SkggWXK7FE5IZoGAYAO45u9Sieju1ulg3uv+7uge-XZ6n+qe7uzAcBofAe2ejwee8kCUZe1e7Cde7oTe6+q7XvAgF3CQuYjobKrI36icuU0YCJa6EG+erOgAGRN0vrjFtqOOWLtwfpAmR3c0SCA3jJVAgGSAkCUBnuUxClpHhDgEjAQfNC520FgEnFJCQzFD0gywk1fWVCfjgAiFVRdidm2wlG4YAD04AABqXEVMVwGEmAJDbQZcFgLcZTCzRmyEgqRyR6J2A7UoLfdm-0FRnh9RnRp+fRmcJrIKA7ADMQFxuABRp9PjKgAAoAxu29FtF0EKWVMMbYdx7CQqN+4uXY9B-0IONlWDbdLx-RxIEtNVJ2NVMMN1XVTRpRn9Ip8JjLauNdOAFxvjczVTeAIDTxvRtp39KJpm3eBAJQdjKQM4FQdo5INIMAAAHXYBSBAk2LgenGcDglAiFEHQ8f8p6GPuBGJorsoakNNBCoUl52hqvr0BywinQuculF3BZO0DuaAOpC6ZvscmSDc16aDkdtKls0CCqDZCQENIFtKg-TgEBdM3Iyuyx0GuufdkHokIua2vgHopuf9DuZQAecAPMZeau07A+c3S+eBc9AIEXX+bBaBc8okFBfBelBukha7RB0GpRbha93yEufgBoYgi-rIHRcxaeZxfu2SGtwJcfiJb2NJZVMBaxLFepdsfpd8HB0Gs5Z0BqVyVPvsdonsgJBBKEAlBqkNBYicmMC0hpWWhRnFEG24GizAk9CG1XHMm4k2dxZRyGsNr5uTtqv8qNomqLz5yMo1r5uTyWDrigyiEZYDZUiDdKDrgFwpK9QjYb1-lUDYGcFIO8jAOnXmBqRo13x-RlsR1ZBowPnjaLerizcjN7Om213Sp-WhZrdfWYVAmbOD3rdyfLevxo3f1fS7eiqNosB0iVsZYpPLebfrFbCrZ7Yyr5rrdFobyLo7wsmHabawZxl1i7Yzrl0gG7teL2KAx9eXEfK3aH13vfsfOklcoj13RDYYiiGZffpMiQHGsveDftxNyiGVfYwJGQHSqTZTcWDWtGvgnPf9H7bAHGEVJV2XGA+xGhaiFhfve-amrbwyMXaA-So9cjHTv2byeWXqmmT4YEf2eiaPbrhexAlSnSm2FYU5pXoBnoHukemKieglBfk2e3u3Ze33vfuSHRrQPeT3Uw9Ee13+P4yyBKu6F6GhyG0QmdGdFin7cIjSgbCo4lHl12BdEaEXE2eifY+PbI5PuSCUEYBBJglJFSH3CaxgAQTIgj3mfoaYIkGsEWnKvMmSDHA839DgyCjHAAB5VVansR2BTMOnXXX1awXOYRIyxwjGn0KBhUxQaAO1eNr6g53k+aCAAdX30JnKOGpr3J79Y49blMM5ZBkgOtdcpHZBuhZHMuHdiuq5k8yuKvCDzHpHtGXZDHhU2QSOVjlNk9lxIwdxD7tnrB+dZA+vL3lw3UhuAC4lvMIvWvxvtHDodBdkLb4ByA4BdUGnInpQhGWARGxGIS2uImAvorJuDvEvOunYZuj7RvavaGrGbHTM+MXnk962o3r25E9wC3P2H2Pvn3o2sv6x32vU-vEOf1f20p-2LRAOoP63QPwOh20PN1YO4B4Ov3H3YN0iF3PCUef0PX52S6Fv0qLMN2g5pBXOSXedFt4cqR+ZOGu4Gx1umub5KuZGLBalmvL3lMvPqR3ky7TDmf6fQvcnIN4c461hWf8JtAWv+e6fzJuud6XtlMyByu2fAcaledZfL3P1afOZSq9eeBhfzJVffWdfVjmQ3OJfSqXv5rsOq5CROwueb5zyxz6x37sgGfpRKfIuafVTOvdvPHufLfOBlwBcZuPejRicN2wayaRq6Gt6GuI9Cv8OrPCOl5+As5wy8POwCOv0iOF7BWGbXnOhEdX7psHfSd4cjdkh0vcuxfB4shZ0sKKvpHqvOfU8LfQdRQ+NffzH994Rm-A-efLOQN7eUvhdw9Lfge8lEDQYGI4DsQcqgpmWEEwB+eGJoju+KcX2hMAvnzDBrk8qXQPOG2q4WGycI978zeu-Pvs4GJkhmWLZN+jQ3f0Jt-7+hNem7-AeY2TdkgH7F-tWTdqf8-+s-M3sK2S4Ilp+oOWfoNX4IL8jQooeLP6HV4y8ugKAakL7hn4C4b+i2BiL30n7GAOItfEloP0LJR8veiNTzsbAXR25c+vPbdB+3X6jtIqORWADv2ZAvtM8ovbEE70QGUDYA0fXBtiEowAZOme+Z8NoER6DsC2yQZcGwLZBUDEUbIDQu7GkGyDw4jLThLS3yDk8p+SeCPLZgoEm4l+pCHWkFCoZZttArWVYEoI4G5QtBEHd3EBkP5GANwJ-OfJRH64R89BxA8kPbizblIE0qA7EHz2vj4A8Aw3Obl+jO5AdguVGSQT+nQFIB3YIAIIU22vi2Mq+C-BNAJBMGM462agfyEYNJCQR-o7kFwTQOnRVxoWdfDIY2xqTQtqInjQJsm3oBlCLAg1ROJkOaGlCXBP+QJpUNLiMsGhfQwyhwCqGMt6uxgDoV0Ky5KsbBmA7AbAPACz98BJQzoS4L4yEs6BuZRVoAOWEslVhXQ9YXgIYJsgRhOw6UF3yh6psAOg1ZcJulzZ5tf+ofPflvxozvCe+PAlst8M0EDttBBbVto4O0Azs82WwhYYq1BEQju29bdQXcIkDJtoeabYkOlV0H+gu+9QmDD+lhamAGwrwyTODhkimBYoLQsIZCL57WDQIOvYAM2zZAtD4heI7CDoGAFphSRIAckayLN5gYQuLzH9AgGha9MwMoI7EayNBEY9-um6WYfNAf5GheG6fO9pj1lFA8WGBHD9ghxpb+gaRCAbQG-XoAuwiR9OF7O-yGI1CP8X3eAD42f5gdqQpo1UmyCB5QZdGvIuUZSXUalsgBdo0tsWw-6+jEAlg6kCwP4Ab9qy0g+-rwIFGvp3Bx-XGKf28Ru0Axd0AMWqJNy6NQRZAM3imJ-TXDw2m6PMWWRhFf4+Muo-USECNEvCHRQZIYNGOdGP8bRv3F-tWLHL1ijQrokUe6IAE+NvRYYsckZwkFOj-+6EDsZuhzGvp5hEHetpOI7LFj-QymH4bvzbF7FlxujPjIuO4Fpj0IyQLcfWDXG3DARYHOQeUO5bYgyxBIy2B5G6AWBs2kIithyLgALAxQ2hB0RYGADmC821I5Ye-QZFQiDhXqVwQGLfGdj2mSQvgZCOXAOj1Bb4zEZCN-RijDxSPEETRnh4yj9BuQ2vKVwID18+BQcakMuKHGz97oS9VtM4PDZZRhIlsYoTOJBFqAeRp4sgGWIsAb8kRQkP9miK0Dqtl+0g+4TD28hHDaRCAKAPfm0C8SOJRArEdIJxGbpzxewMHFZ1vF5skMjI-mLCxf6qA2Q+I0MdSA0lgiWh90Sdv6HoiUSZqsIiUWhIPE+DwBNmAgMuPXERjwBLDXcfsEsmcCyJ8g3Ea+lknM8rxN440RwRJGPjnx3AV8e+MpGfjmB34+kYFJonlDAJcE7EMBNLbiC1MCU+CFBI0IwSQJ8EgEZRHcnlDQRxk0iUCKnEWTraGOZEOujr40FcJJSMftVMohUh7JjUqnkPyCCB8+MoYoIOhICHvIlcq+efkJnCkr9qQWkprK-0LzijhQ8U9Skf08HxjwpTBLqS3wF7rob+vTPnjZj2h5huM4E7iZRBxHo9WRtgu0VBhkjN9t+LQ3pnY3CFj87eS8Xoac2wahCz+ZACIS9NRpoE7uAjeIQezPaJCJBe06+PdKYJX8Ph-UliOQMZzkS6MKA2sUjTL4njsJGQl3DMN2GQYxhBAVIezw772iC2rQ7ENHBdBJlRAg1bGe31kawzZR0gaXmkLl7sAxhRjEmQBjIx8Z9uh3BBgzPkGnc9p0gJ7skBwFwCLh0Mgtk9xyF7c2IwjOkEd0ejMzuAPMl5nzIO5MydB1vTHNhGpwahEBsMsWXbwjpaAepMA9EtjgbxQzzcQ016YGIWijTjprAs6XpJ5EH9TwHg0wAtKGCtYhANSAcTIAJnlSmCCuCGQgMH5QY4Z8QTrM1xOEByNZz4TYSHK4nxkwOrhZDrj0KHm4lAH4rvvOw8JPClAagjQpnJx7ZzdBkhLEOyzgAABpGAARAYm8tHm5ja1qX07CBRTmhLSljSD+bUwFoBAb5p6AnQLRDIvsoOEAVI4slFRKgSuUdC1FYgg4CuYeZsW4BccZsnk5fpYLu5BQJ5OgdfvPMqTDzgco8thr619lkBTOcEOaa7MCZ6Qw5ebXeZgLUYEAN5J0l0MCBJA9BuAe0G+SyRFFrzn5WIeznLncgGFlU6XTmow0VIU5wpfPRYscUvZRCYhx9OIXtLS4xy-pz3WlvyM3TRNlwUCphpex3CPhlomUOkHYFVBNYNoTIXViFGjaCAzGmzRvtvKxkRysB2CsBcbg-4gLAcOC0PpAKrjAKkFWs5+Wb2xkGiWA-k+nCwFjyVRveCUjOGmFfrtdOuSXOCRuKvbyi9itojfi2NKBgCPhy4t0aQgck6Lhx9YBiXm17G-iw62i34c5LdHjjIeoC97mVNfSj5-BmfXWMQRqgNTV8DfW6dn2wip9jAPjLPsbP8X6MjGXfMuhE2amcCs5wRASXqOREiSYlFkZTP30QFaMjG305RVNxsbaNU6cXFbtoDW709DZS09gJvl+jLz6cLWRkaTMZEDDyJhYgqUFAWD3QQUIkR8coKTLpZE4KAKRYFzzz0hDKM4GpSzL-ENKphow-GejMHh0wCmaMYyMyJAhtKF01SgoF0uunoLIR2NSQAumqxCAhldSbMXxkwnsADlymbGZUOYDUhnhP6A9r5lwIigz2H3EbtSGxkrCo5Js2AGctigozT8VM2LC7jbCGTW+bPFYTRgZlbBfMgs8AAcrZDQrWF9YWFaDHfGxZ-W3w35czkaXdDgVk7VBX7Llwtd3FCAzLg0qOxJy9SjPY1i6wAUWFU81IElVMoRl4lyVyQNguSvWlIcmUR2DlfAWZW4EsaaBXzHEKuFkrcCnS5MmKuEJsYhVwnCfhzVwI7seabrFSHyt1j-NZ2gVUVWqscEYE5VTBQlWysgTEsgoDKppWyslUKqGCFouXMAppUT46Vpq7FdMrWUSrkU3crVc0B5W3TF8bBL1W9LcVd9zVbqn7CQVwKdSA10g1VYMijVN4DBxgHrmwSFarBrVQceMVZ2SALBIVxnGQNSAs5ZBrOl4nuA1EhDCRgcSLfnKsFlXwE9M30tNenLZB1qG1lnXOVKu0Ayq9m19OPlKrkJnM-5XzBIsT08UmE+B0TAABrjqsKa0YxTNGXCAguYO4Z8jiElAINZ1IsVCGQBL5MEsGra-johjRoQ08M2-YpdKDHUTrUK06+AMuAZgWI4MSABdbiGXUQkr1csG9UoDvW0LW1RMYjBsUE7bKpAIk5PFWuxD7rEsBNDfo-g7XxFAFxPaws70BCCcrVlsvngKrYzfT4NsWNVvEPg0AzUp-oU9aOsnVoAJYl6udeusXWPrHoq6gFOuo-VbqKgyQPTLurdAobjoB65OEetN69N8NhGi9fBGvXgBb196pdSDCfX8buQb6ncJuuA1oEv1yWH9QIV8zKKgN-oEDUhkGiE0INIM-wj3EbpCANwPHejZbJ6zsAvyUHLYCfVM0tr1BUAIbt4p-T8NH8nYg0RuEaLnkjlAQtIsnOzm2YNiiGuzYXV1g9DpBSS4UJ1PgyBbz0QHeIc5oc0RFcCEksQSUv8K4xyVQRCyLBp81IhBOvm58B+OQ01qXl6G1KoLiw1xE+RYEl5sggi3YTgthc4IhtPC3uNtpUWvaW9JCAuaNi8W9zT+nyKJaAhdqxImxqJmpEUtIWhAfBuiJ5bt0LGtDVlow0RUZp-obDWgoq0itkahmv6AOsvR+rsQnm1gCh2FCubHBZvXrfiuiZAVzoLAOjNkE5oeQzIrAYSFRwwh2hV0hkXoioF7zg4TFQUNeb3kIaXzMypzXnCKG0ACNQd4OMULcDtAl9PqZMQyAMV2a-VRglRborURTANEcta5LWJeSGCDAKiaO+oqjqazvaBiNY0JMjre1jEJiAYKYg6HerVF5ig0ZhUbgR09BiGSqUlAsEOIcKWFFDLtXzSIjWhcMCgXxmqF7XwwG6CAZYPbWlDDyogKJBNhFAXDvBjChbZVQ3kQjBBVd6dPQETMcGot1KQFTHnpWIjNhpd8cquBxGV1hJ78kEVQB+M4CmdCoUBFAW4LgBG6H2HuGqJ7OCikyYiJurgLbpOQ05v4zAMJLhWS6LlQ4hQVOdVBUnhTHdzQZ3UHr4HPkPdyAL3S4C9l+6j5i603fcWD3K5tAmuzsBHr63+zBoc8ypcZq-Lp6u5iQD2Z0N90SDc9uIfPTTkL3VRtAw8nEtbtPE17MKdezPT7u9n+7MKSFFPb8SL3W6cSJe-vbjFr2Y9h9Te0fa3on0F7vBXekvbkJKoglLYDlMziS3YBshh5kEDffDLoU0yCAE+wgHLtbXfSv03XMPVEDr208td7uzHnS2dUqIkw-DaQII0lkHdpZnM+IeYB8Y3679p+p7k-pV3iAMxoMQoC-s-3iyjJg0a3bbrZD0BRx+slqviop46aVgIAZ4jWlP22ZxFcAU-dEVDmAR4McAHzkJz2n3EcNyQ8-sYCr0UGq5Yfaxp8yriOdq4TxF4uwdt2q6PxnnbdLPKrmT7ohHBqVtGLICJ6EAyehXOgYL2LLeKH+z3e7O90r6c9pbPPYHqfF6t9dCwPvajgEMkHODwjCJifs4NUGTDYeo+T+hunlbAZchkCE7rginDs4hQIPWoaEpt6DDwUhA8ECtzmGFgw8+XsEEcMxiNDGey2ZCNS6IH9dyQCA1XJgNadX9wR8LHXq-0BiOIJejA1kb0XYhd9zPA-ZzwO7WGZDkEEvcUecN9aCWYRiIwXq00Zwwj9xWzNqFIzVGHdHhoKMobD0pZdgWMJ2RPsMPaEuj64Uw1fIbZNHLD5MqrrI1P3yMMsNhgiJgeGP2H3greofZcGBJlHmAnPBYxz2pDLGduaxyCJMaPmx96axtEEmCURk99xdAQxEnHHHSQrKo1IeWFsCXQ4kscbnD4zUhXYgqZeuMeiDlC52fGNi7AIDTPMGh4lbMheGE+FOyqNFFpIJtIWCeyjKoRcM2l5djKxMQncTGxGIrFmhNHz-8gsgE0MFRPAnRifRI7TCf-wcR-jBAdzokFRNHal0WwAk1wGxPIgoTERY-XACXT-4EyhcWzC2u5M0nPj3xoYPw1FOeo+S2ESU4tn5i0nDNiQfhryfBM4nBT2RJk2KdZIImSWLapEx+I1PlB0T2piroSb1M1ICtc3HU-yeJMRFSTUQckxSaVM1oQcqp0GOqf1NbB+G9J2LQabxrem+EfCP04EABYBmakcprU7KyNOmkfSrJoKFKbVMonAz8p0Fs6aJP6m1TsJquOKZ9K+nTTbIGM-6cBNomczlZkM4yfDMKkc+bx8s6DArMWnsziZvM-aYbPtnkzuZCU62eFPSmOTnZkwGpuJ1jFezIpos2NArJZwTT6Zis8oMzOWzLT1p3M7ab5P5mHTX0-E1ud1OQmgTbp7XB6aFPa4SxCpZlYOaXMFBFs7ZrM8eatPxHxz3Zo83iadMHmXTBZgoKebnL+n2zl5-VUOXnPO9hzcZms4kAnPMgpz5JqIJmqGBPj90-+DsgmTTP89Y8HZp8+ZvrNwXHxWwJC2+ddPZEUVKFkC+KSTK2ZhTheMKWuc7MvDcL55+CwRZFCiK1eX5ncx+ePpEWfz7p-8++PrZenBy9ZYcuXyP2YXHzkFoKIxbDPMXELrFmS5hdnMgQlyN5+0cub+hYWpLHRdHaC2ABsgeLT5sjFcOUvTl0L+lts5pcksrtN0Ol+omxfv37m2edp9856bPNREaM+lmjIZaO2P6aM1gQS0BePJLlFz6lu85ZesBaWbLBPAnVYAcuOnj6pbHywldG4+WSTf58k6CLJPeFPLoItKxET8uQiArMooK69pSJlmft95qy3RewuqJYr9cynQycyudADLHFnsz+vSyRX-87ya4kOpTWQY1ZLCnbalxMWbThsLoDrtIbEaPlnyY4RIB1wyUvKsl03BLhlllT5KjoRS03q1tBgbLVtkIsGaDh234r9FVk0PghBm4pWM+-oILnqtL53k8kYFUinHCetqV1DgFLSu9fAqQV5KMFDCupQEovWWKa0N6-4dYpl71DqFXSsDeIpxwlKhGiirBQBuIVqKoFGGyRWhvI20K2EeG+DdxuyULA8NiSrDc-LSVSQolJG+oeJufX-DxNzG+oZUrw2VKoN5SoZBpus2ms9N-w-pTlJDK5SFu4wHbgeux7C85B7If1er4hGSWfS2gflxYBm9vp18KxrozxXl7sQCh5PQUcW3+HAKJFdEzOguBZGT6vTV43nH3R8ZnygFdCvrYGtsmfDZvD5fz2UyW3KoOFG28YD2Ja2eDpOa3sEGNuboFceJakOaYtvfkEA9Fd26DF9s1IHbsAp26HegoIBrbL5ka3bb9tm8WT2EeO7RWWgp2q4KgNOzHe9sino7-tupqBeCjtnQ7FNlRDMboUF2jb3Cn24XbLvKNlTC6FtTCeruSVKLedurKXabsFAB7xd9zo3d6YJkg7ZptU93ZQAR2+7JgYe2tqjst2zeol2Rp3edsI24bLZuu7UP7sr3i7K0+28Xa7lj3D8oFvhJXZFOxmZ7iN2u0vYbte2l7R99OyPcXvl2Uz01LHFfcrNd2c7wFXu7vaYKP3j7z99+6waHsH2l7o9p+x-cjOT2NLId-+3PaAdy4QHr9sB1A5-Sp2z7cDrUiDh-vT3GKONnew-fAd0KYHoD7B1XBftF3z7jZUuIXCvvgWZ7OFPW-PfQd0PqHHt8h3veXu4OIHtD1u542NNJlL7U9yy78aIr0V2HqDoOJw+Ed8PKHGD7hyXawdt2fTZZJh53artflibsj6B7w6YJCOFb5Fy+yw70cyVsb991R8o64cQOl5Aj-NiJfbsYXOgm96m4A8MfqO6Fntqhw46MePHOyQd6i5hdDt02xLcj220474eOPYHr6VC6yQIfCn3xCdwyAY9UdxP-HdCkx702nJMOLLv9+HNcRv6b3mbKp+e1k5UcQO7Hij+Q0uW-sWXhTPV3SwwTKds2vHmTwJ0Fm6fRP4nqBnckmTCtIn9eEcVp7lvaec3InS9qp-Y4oeBOTyiOMK80+KfjOHCm9nm0qi+NBHm4Wwb6c3GuNJbXtZwq3mbMDyAaJblmUe8cdxmAbnVB3OdOnwL7SgEqOrHmPo3oPSN4hMi7cYfQu4q3i7uzv5zPweuIDyDdz2y2sJYmM5CyBzjaXQNpAoG+mna24x1VYBdVrAifDBl2jWoy7-QbBQDgbX8qXsraPi42bNUJJ3XFqzABATLZDXe6VcqeEJU+1D5hsU+ufDMVNV8V48gly5ZlxP3AyDhE7PkGyFBFIhPyL6foMgLRCGxlyHrnvAQCSDohVw+91rXYnCqu2lc4gicd4CUCzBCAeQWIYzcXBF0gBRXWkNcP+gVddQTQXWEoAwDuoivdWa4SyITM9CEgJANoCUGtCWLyBHt-PR6CRBgAGRrYchEHViE1Z8ACQwg26n1lmzcBSgogaOKAlSYiBLBhsGAFoCwiBMhsckPhmYBgBYhiwD0EQMsH7nWw+gdYfKln09ki69dRoOcBZH7Zyh3gsTSrNPJAAwwPIpIMyE5wGx0RXO2KXUGuFEhsQglyb3KBG7JD7Q65f6Y18YiczcB5XIgx18tmjgLQyEGr4SGOEYBYgr1YrHcPO4UBSu4AbUcwOO+NiwgsQhAG5TLSRb4oBA5lJaN9utZFtcWr9BEDQDOBFtW53tIKIEEw5IAv0-7t1CyCQCxdKlebd6M7tMpCB1AJarQNoB7nwAAPIpg7CfIDHYgxGAO2D-QHg+audAyHsFmI3A+YfnyTnAHdYEIyGQ7QZcp98KETvJBE7fLcxgSno+igXtDXZIOx+Y-B2l9j5BvWByCguwWQTsMUAJ4lBCfqQoqFkGqnE+CeXQ1IN1KB7dRiffZW4G6FO6GwDalQCB+kONdGzLgePlUaSAyFgiqcOYpfIz8ZwY+VR3YsxI6ioBdfigrGn7jGNxGICnZBwjsJ3vExEA2s5sKgE1r1jYj7RmPs7k0HGDLlXZ0A+riQGACPBdpDqlDC4mSEwZBflXHtmN4q8i8S7G5-xGgB1nJC6uxXBr6HEe94BmvdWFrqzNl5telsZXS73TwgEZB6RGMBrBEBV7HDLglAO4ewM7qNalsevBQA7DABdg7ghsneR6F5y0gqDfoy4GANNyegugFv43sbAUHOiiBMx8EFQIt4KBrehsaiYuF68QgwwHt8ALzgt6W+HfE61X1MN17G-QdIReu4b3t8e98ArWomY7wtBQAtw28j2y74t4m-cBugCRAKPd-giPeT3ebICoEDCgu1VO9gZoCpHIVc4TAvWEXbm7JBNREIHkJzmq6YBSgEpPc+YLwC69EA9ouH-D8JEI9isbouXpQmKyOR6lTEXgQcOgCJC+fIQBCZgLsQtZkh53oXg6HZ4i-s1ovXaU0EqpS+Rv0vw72r9a-fAl8rs9YJvIOBl9doh3Lrhn5LoK+pfyES+tcNr7lxaiqguvo8FoGMCK083iPkpNwC1FQRQYRgI38gkWAm+wUuSXX5BO44ToOEiAC30DCsDW-lwgQNCPWA4BoMEGNX4wKuEdYl8g4DbpsCr6dJbAPfrVeCBbBLu+-sqDURQHEEtf-R3greaHMurm8+QVAMf1tuFGcDwQQ-Joe2OX5D8MhtCogYsGABejdeOEbIGPx96TA2tCETgY2Pd6agAQlJWkaQNAGRoZfNQGP3gFj9K4oALABEPoJKH7mbe3glGjhOG7zYBhLwYkeABGEjBaNTKi-yEFaA28OBmEGevCNwCWwOZdiYAZ38WbA6J-QSyfjsJ74nDdBZgvARv9n+EBKu5sRCAMg6vFSybgOAQv1QZbwL12D9Y-PL1XQeQb-3YB5EUEhhxPfCQFABHtH3x3A--XP1AD+aOQCL9eQEvzq8y-diCe9-QIIFVATIGv0dZ6-GgKb8b-IwBEYK-MgJ78cAm8DVgh-Z0EIxmwMkHH8UAod2C9jYONzn8xwBfyX8rQL1xgA1-FdU39ofbEB38rOAt3DAowI-xP9l-MQGkCL-SYAYDHfD2y4B7-R-2MB0Aqrxf98ybxF19GPWmA4AjAgfwUBmfE5EsC6pKymF0bAtjmcChABwNQC0-Rj3E0coUKlVBbAvwK8D3-NPyPAKQPVyFANoS8Ba9M3McC18H1SaHgBioF0G0ItIVHw2guvQjBCgj4DaGc9NfSqEV84A0VjbkQglpFV8pCBbxkDOAA7E4A1vYkF+grfDSDl95vGoJ3AXvOoPaCJAajzX95OZyHmArhcAOM4xwLQMcBS-WwNGDTcPFD1JU-TOnYhwIS1xqCQIeoP991IRHDu8qsKuFXBrvXT3sAIILuCUBCMKP3YhxvWwL2DcUVMkSBZglLysYQgBe198TSZhBYgevCb1kgc-BBmICFfFzw4R5A6VzJBS-b4K6D4AX+CKJBAJ+Uo1evERhDBi3MhTi9CME+STBOANACuoISdILi8yFc1zS8NfKfytcRBIoMz4QgMwMbw3-VdgTw0-SCVHknPYHxaD1IFuHIQSA9b2G9GAQbhZAmQ6bnUEdvGjEYB9AUz0VpPQZcGZDpIAUPZCNCAUJ5D1vWbwZCh3GP1+C9fXEMBh1vBym91wQnb1eD2QGEOhxUfeEPM9pAZEONZHoNEKiDNQzELyxfAQQP+CSA2ULoDyoeUIRBpQ33208uAsBFVCu-B0O4B2Akfx-ROA6OGH8TQakDoDkwZ3W+hfPaUMhChscQNP8V-c-0cAISLfEIx+AJ3nk4taSqBz8bwS13DD1AyQNX8L-WQO4hojOAADAJwUMAP8D-dwMFsWSIkOERX-IsgsDyQi8XuCJQHcEdoiQZ4OCgRTfQDgAOQtsMCAOubsIOxDldQRFByA7ED5DL1QIAOwOQwIHFCfmSUK+D7Q0zzpBoQ5ME-9SvLbDj987OST9Ik-HQl+oXSWIF0JGAT3zEhyUEGDlBffeojUgvOT4LxD+fTYPBg82eiHRc31XUF-huQE2HggUAWAPgQk4SUErCrg9WhrC1aPYE98ggLNm4AzwpsKsBLwlQGcg4qZaAqhbQyfyODMvLKCfC6wAANu1nQZf0EAPwr8KYJQI0CEdwVfFPwAiZgiKiPD7jXVggje-HPwwjLXId2vCFQukBj9kI5yEfD5gZ8NfDsIy9U-C6-cv0-DUIjiPQiCgGyH7kQA5iM79CMbvyGwPQgfyWRJwG8F4Dkw+wAECcQ8n1EDCMCMI0CpAmQKfU5AwjEUC9-FQMP9s6TMLGC1-HQOv89AtZSVQH-dcLqxKIlcmDsUAy4FIjHA8kJCocgEXWoicA3Twcp-IcUGc9FBGoPugXYIcLZBRwqSLaCe-Y4IYiRNC0LnDy-X3yNZBIzgGfC4oPNi4j3wrBVM8Ogg7zoiDg38F1AAQ7FCiidwFKKPhrI9iLSiFoHKNsDPItvA4A-woCPYE9Sf0l18gEPv11B2AQ0EvBzAIdxKiYI0ANsDbALMGzQ1kDqJTDhAXUCaFxQRiMVdbw+XE1d4guz0IxI3WSNmjDvWrBvBFwugWXDYQoUDM8zOXUNwwjgg0LJAMg6HGXBYvB-2Q9eQjSEvUbo6kK0h2vEQUIxegbdwQYwvEXyxZ6fMsMQjGXK3HLYVfYyikJOo94ItdbvZaDm9Foj6NK41wHgIRCTolEPOjHorMCQ8D3VcKoIHfJgHmBC3PNmXAz5E-gm8cQ9MLt9MeWwLMhw4FXzhAVfSaK6jIY68GhiQA80MYhlo0AMRidQrQD1DI-MkGuj0Yu6Kxjz8HvHMBCYiqAc9X0GbxQihsLUVlCCwosP38owUVGlB7I7SGpjQSWDThBQiBQGcjRBIV0f5tCb6L1FTQWXn4BcSUEjuhjaYwKmjwSMkBnB9QC30Qjbw96PZjDff6K6AR4GmLBQ6YnwINjuAI2O0ATYqmPNj1wUIktiSqa2L78MI+2KahmY612djIROGJWi9RGjELCQwRWMjBlY-0FViPYkOM1iwUbWI4BdY0GJoBwY6aIQiYY1mKWjPokdxxjs1S9SJj4xEmOQi7wnv1ljhwftmd0YYx0LpC7wbgDBNkQuDDrAwAVtgjjowzQIZDgYMQEyhCoXuOWxJg0APxC4aVKDpDaY0Enpj3giuJZicQpONACRY+CEMBEIZuMhFjgmWIpiO4voDghu4wiFSgiiHvwHie4IeLk4aMMeIXiAQqeJU5Z4u+JCgF4rX1TiFY4yKzjsQVWNni6Q-ONEJC405RBiP-cKHxgsAmiP-9VOUTHChL1fnDZAQQ7IEwNwotYO6CEpcPmeiUIgaKlCko8qNTAxoXBLgkjvISQWhqoJV2jgaA7KWXB6AAhNbiiExKNYCUo0qFLYqEr11B9AFcH3oSYAxhIwSBAakJ68-dEmNYCC-YYMYCnYheKfUQ-bbzYhlwMOkkTu-aRKz5mOGGPkTKNWv3+ikQy-zMCSQvFF8p7kCiMCZ4E3yOKjt41gJ0T6A2pBVAmQQ1xPjKNG6Ixi25Gxn3jcYhSDFi4xJrEkSbQ-ryvi6vGjAIj6vSETTjL3YyLdQowf6PX4jEwCJ9i5gnr1DEMtSxJtiMIyuJITx4ldUb8HEqKG5BJwdFXgg3Eu6PSxlEw+JgAAkwNwKhgk611CTAgMCLljIk4sKVi4k1JNCIEkvUkgTi48xMthTWfu078cEy9TDDdPUADBgOAbSPb8aVFcK69W2KxK0gMIR2JhiFvHcHnCllAbzISdvAoGHCjqcwG8TngxuP8T+MQJNqS5ExpMIjZQs91Cho3QvBSSUiAZPTNcYIewB1SksViHsJ0B9AYNffD+JwCW44ODjiRBSHzWTsk0cJKSBY95JQ84AL5MG4eYAQGBJzvXqCkj4AL5JD9yk-ZPriD4l2WJj+MGAJ78+Ep0AESd3Z6CdjSogmJ+D-49OMATCMVWPX4hoEOGajTEvUiSSbgulIGSMtKkIiiHo1UJ784gcZKMBJkrMPVD9o8rxn9j9QjCsT6EyBPwCIAjaEWSBIZZJADVkwEI2S4IQbwJjdvUzwqTxYk5JqSu4kALCT2sCJIASD-IBNfRaU1JPZTOkoKGIjXItKkAiek6BLrDUkrlHuD7ooQBGTqQvlI4ABUvGCFSsgGZMyCxU+ZIyTdQftmvFFU+OOVT1koJMsBnIV712S64vGO4BfE+aWOSvOU5P1T44w1OaSTUpWJpTighyJSIuURlLcitgFlMHB7k43CzhQiN1K5SPUnlKGxvUiZL9SowgNI1CpwYNIlTQ0qVJppeADRMgCtIcNKsBAUm7WjTsk2NPVTblTVP3ixYo+N1TVU85KaTKUqJNNSC0rNGLS7AUOJsIbUlyP-D7U7pL7SoE0EhLj4IStFmibNTbUAVdg-O21AZsOIFmi2EvELljGve+PWxrQBaFABPQKzlrBrAKt2NYIfC8Q2gBQsDjWSTQstlAhQRSgMkBjABgFTAUAbgBCgmhIGHM8ugElMlhfXMEIBjc0qlIP83YMRlVjz0rNiXYakEGO8DNqSxGRYsWWzBujbEOL2dBEvNADFAmwSXwRDlfFyNoB0YilQ5pbUzjIf8m8K7HoAnOZLwPh1Vf0G7Ik-H3jEzEpUl008yAPXQ3RB9Y3UwpDALIBSxIrceCsB8EG8Xn0TNJTM0NEgSMC-JVM7FgsA2QBYDpYtgCwHMIcIklnYFdJegDpcg4CwEesCePo35x4hNPSX0hgIzJ-R3BNTMIAzMx8UsyhgBiicNnVCwBURbLdzMcy9pLzIMzRGTdH8zTM8zJCzEgMLIow+MEzOeYCWacXrZ6OTdCVIaMPnhczoUggEiy-DUrJi5OxFKRYNIRSLI6kaMWxV-QO1JgkTc5+NBLUAsEy51KzIPdwyT1PDNUheZ4suI0Myks52QCygsizP5gMsyPT4cGsvrI1tPDWLOGzYjevUSy-MibJSzgsmbLHEwtIKFKz0s8wCMYwovaSWyeyTzLWyicTTAYwdMFIGY92s7jHGzsswgCmDrQRkQpIHMikno4ds9Ezelt0LTOvEaka0DFAvkwHL8koARzL8MBtfnHYEoAXSRhzIcxkSwSbFTZUoT3MyHL8MRs9bI0w8EW7KYx7suz0ez8w2aQchnmN7PoB7M77K+zq4BNFSzRDPNhhzEcuHN0lIcwXHPI8PK4QSJ+cOnK6zxAC8wSl6jczD2yVtQGRKzzAdLLEATs+IXOyUsS7N2MWkG7O0wCch7NEAnszbJeypgynI+zxAGnN5zpsv7P4xqQcHJqQE0UHPKyYAbTNNyStHazIAmc7nPszMDdnN1zMDRzJqy0cyEVlzKcrHKuyhgXHPoxlc5jFVyoAdXLglks8nKiBKcqnPEB4czA0jykc37JfNcxbnMRzkcmPOdzKchHO5zKcn7M5zxAKHOSkaskXJcNcNbEBeyaMSKhowNJGjAKz6sjNnUwAcsQDByVsoCSlyMsbKVqzbcxKWOz285KXrZcjObIWpeDHTQz8CAWdF3sB9Q3W8zEgTXKQN-uNQCiBKzFckyMlSDLDpZjMsnNey08n7INy0g61ToVhMvjPcTvaUFnt0nNbdGEz2UPwybwnDELj54nOeg2A83DDODn4X+Ss0FxspPnjyRpDEHK7zSEDvI9y4JdrNhzt8uo3dz9rOCQp4f9N-KwTP87dBURpDM3L-y-AZKUALIRYAsdz88sAqazrpANAQDKoXgDHytgWfLWydcpfLnzv2OAFXy3UAfO00nOX2GDiYYogqM0F9fTNGzb0ScEQD90DfICzMCnfLSztgUQFqRE5Rgrq9QWZ3Icz-8PgwYLGAT2JADmCifNYKp8hLM-8uCpdB4LsWPgvpyU-IQswKZCuQutdQWKHPHg+DcoFo5bMPgt6MBsnsm6y3dakEyNDDd2REKzYubx0ksEr8i+M2QOvR5wRC2QvNjDC1nNb0HLEgveyF86uBpyE81fKgALAOllBESC7XLCK88lcl5zV8+gBiKcVdEy-y4IDkzghpcnawwKWctkDML+AHnNALsxO-PgLsi6uFyL4ufIqELii05T4KM8hzLdyxxNAuxBU8vnNaKnDfwQc4dNUQsUzsQSfPUMFc8QHrjqQI5LABW9EgsyNdJA3KGAIbfw01ztCoYAGKPMkwv6KXCjWNrTq9JQpGLp852UQgNCiPNIK+c+YsSBTQfEHMZ7dY4q3zE8xIAGLYNdYucJ+ivwttS9uPYv8NRig5ImLsU+MWmLN8mnIcKBCxYvDzCAfgpDw3i0EjlyNipzlziVfDLV2K9M5QvYLKk24qBLMeFYouKrinSQBKAsiEr2coS7dNNypCnTRMDS1AYt0zF9BLP9ytMRjCDy7PckuVQBi0PPUMZizEvEAsS8QFuKtC+4sELhJJkuBwti4HPSxJC0sgdiTBUD0QBTsy2VlyEAKUoQBTsuwsyM9Se8PUoECbwphwPC7LKfE2QHUp+IrgoQvlLY8YUubAwozA3foqvIUvViakRUoFy1bPYXVhJS2KBlLd7OUoVKlSjwpVKTkDwvRhNSjsG1Kyc3Uq2ztnfmAaLmwKUrWK7Si0owDmS00rtLDnF4vx9YEzsHHyPi5Ev2KEs+wo5LR9LwpVEeS7fK5LoxL5gY0IUtuVPy3Re-KiEGDNw06yLFfnPAKxci-LoMay0tjwlQikEKdz2wECBTLxC4oxALMIyCHDKEiyQtRyIChIyrhSiwctdzuygxM9Ul8-svDLMCzHPQTpAGcpqzcCqRG8y1sg1Fd9vM9MupL2CsOmOLHCrUz91YSsvkcc0y-0GGKvig4tH0CyroqLKK8x+FLLbomVkrMz8-y2rLfMvNhmtLyhy2AxtvcIWbLH8vwwbZspMQXaK4JQdEw9msvNm606CpMFjL3jFgozK7yhLLr1HyhzO0K98i-TzYSy1GjLKT8z8srLmyqaz8MjQB2M6zuivNk7yqysCq7yX8xUVjK+yuAp7JYFauCGyAxG-LoroK19AKLQCjvMbLS81RxelkKqryMLijPngQK50FvLSkUCwXP4r-QDAu3zaKyESFzkXcLKTK7AwgukspSuoKsLFDTwxCjlgp2WzL58u0phwXYX0qlL-S7xDdQPCmjBCKpS7slUApS5IqlLV8iwBoLgVAwE3y3skTzCLVAIKuSKgq7ypdhYimUUyKAcg7DBzPSqkQBzJrR9D8N1JIKpqCxy1wzbLJyqACCqWlcQBlKeyy-x0kDKsKOylwy6wMaKpS3KtFKpSyqpSwPKsKJsU9rJsoOyDsaQ1i5oxdSVKryi8cogd+cKUvyr6ACDyKrPVEKvugg+PNgqq8YIuKgBqq80rUAgq+quGrMDJquuleipCrOBdWEllMrDKhPXczdqhKvVKHC-mCwrMKTwrWzTq5TPVKXKnXPcq488QEGrYi6UoZzZcucuaEPS7W3UN+cIKtzKCqoFjhQakLaoXQ5q88gWrgahqtWr7S86tyrYoUAX+qtgcMohrQa6uAWr7qjGH2UVq-6uiM5Mh0uHynOPwNCweq-ausKkMYmuVKOS08rWzbKvMofYTkRyvOrbq4Ko8rI8p6u6VXS6LNJr3qkqpdKvq-wx+rRIP3ShrEa2jmpA-AgarBraq7rjgw-9Rquhr1S2GsDE-aBGsZIphK5XFqUamqulrrYSGuxqxxDauV8eoqirupTxNPSaw9HAt11iXSWQANYmAPrFJKnOSOETJDQULGUEjK5PVd1Dy9bPxjSc3gsLK+Sp2ptropLv0YRo3St3XANZZAB3BdwS2pwrfzRMr6LHasVnJQIAFvmDspSsb3drPDRb2UEjq76pAoR493Sax+YX8vzqmsczN4I9IJ9A8L8qguv5gGa9UpQlQ62BL-SI67t3fUY6qlnRqsaxbz8r34B63DrtMSYGjrY60KqCrM6wS0jtD8t5PLL0akKrN4qy5rSfz-LFqtEqOi5OsYBU6yYS4Bna+kR7qn0QYJ3qg6lLHHq1q4vLxqwAtuSJrQoj8WQ8U6wIG3rXfI2rJqvC4usPqn6w0CQwgquuv-wF4nauJrVa8ssOrhMe1ETqllfYOd5gGkmuMr9Km+tT0goE6phwkxc6trqVRIMz91Ay3gopJXKqIG7rWa+nL1KAqikiCq3K0Ksjy8qyzLSCOa1R2nriKkFjnqyquZUMofyxZXODPjTWtOyb0NhtNy5a1eou9QK1ss9yFgz4yZq3KlmtOLV8yMGeqaquAC4bhGnht5q+Gna24bfirBtOKxGh6qxrJG56sNFUMcBrXAJal6s3K5s-Az7c7gggALtFC9CuxzzNPEs0L-a84p2sDRK+w-yaMfhi-KqREICvt1Ki+sihWIZTlbMPibhizrpLJ2VGKvGbCswMuSi8W8bRINwv8aN+FtXYEvGPGg2rTGieBPC5+OUDQqvapBs0BImzkr5KsBe3Vkbj0Y8MlB6VNzVKaMmippQBYCnSsNTkgbJqsbcm+UwwaVMgKocaBC4pvE9nyQ1Mqbq4XprBAwIgZtor0m2sFBJtqzmnClbymxqGAzq32vsany37Lwr-NOhSgBogQzkciBm1xonLYM1QCabcSzsQp5Nmixu2a6mhsuKzt0FABKa3DL-M4qNm6ptkrxAaIHArFKuCU7y3DMgCXLogbfNebhKprOUr8A9WH5xfml5uarz69Joai43DLhmbPiuZqgtMjbwoKaCS-CtUd+cdGD6Juy6Fp1iLm3ZoIrHeA5oy4jml8uMAUsdGHoB05JpuwgvIouIuafGsQxNVbm0tmpAly9GAcysYQ+pBa+iTA3TlMqtevgJLlYHIpbOWuACXKW1BzL5aNyyFvxq-obCEKTHAJEtaaxsjpr9rCmxxtGiFW4STVIYuTrk1bs0GEoaaSA++vKRuGOFusbfchvW4YUWrktL97665V0l1BO1s3qH6rxiwTTPfFqCwGQggBy4AY+1vh4QIf-FASFIQ+mFKFUFeJkBEStWLzjQiC8q3kFCg8rYL1sn4smK7G8nK6a6XA-LfLj8kFlIrz8oKEvzBGuCVUARKurLzZWBAMRjMAxBiqLaFKlyQUrPmzD3EBIKnKQSkIW7SrAa2UpaAjrU62zFUBBOKlpyak2rYH7abW+4qYb3GvmqIwHk7tvtbdJJJt6qsqyES7baUF1p0kB2+po7akKldtzsF7IdpRLk28YtTax284onbcSxZR3ae2h+vna3NJRujFL27xsQrxmy1NnbQiE1pJZ+20SA-FZmy1o0ocS-trTa7iuOtPaG89M3PadrS9tg0520SFva2ivqpvKX22lDfa12z9pMBN2zLJ0rIOnYr3aWm4dqGA0S1VqWbgOtLLPb7dC9sQ6a0kyGg60OwZrva3GijuJLH24xu3aXUrdPfagoVDsHbcOg9pHbS6pYs6blmkDsljt0SdvI7N0rOBQ6YOy5tvz4OoYtY6JOres47YOrdufbxOzsEsbE2njppMj2v4uLqT2kjtA7gocDvvb5Oq9viaW1BlpUxZO6durSvZZTow7O20zqg6XWvtoHbv2+Ft-bLio0HXbAO3kqE7GWozrI6IOpzuQ7FOqTss7G25dpC6qOlDo3baOmVutinOOlK5Qo2jTpvKPO0YoI7Fm9NsE6DO4TrA6gukzrU7nOsLpo6Iu-iuS62O0Ihcan22VrpTsO68qGKMug4qy62SgTuI7M2vh1ob3y8srzarmgtpYau8rzuuL+Wstvs0OkkyEArsQKtoUqa25eoUqD4Ftsi6Fu2Cobbtvdtoc6bVHWgWAGiiwtAKIFabW-yrs-8pnqT8+EuhKJCsUDAqaMG9BSxqyofRO66GrupNKbSuXKu6hOeISXKhK0XLXr6q5JrtFRyvWSQrb5CxvNblW6msI6cujrqMNRCYsov5TmgAiwEF245rqEEeydpR7jAhHpWELOsio4rohAgEeab0IlukNVATZpvRnm+gFeau83ipLyxupxW26fmxkTBbKejbpMaDg5EG2iwcYIQJ7LnPgz2CqLKppfNZc4U24rNsmekF7EWjksFxxspTy78APPOSkYclIYFUbNCigsfYwi+XvEA1etkGoLpG6I2fJqQIKuD9BOccIV6bNXglLZy8utqiB2S+fO7JNe5fI5LdevuvEzF80DwDFHe6UQUrV8kT2SkXe6uCysZemOhr8TeqUp7CzepXqgtLezfIDEpg23soL7ewTk97KC53uAqNe93oUqVyePvV77eshokaU6KKu96ogX3sFz-eyvMhF9e7zgl7SW0GDn4xwTbkUV0W2ACUBMW2cvAh+eOHLdFZc0Xr-KgOZfWz0W9GjGfJIJTIAj7DcpghSwrcwXvAb+eBph6hzjeLoSlDKB3IUkTSwut8lRW-Fq3a5st9CbY9g4MRsEKZTnmdyStHqS3UlAPoSFZoG5PR771DMzWERrqu-oA9bNDgq-8CC05QA9W9Y3orMlvJwo35Te1-rUK4hUzU16ABnsJf638oKrfyDK-AsTgP+uIS-7QBsPqCrAgG7g9w7RVAawgMBqAYwGYBzgvf7F0BAcQHQ+isxQHg+wIDDBbNQ-AwGwwLAf-7g+yAboHF0PAbf64Bwgbxp5a58gQtTCC-oehOhVtCaED+2kT4H1wWmFOgsaJ7sLwStfwQozRsK7GPAOsHEHLkpfNXyxCzQpz3eA1IAdI2hBoqz1iA8IxuWpB9wjqPriXQRWjHAwvTQbWBRJYyD-QhfDqnWB0hFAD-Qm0n12HiPgkYIN8rBo32gyj0ncrT8y4ndz08RMZUDWA6CfbQ-SCgc+JASEiZajdVvEIwbqRPfQkBShM-doLA5MkpVMb9nILSB6VAoqwbID6olZibBYgWKESGDSuwIqCaALBWMgQIbAMtKafZbwQTbYpxhQBQAUdIRA6QKOG2gK-LEDYgDk-2L2gcjfjAtcChs+IfZ6o4yCqByh36k988hrP1DTch4yHaGsveOK6GCh3oexB+h+uMGHhhqWP6pQhtuOiHC08kFBQakfcNmG0-FunmBNWoqIBCtQHUDz9vB-6IDp6Sc4bqRG8DeOmi4gKGirjd47oesGXh8WmmGLhjsHKGvh7r1USRh7H1dixh8mPnzxEiQTWS83GCBkBbAk4Dd93h-mGuDSsG2O6jeo3VifSmIoIYBGTQI8HvAtWFBMaSM9dACU8EuE4aP6QRj4b9zicStINE3U711gTngsMLeDpoxehBhdBzYbfQ706xPjichtL1qGq4gEd5j6QsUYAyfatWgQBWOKUeeHI3aUa3wxie+MH8fQ30H+iDREoYqRHkMof3C-CStPrCYIs1rdD4INsOpAuwkTt8YeGccLFAewsUEHCRTGEwljhkmvx2DdQPIZVHQhuXvqDlXf6BdA5vdKhe9AgdgFISXwIwFY45vMkbog4RuSKdDofFpIzitGWlM3CdSJJDZBQR2oC0VhgY0cOVEkUoA2pzEe9wcHuYBQaUGpfXFhmGRMqdiuISM8ocV14AaRlkyDgKgLjc69GzPFYGeeJADb2x0RiHym4OKh-1fWoDEI8FBWCXkN2eZIFAatK-+XFp3mSdHiRCPc8lkBXMdnhHGQFVIZJY6zOlynGCAYPwV7CPGcZAg5xn1rnHqsifiYJfvbJoWZZSg6qQ8nZZcGYkFeoSSoGCeJDzr56219B0A2uK8ZO5e8n9GYlQ7e-o5Nxi5FrZ79Qh8Zy5pQN6pfH4Gt8cLr1BBYBf7mJUzRf6fi6Cd8aMR7ct9ajx48dgkSuDnhXHVEdngNRzG281Dk4AMsWcaW1Qj3-x6w1sxUYDJLYG8l5JFvqvs2Ji8Y0ziAcDCAA

module type OBJ = {
/** Operations on internal representations of values.
Not for the casual user.
*/;
type t;
external repr: 'a => t = "%identity";
external obj: t => 'a = "%identity";
external magic: 'a => 'b = "%identity";
let is_block: t => bool;
external is_int: t => bool = "%obj_is_int";
external tag: t => int = "caml_obj_tag";
external size: t => int = "%obj_size";
/**
Computes the total size (in words, including the headers) of all
heap blocks accessible from the argument. Statically
allocated blocks are excluded.
@Since 4.04
*/
external reachable_words: t => int = "caml_obj_reachable_words";
external field: (t, int) => t = "%obj_field";
/** When using flambda:
[set_field] MUST NOT be called on immutable blocks. (Blocks allocated
in C stubs, or with [new_block] below, are always considered mutable.)
The same goes for [set_tag]. However, for
[set_tag], in the case of immutable blocks where the middle-end optimizers
never see code that discriminates on their tag (for example records), the
operation should be safe. Such uses are nonetheless discouraged.
For experts only:
[set_field] et al can be made safe by first wrapping the block in
{!Sys.opaque_identity}, so any information about its contents will not
be propagated.
*/
external set_field: (t, int, t) => unit = "%obj_set_field";
external set_tag: (t, int) => unit = "caml_obj_set_tag";
external new_block: (int, int) => t = "caml_obj_block";
external dup: t => t = "caml_obj_dup";
external truncate: (t, int) => unit = "caml_obj_truncate";
external add_offset: (t, Int32.t) => t = "caml_obj_add_offset";
let first_non_constant_constructor_tag: int;
let last_non_constant_constructor_tag: int;
let lazy_tag: int;
let closure_tag: int;
let object_tag: int;
let infix_tag: int;
let forward_tag: int;
let no_scan_tag: int;
let abstract_tag: int;
let string_tag: int;
let double_tag: int;
let double_array_tag: int;
let custom_tag: int;
[@ocaml.deprecated "Replaced by custom_tag."]
let final_tag: int;
let int_tag: int;
let out_of_heap_tag: int;
let unaligned_tag: int;
type extension_constructor;
[@inline always];
let extension_constructor: 'a => extension_constructor;
let extension_name: extension_constructor => string;
let extension_id: extension_constructor => int;
};
module Obj: OBJ = {
type t;
external repr: 'a => t = "%identity";
external obj: t => 'a = "%identity";
external magic: 'a => 'b = "%identity";
external is_int: t => bool = "%obj_is_int";
let is_block = a => !is_int(a);
external tag: t => int = "caml_obj_tag";
external set_tag: (t, int) => unit = "caml_obj_set_tag";
external size: t => int = "%obj_size";
external reachable_words: t => int = "caml_obj_reachable_words";
external field: (t, int) => t = "%obj_field";
external set_field: (t, int, t) => unit = "%obj_set_field";
external new_block: (int, int) => t = "caml_obj_block";
external dup: t => t = "caml_obj_dup";
external truncate: (t, int) => unit = "caml_obj_truncate";
external add_offset: (t, Int32.t) => t = "caml_obj_add_offset";
let first_non_constant_constructor_tag = 0;
let last_non_constant_constructor_tag = 245;
let lazy_tag = 246;
let closure_tag = 247;
let object_tag = 248;
let infix_tag = 249;
let forward_tag = 250;
let no_scan_tag = 251;
let abstract_tag = 251;
let string_tag = 252;
let double_tag = 253;
let double_array_tag = 254;
let custom_tag = 255;
let final_tag = custom_tag;
let int_tag = 1000;
let out_of_heap_tag = 1001;
let unaligned_tag = 1002;
type extension_constructor;
let extension_constructor = x => {
let x = repr(x);
let slot =
if (is_block(x) && tag(x) != object_tag && size(x) >= 1) {
field(x, 0);
} else {
x;
};
let name =
if (is_block(slot) && tag(slot) == object_tag) {
field(slot, 0);
} else {
invalid_arg("Obj.extension_constructor");
};
if (tag(name) == string_tag) {
(obj(slot): extension_constructor);
} else {
invalid_arg("Obj.extension_constructor");
};
};
let extension_name = (slot: extension_constructor): string =>
obj(field(repr(slot), 0));
let extension_id = (slot: extension_constructor): int =>
obj(field(repr(slot), 1));
};
module type COO = {
/** Run-time support for objects and classes.
All functions in this module are for system use only, not for the
casual user. */;
/** {1 Classes} */;
type tag;
type label;
type table;
type meth;
type t;
type obj;
type closure;
let public_method_label: string => tag;
let new_method: table => label;
let new_variable: (table, string) => int;
let new_methods_variables:
(table, array(string), array(string)) => array(label);
let get_variable: (table, string) => int;
let get_variables: (table, array(string)) => array(int);
let get_method_label: (table, string) => label;
let get_method_labels: (table, array(string)) => array(label);
let get_method: (table, label) => meth;
let set_method: (table, label, meth) => unit;
let set_methods: (table, array(label)) => unit;
let narrow: (table, array(string), array(string), array(string)) => unit;
let widen: table => unit;
let add_initializer: (table, obj => unit) => unit;
let dummy_table: table;
let create_table: array(string) => table;
let init_class: table => unit;
let inherits:
(
table,
array(string),
array(string),
array(string),
(t, (table, obj) => Obj.t, t, obj),
bool
) =>
array(Obj.t);
let make_class:
(array(string), (table, Obj.t) => t) =>
(t, (table, Obj.t) => t, Obj.t => t, Obj.t);
type init_table;
let make_class_store: (array(string), table => t, init_table) => unit;
let dummy_class:
((string, int, int)) => (t, (table, Obj.t) => t, Obj.t => t, Obj.t);
/** {1 Objects} */;
let copy: ({..} as 'a) => 'a;
let create_object: table => obj;
let create_object_opt: (obj, table) => obj;
let run_initializers: (obj, table) => unit;
let run_initializers_opt: (obj, obj, table) => obj;
let create_object_and_run_initializers: (obj, table) => obj;
external send: (obj, tag) => t = "%send";
external sendcache: (obj, tag, t, int) => t = "%sendcache";
external sendself: (obj, label) => t = "%sendself";
[@noalloc]
external get_public_method: (obj, tag) => closure = "caml_get_public_method";
/** {1 Table cache} */;
type tables;
let lookup_tables: (tables, array(closure)) => tables;
/** {1 Builtins to reduce code size} */;
let get_const: t => closure;
let get_var: int => closure;
let get_env: (int, int) => closure;
let get_meth: label => closure;
let set_var: int => closure;
let app_const: (t => t, t) => closure;
let app_var: (t => t, int) => closure;
let app_env: (t => t, int, int) => closure;
let app_meth: (t => t, label) => closure;
let app_const_const: ((t, t) => t, t, t) => closure;
let app_const_var: ((t, t) => t, t, int) => closure;
let app_const_env: ((t, t) => t, t, int, int) => closure;
let app_const_meth: ((t, t) => t, t, label) => closure;
let app_var_const: ((t, t) => t, int, t) => closure;
let app_env_const: ((t, t) => t, int, int, t) => closure;
let app_meth_const: ((t, t) => t, label, t) => closure;
let meth_app_const: (label, t) => closure;
let meth_app_var: (label, int) => closure;
let meth_app_env: (label, int, int) => closure;
let meth_app_meth: (label, label) => closure;
let send_const: (tag, obj, int) => closure;
let send_var: (tag, int, int) => closure;
let send_env: (tag, int, int, int) => closure;
let send_meth: (tag, label, int) => closure;
type impl =
| GetConst
| GetVar
| GetEnv
| GetMeth
| SetVar
| AppConst
| AppVar
| AppEnv
| AppMeth
| AppConstConst
| AppConstVar
| AppConstEnv
| AppConstMeth
| AppVarConst
| AppEnvConst
| AppMethConst
| MethAppConst
| MethAppVar
| MethAppEnv
| MethAppMeth
| SendConst
| SendVar
| SendEnv
| SendMeth
| Closure(closure);
/** {1 Parameters} */;
type params = {
mutable compact_table: bool,
mutable copy_parent: bool,
mutable clean_when_copying: bool,
mutable retry_count: int,
mutable bucket_small_size: int,
};
let params: params;
/** {1 Statistics} */;
type stats = {
classes: int,
methods: int,
inst_vars: int,
};
let stats: unit => stats;
};
module Coo: COO = {
open Obj;
/**** Object representation ****/
[@noalloc] external set_id: 'a => 'a = "caml_set_oo_id";
/**** Object copy ****/
let copy = o => {
let o = Obj.obj(Obj.dup(Obj.repr(o)));
set_id(o);
};
/**** Compression options ****/
/* Parameters */
type params = {
mutable compact_table: bool,
mutable copy_parent: bool,
mutable clean_when_copying: bool,
mutable retry_count: int,
mutable bucket_small_size: int,
};
let params = {
compact_table: true,
copy_parent: true,
clean_when_copying: true,
retry_count: 3,
bucket_small_size: 16,
};
/**** Parameters ****/
let initial_object_size = 2;
/**** Items ****/
type item =
| DummyA
| DummyB
| DummyC(int);
[DummyA, DummyB, DummyC(0)]; /* to avoid warnings */
let dummy_item: item = magic();
/**** Types ****/
type tag;
type label = int;
type closure = item;
type t =
| DummyA
| DummyB
| DummyC(int);
[DummyA, DummyB, DummyC(0)]; /* to avoid warnings */
type obj = array(t);
external ret: (obj => 'a) => closure = "%identity";
/**** Labels ****/
let public_method_label = s: tag => {
let accu = ref(0);
for (i in 0 to String.length(s) - 1) {
accu := 223 * accu^ + Char.code(s.[i]);
};
/* reduce to 31 bits */
accu := accu^ land (1 lsl 31 - 1);
/* make it signed for 64 bits architectures */
let tag =
if (accu^ > 1073741823) {
accu^ - 1 lsl 31;
} else {
accu^;
};
/* Printf.eprintf "%s = %d\n" s tag; flush stderr; */
magic(tag);
};
/**** Sparse array ****/
module Vars =
Map.Make({
type t = string;
let compare = (x: t, y) => compare(x, y);
});
type vars = Vars.t(int);
module Meths =
Map.Make({
type t = string;
let compare = (x: t, y) => compare(x, y);
});
type meths = Meths.t(label);
module Labs =
Map.Make({
type t = label;
let compare = (x: t, y) => compare(x, y);
});
type labs = Labs.t(bool);
/* The compiler assumes that the first field of this structure is [size]. */
type table = {
mutable size: int,
mutable methods: array(closure),
mutable methods_by_name: meths,
mutable methods_by_label: labs,
mutable previous_states:
list(
(
meths,
labs,
list((label, item)),
vars,
list(label),
list(string),
),
),
mutable hidden_meths: list((label, item)),
mutable vars,
mutable initializers: list(obj => unit),
};
let dummy_table = {
methods: [|dummy_item|],
methods_by_name: Meths.empty,
methods_by_label: Labs.empty,
previous_states: [],
hidden_meths: [],
vars: Vars.empty,
initializers: [],
size: 0,
};
let table_count = ref(0);
/* dummy_met should be a pointer, so use an atom */
let dummy_met: item = obj(Obj.new_block(0, 0));
/* if debugging is needed, this could be a good idea: */
/* let dummy_met () = failwith "Undefined method" */
let rec fit_size = n =>
if (n <= 2) {
n;
} else {
fit_size((n + 1) / 2) * 2;
};
let new_table = pub_labels => {
incr(table_count);
let len = Array.length(pub_labels);
let methods = Array.make(len * 2 + 2, dummy_met);
methods[0] = magic(len);
methods[1] = magic(fit_size(len) * Sys.word_size / 8 - 1);
for (i in 0 to len - 1) {
methods[i * 2 + 3] = magic(pub_labels[i]);
};
{
methods,
methods_by_name: Meths.empty,
methods_by_label: Labs.empty,
previous_states: [],
hidden_meths: [],
vars: Vars.empty,
initializers: [],
size: initial_object_size,
};
};
let resize = (array, new_size) => {
let old_size = Array.length(array.methods);
if (new_size > old_size) {
let new_buck = Array.make(new_size, dummy_met);
Array.blit(array.methods, 0, new_buck, 0, old_size);
array.methods = new_buck;
};
};
let put = (array, label, element) => {
resize(array, label + 1);
array.methods[label] = element;
};
/**** Classes ****/
let method_count = ref(0);
let inst_var_count = ref(0);
/* type t */
type meth = item;
let new_method = table => {
let index = Array.length(table.methods);
resize(table, index + 1);
index;
};
let get_method_label = (table, name) =>
try (Meths.find(name, table.methods_by_name)) {
| Not_found =>
let label = new_method(table);
table.methods_by_name = Meths.add(name, label, table.methods_by_name);
table.methods_by_label = Labs.add(label, true, table.methods_by_label);
label;
};
let get_method_labels = (table, names) =>
Array.map(get_method_label(table), names);
let set_method = (table, label, element) => {
incr(method_count);
if (Labs.find(label, table.methods_by_label)) {
put(table, label, element);
} else {
table.hidden_meths = [(label, element), ...table.hidden_meths];
};
};
let get_method = (table, label) =>
try (List.assoc(label, table.hidden_meths)) {
| Not_found => table.methods[label]
};
let to_list = arr =>
if (arr === magic(0)) {
[];
} else {
Array.to_list(arr);
};
let narrow = (table, vars, virt_meths, concr_meths) => {
let vars = to_list(vars)
and virt_meths = to_list(virt_meths)
and concr_meths = to_list(concr_meths);
let virt_meth_labs = List.map(get_method_label(table), virt_meths);
let concr_meth_labs = List.map(get_method_label(table), concr_meths);
table.previous_states = [
(
table.methods_by_name,
table.methods_by_label,
table.hidden_meths,
table.vars,
virt_meth_labs,
vars,
),
...table.previous_states,
];
table.vars =
Vars.fold(
(lab, info, tvars) =>
if (List.mem(lab, vars)) {
Vars.add(lab, info, tvars);
} else {
tvars;
},
table.vars,
Vars.empty,
);
let by_name = ref(Meths.empty);
let by_label = ref(Labs.empty);
List.iter2(
(met, label) => {
by_name := Meths.add(met, label, by_name^);
by_label :=
Labs.add(
label,
try (Labs.find(label, table.methods_by_label)) {
| Not_found => true
},
by_label^,
);
},
concr_meths,
concr_meth_labs,
);
List.iter2(
(met, label) => {
by_name := Meths.add(met, label, by_name^);
by_label := Labs.add(label, false, by_label^);
},
virt_meths,
virt_meth_labs,
);
table.methods_by_name = by_name^;
table.methods_by_label = by_label^;
table.hidden_meths =
List.fold_right(
((lab, _) as met, hm) =>
if (List.mem(lab, virt_meth_labs)) {
hm;
} else {
[met, ...hm];
},
table.hidden_meths,
[],
);
};
let widen = table => {
let (by_name, by_label, saved_hidden_meths, saved_vars, virt_meths, vars) =
List.hd(table.previous_states);
table.previous_states = List.tl(table.previous_states);
table.vars =
List.fold_left(
(s, v) => Vars.add(v, Vars.find(v, table.vars), s),
saved_vars,
vars,
);
table.methods_by_name = by_name;
table.methods_by_label = by_label;
table.hidden_meths =
List.fold_right(
((lab, _) as met, hm) =>
if (List.mem(lab, virt_meths)) {
hm;
} else {
[met, ...hm];
},
table.hidden_meths,
saved_hidden_meths,
);
};
let new_slot = table => {
let index = table.size;
table.size = index + 1;
index;
};
let new_variable = (table, name) =>
try (Vars.find(name, table.vars)) {
| Not_found =>
let index = new_slot(table);
if (name != "") {
table.vars = Vars.add(name, index, table.vars);
};
index;
};
let to_array = arr =>
if (arr == Obj.magic(0)) {
[||];
} else {
arr;
};
let new_methods_variables = (table, meths, vals) => {
let meths = to_array(meths);
let nmeths = Array.length(meths)
and nvals = Array.length(vals);
let res = Array.make(nmeths + nvals, 0);
for (i in 0 to nmeths - 1) {
res[i] = get_method_label(table, meths[i]);
};
for (i in 0 to nvals - 1) {
res[i + nmeths] = new_variable(table, vals[i]);
};
res;
};
let get_variable = (table, name) =>
try (Vars.find(name, table.vars)) {
| Not_found => assert(false)
};
let get_variables = (table, names) =>
Array.map(get_variable(table), names);
let add_initializer = (table, f) =>
table.initializers = [f, ...table.initializers];
/*
module Keys =
Map.Make(struct type t = tag array let compare (x:t) y = compare x y end)
let key_map = ref Keys.empty
let get_key tags : item =
try magic (Keys.find tags !key_map : tag array)
with Not_found ->
key_map := Keys.add tags tags !key_map;
magic tags
*/
let create_table = public_methods =>
if (public_methods === magic(0)) {
new_table([||]);
} else {
/* [public_methods] must be in ascending order for bytecode */
let tags = Array.map(public_method_label, public_methods);
let table = new_table(tags);
Array.iteri(
(i, met) => {
let lab = i * 2 + 2;
table.methods_by_name = Meths.add(met, lab, table.methods_by_name);
table.methods_by_label =
Labs.add(lab, true, table.methods_by_label);
},
public_methods,
);
table;
};
let init_class = table => {
inst_var_count := inst_var_count^ + table.size - 1;
table.initializers = List.rev(table.initializers);
resize(table, 3 + magic(table.methods[1]) * 16 / Sys.word_size);
};
let inherits =
(cla, vals, virt_meths, concr_meths, (_, super, _, env), top) => {
narrow(cla, vals, virt_meths, concr_meths);
let init =
if (top) {
super(cla, env);
} else {
Obj.repr(super(cla));
};
widen(cla);
Array.concat([
[|repr(init)|],
magic(Array.map(get_variable(cla), to_array(vals)): array(int)),
Array.map(
nm => repr(get_method(cla, get_method_label(cla, nm)): closure),
to_array(concr_meths),
),
]);
};
let make_class = (pub_meths, class_init) => {
let table = create_table(pub_meths);
let env_init = class_init(table);
init_class(table);
(env_init(Obj.repr(0)), class_init, env_init, Obj.repr(0));
};
type init_table = {
mutable env_init: t,
mutable class_init: table => t,
};
let make_class_store = (pub_meths, class_init, init_table) => {
let table = create_table(pub_meths);
let env_init = class_init(table);
init_class(table);
init_table.class_init = class_init;
init_table.env_init = env_init;
};
let dummy_class = loc => {
let undef = _ => raise(Undefined_recursive_module(loc));
(Obj.magic(undef), undef, undef, Obj.repr(0));
};
/**** Objects ****/
let create_object = table => {
/* XXX Appel de [obj_block] | Call to [obj_block] */
let obj = Obj.new_block(Obj.object_tag, table.size);
/* XXX Appel de [caml_modify] | Call to [caml_modify] */
Obj.set_field(obj, 0, Obj.repr(table.methods));
Obj.obj(set_id(obj));
};
let create_object_opt = (obj_0, table) =>
if ((Obj.magic(obj_0): bool)) {
obj_0;
} else {
/* XXX Appel de [obj_block] | Call to [obj_block] */
let obj = Obj.new_block(Obj.object_tag, table.size);
/* XXX Appel de [caml_modify] | Call to [caml_modify] */
Obj.set_field(obj, 0, Obj.repr(table.methods));
Obj.obj(set_id(obj));
};
let rec iter_f = obj =>
fun
| [] => ()
| [f, ...l] => {
f(obj);
iter_f(obj, l);
};
let run_initializers = (obj, table) => {
let inits = table.initializers;
if (inits != []) {
iter_f(obj, inits);
};
};
let run_initializers_opt = (obj_0, obj, table) =>
if ((Obj.magic(obj_0): bool)) {
obj;
} else {
let inits = table.initializers;
if (inits != []) {
iter_f(obj, inits);
};
obj;
};
let create_object_and_run_initializers = (obj_0, table) =>
if ((Obj.magic(obj_0): bool)) {
obj_0;
} else {
let obj = create_object(table);
run_initializers(obj, table);
obj;
};
/* Equivalent primitive below
let sendself obj lab =
(magic obj : (obj -> t) array array).(0).(lab) obj
*/
external send: (obj, tag) => 'a = "%send";
external sendcache: (obj, tag, t, int) => 'a = "%sendcache";
external sendself: (obj, label) => 'a = "%sendself";
[@noalloc]
external get_public_method: (obj, tag) => closure = "caml_get_public_method";
/**** table collection access ****/
type tbls = {
key: closure,
mutable data: tables,
mutable next: tables,
}
and tables =
| Empty
| Cons(tbls);
let set_data = (tables, v) =>
switch (tables) {
| Empty => assert(false)
| Cons(tables) => tables.data = v
};
let set_next = (tables, v) =>
switch (tables) {
| Empty => assert(false)
| Cons(tables) => tables.next = v
};
let get_key =
fun
| Empty => assert(false)
| Cons(tables) => tables.key;
let get_data =
fun
| Empty => assert(false)
| Cons(tables) => tables.data;
let get_next =
fun
| Empty => assert(false)
| Cons(tables) => tables.next;
let build_path = (n, keys, tables) => {
let res = Cons({key: Obj.magic(0), data: Empty, next: Empty});
let r = ref(res);
for (i in 0 to n) {
r := Cons({key: keys[i], data: r^, next: Empty});
};
set_data(tables, r^);
res;
};
let rec lookup_keys = (i, keys, tables) =>
if (i < 0) {
tables;
} else {
let key = keys[i];
let rec lookup_key = (tables: tables) =>
if (get_key(tables) === key) {
switch (get_data(tables)) {
| Empty => assert(false)
| Cons(_) as tables_data => lookup_keys(i - 1, keys, tables_data)
};
} else {
switch (get_next(tables)) {
| Cons(_) as next => lookup_key(next)
| Empty =>
let next: tables = Cons({key, data: Empty, next: Empty});
set_next(tables, next);
build_path(i - 1, keys, next);
};
};
lookup_key(tables);
};
let lookup_tables = (root, keys) =>
switch (get_data(root)) {
| Cons(_) as root_data =>
lookup_keys(Array.length(keys) - 1, keys, root_data)
| Empty => build_path(Array.length(keys) - 1, keys, root)
};
/**** builtin methods ****/
let get_const = x => ret(_obj => x);
let get_var = n => ret(obj => Array.unsafe_get(obj, n));
let get_env = (e, n) =>
ret(obj =>
Array.unsafe_get(Obj.magic(Array.unsafe_get(obj, e)): obj, n)
);
let get_meth = n => ret(obj => sendself(obj, n));
let set_var = n => ret((obj, x) => Array.unsafe_set(obj, n, x));
let app_const = (f, x) => ret(_obj => f(x));
let app_var = (f, n) => ret(obj => f(Array.unsafe_get(obj, n)));
let app_env = (f, e, n) =>
ret(obj =>
f(Array.unsafe_get(Obj.magic(Array.unsafe_get(obj, e)): obj, n))
);
let app_meth = (f, n) => ret(obj => f(sendself(obj, n)));
let app_const_const = (f, x, y) => ret(_obj => f(x, y));
let app_const_var = (f, x, n) =>
ret(obj => f(x, Array.unsafe_get(obj, n)));
let app_const_meth = (f, x, n) => ret(obj => f(x, sendself(obj, n)));
let app_var_const = (f, n, x) =>
ret(obj => f(Array.unsafe_get(obj, n), x));
let app_meth_const = (f, n, x) => ret(obj => f(sendself(obj, n), x));
let app_const_env = (f, x, e, n) =>
ret(obj =>
f(x, Array.unsafe_get(Obj.magic(Array.unsafe_get(obj, e)): obj, n))
);
let app_env_const = (f, e, n, x) =>
ret(obj =>
f(Array.unsafe_get(Obj.magic(Array.unsafe_get(obj, e)): obj, n), x)
);
let meth_app_const = (n, x) => ret(obj => (sendself(obj, n): _ => _)(x));
let meth_app_var = (n, m) =>
ret(obj => (sendself(obj, n): _ => _)(Array.unsafe_get(obj, m)));
let meth_app_env = (n, e, m) =>
ret(obj =>
(sendself(obj, n): _ => _)(
Array.unsafe_get(Obj.magic(Array.unsafe_get(obj, e)): obj, m),
)
);
let meth_app_meth = (n, m) =>
ret(obj => (sendself(obj, n): _ => _)(sendself(obj, m)));
let send_const = (m, x, c) =>
ret(obj => sendcache(x, m, Array.unsafe_get(obj, 0), c));
let send_var = (m, n, c) =>
ret(obj =>
sendcache(
Obj.magic(Array.unsafe_get(obj, n)): obj,
m,
Array.unsafe_get(obj, 0),
c,
)
);
let send_env = (m, e, n, c) =>
ret(obj =>
sendcache(
Obj.magic(
Array.unsafe_get(Obj.magic(Array.unsafe_get(obj, e)): obj, n),
): obj,
m,
Array.unsafe_get(obj, 0),
c,
)
);
let send_meth = (m, n, c) =>
ret(obj => sendcache(sendself(obj, n), m, Array.unsafe_get(obj, 0), c));
let new_cache = table => {
let n = new_method(table);
let n =
if (n mod 2 == 0 || n > 2 + magic(table.methods[1]) * 16 / Sys.word_size) {
n;
} else {
new_method(table);
};
table.methods[n] = Obj.magic(0);
n;
};
type impl =
| GetConst
| GetVar
| GetEnv
| GetMeth
| SetVar
| AppConst
| AppVar
| AppEnv
| AppMeth
| AppConstConst
| AppConstVar
| AppConstEnv
| AppConstMeth
| AppVarConst
| AppEnvConst
| AppMethConst
| MethAppConst
| MethAppVar
| MethAppEnv
| MethAppMeth
| SendConst
| SendVar
| SendEnv
| SendMeth
| Closure(closure);
let method_impl = (table, i, arr) => {
let next = () => {
incr(i);
magic(arr[i^]);
};
switch (next()) {
| GetConst =>
let x: t = next();
get_const(x);
| GetVar =>
let n = next();
get_var(n);
| GetEnv =>
let e = next();
let n = next();
get_env(e, n);
| GetMeth =>
let n = next();
get_meth(n);
| SetVar =>
let n = next();
set_var(n);
| AppConst =>
let f = next();
let x = next();
app_const(f, x);
| AppVar =>
let f = next();
let n = next();
app_var(f, n);
| AppEnv =>
let f = next();
let e = next();
let n = next();
app_env(f, e, n);
| AppMeth =>
let f = next();
let n = next();
app_meth(f, n);
| AppConstConst =>
let f = next();
let x = next();
let y = next();
app_const_const(f, x, y);
| AppConstVar =>
let f = next();
let x = next();
let n = next();
app_const_var(f, x, n);
| AppConstEnv =>
let f = next();
let x = next();
let e = next();
let n = next();
app_const_env(f, x, e, n);
| AppConstMeth =>
let f = next();
let x = next();
let n = next();
app_const_meth(f, x, n);
| AppVarConst =>
let f = next();
let n = next();
let x = next();
app_var_const(f, n, x);
| AppEnvConst =>
let f = next();
let e = next();
let n = next();
let x = next();
app_env_const(f, e, n, x);
| AppMethConst =>
let f = next();
let n = next();
let x = next();
app_meth_const(f, n, x);
| MethAppConst =>
let n = next();
let x = next();
meth_app_const(n, x);
| MethAppVar =>
let n = next();
let m = next();
meth_app_var(n, m);
| MethAppEnv =>
let n = next();
let e = next();
let m = next();
meth_app_env(n, e, m);
| MethAppMeth =>
let n = next();
let m = next();
meth_app_meth(n, m);
| SendConst =>
let m = next();
let x = next();
send_const(m, x, new_cache(table));
| SendVar =>
let m = next();
let n = next();
send_var(m, n, new_cache(table));
| SendEnv =>
let m = next();
let e = next();
let n = next();
send_env(m, e, n, new_cache(table));
| SendMeth =>
let m = next();
let n = next();
send_meth(m, n, new_cache(table));
| Closure(_) as clo => magic(clo)
};
};
let set_methods = (table, methods) => {
let len = Array.length(methods);
let i = ref(0);
while (i^ < len) {
let label = methods[i^];
let clo = method_impl(table, i, methods);
set_method(table, label, clo);
incr(i);
};
};
/**** Statistics ****/
type stats = {
classes: int,
methods: int,
inst_vars: int,
};
let stats = () => {
classes: table_count^,
methods: method_count^,
inst_vars: inst_var_count^,
};
};
/** Sets over ordered types.
This module implements the set data structure, given a total ordering
function over the set elements. All operations over sets
are purely applicative (no side-effects).
The implementation uses balanced binary trees, and is therefore
reasonably efficient: insertion and membership take time
logarithmic in the size of the set, for instance.
The {!Make} functor constructs implementations for any type, given a
[compare] function.
For instance:
{[
module IntPairs =
struct
type t = int * int
let compare (x0,y0) (x1,y1) =
match Pervasives.compare x0 x1 with
0 -> Pervasives.compare y0 y1
| c -> c
end
module PairsSet = Set.Make(IntPairs)
let m = PairsSet.(empty |> add (2,3) |> add (5,7) |> add (11,13))
]}
This creates a new module [PairsSet], with a new type [PairsSet.t]
of sets of [int * int].
*/;
/** Input signature of the functor {!Set.Make}. */
module type OrderedType = {
/** The type of the set elements. */
type t;
/** A total ordering function over the set elements.
This is a two-argument function [f] such that
[f e1 e2] is zero if the elements [e1] and [e2] are equal,
[f e1 e2] is strictly negative if [e1] is smaller than [e2],
and [f e1 e2] is strictly positive if [e1] is greater than [e2].
Example: a suitable ordering function is the generic structural
comparison function {!Pervasives.compare}. */
let compare: (t, t) => int;
};
/** Output signature of the functor {!Set.Make}. */
module type S = {
/** The type of the set elements. */
type elt;
/** The type of sets. */
type t;
/** The empty set. */
let empty: t;
/** Test whether a set is empty or not. */
let is_empty: t => bool;
/** [mem x s] tests whether [x] belongs to the set [s]. */
let mem: (elt, t) => bool;
/** [add x s] returns a set containing all elements of [s],
plus [x]. If [x] was already in [s], [s] is returned unchanged
(the result of the function is then physically equal to [s]).
@before 4.03 Physical equality was not ensured. */
let add: (elt, t) => t;
/** [singleton x] returns the one-element set containing only [x]. */
let singleton: elt => t;
/** [remove x s] returns a set containing all elements of [s],
except [x]. If [x] was not in [s], [s] is returned unchanged
(the result of the function is then physically equal to [s]).
@before 4.03 Physical equality was not ensured. */
let remove: (elt, t) => t;
/** Set union. */
let union: (t, t) => t;
/** Set intersection. */
let inter: (t, t) => t;
/** Set difference. */
let diff: (t, t) => t;
/** Total ordering between sets. Can be used as the ordering function
for doing sets of sets. */
let compare: (t, t) => int;
/** [equal s1 s2] tests whether the sets [s1] and [s2] are
equal, that is, contain equal elements. */
let equal: (t, t) => bool;
/** [subset s1 s2] tests whether the set [s1] is a subset of
the set [s2]. */
let subset: (t, t) => bool;
/** [iter f s] applies [f] in turn to all elements of [s].
The elements of [s] are presented to [f] in increasing order
with respect to the ordering over the type of the elements. */
let iter: (elt => unit, t) => unit;
/** [map f s] is the set whose elements are [f a0],[f a1]... [f
aN], where [a0],[a1]...[aN] are the elements of [s].
The elements are passed to [f] in increasing order
with respect to the ordering over the type of the elements.
If no element of [s] is changed by [f], [s] is returned
unchanged. (If each output of [f] is physically equal to its
input, the returned set is physically equal to [s].)
@since 4.04.0 */
let map: (elt => elt, t) => t;
/** [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)],
where [x1 ... xN] are the elements of [s], in increasing order. */
let fold: ((elt, 'a) => 'a, t, 'a) => 'a;
/** [for_all p s] checks if all elements of the set
satisfy the predicate [p]. */
let for_all: (elt => bool, t) => bool;
/** [exists p s] checks if at least one element of
the set satisfies the predicate [p]. */
let exists: (elt => bool, t) => bool;
/** [filter p s] returns the set of all elements in [s]
that satisfy predicate [p]. If [p] satisfies every element in [s],
[s] is returned unchanged (the result of the function is then
physically equal to [s]).
@before 4.03 Physical equality was not ensured.*/
let filter: (elt => bool, t) => t;
/** [partition p s] returns a pair of sets [(s1, s2)], where
[s1] is the set of all the elements of [s] that satisfy the
predicate [p], and [s2] is the set of all the elements of
[s] that do not satisfy [p]. */
let partition: (elt => bool, t) => (t, t);
/** Return the number of elements of a set. */
let cardinal: t => int;
/** Return the list of all elements of the given set.
The returned list is sorted in increasing order with respect
to the ordering [Ord.compare], where [Ord] is the argument
given to {!Set.Make}. */
let elements: t => list(elt);
/** Return the smallest element of the given set
(with respect to the [Ord.compare] ordering), or raise
[Not_found] if the set is empty. */
let min_elt: t => elt;
/** Return the smallest element of the given set
(with respect to the [Ord.compare] ordering), or [None]
if the set is empty.
@since 4.05
*/
let min_elt_opt: t => option(elt);
/** Same as {!Set.S.min_elt}, but returns the largest element of the
given set. */
let max_elt: t => elt;
/** Same as {!Set.S.min_elt_opt}, but returns the largest element of the
given set.
@since 4.05
*/
let max_elt_opt: t => option(elt);
/** Return one element of the given set, or raise [Not_found] if
the set is empty. Which element is chosen is unspecified,
but equal elements will be chosen for equal sets. */
let choose: t => elt;
/** Return one element of the given set, or [None] if
the set is empty. Which element is chosen is unspecified,
but equal elements will be chosen for equal sets.
@since 4.05
*/
let choose_opt: t => option(elt);
/** [split x s] returns a triple [(l, present, r)], where
[l] is the set of elements of [s] that are
strictly less than [x];
[r] is the set of elements of [s] that are
strictly greater than [x];
[present] is [false] if [s] contains no element equal to [x],
or [true] if [s] contains an element equal to [x]. */
let split: (elt, t) => (t, bool, t);
/** [find x s] returns the element of [s] equal to [x] (according
to [Ord.compare]), or raise [Not_found] if no such element
exists.
@since 4.01.0 */
let find: (elt, t) => elt;
/** [find_opt x s] returns the element of [s] equal to [x] (according
to [Ord.compare]), or [None] if no such element
exists.
@since 4.05 */
let find_opt: (elt, t) => option(elt);
/** [find_first f s], where [f] is a monotonically increasing function,
returns the lowest element [e] of [s] such that [f e],
or raises [Not_found] if no such element exists.
For example, [find_first (fun e -> Ord.compare e x >= 0) s] will return
the first element [e] of [s] where [Ord.compare e x >= 0] (intuitively:
[e >= x]), or raise [Not_found] if [x] is greater than any element of
[s].
@since 4.05
*/
let find_first: (elt => bool, t) => elt;
/** [find_first_opt f s], where [f] is a monotonically increasing function,
returns an option containing the lowest element [e] of [s] such that
[f e], or [None] if no such element exists.
@since 4.05
*/
let find_first_opt: (elt => bool, t) => option(elt);
/** [find_last f s], where [f] is a monotonically decreasing function,
returns the highest element [e] of [s] such that [f e],
or raises [Not_found] if no such element exists.
@since 4.05
*/
let find_last: (elt => bool, t) => elt;
/** [find_last_opt f s], where [f] is a monotonically decreasing function,
returns an option containing the highest element [e] of [s] such that
[f e], or [None] if no such element exists.
@since 4.05
*/
let find_last_opt: (elt => bool, t) => option(elt);
/** [of_list l] creates a set from a list of elements.
This is usually more efficient than folding [add] over the list,
except perhaps for lists with many duplicated elements.
@since 4.02.0 */
let of_list: list(elt) => t;
};
module Make = (Ord: OrderedType) : (S with type elt = Ord.t) => {
type elt = Ord.t;
type rc = {
l: t,
v: elt,
r: t,
h: int,
}
and t =
| Empty
| Node(rc);
let height =
fun
| Empty => 0
| Node({h, _}) => h;
let create = (l, v, r) => {
let hl =
switch (l) {
| Empty => 0
| Node({h, _}) => h
};
let hr =
switch (r) {
| Empty => 0
| Node({h, _}) => h
};
Node({
l,
v,
r,
h:
if (hl >= hr) {
hl + 1;
} else {
hr + 1;
},
});
};
let bal = (l, v, r) => {
let hl =
switch (l) {
| Empty => 0
| Node({h, _}) => h
};
let hr =
switch (r) {
| Empty => 0
| Node({h, _}) => h
};
if (hl > hr + 2) {
switch (l) {
| Empty => invalid_arg("Set.bal")
| Node({l: ll, v: lv, r: lr, _}) =>
if (height(ll) >= height(lr)) {
create(ll, lv, create(lr, v, r));
} else {
switch (lr) {
| Empty => invalid_arg("Set.bal")
| Node({l: lrl, v: lrv, r: lrr, _}) =>
create(create(ll, lv, lrl), lrv, create(lrr, v, r))
};
}
};
} else if (hr > hl + 2) {
switch (r) {
| Empty => invalid_arg("Set.bal")
| Node({l: rl, v: rv, r: rr, _}) =>
if (height(rr) >= height(rl)) {
create(create(l, v, rl), rv, rr);
} else {
switch (rl) {
| Empty => invalid_arg("Set.bal")
| Node({l: rll, v: rlv, r: rlr, _}) =>
create(create(l, v, rll), rlv, create(rlr, rv, rr))
};
}
};
} else {
Node({
l,
v,
r,
h:
if (hl >= hr) {
hl + 1;
} else {
hr + 1;
},
});
};
};
let rec add = x =>
fun
| Empty => Node({l: Empty, v: x, r: Empty, h: 1})
| Node({l, v, r, _}) as t => {
let c = Ord.compare(x, v);
if (c == 0) {
t;
} else if (c < 0) {
let ll = add(x, l);
if (l === ll) {
t;
} else {
bal(ll, v, r);
};
} else {
let rr = add(x, r);
if (r === rr) {
t;
} else {
bal(l, v, rr);
};
};
};
let singleton = x => Node({l: Empty, v: x, r: Empty, h: 1});
let rec add_min_element = x =>
fun
| Empty => singleton(x)
| Node({l, v, r, _}) => bal(add_min_element(x, l), v, r);
let rec add_max_element = x =>
fun
| Empty => singleton(x)
| Node({l, v, r, _}) => bal(l, v, add_max_element(x, r));
let rec join = (l, v, r) =>
switch (l, r) {
| (Empty, _) => add_min_element(v, r)
| (_, Empty) => add_max_element(v, l)
| (
Node({l: ll, v: lv, r: lr, h: lh}),
Node({l: rl, v: rv, r: rr, h: rh}),
) =>
if (lh > rh + 2) {
bal(ll, lv, join(lr, v, r));
} else if (rh > lh + 2) {
bal(join(l, v, rl), rv, rr);
} else {
create(l, v, r);
}
};
let rec min_elt =
fun
| Empty => raise(Not_found)
| Node({l: Empty, v, _}) => v
| Node({l, _}) => min_elt(l);
let rec min_elt_opt =
fun
| Empty => None
| Node({l: Empty, v, _}) => Some(v)
| Node({l, _}) => min_elt_opt(l);
let rec max_elt =
fun
| Empty => raise(Not_found)
| Node({v, r: Empty, _}) => v
| Node({r, _}) => max_elt(r);
let rec max_elt_opt =
fun
| Empty => None
| Node({v, r: Empty, _}) => Some(v)
| Node({r, _}) => max_elt_opt(r);
let rec remove_min_elt =
fun
| Empty => invalid_arg("Set.remove_min_elt")
| Node({l: Empty, r, _}) => r
| Node({l, v, r, _}) => bal(remove_min_elt(l), v, r);
let merge = (t1, t2) =>
switch (t1, t2) {
| (Empty, t) => t
| (t, Empty) => t
| (Node(_), Node(_)) => bal(t1, min_elt(t2), remove_min_elt(t2))
};
let concat = (t1, t2) =>
switch (t1, t2) {
| (Empty, t) => t
| (t, Empty) => t
| (Node(_), Node(_)) => join(t1, min_elt(t2), remove_min_elt(t2))
};
let rec split = x =>
fun
| Empty => (Empty, false, Empty)
| Node({l, v, r, _}) => {
let c = Ord.compare(x, v);
if (c == 0) {
(l, true, r);
} else if (c < 0) {
let (ll, pres, rl) = split(x, l);
(ll, pres, join(rl, v, r));
} else {
let (lr, pres, rr) = split(x, r);
(join(l, v, lr), pres, rr);
};
};
let empty = Empty;
let is_empty =
fun
| Empty => true
| Node(_) => false;
let rec mem = x =>
fun
| Empty => false
| Node({l, v, r, _}) => {
let c = Ord.compare(x, v);
c == 0
|| mem(
x,
if (c < 0) {
l;
} else {
r;
},
);
};
let rec remove = x =>
fun
| Empty => Empty
| Node({l, v, r, _}) as t => {
let c = Ord.compare(x, v);
if (c == 0) {
merge(l, r);
} else if (c < 0) {
let ll = remove(x, l);
if (l === ll) {
t;
} else {
bal(ll, v, r);
};
} else {
let rr = remove(x, r);
if (r === rr) {
t;
} else {
bal(l, v, rr);
};
};
};
let rec union = (s1, s2) =>
switch (s1, s2) {
| (Empty, t2) => t2
| (t1, Empty) => t1
| (
Node({l: l1, v: v1, r: r1, h: h1}),
Node({l: l2, v: v2, r: r2, h: h2}),
) =>
if (h1 >= h2) {
if (h2 == 1) {
add(v2, s1);
} else {
let (l2, _, r2) = split(v1, s2);
join(union(l1, l2), v1, union(r1, r2));
};
} else if (h1 == 1) {
add(v1, s2);
} else {
let (l1, _, r1) = split(v2, s1);
join(union(l1, l2), v2, union(r1, r2));
}
};
let rec inter = (s1, s2) =>
switch (s1, s2) {
| (Empty, _) => Empty
| (_, Empty) => Empty
| (Node({l: l1, v: v1, r: r1, _}), t2) =>
switch (split(v1, t2)) {
| (l2, false, r2) => concat(inter(l1, l2), inter(r1, r2))
| (l2, true, r2) => join(inter(l1, l2), v1, inter(r1, r2))
}
};
let rec diff = (s1, s2) =>
switch (s1, s2) {
| (Empty, _) => Empty
| (t1, Empty) => t1
| (Node({l: l1, v: v1, r: r1, _}), t2) =>
switch (split(v1, t2)) {
| (l2, false, r2) => join(diff(l1, l2), v1, diff(r1, r2))
| (l2, true, r2) => concat(diff(l1, l2), diff(r1, r2))
}
};
type enumeration =
| End
| More(elt, t, enumeration);
let rec cons_enum = (s, e) =>
switch (s) {
| Empty => e
| Node({l, v, r, _}) => cons_enum(l, [@implicit_arity] More(v, r, e))
};
let rec compare_aux = (e1, e2) =>
switch (e1, e2) {
| (End, End) => 0
| (End, _) => (-1)
| (_, End) => 1
| (
[@implicit_arity] More(v1, r1, e1),
[@implicit_arity] More(v2, r2, e2),
) =>
let c = Ord.compare(v1, v2);
if (c != 0) {
c;
} else {
compare_aux(cons_enum(r1, e1), cons_enum(r2, e2));
};
};
let compare = (s1, s2) =>
compare_aux(cons_enum(s1, End), cons_enum(s2, End));
let equal = (s1, s2) => compare(s1, s2) == 0;
let rec subset = (s1, s2) =>
switch (s1, s2) {
| (Empty, _) => true
| (_, Empty) => false
| (Node({l: l1, v: v1, r: r1, _}), Node({l: l2, v: v2, r: r2, _}) as t2) =>
let c = Ord.compare(v1, v2);
if (c == 0) {
subset(l1, l2) && subset(r1, r2);
} else if (c < 0) {
subset(Node({l: l1, v: v1, r: Empty, h: 0}), l2) && subset(r1, t2);
} else {
subset(Node({l: Empty, v: v1, r: r1, h: 0}), r2) && subset(l1, t2);
};
};
let rec iter = f =>
fun
| Empty => ()
| Node({l, v, r, _}) => {
iter(f, l);
f(v);
iter(f, r);
};
let rec fold = (f, s, accu) =>
switch (s) {
| Empty => accu
| Node({l, v, r, _}) => fold(f, r, f(v, fold(f, l, accu)))
};
let rec for_all = p =>
fun
| Empty => true
| Node({l, v, r, _}) => p(v) && for_all(p, l) && for_all(p, r);
let rec exists = p =>
fun
| Empty => false
| Node({l, v, r, _}) => p(v) || exists(p, l) || exists(p, r);
let rec filter = p =>
fun
| Empty => Empty
| Node({l, v, r, _}) as t => {
let l' = filter(p, l);
let pv = p(v);
let r' = filter(p, r);
if (pv) {
if (l === l' && r === r') {
t;
} else {
join(l', v, r');
};
} else {
concat(l', r');
};
};
let rec partition = p =>
fun
| Empty => (Empty, Empty)
| Node({l, v, r, _}) => {
let (lt, lf) = partition(p, l);
let pv = p(v);
let (rt, rf) = partition(p, r);
if (pv) {
(join(lt, v, rt), concat(lf, rf));
} else {
(concat(lt, rt), join(lf, v, rf));
};
};
let rec cardinal =
fun
| Empty => 0
| Node({l, r, _}) => cardinal(l) + 1 + cardinal(r);
let rec elements_aux = accu =>
fun
| Empty => accu
| Node({l, v, r, _}) => elements_aux([v, ...elements_aux(accu, r)], l);
let elements = s => elements_aux([], s);
let choose = min_elt;
let choose_opt = min_elt_opt;
let rec find = x =>
fun
| Empty => raise(Not_found)
| Node({l, v, r, _}) => {
let c = Ord.compare(x, v);
if (c == 0) {
v;
} else {
find(
x,
if (c < 0) {
l;
} else {
r;
},
);
};
};
let rec find_first_aux = (v0, f) =>
fun
| Empty => v0
| Node({l, v, r, _}) =>
if (f(v)) {
find_first_aux(v, f, l);
} else {
find_first_aux(v0, f, r);
};
let rec find_first = f =>
fun
| Empty => raise(Not_found)
| Node({l, v, r, _}) =>
if (f(v)) {
find_first_aux(v, f, l);
} else {
find_first(f, r);
};
let rec find_first_opt_aux = (v0, f) =>
fun
| Empty => Some(v0)
| Node({l, v, r, _}) =>
if (f(v)) {
find_first_opt_aux(v, f, l);
} else {
find_first_opt_aux(v0, f, r);
};
let rec find_first_opt = f =>
fun
| Empty => None
| Node({l, v, r, _}) =>
if (f(v)) {
find_first_opt_aux(v, f, l);
} else {
find_first_opt(f, r);
};
let rec find_last_aux = (v0, f) =>
fun
| Empty => v0
| Node({l, v, r, _}) =>
if (f(v)) {
find_last_aux(v, f, r);
} else {
find_last_aux(v0, f, l);
};
let rec find_last = f =>
fun
| Empty => raise(Not_found)
| Node({l, v, r, _}) =>
if (f(v)) {
find_last_aux(v, f, r);
} else {
find_last(f, l);
};
let rec find_last_opt_aux = (v0, f) =>
fun
| Empty => Some(v0)
| Node({l, v, r, _}) =>
if (f(v)) {
find_last_opt_aux(v, f, r);
} else {
find_last_opt_aux(v0, f, l);
};
let rec find_last_opt = f =>
fun
| Empty => None
| Node({l, v, r, _}) =>
if (f(v)) {
find_last_opt_aux(v, f, r);
} else {
find_last_opt(f, l);
};
let rec find_opt = x =>
fun
| Empty => None
| Node({l, v, r, _}) => {
let c = Ord.compare(x, v);
if (c == 0) {
Some(v);
} else {
find_opt(
x,
if (c < 0) {
l;
} else {
r;
},
);
};
};
let try_join = (l, v, r) =>
if ((l == Empty || Ord.compare(max_elt(l), v) < 0)
&& (r == Empty || Ord.compare(v, min_elt(r)) < 0)) {
join(l, v, r);
} else {
union(l, add(v, r));
};
let rec map = f =>
fun
| Empty => Empty
| Node({l, v, r, _}) as t => {
let l' = map(f, l);
let v' = f(v);
let r' = map(f, r);
if (l === l' && v === v' && r === r') {
t;
} else {
try_join(l', v', r');
};
};
let of_sorted_list = l => {
let rec sub = (n, l) =>
switch (n, l) {
| (0, l) => (Empty, l)
| (1, [x0, ...l]) => (Node({l: Empty, v: x0, r: Empty, h: 1}), l)
| (2, [x0, x1, ...l]) => (
Node({
l: Node({l: Empty, v: x0, r: Empty, h: 1}),
v: x1,
r: Empty,
h: 2,
}),
l,
)
| (3, [x0, x1, x2, ...l]) => (
Node({
l: Node({l: Empty, v: x0, r: Empty, h: 1}),
v: x1,
r: Node({l: Empty, v: x2, r: Empty, h: 1}),
h: 2,
}),
l,
)
| (n, l) =>
let nl = n / 2;
let (left, l) = sub(nl, l);
switch (l) {
| [] => assert(false)
| [mid, ...l] =>
let (right, l) = sub(n - nl - 1, l);
(create(left, mid, right), l);
};
};
fst(sub(List.length(l), l));
};
let of_list = l =>
switch (l) {
| [] => empty
| [x0] => singleton(x0)
| [x0, x1] => add(x1, singleton(x0))
| [x0, x1, x2] => add(x2, add(x1, singleton(x0)))
| [x0, x1, x2, x3] => add(x3, add(x2, add(x1, singleton(x0))))
| [x0, x1, x2, x3, x4] =>
add(x4, add(x3, add(x2, add(x1, singleton(x0)))))
| _ => of_sorted_list(List.sort_uniq(Ord.compare, l))
};
};
module type STACK = {
/** The type of stacks containing elements of type ['a]. */
type t('a);
/** Raised when {!Stack.pop} or {!Stack.top} is applied to an empty stack. */
exception Empty;
/** Return a new stack, initially empty. */
let create: unit => t('a);
/** [push x s] adds the element [x] at the top of stack [s]. */
let push: ('a, t('a)) => unit;
/** [pop s] removes and returns the topmost element in stack [s],
or raises {!Empty} if the stack is empty. */
let pop: t('a) => 'a;
/** [top s] returns the topmost element in stack [s],
or raises {!Empty} if the stack is empty. */
let top: t('a) => 'a;
/** Discard all elements from a stack. */
let clear: t('a) => unit;
/** Return a copy of the given stack. */
let copy: t('a) => t('a);
/** Return [true] if the given stack is empty, [false] otherwise. */
let is_empty: t('a) => bool;
/** Return the number of elements in a stack. Time complexity O(1) */
let length: t('a) => int;
/** [iter f s] applies [f] in turn to all elements of [s],
from the element at the top of the stack to the element at the
bottom of the stack. The stack itself is unchanged. */
let iter: ('a => unit, t('a)) => unit;
/** [fold f accu s] is [(f (... (f (f accu x1) x2) ...) xn)]
where [x1] is the top of the stack, [x2] the second element,
and [xn] the bottom element. The stack is unchanged.
@since 4.03 */
let fold: (('b, 'a) => 'b, 'b, t('a)) => 'b;
};
module Stack: STACK = {
type t('a) = {
mutable c: list('a),
mutable len: int,
};
exception Empty;
let create = () => {c: [], len: 0};
let clear = s => {
s.c = [];
s.len = 0;
};
let copy = s => {c: s.c, len: s.len};
let push = (x, s) => {
s.c = [x, ...s.c];
s.len = s.len + 1;
};
let pop = s =>
switch (s.c) {
| [hd, ...tl] =>
s.c = tl;
s.len = s.len - 1;
hd;
| [] => raise(Empty)
};
let top = s =>
switch (s.c) {
| [hd, ..._] => hd
| [] => raise(Empty)
};
let is_empty = s => s.c == [];
let length = s => s.len;
let iter = (f, s) => List.iter(f, s.c);
let fold = (f, acc, s) => List.fold_left(f, acc, s.c);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment