123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161(*---------------------------------------------------------------------------
Copyright (c) 2020 The brr programmers. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)(* Mini Jv, this allows us to use Jstr in Jv *)typejvexternaljv_call:jv->string->jvarray->'a="caml_js_meth_call"externaljv_apply:jv->jvarray->'a="caml_js_fun_call"externaljv_get:jv->string->jv="caml_js_get"externaljv_of_int:int->jv="%identity"externaljv_to_int:jv->int="%identity"externaljv_of_float:float->jv="caml_js_from_float"externaljv_to_float:jv->float="caml_js_to_float"externaljv_to_bool:jv->bool="caml_js_to_bool"externaljv_pure_js_expr:string->'a="caml_pure_js_expr"letjv_global=jv_pure_js_expr"globalThis"(* Strings *)typet=jvexternaljv_to_jstr_list:jv->tlist="caml_list_of_js_array"externaljv_of_jstr_list:tlist->jv="caml_list_to_js_array"externalv:string->t="caml_jsstring_of_string"letlengths=jv_to_int(jv_gets"length")externaljstr_to_string:t->string="caml_string_of_jsstring"letjstr_of_int?(base=10)i=jv_call(jv_of_inti)"toString"[|jv_of_intbase|]leterr_boundsilen=let(+)s0s1=jv_calls0"concat"[|s1|]injstr_to_string@@v"index "+jstr_of_inti+v" not in bounds [0;"+jstr_of_int(len-1)+v"]"letgetsi=ifi>=lengthstheninvalid_arg(err_boundsi(lengths))elseletu=jv_to_int(jv_calls"codePointAt"[|jv_of_inti|])inletu=ifu<0xD800||u>0xDFFFthenuelse0xFFFD(* Uchar.rep *)inUchar.unsafe_of_intuletjstr_of_uchar_inti=jv_call(jv_getjv_global"String")"fromCodePoint"[|jv_of_inti|]letget_jstrsi=jstr_of_uchar_int(Uchar.to_int(getsi))(* Constants *)letempty=v""letsp=v" "letnl=v"\n"(* Assembling *)letappends0s1=jv_calls0"concat"[|s1|]let(+)=appendletconcat?(sep=empty)ss=jv_call(jv_of_jstr_listss)"join"[|sep|]letpad_start?(pad=sp)lens=jv_calls"padStart"[|jv_of_intlen;pad|]letpad_end?(pad=sp)lens=jv_calls"padEnd"[|jv_of_intlen;pad|]letrepeatns=jv_calls"repeat"[|jv_of_intn|](* Finding *)letfind_sub?(start=0)~subs=leti=jv_to_int(jv_calls"indexOf"[|sub;jv_of_intstart|])inifi=-1thenNoneelseSomeiletfind_last_sub?before~subs=letbefore=matchbeforewithNone->lengths|Someb->binletpos=before-lengthsubinifpos<0thenNoneelseleti=jv_to_int(jv_calls"lastIndexOf"[|sub;jv_of_intpos|])inifi=-1thenNoneelseSomei(* Breaking *)letslice?(start=0)?stops=letargs=matchstopwith|None->[|jv_of_intstart|]|Somestop->[|jv_of_intstart;jv_of_intstop|]injv_calls"slice"argsletsub?(start=0)?lens=letargs=matchlenwith|None->[|jv_of_intstart|]|Somelen->[|jv_of_intstart;jv_of_intlen|]injv_calls"substr"argsletcuts~seps=jv_to_jstr_list(jv_calls"split"[|sep|])(* Traversing and transforming *)letiterator:jv=jv_pure_js_expr"Symbol.iterator"externalget_symbol:jv->jv->jv="caml_js_get"letfold_ucharsfsacc=letrecloopitacc=letr=jv_callit"next"[||]inifjv_to_bool(jv_getr"done")thenaccelseletu=jv_call(jv_getr"value")"codePointAt"[|jv_of_int0|]inletu=ifu<0xD800||u>0xDFFFthenuelse0xFFFD(* Uchar.rep *)inloopit(f(Uchar.unsafe_of_intu)acc)inloop(jv_apply(get_symbolsiterator)[||])accletfold_jstr_ucharsfsacc=letf'uacc=f(jstr_of_uchar_int(Uchar.to_intu))accinfold_ucharsf'sacclettrims=jv_calls"trim"[||](* Normalization *)typenormalization=[`NFD|`NFC|`NFKD|`NFKC]letnormalizednfs=letnf=matchnfwith|`NFD->v"NFD"|`NFC->v"NFC"|`NFKD->v"NFKD"|`NFKC->v"NFKC"injv_calls"normalize"[|nf|](* Case mapping *)letlowercaseds=jv_calls"toLowerCase"[||]letuppercaseds=jv_calls"toUpperCase"[||](* Predicates and comparisons *)letis_emptys=lengths=0letstarts_with~prefixs=jv_to_bool@@jv_calls"startsWith"[|prefix|]letincludes~affixs=jv_to_bool@@jv_calls"includes"[|affix|]letends_with~suffixs=jv_to_bool@@jv_calls"endsWith"[|suffix|]letequal=(=)letcompare=compare(* Conversions *)letof_ucharu=jstr_of_uchar_int(Uchar.to_intu)letof_charc=jstr_of_uchar_int(Char.codec)externalof_string:string->t="caml_jsstring_of_string"externalto_string:t->string="caml_string_of_jsstring"externalbinary_to_octets:t->string="caml_string_of_jsbytes"externalbinary_of_octets:string->t="caml_jsbytes_of_string"letnumber=jv_getjv_global"Number"letof_int=jstr_of_intletto_int?bases=letargs=matchbasewithNone->[|s|]|Someb->[|s;jv_of_intb|]inletn=jv_callnumber"parseInt"argsinifnot(n=n)then(* NaN *)NoneelseSome(jv_to_intn)letto_floats=jv_to_float@@jv_callnumber"parseFloat"[|s|]letof_float?fracn=matchfracwith|None->jv_call(jv_of_floatn)"toString"[||]|Somefrac->jv_call(jv_of_floatn)"toFixed"[|jv_of_intfrac|]