123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
* Copyright (C) 2010 Jérôme Vouillon
* Laboratoire PPS - CNRS Université Paris Diderot
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)open!StdlibmoduleNum:sigtypet(** Conversions *)valof_string_unsafe:string->tvalof_targetint:Targetint.t->tvalof_float:float->tvalto_string:t->stringvalto_targetint:t->Targetint.tvalhash:t->int(** Predicates *)valis_zero:t->boolvalis_one:t->boolvalis_neg:t->boolvalequal:t->t->bool(** Arithmetic *)valadd:t->t->tvalneg:t->tend=structtypet=stringletof_string_unsafes=sletto_strings=sletto_targetints=ifString.starts_withs~prefix:"0"&&String.lengths>1&&String.for_alls~f:(function|'0'..'7'->true|_->false)then(* legacy octal notation *)Targetint.of_string_exn("0o"^s)elseTargetint.of_string_exnsletof_targetint=Targetint.to_stringexternalformat_float:string->float->string="caml_format_float"letfmts=Array.init19~f:(funi->"%."^string_of_inti^"g")letfloat_to_stringprecv=format_floatfmts.(prec)vletrecfind_smaller~f~bad~good~good_s=ifbad+1=goodthengood_selseletmid=(good+bad)/2inassert(mid<>good);assert(mid<>bad);matchfmidwith|None->find_smaller~f~bad:mid~good~good_s|Somes->find_smaller~f~bad~good:mid~good_s:s(* Windows uses 3 digits for the exponent, let's fix it. *)letfix_exponents=tryletstart=String.index_froms0'e'+1inletstart=matchString.getsstartwith|'-'|'+'->succstart|_->startinletstop=refstartinwhileChar.equal(String.gets!stop)'0'doincrstopdone;ifstart=!stopthenselseString.subs~pos:0~len:start^String.subs~pos:!stop~len:(String.lengths-!stop)withNot_found->sletof_floatv=matchFloat.classify_floatvwith|FP_nan->"NaN"|FP_zero->(* [1/-0] < 0. seems to be the only way to detect -0 in JavaScript *)ifFloat.(1./.v<0.)then"-0."else"0."|FP_infinite->ifFloat.(v<0.)then"-Infinity"else"Infinity"|FP_normal|FP_subnormal->(letvint=int_of_floatvinifFloat.ieee_equal(float_of_intvint)vthenPrintf.sprintf"%d."vintelsematchfind_smaller~f:(funprec->lets=float_to_stringprecvinifFloat.ieee_equalv(float_of_strings)thenSomeselseNone)~bad:0~good:18~good_s:"max"with|"max"->float_to_string18v|>fix_exponent|s->fix_exponents)letis_zeros=String.equals"0"letis_ones=String.equals"1"letis_negs=Char.equals.[0]'-'letequalab=String.equalablethasha=String.hashaletnegs=matchString.drop_prefixs~prefix:"-"with|None->"-"^s|Somes->sletaddab=of_targetint(Targetint.add(to_targetinta)(to_targetintb))endmoduleLabel=structtypet=|LofCode.Var.t|SofUtf8_string.tletfresh()=L(Code.Var.fresh())letof_strings=Ssletequalab=matcha,bwith|Lx,Ly->Code.Var.equalxy|Ss,St->Utf8_string.equalst|L_,S_|S_,L_->falseendtypelocation=|PiofParse_info.t|N|Utypeidentifier=Utf8_string.ttypeident_string={name:identifier;var:Code.Var.toption;loc:location}typeearly_error={loc:Parse_info.t;reason:stringoption}typeident=|Sofident_string|VofCode.Var.t(* A.3 Expressions *)andarray_litteral=element_listandelement_list=elementlistandelement=|ElementHole|Elementofexpression|ElementSpreadofexpressionandbinop=|Eq|StarEq|SlashEq|ModEq|PlusEq|MinusEq|LslEq|AsrEq|LsrEq|BandEq|BxorEq|BorEq|Or|OrEq|And|AndEq|Bor|Bxor|Band|EqEq|NotEq|EqEqEq|NotEqEq|Lt|Le|Gt|Ge|LtInt|LeInt|GtInt|GeInt|InstanceOf|In|Lsl|Lsr|Asr|Plus|Minus|Mul|Div|Mod|Exp|ExpEq|Coalesce|CoalesceEqandunop=|Not|Neg|Pl|Typeof|Void|Delete|Bnot|IncrA|DecrA|IncrB|DecrB|Awaitandarguments=argumentlistandargument=|Argofexpression|ArgSpreadofexpressionandproperty_list=propertylistandproperty=|Propertyofproperty_name*expression|PropertySpreadofexpression|PropertyMethodofproperty_name*method_|CoverInitializedNameofearly_error*ident*initialiserandmethod_=|MethodGetoffunction_declaration|MethodSetoffunction_declaration|Methodoffunction_declarationandproperty_name=|PNIofidentifier|PNSofUtf8_string.t|PNNofNum.t|PComputedofexpressionandexpression=|ESeqofexpression*expression|ECondofexpression*expression*expression|EAssignTargetofassignment_target|EBinofbinop*expression*expression|EUnofunop*expression|ECallofexpression*access_kind*arguments*location|ECallTemplateofexpression*template*location|EAccessofexpression*access_kind*expression|EDotofexpression*access_kind*identifier|EDotPrivateofexpression*access_kind*identifier|ENewofexpression*argumentsoption*location|EVarofident|EFunofidentoption*function_declaration|EClassofidentoption*class_declaration|EArrowoffunction_declaration*bool*arrow_info|EStrofUtf8_string.t|ETemplateoftemplate|EArrofarray_litteral|EBoolofbool|ENumofNum.t|EObjofproperty_list|ERegexpofstring*stringoption|EYieldof{delegate:bool;expr:expressionoption}|EPrivNameofidentifier|CoverParenthesizedExpressionAndArrowParameterListofearly_error|CoverCallExpressionAndAsyncArrowHeadofearly_errorandarrow_info=|AUnknown|AUse_parent_fun_context|ANo_fun_contextandtemplate=template_partlistandtemplate_part=|TStrofUtf8_string.t|TExpofexpressionandaccess_kind=|ANormal|ANullish(****)(* A.4 Statements *)andstatement=|Blockofblock|Variable_statementofvariable_declaration_kind*variable_declarationlist|Function_declarationofident*function_declaration|Class_declarationofident*class_declaration|Empty_statement|Expression_statementofexpression|If_statementofexpression*(statement*location)*(statement*location)option|Do_while_statementof(statement*location)*expression|While_statementofexpression*(statement*location)|For_statementof(expressionoption,variable_declaration_kind*variable_declarationlist)either*expressionoption*expressionoption*(statement*location)|ForIn_statementof(expression,variable_declaration_kind*for_binding)either*expression*(statement*location)|ForOf_statementof(expression,variable_declaration_kind*for_binding)either*expression*(statement*location)|ForAwaitOf_statementof(expression,variable_declaration_kind*for_binding)either*expression*(statement*location)|Continue_statementofLabel.toption|Break_statementofLabel.toption|Return_statementofexpressionoption*location|With_statementofexpression*(statement*location)|Labelled_statementofLabel.t*(statement*location)|Switch_statementofexpression*case_clauselist*statement_listoption*case_clauselist|Throw_statementofexpression|Try_statementofblock*(formal_parameteroption*block)option*blockoption|Debugger_statement|Importofimport*Parse_info.t|Exportofexport*Parse_info.tand('left,'right)either=|Leftof'left|Rightof'rightandblock=statement_listandstatement_list=(statement*location)listandvariable_declaration=|DeclIdentofident*initialiseroption|DeclPatternofbinding_pattern*initialiserandvariable_declaration_kind=|Var|Let|Constandcase_clause=expression*statement_listandinitialiser=expression*location(****)andfunction_declaration=function_kind*formal_parameter_list*function_body*locationandfunction_kind={async:bool;generator:bool}andclass_declaration={extends:expressionoption;body:class_elementlist}andclass_element=|CEMethodofbool*class_element_name*method_|CEFieldofbool*class_element_name*initialiseroption|CEStaticBLockofstatement_listandclass_element_name=|PropNameofproperty_name|PrivNameofidentifierand('a,'b)list_with_rest={list:'alist;rest:'boption}andformal_parameter_list=(formal_parameter,binding)list_with_restandformal_parameter=binding_elementandfor_binding=bindingandbinding_element=binding*initialiseroptionandbinding=|BindingIdentofident|BindingPatternofbinding_patternandbinding_pattern=|ObjectBindingof(binding_property,ident)list_with_rest|ArrayBindingof(binding_elementoption,binding)list_with_restandobject_target_elt=|TargetPropertyIdofident_prop*initialiseroption|TargetPropertyofproperty_name*expression*initialiseroption|TargetPropertySpreadofexpression|TargetPropertyMethodofproperty_name*method_andarray_target_elt=|TargetElementIdofident*initialiseroption|TargetElementHole|TargetElementofexpression|TargetElementSpreadofexpressionandassignment_target=|ObjectTargetofobject_target_eltlist|ArrayTargetofarray_target_eltlistandident_prop=Prop_and_identofidentandbinding_property=|Prop_bindingofproperty_name*binding_element|Prop_identofident_prop*initialiseroptionandfunction_body=statement_listandprogram=statement_listandexport=|ExportVarofvariable_declaration_kind*variable_declarationlist|ExportFunofident*function_declaration|ExportClassofident*class_declaration|ExportNamesof(ident*Utf8_string.t)list(* default *)|ExportDefaultFunofidentoption*function_declaration|ExportDefaultClassofidentoption*class_declaration|ExportDefaultExpressionofexpression(* from *)|ExportFromof{kind:export_from_kind;from:Utf8_string.t}|CoverExportFromofearly_errorandexport_from_kind=|Export_allofUtf8_string.toption|Export_namesof(Utf8_string.t*Utf8_string.t)listandimport={from:Utf8_string.t;kind:import_kind}andimport_default=identandimport_kind=|Namespaceofimport_defaultoption*ident(* import * as name from "fname" *)(* import defaultname, * as name from "fname" *)|Namedofimport_defaultoption*(Utf8_string.t*ident)list(* import { 'a' as a, ...} from "fname" *)(* import defaultname, { 'a' as a, ...} from "fname" *)|Defaultofimport_default(* import defaultname from "fname" *)|SideEffect(* import "fname" *)andprogram_with_annots=(statement_list*(Js_token.Annot.t*Parse_info.t)list)listletcompare_identt1t2=matcht1,t2with|Vv1,Vv2->Code.Var.comparev1v2|S{name=Utf8s1;var=v1;loc=_},S{name=Utf8s2;var=v2;loc=_}->((* ignore locations *)matchString.compares1s2with|0->Option.compareCode.Var.comparev1v2|n->n)|S_,V_->-1|V_,S_->1letis_ident=Flow_lexer.is_valid_identifier_nameletis_ident'(Utf8_string.Utf8s)=is_identsletident?(loc=N)?var(Utf8_string.Utf8nasname)=ifnot(is_ident'name)thenfailwith(Printf.sprintf"%s not a valid ident"n);S{name;var;loc}letident_equal(a:ident)b=Poly.equalabletparam'id=BindingIdentid,Noneletparam?loc?varname=param'(ident?loc?varname)letident_unsafe?(loc=N)?varname=S{name;var;loc}letrecbound_idents_of_bindingp=matchpwith|BindingIdentid->[id]|BindingPatternp->bound_idents_of_patternpandbound_idents_of_params{list;rest}=List.concat_maplist~f:bound_idents_of_element@matchrestwith|None->[]|Somep->bound_idents_of_bindingpandbound_idents_of_patternp=matchpwith|ObjectBinding{list;rest}->(List.concat_maplist~f:(function|Prop_ident(Prop_and_identi,_)->[i]|Prop_binding(_,e)->bound_idents_of_elemente)@matchrestwith|None->[]|Somex->[x])|ArrayBinding{list;rest}->(List.concat_maplist~f:(function|None->[]|Somee->bound_idents_of_elemente)@matchrestwith|None->[]|Somex->bound_idents_of_bindingx)andbound_idents_of_variable_declaration=function|DeclIdent(id,_)->[id]|DeclPattern(p,_)->bound_idents_of_patternpandbound_idents_of_element(b,_)=bound_idents_of_bindingbmoduleIdentSet=Set.Make(structtypet=identletcompare=compare_identend)moduleIdentMap=Map.Make(structtypet=identletcompare=compare_identend)letdotel=EDot(e,ANormal,l)letvariable_declaration?(kind=Var)l=Variable_statement(kind,List.mapl~f:(fun(i,e)->DeclIdent(i,Somee)))letarrayl=EArr(List.mapl~f:(funx->Elementx))letcallfargsloc=ECall(f,ANormal,List.mapargs~f:(funx->Argx),loc)letlistlist={list;rest=None}letearly_error?reasonloc={loc;reason}letfun_paramsbodyloc=({async=false;generator=false},list(List.mapparams~f:(funx->BindingIdentx,None)),body,loc)letrecassignment_target_of_expr'x=matchxwith|EObjl->letlist=List.mapl~f:(function|Property(PNIn,EVar(S{name=n';_}asid))whenUtf8_string.equalnn'->TargetPropertyId(Prop_and_identid,None)|Property(n,e)->lete,i=matchewith|EBin(Eq,e,i)->e,Some(i,N)|_->e,NoneinTargetProperty(n,assignment_target_of_expr'e,i)|CoverInitializedName(_,i,(e,loc))->TargetPropertyId(Prop_and_identi,Some(assignment_target_of_expr'e,loc))|PropertySpreade->TargetPropertySpread(assignment_target_of_expr'e)|PropertyMethod(n,m)->TargetPropertyMethod(n,m))inEAssignTarget(ObjectTargetlist)|EArrl->letlist=List.mapl~f:(function|ElementHole->TargetElementHole|Element(EVarx)->TargetElementId(x,None)|Element(EBin(Eq,EVarx,rhs))->TargetElementId(x,Some(rhs,N))|Elemente->TargetElement(assignment_target_of_expr'e)|ElementSpreade->TargetElementSpread(assignment_target_of_expr'e))inEAssignTarget(ArrayTargetlist)|_->xandassignment_target_of_expropx=matchopwith|None|SomeEq->assignment_target_of_expr'x|_->xletlocation_equal(a:location)b=Poly.equalab