1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279(* 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.
*)(* Beware automatic semi-colon insertion...
{v
a=b
++c
v}
is not the same as
{v
a=b ++c
v}
see so-called "restricted productions":
the space cannot be replaced by a newline in the following expressions:
{v
e ++
e --
continue e
break e
return e
throw
v}
*)open!Stdlibletstats=Debug.find"output"openJavascriptmodulePP=Pretty_printmoduleMake(D:sigvalsource_map:Source_map.toptionend)=structlettemp_mappings=ref[]letpush_mapping,get_file_index,get_name_index,source_map_enabled=letidx_files=ref0inletidx_names=ref0inletfiles=Hashtbl.create17inletnames=Hashtbl.create17inmatchD.source_mapwith|None->(fun__->()),(fun_->-1),(fun_->-1),false|Somesm->List.iter(List.revsm.Source_map.sources)~f:(funf->Hashtbl.addfilesf!idx_files;incridx_files);((funposm->temp_mappings:=(pos,m)::!temp_mappings),(funfile->tryHashtbl.findfilesfilewithNot_found->letpos=!idx_filesinHashtbl.addfilesfilepos;incridx_files;sm.Source_map.sources<-file::sm.Source_map.sources;pos),(funname->tryHashtbl.findnamesnamewithNot_found->letpos=!idx_namesinHashtbl.addnamesnamepos;incridx_names;sm.Source_map.names<-name::sm.Source_map.names;pos),true)letdebug_enabled=Config.Flag.debuginfo()letoutput_debug_infofloc=(ifdebug_enabledthenmatchlocwith|Pi{Parse_info.name=Somefile;line;col;_}|Pi{Parse_info.src=Somefile;line;col;_}->PP.non_breaking_spacef;PP.stringf(Format.sprintf"/*<<%s %d %d>>*/"filelinecol);PP.non_breaking_spacef|N->()|U|Pi_->PP.non_breaking_spacef;PP.stringf"/*<<?>>*/";PP.non_breaking_spacef);ifsource_map_enabledthenmatchlocwith|N->()|U|Pi{Parse_info.src=None;_}->push_mapping(PP.posf){Source_map.gen_line=-1;gen_col=-1;ori_source=-1;ori_line=-1;ori_col=-1;ori_name=None}|Pi{Parse_info.src=Somefile;line;col;_}->push_mapping(PP.posf){Source_map.gen_line=-1;gen_col=-1;ori_source=get_file_indexfile;ori_line=line;ori_col=col;ori_name=None}letoutput_debug_info_identfnmloc=ifsource_map_enabledthenmatchlocwith|None->()|Some{Parse_info.src=Somefile;line;col;_}->push_mapping(PP.posf){Source_map.gen_line=-1;gen_col=-1;ori_source=get_file_indexfile;ori_line=line;ori_col=col;ori_name=Some(get_name_indexnm)}|Some_->()letidentf=function|S{name;var=Somev;_}->output_debug_info_identfname(Code.Var.get_locv);PP.stringfname|S{name;var=None;loc=Pipi}->output_debug_info_identfname(Somepi);PP.stringfname|S{name;var=None;loc=U|N}->PP.stringfname|V_v->assertfalseletopt_identifierfi=matchiwith|None->()|Somei->PP.spacef;identfiletrecformal_parameter_listfl=matchlwith|[]->()|[i]->identfi|i::r->identfi;PP.stringf",";PP.breakf;formal_parameter_listfr(*
0 Expression
1 AssignementExpression
2 ConditionalExpression
3 LogicalORExpression
4 LogicalANDExpression
5 BitwiseORExpression
6 BitwiseXORExpression
7 BitwiseANDExpression
8 EqualityExpression
9 RelationalExpression
10 ShiftExpression
11 AdditiveExpression
12 MultiplicativeExpression
13 UnaryExpression
14 PostfixExpression
15 LeftHandsideExpression
NewExpression
CallExpression
16 MemberExpression
FunctionExpression
PrimaryExpression
*)letop_precop=matchopwith|Eq|StarEq|SlashEq|ModEq|PlusEq|MinusEq|LslEq|AsrEq|LsrEq|BandEq|BxorEq|BorEq->1,13,1(*
| Or -> 3, 3, 4
| And -> 4, 4, 5
| Bor -> 5, 5, 6
| Bxor -> 6, 6, 7
| Band -> 7, 7, 8
*)|Or->3,3,3|And->4,4,4|Bor->5,5,5|Bxor->6,6,6|Band->7,7,7|EqEq|NotEq|EqEqEq|NotEqEq->8,8,9|Gt|GtInt|Ge|GeInt|Lt|LtInt|Le|LeInt|InstanceOf|In->9,9,10|Lsl|Lsr|Asr->10,10,11|Plus|Minus->11,11,12|Mul|Div|Mod->12,12,13letop_strop=matchopwith|Eq->"="|StarEq->"*="|SlashEq->"/="|ModEq->"%="|PlusEq->"+="|MinusEq->"-="|Or->"||"|And->"&&"|Bor->"|"|Bxor->"^"|Band->"&"|EqEq->"=="|NotEq->"!="|EqEqEq->"==="|NotEqEq->"!=="|LslEq->"<<="|AsrEq->">>="|LsrEq->">>>="|BandEq->"&="|BxorEq->"^="|BorEq->"|="|Lt|LtInt->"<"|Le|LeInt->"<="|Gt|GtInt->">"|Ge|GeInt->">="|Lsl->"<<"|Lsr->">>>"|Asr->">>"|Plus->"+"|Minus->"-"|Mul->"*"|Div->"/"|Mod->"%"|InstanceOf|In->assertfalseletunop_strop=matchopwith|Not->"!"|Neg->"-"|Pl->"+"|Bnot->"~"|IncrA|IncrB|DecrA|DecrB|Typeof|Void|Delete->assertfalseletrecends_with_if_without_elsest=matchfststwith|Labelled_statement(_,st)|If_statement(_,_,Somest)|While_statement(_,st)|For_statement(_,_,_,st)|ForIn_statement(_,_,st)->ends_with_if_without_elsest|If_statement(_,_,None)->true|Block_|Variable_statement_|Empty_statement|Expression_statement_|Continue_statement_|Break_statement_|Return_statement_|Throw_statement_|Do_while_statement_|Switch_statement_|Try_statement_|Debugger_statement->falseletrecneed_parenle=matchewith|ESeq(e,_)->l<=0&&need_paren0e|ECond(e,_,_)->l<=2&&need_paren3e|EBin(op,e,_)->letout,lft,_rght=op_precopinl<=out&&need_parenlfte|ECall(e,_,_)|EAccess(e,_)|EDot(e,_)->l<=15&&need_paren15e|EVar_|EStr_|EArr_|EBool_|ENum_|EQuote_|ERegexp_|EUn_|ENew_->false|EFun_|EObj_->trueletbest_string_quotes=letsimple=ref0anddouble=ref0infori=0toString.lengths-1domatchs.[i]with|'\''->incrsimple|'"'->incrdouble|_->()done;if!simple<!doublethen'\''else'"'letarray_conv=Array.init16~f:(funi->"0123456789abcdef".[i])letpp_stringf?(quote='"')?(utf=false)s=letl=String.lengthsinletb=Buffer.create(String.lengths+2)inBuffer.add_charbquote;fori=0tol-1doletc=s.[i]inmatchcwith|'\000'wheni=l-1||not(Char.is_nums.[i+1])->Buffer.add_stringb"\\0"|'\b'->Buffer.add_stringb"\\b"|'\t'->Buffer.add_stringb"\\t"|'\n'->Buffer.add_stringb"\\n"(* This escape sequence is not supported by IE < 9
| '\011' -> "\\v"
*)|'\012'->Buffer.add_stringb"\\f"(* https://github.com/ocsigen/js_of_ocaml/issues/898 *)|'/'wheni>0&&Char.equals.[i-1]'<'->Buffer.add_stringb"\\/"|'\\'whennotutf->Buffer.add_stringb"\\\\"|'\r'->Buffer.add_stringb"\\r"|'\000'..'\031'|'\127'->letc=Char.codecinBuffer.add_stringb"\\x";Buffer.add_charb(Array.unsafe_getarray_conv(clsr4));Buffer.add_charb(Array.unsafe_getarray_conv(cland0xf))|'\128'..'\255'whennotutf->letc=Char.codecinBuffer.add_stringb"\\x";Buffer.add_charb(Array.unsafe_getarray_conv(clsr4));Buffer.add_charb(Array.unsafe_getarray_conv(cland0xf))|_->ifChar.equalcquotethen(Buffer.add_charb'\\';Buffer.add_charbc)elseBuffer.add_charbcdone;Buffer.add_charbquote;PP.stringf(Buffer.contentsb)letrecexpressionlfe=matchewith|EVarv->identfv|ESeq(e1,e2)->ifl>0then(PP.start_groupf1;PP.stringf"(");expression0fe1;PP.stringf",";PP.breakf;expression0fe2;ifl>0then(PP.stringf")";PP.end_groupf)|EFun(i,l,b,pc)->PP.start_groupf1;PP.start_groupf0;PP.start_groupf0;PP.stringf"function";opt_identifierfi;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"(";formal_parameter_listfl;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"{";function_bodyfb;output_debug_infofpc;PP.stringf"}";PP.end_groupf;PP.end_groupf|ECall(e,el,loc)->ifl>15then(PP.start_groupf1;PP.stringf"(");output_debug_infofloc;PP.start_groupf1;expression15fe;PP.breakf;PP.start_groupf1;PP.stringf"(";argumentsfel;PP.stringf")";PP.end_groupf;PP.end_groupf;ifl>15then(PP.stringf")";PP.end_groupf)|EStr(s,kind)->letquote=best_string_quotesinpp_stringf~utf:Poly.(kind=`Utf8)~quotes|EBoolb->PP.stringf(ifbthen"true"else"false")|ENumnum->lets=Num.to_stringnuminletneed_parent=ifNum.is_negnumthenl>13(* Negative numbers may need to be parenthesized. *)elsel=15(* Parenthesize as well when followed by a dot. *)&&(not(Char.equals.[0]'I'))(* Infinity *)&¬(Char.equals.[0]'N')(* NaN *)inifneed_parentthenPP.stringf"(";PP.stringfs;ifneed_parentthenPP.stringf")"|EUn(Typeof,e)->ifl>13then(PP.start_groupf1;PP.stringf"(");PP.start_groupf0;PP.stringf"typeof";PP.spacef;expression13fe;PP.end_groupf;ifl>13then(PP.stringf")";PP.end_groupf)|EUn(Void,e)->ifl>13then(PP.start_groupf1;PP.stringf"(");PP.start_groupf0;PP.stringf"void";PP.spacef;expression13fe;PP.end_groupf;ifl>13then(PP.stringf")";PP.end_groupf)|EUn(Delete,e)->ifl>13then(PP.start_groupf1;PP.stringf"(");PP.start_groupf0;PP.stringf"delete";PP.spacef;expression13fe;PP.end_groupf;ifl>13then(PP.stringf")";PP.end_groupf)|EUn(((IncrA|DecrA|IncrB|DecrB)asop),e)->ifl>13then(PP.start_groupf1;PP.stringf"(");ifPoly.(op=IncrA)||Poly.(op=DecrA)thenexpression13fe;ifPoly.(op=IncrA)||Poly.(op=IncrB)thenPP.stringf"++"elsePP.stringf"--";ifPoly.(op=IncrB)||Poly.(op=DecrB)thenexpression13fe;ifl>13then(PP.stringf")";PP.end_groupf)|EUn(op,e)->ifl>13then(PP.start_groupf1;PP.stringf"(");PP.stringf(unop_strop);PP.spacef;expression13fe;ifl>13then(PP.stringf")";PP.end_groupf)|EBin(InstanceOf,e1,e2)->letout,lft,rght=op_precInstanceOfinifl>outthen(PP.start_groupf1;PP.stringf"(");PP.start_groupf0;expressionlftfe1;PP.spacef;PP.stringf"instanceof";PP.spacef;expressionrghtfe2;PP.end_groupf;ifl>outthen(PP.stringf")";PP.end_groupf)|EBin(In,e1,e2)->letout,lft,rght=op_precInstanceOfinifl>outthen(PP.start_groupf1;PP.stringf"(");PP.start_groupf0;expressionlftfe1;PP.spacef;PP.stringf"in";PP.spacef;expressionrghtfe2;PP.end_groupf;ifl>outthen(PP.stringf")";PP.end_groupf)|EBin(op,e1,e2)->letout,lft,rght=op_precopinifl>outthen(PP.start_groupf1;PP.stringf"(");expressionlftfe1;PP.spacef;PP.stringf(op_strop);PP.spacef;expressionrghtfe2;ifl>outthen(PP.stringf")";PP.end_groupf)|EArrel->PP.start_groupf1;PP.stringf"[";element_listfel;PP.stringf"]";PP.end_groupf|EAccess(e,e')->ifl>15then(PP.start_groupf1;PP.stringf"(");PP.start_groupf1;expression15fe;PP.breakf;PP.start_groupf1;PP.stringf"[";expression0fe';PP.stringf"]";PP.end_groupf;PP.end_groupf;ifl>15then(PP.stringf")";PP.end_groupf)|EDot(e,nm)->ifl>15then(PP.start_groupf1;PP.stringf"(");expression15fe;PP.stringf".";PP.stringfnm;ifl>15then(PP.stringf")";PP.end_groupf)|ENew(e,None)->(*FIX: should omit parentheses when possible*)ifl>15then(PP.start_groupf1;PP.stringf"(");PP.start_groupf1;PP.stringf"new";PP.spacef;expression16fe;PP.breakf;PP.stringf"()";PP.end_groupf;ifl>15then(PP.stringf")";PP.end_groupf)|ENew(e,Someel)->ifl>15then(PP.start_groupf1;PP.stringf"(");PP.start_groupf1;PP.stringf"new";PP.spacef;expression16fe;PP.breakf;PP.start_groupf1;PP.stringf"(";argumentsfel;PP.stringf")";PP.end_groupf;PP.end_groupf;ifl>15then(PP.stringf")";PP.end_groupf)|ECond(e,e1,e2)->ifl>2then(PP.start_groupf1;PP.stringf"(");PP.start_groupf1;PP.start_groupf0;expression3fe;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"?";expression1fe1;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf":";expression1fe2;PP.end_groupf;PP.end_groupf;ifl>2then(PP.stringf")";PP.end_groupf)|EObjlst->PP.start_groupf1;PP.stringf"{";property_name_and_value_listflst;PP.stringf"}";PP.end_groupf|ERegexp(s,opt)->(PP.stringf"/";PP.stringfs;PP.stringf"/";matchoptwith|None->()|Someo->PP.stringfo)|EQuotes->PP.stringf"(";PP.stringfs;PP.stringf")"andproperty_namefn=matchnwith|PNIs->PP.stringfs|PNSs->letquote=best_string_quotesinpp_stringf~utf:true~quotes|PNNv->expression0f(ENumv)andproperty_name_and_value_listfl=matchlwith|[]->()|[(pn,e)]->PP.start_groupf0;property_namefpn;PP.stringf":";PP.breakf;expression1fe;PP.end_groupf|(pn,e)::r->PP.start_groupf0;property_namefpn;PP.stringf":";PP.breakf;expression1fe;PP.end_groupf;PP.stringf",";PP.breakf;property_name_and_value_listfrandelement_listfel=matchelwith|[]->()|[e]->(matchewith|None->PP.stringf","|Somee->PP.start_groupf0;expression1fe;PP.end_groupf)|e::r->(matchewith|None->()|Somee->PP.start_groupf0;expression1fe;PP.end_groupf);PP.stringf",";PP.breakf;element_listfrandfunction_bodyfb=source_elementsf~skip_last_semi:truebandargumentsfl=matchlwith|[]->()|[(e,s)]->PP.start_groupf0;(matchswith|`Spread->PP.stringf"..."|`Not_spread->());expression1fe;PP.end_groupf|(e,s)::r->PP.start_groupf0;(matchswith|`Spread->PP.stringf"..."|`Not_spread->());expression1fe;PP.end_groupf;PP.stringf",";PP.breakf;argumentsfrandvariable_declarationf(i,init)=matchinitwith|None->identfi|Some(e,pc)->PP.start_groupf1;output_debug_infofpc;identfi;PP.stringf"=";PP.breakf;expression1fe;PP.end_groupfandvariable_declaration_list_auxfl=matchlwith|[]->assertfalse|[d]->variable_declarationfd|d::r->variable_declarationfd;PP.stringf",";PP.breakf;variable_declaration_list_auxfrandvariable_declaration_listclosef=function|[]->()|[(i,None)]->PP.start_groupf1;PP.stringf"var";PP.spacef;identfi;ifclosethenPP.stringf";";PP.end_groupf|[(i,Some(e,pc))]->PP.start_groupf1;output_debug_infofpc;PP.stringf"var";PP.spacef;identfi;PP.stringf"=";PP.break1f;PP.start_groupf0;expression1fe;ifclosethenPP.stringf";";PP.end_groupf;PP.end_groupf|l->PP.start_groupf1;PP.stringf"var";PP.spacef;variable_declaration_list_auxfl;ifclosethenPP.stringf";";PP.end_groupfandopt_expressionlfe=matchewith|None->()|Somee->expressionlfeandstatement?(last=false)f(s,loc)=letlast_semi()=iflastthen()elsePP.stringf";"inoutput_debug_infofloc;matchswith|Blockb->blockfb|Variable_statementl->variable_declaration_list(notlast)fl|Empty_statement->PP.stringf";"|Debugger_statement->PP.stringf"debugger";last_semi()|Expression_statemente->(* Parentheses are required when the expression
starts syntactically with "{" or "function" *)ifneed_paren0ethen(PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";last_semi();PP.end_groupf)else(PP.start_groupf0;expression0fe;last_semi();PP.end_groupf)|If_statement(e,s1,(Some_ass2))whenends_with_if_without_elses1->(* Dangling else issue... *)statement~lastf(If_statement(e,(Block[s1],N),s2),N)|If_statement(e,s1,Some((Block_,_)ass2))->PP.start_groupf0;PP.start_groupf1;PP.stringf"if";PP.breakf;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.break1f;PP.start_groupf0;statementfs1;PP.end_groupf;PP.breakf;PP.stringf"else";PP.break1f;PP.start_groupf0;statement~lastfs2;PP.end_groupf;PP.end_groupf|If_statement(e,s1,Somes2)->PP.start_groupf0;PP.start_groupf1;PP.stringf"if";PP.breakf;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.break1f;PP.start_groupf0;statementfs1;PP.end_groupf;PP.breakf;PP.stringf"else";PP.space~indent:1f;PP.start_groupf0;statement~lastfs2;PP.end_groupf;PP.end_groupf|If_statement(e,s1,None)->PP.start_groupf1;PP.start_groupf0;PP.stringf"if";PP.breakf;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf0;statement~lastfs1;PP.end_groupf;PP.end_groupf|While_statement(e,s)->PP.start_groupf1;PP.start_groupf0;PP.stringf"while";PP.breakf;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf0;statement~lastfs;PP.end_groupf;PP.end_groupf|Do_while_statement(((Block_,_)ass),e)->PP.start_groupf0;PP.stringf"do";PP.break1f;PP.start_groupf0;statementfs;PP.end_groupf;PP.breakf;PP.stringf"while";PP.break1f;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";last_semi();PP.end_groupf;PP.end_groupf|Do_while_statement(s,e)->PP.start_groupf0;PP.stringf"do";PP.space~indent:1f;PP.start_groupf0;statementfs;PP.end_groupf;PP.breakf;PP.stringf"while";PP.breakf;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";last_semi();PP.end_groupf;PP.end_groupf|For_statement(e1,e2,e3,s)->PP.start_groupf1;PP.start_groupf0;PP.stringf"for";PP.breakf;PP.start_groupf1;PP.stringf"(";(matche1with|Lefte->opt_expression0fe|Rightl->variable_declaration_listfalsefl);PP.stringf";";PP.breakf;opt_expression0fe2;PP.stringf";";PP.breakf;opt_expression0fe3;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf0;statement~lastfs;PP.end_groupf;PP.end_groupf|ForIn_statement(e1,e2,s)->PP.start_groupf1;PP.start_groupf0;PP.stringf"for";PP.breakf;PP.start_groupf1;PP.stringf"(";(matche1with|Lefte->expression0fe|Rightv->variable_declaration_listfalsef[v]);PP.spacef;PP.stringf"in";PP.breakf;PP.spacef;expression0fe2;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf0;statement~lastfs;PP.end_groupf;PP.end_groupf|Continue_statementNone->PP.stringf"continue";last_semi()|Continue_statement(Somes)->PP.stringf"continue ";PP.stringf(Javascript.Label.to_strings);last_semi()|Break_statementNone->PP.stringf"break";last_semi()|Break_statement(Somes)->PP.stringf"break ";PP.stringf(Javascript.Label.to_strings);last_semi()|Return_statemente->(matchewith|None->PP.stringf"return";last_semi()|Some(EFun(i,l,b,pc))->PP.start_groupf1;PP.start_groupf0;PP.start_groupf0;PP.stringf"return function";opt_identifierfi;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"(";formal_parameter_listfl;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"{";function_bodyfb;output_debug_infofpc;PP.stringf"}";last_semi();PP.end_groupf;PP.end_groupf|Somee->PP.start_groupf7;PP.stringf"return";PP.non_breaking_spacef;PP.start_groupf0;expression0fe;last_semi();PP.end_groupf;PP.end_groupf(* There MUST be a space between the return and its
argument. A line return will not work *))|Labelled_statement(i,s)->PP.stringf(Javascript.Label.to_stringi);PP.stringf":";PP.breakf;statement~lastfs|Switch_statement(e,cc,def,cc')->PP.start_groupf1;PP.start_groupf0;PP.stringf"switch";PP.breakf;PP.start_groupf1;PP.stringf"(";expression0fe;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"{";letoutput_onelast(e,sl)=PP.start_groupf1;PP.start_groupf1;PP.stringf"case";PP.spacef;expression0fe;PP.stringf":";PP.end_groupf;PP.breakf;PP.start_groupf0;statement_list~skip_last_semi:lastfsl;PP.end_groupf;PP.end_groupf;PP.breakfinletreclooplast=function|[]->()|[x]->output_onelastx|x::xs->output_onefalsex;looplastxsinloop(Option.is_nonedef&&List.is_emptycc')cc;(matchdefwith|None->()|Somedef->PP.start_groupf1;PP.stringf"default:";PP.breakf;PP.start_groupf0;statement_list~skip_last_semi:(List.is_emptycc')fdef;PP.end_groupf;PP.end_groupf);looptruecc';PP.stringf"}";PP.end_groupf;PP.end_groupf|Throw_statemente->PP.start_groupf6;PP.stringf"throw";PP.non_breaking_spacef;PP.start_groupf0;expression0fe;last_semi();PP.end_groupf;PP.end_groupf(* There must be a space between the return and its
argument. A line return would not work *)|Try_statement(b,ctch,fin)->PP.start_groupf0;PP.stringf"try";PP.space~indent:1f;blockfb;(matchctchwith|None->()|Some(i,b)->PP.breakf;PP.start_groupf1;PP.stringf"catch(";identfi;PP.stringf")";PP.breakf;blockfb;PP.end_groupf);(matchfinwith|None->()|Someb->PP.breakf;PP.start_groupf1;PP.stringf"finally";PP.spacef;blockfb;PP.end_groupf);PP.end_groupfandstatement_listf?skip_last_semib=matchbwith|[]->()|[s]->statementf?last:skip_last_semis|s::r->statementfs;PP.breakf;statement_listf?skip_last_semirandblockfb=PP.start_groupf1;PP.stringf"{";statement_list~skip_last_semi:truefb;PP.stringf"}";PP.end_groupfandsource_elementf?skip_last_semise=matchsewith|Statements,loc->statementf?last:skip_last_semi(s,loc)|Function_declaration(i,l,b,loc'),loc->output_debug_infofloc;PP.start_groupf1;PP.start_groupf0;PP.start_groupf0;PP.stringf"function";PP.spacef;identfi;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"(";formal_parameter_listfl;PP.stringf")";PP.end_groupf;PP.end_groupf;PP.breakf;PP.start_groupf1;PP.stringf"{";function_bodyfb;output_debug_infofloc';PP.stringf"}";PP.end_groupf;PP.end_groupfandsource_elementsf?skip_last_semise=matchsewith|[]->()|[s]->source_elementf?skip_last_semis|s::r->source_elementfs;PP.breakf;source_elementsf?skip_last_semirandprogramfs=source_elementsfsendletpart_of_ident=leta=Array.init256~f:(funi->matchChar.chriwith|'a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$'->true|_->false)infunc->Array.unsafe_geta(Char.codec)letneed_spaceab=(* do not concat 2 different identifier *)(part_of_identa&&part_of_identb)(* do not generate end_of_line_comment.
handle the case of "num / /* comment */ b " *)||matcha,bwith|'/','/'(* https://github.com/ocsigen/js_of_ocaml/issues/507 *)|'-','-'|'+','+'->true|_,_->falseletprogramf?source_mapp=letsmo=matchsource_mapwith|None->None|Some(_,sm)->SomesminletmoduleO=Make(structletsource_map=smoend)inPP.set_needed_space_functionfneed_space;ifConfig.Flag.effects()thenPP.set_adjust_indentation_functionf(funn->nmod40);PP.start_groupf0;O.programfp;PP.end_groupf;PP.newlinef;(matchsource_mapwith|None->()|Some(out_file,sm)->letsm={smwithSource_map.sources=List.revsm.Source_map.sources;Source_map.names=List.revsm.Source_map.names}inletsources=sm.Source_map.sourcesinletsources_content=matchsm.Source_map.sources_contentwith|None->None|Some[]->Some(List.mapsources~f:(funfile->matchBuiltins.findfilewith|Somef->Some(Builtins.File.contentf)|None->ifSys.file_existsfilethenletcontent=Fs.read_filefileinSomecontentelseNone))|Some_->assertfalseinletsources=List.mapsources~f:(funfilename->matchBuiltins.findfilenamewith|None->filename|Some_->Filename.concat"/builtin"filename)inletmappings=List.map!O.temp_mappings~f:(fun(pos,m)->{mwith(* [p_line] starts at zero, [gen_line] at 1 *)Source_map.gen_line=pos.PP.p_line+1;Source_map.gen_col=pos.PP.p_col})inletsm={smwithSource_map.sources;sources_content;mappings}inleturlData=matchout_filewith|None->letdata=Source_map_io.to_stringsmin"data:application/json;base64,"^Base64.encode_exndata|Someout_file->Source_map_io.to_filesmout_file;Filename.basenameout_fileinPP.newlinef;PP.stringf(Printf.sprintf"//# sourceMappingURL=%s\n"urlData));ifstats()thenletsizei=Printf.sprintf"%.2fKo"(float_of_inti/.1024.)inlet_percentnd=Printf.sprintf"%.1f%%"(float_of_intn*.100./.float_of_intd)inlettotal_s=PP.totalfinFormat.eprintf"total size : %s@."(sizetotal_s)