123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240(* This file is part of asak.
*
* Copyright (C) 2019 IRIF / OCaml Software Foundation.
*
* asak is distributed under the terms of the MIT license. See the
* included LICENSE file for details. *)openLambdaletmap_sndaux=List.map(fun(e,x)->e,aux x)letmap_opt aux=function|None->None|Some x->Some(auxx)letfold_lambdalvarllet=letrecauxexpr=match expr with|Lvarx->lvarx|Lconst _->expr|Llet(k,e,ident,l,r)->lletauxkeidentlr|Lapplyx->letap_func=auxx.ap_funcinletap_args=List.mapauxx.ap_argsinLapply{xwithap_func;ap_args}|Lfunctionx->#ifOCAML_VERSION>=(5,2,0)Lfunction(lfuncx)#elselfuncx#endif|Lletrec(lst,l)->#ifOCAML_VERSION>=(5,2,0)Lletrec(List.map(funx->{xwithdef=lfuncx.def})lst,auxl)#elseLletrec (map_sndauxlst,auxl)#endif|Lprim (a,lst,b)->Lprim(a,List.mapauxlst,b)|Lstaticraise(a,lst)->Lstaticraise(a,List.mapauxlst)|Lifthenelse(i,f,e)->Lifthenelse(auxi,auxf,auxe)|Lsequence(l,r)->Lsequence(auxl,auxr)|Lwhile(l,r)->Lwhile(auxl,auxr)|Lifused(i,l)->Lifused(i,auxl)#ifOCAML_VERSION>=(4,06,0)|Lswitch(l,s,i)->letsw_consts=map_sndauxs.sw_constsinletsw_blocks=map_sndauxs.sw_blocksinLswitch(auxl,{swithsw_consts;sw_blocks},i)#else|Lswitch(l,s)->letsw_consts=map_sndauxs.sw_constsinletsw_blocks=map_sndauxs.sw_blocksinLswitch(auxl,{swithsw_consts;sw_blocks})#endif|Lstringswitch (l,lst,opt,e)->Lstringswitch(auxl,map_sndauxlst,map_optauxopt,e)|Lassign(i,l)->Lassign(i,auxl)|Levent(l,e)->Levent(auxl,e)|Lstaticcatch(l,lst,r)->Lstaticcatch(auxl,lst,auxr)|Ltrywith(l,i,r)->Ltrywith(auxl,i,auxr)|Lfor(e,a,b,d,c)->Lfor(e,auxa,auxb,d,auxc)|Lsend(a,b,c,d,e)->Lsend(a,auxb,auxc,List.mapauxd,e)#ifOCAML_VERSION>=(4,13,0)|Lmutvarx->lvarx|Lmutlet(e,ident,l,r)->lletauxStricteidentlr#endifandlfunc{kind;params;return;body;attr;loc}=letbody=auxbodyin#ifOCAML_VERSION>=(5,2,0)lfunction' ~kind~params~return~body~attr~loc#elifOCAML_VERSION>=(4,14,0)lfunction~kind~params~return~body~attr ~loc#elseLfunction{kind;params;return;body;attr;loc}#endifinaux(*Replace everyoccurenceof ident by its body *)letreplaceidentbody=letlvarx=ifx=identthenbodyelseLvarxinletlletauxabcde=Llet(a,b,c,auxd,auxe)infold_lambdalvarllet(* Is the definition inlineable ? *)letinlineablexf=matchxwith|Alias->true|Strict->beginmatchfwith|Lvar_|Lconst_->true|_->falseend|_->false(*Inlineall possible "let definitions"
(that is, all "let definitions" without a side effet) *)letinline_all=letlvarx=Lvarxinlet llet auxkeidentlr=if inlineableklthenaux(replaceidentlr)elseLlet(k,e,ident,auxl,auxr)infold_lambda lvarlletletextract_params_namexs=#ifOCAML_VERSION>=(4,08,0)List.mapfstxs#elsexs#endifletcreate_identx=#ifOCAML_VERSION>=(4,08,0)Ident.create_localx#elseIdent.createx#endifletnormalize_local_variables?namex=(*ifor nonrec (from 1 to infinity), j for rec (from -1 to -infinity)*)let recauxijletbindsx=letaux'=auxijletbindsinletlvarvar=matchList.assoc_optvarletbinds with|None->x|Somex->Lvar(create_ident(string_of_intx))inmatchxwith|Lvarvar->lvarvar|Lconst_->x|Lapplyx->Lapply{xwithap_func=aux'x.ap_func;ap_args=List.mapaux'x.ap_args}|Lfunctionx->#ifOCAML_VERSION>=(5,2,0)Lfunction(lfuncijletbinds x)#elselfuncijletbindsx#endif|Llet(a,b,id,l,r)->Llet(a,b,id,aux'l,aux(i+1)j((id,i)::letbinds)r)|Lletrec(lst,l)->letgetidx=#ifOCAML_VERSION>=(5,2,0)x.id#elsefstx#endifinlet(j,letbinds)=List.fold_right(funx(j,acc)->(j-1),(getidx,j)::acc)lst(j,letbinds)inletgodefx=#ifOCAML_VERSION >=(5,2,0){xwithdef=lfuncijletbindsx.def}#else(fst x,auxijletbinds (sndx))#endifinLletrec(List.mapgodeflst,auxijletbindsl)|Lprim(a,b,c)->Lprim(a,List.mapaux'b,c)|Lstaticraise(a,b)->Lstaticraise(a,List.mapaux'b)|Lifthenelse(i,f,e)->Lifthenelse(aux'i,aux'f,aux'e)|Lsequence(l,r)->Lsequence (aux'l,aux'r)|Lwhile(l,r)->Lwhile(aux'l,aux'r)|Lifused(a,b)->Lifused(a,aux'b)#ifOCAML_VERSION>=(4,06,0)|Lswitch(l,s,u)->lets={swithsw_consts=map_snd aux's.sw_consts;sw_blocks=map_sndaux's.sw_blocks}inLswitch(aux'l,s,u)#else|Lswitch(l,s)->lets={swithsw_consts=map_sndaux' s.sw_consts;sw_blocks=map_snd aux's.sw_blocks}inLswitch(aux'l,s)#endif|Lstringswitch(l,lst,opt,loc)->Lstringswitch(aux'l,map_sndaux'lst,map_optaux'opt,loc)|Lassign(a,b)->Lassign (a,aux'b)|Levent(a,b)->Levent(aux'a,b)|Lstaticcatch (a,b,c)->Lstaticcatch(aux'a,b,aux'c)|Ltrywith(l,id,r)->Ltrywith(aux'l,id,aux(i+1)j((id,i)::letbinds)r)|Lfor(id,a,b,d,c)->Lfor (id,aux'a,aux'b,d,aux(i+1)j((id,i)::letbinds)c)|Lsend(a,b,c,d,e)->Lsend(a,aux'b,aux'c,List.mapaux'd,e)#ifOCAML_VERSION>=(4,13,0)|Lmutvarvar->lvarvar|Lmutlet(b,id,l,r)->Lmutlet(b,id,aux'l,aux(i+1)j((id,i)::letbinds)r)#endifandlfuncijletbinds{kind;params;return;body;attr;loc}=letparams'=extract_params_nameparamsinlet(i,letbinds)=List.fold_right(funid(i,acc)->(i+1,(id,i)::acc))params'(i,letbinds)inletbody=auxijletbinds bodyin#ifOCAML_VERSION>=(5,2,0)lfunction'~kind~params~return~body~attr~loc#elifOCAML_VERSION>=(4,14,0)lfunction~kind~params~return~body~attr~loc#elseLfunction{kind;params;return;body;attr;loc}#endifinletstart=matchnamewith|None->[]|Somename->[name,0]inaux1(-1)startx