1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102# 1 "lambda/lambda.ml"(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)openMiscopenAsttypestypecompile_time_constant=|Big_endian|Word_size|Int_size|Max_wosize|Ostype_unix|Ostype_win32|Ostype_cygwin|Backend_typetypetag_info=|Blk_constructorof{name:string;num_nonconst:int}|Blk_tuple|Blk_array|Blk_poly_varofstring|Blk_recordofstringarray(* when its empty means we dont get such information *)|Blk_moduleofstringlist|Blk_module_exportofIdent.tlist|Blk_extension_slot|Blk_extension|Blk_naofstring|Blk_some|Blk_some_not_nested(* ['a option] where ['a] can not inhabit a non-like value *)|Blk_record_inlinedof{name:string;num_nonconst:int;fields:stringarray}|Blk_record_extofstringarray|Blk_lazy_general|Blk_class(* Ocaml style class*)letdefault_tag_info:tag_info=Blk_na""letblk_record=ref(funfields->letall_labels_info=fields|>Array.map(fun(x,_)->x.Types.lbl_name)inBlk_recordall_labels_info)letblk_record_ext=ref(funfields->letall_labels_info=fields|>Array.map(fun(x,_)->x.Types.lbl_name)inBlk_record_extall_labels_info)letblk_record_inlined=ref(funfieldsnamenum_nonconst->letfields=fields|>Array.map(fun(x,_)->x.Types.lbl_name)inBlk_record_inlined{fields;name;num_nonconst})letref_tag_info:tag_info=Blk_record[|"contents"|]typefield_dbg_info=|Fld_naofstring|Fld_recordof{name:string;mutable_flag:Asttypes.mutable_flag}|Fld_moduleof{name:string}|Fld_record_inlineof{name:string}|Fld_record_extensionof{name:string}|Fld_tuple|Fld_poly_var_tag|Fld_poly_var_content|Fld_extension|Fld_variant|Fld_cons|Fld_arrayletfld_record=ref(fun(lbl:Types.label_description)->Fld_record{name=lbl.lbl_name;mutable_flag=Mutable})letref_field_info:field_dbg_info=Fld_record{name="contents";mutable_flag=Mutable}letfld_na=Fld_na""typeset_field_dbg_info=|Fld_set_na|Fld_record_setofstring|Fld_record_inline_setofstring|Fld_record_extension_setofstringletref_field_set_info:set_field_dbg_info=Fld_record_set"contents"letfld_record_set=ref(fun(lbl:Types.label_description)->Fld_record_setlbl.lbl_name)typeimmediate_or_pointer=|Immediate|Pointertypeinitialization_or_assignment=|Assignment|Heap_initialization|Root_initializationtypeis_safe=|Safe|Unsafetypeprimitive=|Pbytes_to_string|Pbytes_of_string|Pignore(* Globals *)|PgetglobalofIdent.t|PsetglobalofIdent.t(* Operations on heap blocks *)|Pmakeblockofint*tag_info*mutable_flag*block_shape|Pfieldofint*field_dbg_info|Pfield_computed|Psetfieldofint*immediate_or_pointer*initialization_or_assignment*set_field_dbg_info|Psetfield_computedofimmediate_or_pointer*initialization_or_assignment|Pfloatfieldofint*field_dbg_info|Psetfloatfieldofint*initialization_or_assignment*set_field_dbg_info|PduprecordofTypes.record_representation*int(* Force lazy values *)(* External call *)|PccallofPrimitive.description(* Exceptions *)|Praiseofraise_kind(* Boolean operations *)|Psequand|Psequor|Pnot(* Integer operations *)|Pnegint|Paddint|Psubint|Pmulint|Pdivintofis_safe|Pmodintofis_safe|Pandint|Porint|Pxorint|Plslint|Plsrint|Pasrint|Pintcompofinteger_comparison|Pcompare_ints|Pcompare_floats|Pcompare_bintsofboxed_integer|Poffsetintofint|Poffsetrefofint(* Float operations *)|Pintoffloat|Pfloatofint|Pnegfloat|Pabsfloat|Paddfloat|Psubfloat|Pmulfloat|Pdivfloat|Pfloatcompoffloat_comparison(* String operations *)|Pstringlength|Pstringrefu|Pstringrefs|Pbyteslength|Pbytesrefu|Pbytessetu|Pbytesrefs|Pbytessets(* Array operations *)|Pmakearrayofarray_kind*mutable_flag|Pduparrayofarray_kind*mutable_flag|Parraylengthofarray_kind|Parrayrefuofarray_kind|Parraysetuofarray_kind|Parrayrefsofarray_kind|Parraysetsofarray_kind(* Test if the argument is a block or an immediate integer *)|Pisint(* Test if the (integer) argument is outside an interval *)|Pisout(* Operations on boxed integers (Nativeint.t, Int32.t, Int64.t) *)|Pbintofintofboxed_integer|Pintofbintofboxed_integer|Pcvtbintofboxed_integer(*source*)*boxed_integer(*destination*)|Pnegbintofboxed_integer|Paddbintofboxed_integer|Psubbintofboxed_integer|Pmulbintofboxed_integer|Pdivbintof{size:boxed_integer;is_safe:is_safe}|Pmodbintof{size:boxed_integer;is_safe:is_safe}|Pandbintofboxed_integer|Porbintofboxed_integer|Pxorbintofboxed_integer|Plslbintofboxed_integer|Plsrbintofboxed_integer|Pasrbintofboxed_integer|Pbintcompofboxed_integer*integer_comparison(* Operations on Bigarrays: (unsafe, #dimensions, kind, layout) *)|Pbigarrayrefofbool*int*bigarray_kind*bigarray_layout|Pbigarraysetofbool*int*bigarray_kind*bigarray_layout(* size of the nth dimension of a Bigarray *)|Pbigarraydimofint(* load/set 16,32,64 bits from a string: (unsafe)*)|Pstring_load_16ofbool|Pstring_load_32ofbool|Pstring_load_64ofbool|Pbytes_load_16ofbool|Pbytes_load_32ofbool|Pbytes_load_64ofbool|Pbytes_set_16ofbool|Pbytes_set_32ofbool|Pbytes_set_64ofbool(* load/set 16,32,64 bits from a
(char, int8_unsigned_elt, c_layout) Bigarray.Array1.t : (unsafe) *)|Pbigstring_load_16ofbool|Pbigstring_load_32ofbool|Pbigstring_load_64ofbool|Pbigstring_set_16ofbool|Pbigstring_set_32ofbool|Pbigstring_set_64ofbool(* Compile time constants *)|Pctconstofcompile_time_constant(* byte swap *)|Pbswap16|Pbbswapofboxed_integer(* Integer to external pointer *)|Pint_as_pointer(* Inhibition of optimisation *)|Popaqueandinteger_comparison=Ceq|Cne|Clt|Cgt|Cle|Cgeandfloat_comparison=CFeq|CFneq|CFlt|CFnlt|CFgt|CFngt|CFle|CFnle|CFge|CFngeandvalue_kind=Pgenval|Pfloatval|Pboxedintvalofboxed_integer|Pintvalandblock_shape=value_kindlistoptionandarray_kind=Pgenarray|Paddrarray|Pintarray|Pfloatarrayandboxed_integer=Primitive.boxed_integer=Pnativeint|Pint32|Pint64andbigarray_kind=Pbigarray_unknown|Pbigarray_float32|Pbigarray_float64|Pbigarray_sint8|Pbigarray_uint8|Pbigarray_sint16|Pbigarray_uint16|Pbigarray_int32|Pbigarray_int64|Pbigarray_caml_int|Pbigarray_native_int|Pbigarray_complex32|Pbigarray_complex64andbigarray_layout=Pbigarray_unknown_layout|Pbigarray_c_layout|Pbigarray_fortran_layoutandraise_kind=|Raise_regular|Raise_reraise|Raise_notraceletequal_boxed_integer=Primitive.equal_boxed_integerletequal_primitive=(* Should be implemented like [equal_value_kind] of [equal_boxed_integer],
i.e. by matching over the various constructors but the type has more
than 100 constructors... *)(=)letequal_value_kindxy=matchx,ywith|Pgenval,Pgenval->true|Pfloatval,Pfloatval->true|Pboxedintvalbi1,Pboxedintvalbi2->equal_boxed_integerbi1bi2|Pintval,Pintval->true|(Pgenval|Pfloatval|Pboxedintval_|Pintval),_->falsetypepointer_info=|Pt_constructorof{name:string;const:int;non_const:int}|Pt_variantof{name:string}|Pt_module_alias|Pt_builtin_boolean|Pt_shape_none|Pt_assertfalse|Pt_naletdefault_pointer_info=Pt_natypestructured_constant=Const_baseofconstant*pointer_info|Const_blockofint*tag_info*structured_constantlist|Const_float_arrayofstringlist|Const_immstringofstringtypetailcall_attribute=|Tailcall_expectationofbool(* [@tailcall] and [@tailcall true] have [true],
[@tailcall false] has [false] *)|Default_tailcall(* no [@tailcall] attribute *)typeinline_attribute=|Always_inline(* [@inline] or [@inline always] *)|Never_inline(* [@inline never] *)|Hint_inline(* [@inlined hint] attribute *)|Unrollofint(* [@unroll x] *)|Default_inline(* no [@inline] attribute *)letequal_inline_attributexy=matchx,ywith|Always_inline,Always_inline|Never_inline,Never_inline|Hint_inline,Hint_inline|Default_inline,Default_inline->true|Unrollu,Unrollv->u=v|(Always_inline|Never_inline|Hint_inline|Unroll_|Default_inline),_->falsetypespecialise_attribute=|Always_specialise(* [@specialise] or [@specialise always] *)|Never_specialise(* [@specialise never] *)|Default_specialise(* no [@specialise] attribute *)letequal_specialise_attributexy=matchx,ywith|Always_specialise,Always_specialise|Never_specialise,Never_specialise|Default_specialise,Default_specialise->true|(Always_specialise|Never_specialise|Default_specialise),_->falsetypelocal_attribute=|Always_local(* [@local] or [@local always] *)|Never_local(* [@local never] *)|Default_local(* [@local maybe] or no [@local] attribute *)typepoll_attribute=|Error_poll(* [@poll error] *)|Default_poll(* no [@poll] attribute *)typefunction_kind=Curried|Tupledtypelet_kind=Strict|Alias|StrictOpttypepublic_info=stringoption(* label name *)typemeth_kind=Self|Publicofpublic_info|Cachedletequal_meth_kindxy=matchx,ywith|Self,Self->true|Public_,Public_->true|Cached,Cached->true|(Self|Public_|Cached),_->falsetypeshared_code=(int*int)listtypefunction_attribute={inline:inline_attribute;specialise:specialise_attribute;local:local_attribute;poll:poll_attribute;is_a_functor:bool;stub:bool;tmc_candidate:bool;return_unit:bool;}typeswitch_names={consts:stringarray;blocks:stringarray}typescoped_location=Debuginfo.Scoped_location.ttypelambda=LvarofIdent.t|LmutvarofIdent.t|Lconstofstructured_constant|Lapplyoflambda_apply|Lfunctionoflfunction|Lletoflet_kind*value_kind*Ident.t*lambda*lambda|Lmutletofvalue_kind*Ident.t*lambda*lambda|Lletrecof(Ident.t*lambda)list*lambda|Lprimofprimitive*lambdalist*scoped_location|Lswitchoflambda*lambda_switch*scoped_location|Lstringswitchoflambda*(string*lambda)list*lambdaoption*scoped_location|Lstaticraiseofint*lambdalist|Lstaticcatchoflambda*(int*(Ident.t*value_kind)list)*lambda|Ltrywithoflambda*Ident.t*lambda|Lifthenelseoflambda*lambda*lambda|Lsequenceoflambda*lambda|Lwhileoflambda*lambda|LforofIdent.t*lambda*lambda*direction_flag*lambda|LassignofIdent.t*lambda|Lsendofmeth_kind*lambda*lambda*lambdalist*scoped_location|Leventoflambda*lambda_event|LifusedofIdent.t*lambdaandlfunction={kind:function_kind;params:(Ident.t*value_kind)list;return:value_kind;body:lambda;attr:function_attribute;(* specified with [@inline] attribute *)loc:scoped_location;}andlambda_apply={ap_func:lambda;ap_args:lambdalist;ap_loc:scoped_location;ap_tailcall:tailcall_attribute;ap_inlined:inline_attribute;ap_specialised:specialise_attribute;}andlambda_switch={sw_numconsts:int;sw_consts:(int*lambda)list;sw_numblocks:int;sw_blocks:(int*lambda)list;sw_failaction:lambdaoption;sw_names:switch_namesoption}andlambda_event={lev_loc:scoped_location;lev_kind:lambda_event_kind;lev_repr:intrefoption;lev_env:Env.t}andlambda_event_kind=Lev_before|Lev_afterofTypes.type_expr|Lev_function|Lev_pseudo|Lev_module_definitionofIdent.ttypeprogram={module_ident:Ident.t;main_module_block_size:int;required_globals:Ident.Set.t;code:lambda}letconst_int?(ptr_info=Pt_na)n=Const_base(Const_intn,ptr_info)(* This is actually a dummy value
not necessary "()", it can be used as a place holder for module
alias etc.
*)letconst_unit=const_int0~ptr_info:(Pt_constructor{name="()";const=1;non_const=0})letlambda_assert_false=Lconst(const_int~ptr_info:Pt_assertfalse0)letlambda_unit=Lconstconst_unitletlambda_module_alias=Lconst(const_int~ptr_info:Pt_module_alias0)letmax_arity()=if!Clflags.native_codethen126elsemax_int(* 126 = 127 (the maximal number of parameters supported in C--)
- 1 (the hidden parameter containing the environment) *)letlfunction~kind~params~return~body~attr~loc=assert(List.lengthparams<=max_arity());Lfunction{kind;params;return;body;attr;loc}letdefault_function_attribute={inline=Default_inline;specialise=Default_specialise;local=Default_local;poll=Default_poll;is_a_functor=false;stub=false;tmc_candidate=false;return_unit=false;}letdefault_stub_attribute={default_function_attributewithstub=true}(* Build sharing keys *)(*
Those keys are later compared with Stdlib.compare.
For that reason, they should not include cycles.
*)letmax_raw=32letmake_keye=letexceptionNot_simpleinletcount=ref0(* Used for controlling size *)andmake_key=Ident.make_key_generator()in(* make_key is used for normalizing let-bound variables *)letrectr_recenve=incrcount;if!count>max_rawthenraiseNot_simple;(* Too big ! *)matchewith|Lvarid|Lmutvarid->begintryIdent.find_sameidenvwithNot_found->eend|Lconst(Const_base(Const_string_,_))->(* Mutable constants are not shared *)raiseNot_simple|Lconst_->e|Lapplyap->Lapply{apwithap_func=tr_recenvap.ap_func;ap_args=tr_recsenvap.ap_args;ap_loc=Loc_unknown}|Llet(Alias,_k,x,ex,e)->(* Ignore aliases -> substitute *)letex=tr_recenvexintr_rec(Ident.addxexenv)e|Llet((Strict|StrictOpt),_k,x,ex,Lvarv)whenIdent.samevx->tr_recenvex|Llet(str,k,x,ex,e)->(* Because of side effects, keep other lets with normalized names *)letex=tr_recenvexinlety=make_keyxinLlet(str,k,y,ex,tr_rec(Ident.addx(Lvary)env)e)|Lmutlet(k,x,ex,e)->letex=tr_recenvexinlety=make_keyxinLmutlet(k,y,ex,tr_rec(Ident.addx(Lmutvary)env)e)|Lprim(p,es,_)->Lprim(p,tr_recsenves,Loc_unknown)|Lswitch(e,sw,loc)->Lswitch(tr_recenve,tr_swenvsw,loc)|Lstringswitch(e,sw,d,_)->Lstringswitch(tr_recenve,List.map(fun(s,e)->s,tr_recenve)sw,tr_optenvd,Loc_unknown)|Lstaticraise(i,es)->Lstaticraise(i,tr_recsenves)|Lstaticcatch(e1,xs,e2)->Lstaticcatch(tr_recenve1,xs,tr_recenve2)|Ltrywith(e1,x,e2)->Ltrywith(tr_recenve1,x,tr_recenve2)|Lifthenelse(cond,ifso,ifnot)->Lifthenelse(tr_recenvcond,tr_recenvifso,tr_recenvifnot)|Lsequence(e1,e2)->Lsequence(tr_recenve1,tr_recenve2)|Lassign(x,e)->Lassign(x,tr_recenve)|Lsend(m,e1,e2,es,_loc)->Lsend(m,tr_recenve1,tr_recenve2,tr_recsenves,Loc_unknown)|Lifused(id,e)->Lifused(id,tr_recenve)|Lletrec_|Lfunction_|Lfor_|Lwhile_(* Beware: (PR#6412) the event argument to Levent
may include cyclic structure of type Type.typexpr *)|Levent_->raiseNot_simpleandtr_recsenves=List.map(tr_recenv)esandtr_swenvsw={swwithsw_consts=List.map(fun(i,e)->i,tr_recenve)sw.sw_consts;sw_blocks=List.map(fun(i,e)->i,tr_recenve)sw.sw_blocks;sw_failaction=tr_optenvsw.sw_failaction;}andtr_optenv=function|None->None|Somee->Some(tr_recenve)intrySome(tr_recIdent.emptye)withNot_simple->None(***************)letname_lambdastrictargfn=matchargwithLvarid->fnid|_->letid=Ident.create_local"let"inLlet(strict,Pgenval,id,arg,fnid)letname_lambda_listargsfn=letrecname_listnames=function[]->fn(List.revnames)|(Lvar_asarg)::rem->name_list(arg::names)rem|arg::rem->letid=Ident.create_local"let"inLlet(Strict,Pgenval,id,arg,name_list(Lvarid::names)rem)inname_list[]argsletiter_optf=function|None->()|Somee->feletshallow_iter~tail~non_tail:f=functionLvar_|Lmutvar_|Lconst_->()|Lapply{ap_func=fn;ap_args=args}->ffn;List.iterfargs|Lfunction{body}->fbody|Llet(_,_k,_id,arg,body)|Lmutlet(_k,_id,arg,body)->farg;tailbody|Lletrec(decl,body)->tailbody;List.iter(fun(_id,exp)->fexp)decl|Lprim(Psequand,[l1;l2],_)|Lprim(Psequor,[l1;l2],_)->fl1;taill2|Lprim(_p,args,_loc)->List.iterfargs|Lswitch(arg,sw,_)->farg;List.iter(fun(_key,case)->tailcase)sw.sw_consts;List.iter(fun(_key,case)->tailcase)sw.sw_blocks;iter_opttailsw.sw_failaction|Lstringswitch(arg,cases,default,_)->farg;List.iter(fun(_,act)->tailact)cases;iter_opttaildefault|Lstaticraise(_,args)->List.iterfargs|Lstaticcatch(e1,_,e2)->taile1;taile2|Ltrywith(e1,_,e2)->fe1;taile2|Lifthenelse(e1,e2,e3)->fe1;taile2;taile3|Lsequence(e1,e2)->fe1;taile2|Lwhile(e1,e2)->fe1;fe2|Lfor(_v,e1,e2,_dir,e3)->fe1;fe2;fe3|Lassign(_,e)->fe|Lsend(_k,met,obj,args,_)->List.iterf(met::obj::args)|Levent(e,_evt)->taile|Lifused(_v,e)->taileletiter_head_constructorfl=shallow_iter~tail:f~non_tail:flletrecfree_variables=function|Lvarid|Lmutvarid->Ident.Set.singletonid|Lconst_->Ident.Set.empty|Lapply{ap_func=fn;ap_args=args}->free_variables_list(free_variablesfn)args|Lfunction{body;params}->Ident.Set.diff(free_variablesbody)(Ident.Set.of_list(List.mapfstparams))|Llet(_,_k,id,arg,body)|Lmutlet(_k,id,arg,body)->Ident.Set.union(free_variablesarg)(Ident.Set.removeid(free_variablesbody))|Lletrec(decl,body)->letset=free_variables_list(free_variablesbody)(List.mapsnddecl)inIdent.Set.diffset(Ident.Set.of_list(List.mapfstdecl))|Lprim(_p,args,_loc)->free_variables_listIdent.Set.emptyargs|Lswitch(arg,sw,_)->letset=free_variables_list(free_variables_list(free_variablesarg)(List.mapsndsw.sw_consts))(List.mapsndsw.sw_blocks)inbeginmatchsw.sw_failactionwith|None->set|Somefailaction->Ident.Set.unionset(free_variablesfailaction)end|Lstringswitch(arg,cases,default,_)->letset=free_variables_list(free_variablesarg)(List.mapsndcases)inbeginmatchdefaultwith|None->set|Somedefault->Ident.Set.unionset(free_variablesdefault)end|Lstaticraise(_,args)->free_variables_listIdent.Set.emptyargs|Lstaticcatch(body,(_,params),handler)->Ident.Set.union(Ident.Set.diff(free_variableshandler)(Ident.Set.of_list(List.mapfstparams)))(free_variablesbody)|Ltrywith(body,param,handler)->Ident.Set.union(Ident.Set.removeparam(free_variableshandler))(free_variablesbody)|Lifthenelse(e1,e2,e3)->Ident.Set.union(Ident.Set.union(free_variablese1)(free_variablese2))(free_variablese3)|Lsequence(e1,e2)->Ident.Set.union(free_variablese1)(free_variablese2)|Lwhile(e1,e2)->Ident.Set.union(free_variablese1)(free_variablese2)|Lfor(v,lo,hi,_dir,body)->letset=Ident.Set.union(free_variableslo)(free_variableshi)inIdent.Set.unionset(Ident.Set.removev(free_variablesbody))|Lassign(id,e)->Ident.Set.addid(free_variablese)|Lsend(_k,met,obj,args,_)->free_variables_list(Ident.Set.union(free_variablesmet)(free_variablesobj))args|Levent(lam,_evt)->free_variableslam|Lifused(_v,e)->(* Shouldn't v be considered a free variable ? *)free_variableseandfree_variables_listsetexprs=List.fold_left(funsetexpr->Ident.Set.union(free_variablesexpr)set)setexprs(* Check if an action has a "when" guard *)letraise_count=ref0letnext_raise_count()=incrraise_count;!raise_count(* Anticipated staticraise, for guards *)letstaticfail=Lstaticraise(0,[])letrecis_guarded=function|Lifthenelse(_cond,_body,Lstaticraise(0,[]))->true|Llet(_str,_k,_id,_lam,body)->is_guardedbody|Levent(lam,_ev)->is_guardedlam|_->falseletrecpatch_guardedpatch=function|Lifthenelse(cond,body,Lstaticraise(0,[]))->Lifthenelse(cond,body,patch)|Llet(str,k,id,lam,body)->Llet(str,k,id,lam,patch_guardedpatchbody)|Levent(lam,ev)->Levent(patch_guardedpatchlam,ev)|_->fatal_error"Lambda.patch_guarded"(* Translate an access path *)letrectransl_addresslocenvpath=function|Env.Aidentid->ifIdent.globalidthenLprim(Pgetglobalid,[],loc)elseLvarid|Env.Adot(addr,pos)->letloc'=Some(Debuginfo.Scoped_location.to_locationloc)inletpath',name=matchEnv.normalize_module_pathloc'envpathwith|Path.Pdot(path',s)->path',s|Path.Pidentid->path,Ident.nameid|Path.Papply_->assertfalseinLprim(Pfield(pos,Fld_module{name}),[transl_addresslocenvpath'addr],loc)lettransl_pathfindlocenvpath=matchfindpathenvwith|exceptionNot_found->fatal_error("Cannot find address for: "^(Path.namepath))|addr->transl_addresslocenvpathaddr(* Translation of identifiers *)lettransl_module_pathlocenvpath=transl_pathEnv.find_module_addresslocenvpathlettransl_value_pathlocenvpath=transl_pathEnv.find_value_addresslocenvpathlettransl_extension_pathlocenvpath=transl_pathEnv.find_constructor_addresslocenvpathlettransl_class_pathlocenvpath=transl_pathEnv.find_class_addresslocenvpathlettransl_primmod_namename=letpers=Ident.create_persistentmod_nameinletenv=Env.add_persistent_structurepersEnv.emptyinletlid=Longident.Ldot(Longident.Lidentmod_name,name)inmatchEnv.find_value_by_namelidenvwith|path,_->transl_value_pathLoc_unknownenvpath|exceptionNot_found->fatal_error("Primitive "^name^" not found.")(* Compile a sequence of expressions *)letrecmake_sequencefn=function[]->lambda_unit|[x]->fnx|x::rem->letlam=fnxinLsequence(lam,make_sequencefnrem)(* Apply a substitution to a lambda-term.
Assumes that the image of the substitution is out of reach
of the bound variables of the lambda-term (no capture). *)letsubstupdate_env?(freshen_bound_variables=false)sinput_lam=(* [s] contains a partial substitution for the free variables of the
input term [input_lam].
During our traversal of the term we maintain a second environment
[l] with all the bound variables of [input_lam] in the current
scope, mapped to either themselves or freshened versions of
themselves when [freshen_bound_variables] is set. *)letbindidl=letid'=ifnotfreshen_bound_variablesthenidelseIdent.renameidinid',Ident.Map.addidid'linletbind_manyidsl=List.fold_right(fun(id,rhs)(ids',l)->letid',l=bindidlin((id',rhs)::ids',l))ids([],l)inletrecsubstsllam=matchlamwith|Lvaridaslam->beginmatchIdent.Map.findidlwith|id'->Lvarid'|exceptionNot_found->(* note: as this point we know [id] is not a bound
variable of the input term, otherwise it would belong
to [l]; it is a free variable of the input term. *)begintryIdent.Map.findidswithNot_found->lamendend|Lmutvaridaslam->beginmatchIdent.Map.findidlwith|id'->Lmutvarid'|exceptionNot_found->(* Note: a mutable [id] should not appear in [s].
Keeping the behavior of Lvar case for now. *)begintryIdent.Map.findidswithNot_found->lamendend|Lconst_asl->l|Lapplyap->Lapply{apwithap_func=substslap.ap_func;ap_args=subst_listslap.ap_args}|Lfunctionlf->letparams,l'=bind_manylf.paramslinLfunction{lfwithparams;body=substsl'lf.body}|Llet(str,k,id,arg,body)->letid,l'=bindidlinLlet(str,k,id,substslarg,substsl'body)|Lmutlet(k,id,arg,body)->letid,l'=bindidlinLmutlet(k,id,substslarg,substsl'body)|Lletrec(decl,body)->letdecl,l'=bind_manydecllinLletrec(List.map(subst_declsl')decl,substsl'body)|Lprim(p,args,loc)->Lprim(p,subst_listslargs,loc)|Lswitch(arg,sw,loc)->Lswitch(substslarg,{swwithsw_consts=List.map(subst_casesl)sw.sw_consts;sw_blocks=List.map(subst_casesl)sw.sw_blocks;sw_failaction=subst_optslsw.sw_failaction;},loc)|Lstringswitch(arg,cases,default,loc)->Lstringswitch(substslarg,List.map(subst_strcasesl)cases,subst_optsldefault,loc)|Lstaticraise(i,args)->Lstaticraise(i,subst_listslargs)|Lstaticcatch(body,(id,params),handler)->letparams,l'=bind_manyparamslinLstaticcatch(substslbody,(id,params),substsl'handler)|Ltrywith(body,exn,handler)->letexn,l'=bindexnlinLtrywith(substslbody,exn,substsl'handler)|Lifthenelse(e1,e2,e3)->Lifthenelse(substsle1,substsle2,substsle3)|Lsequence(e1,e2)->Lsequence(substsle1,substsle2)|Lwhile(e1,e2)->Lwhile(substsle1,substsle2)|Lfor(v,lo,hi,dir,body)->letv,l'=bindvlinLfor(v,substsllo,substslhi,dir,substsl'body)|Lassign(id,e)->assert(not(Ident.Map.memids));letid=tryIdent.Map.findidlwithNot_found->idinLassign(id,substsle)|Lsend(k,met,obj,args,loc)->Lsend(k,substslmet,substslobj,subst_listslargs,loc)|Levent(lam,evt)->letold_env=evt.lev_envinletenv_updates=letfind_in_oldid=Env.find_value(Path.Pidentid)old_envinletrebindidid'new_env=matchfind_in_oldidwith|exceptionNot_found->new_env|vd->Env.add_valueid'vdnew_envinletupdate_freeidnew_env=matchfind_in_oldidwith|exceptionNot_found->new_env|vd->update_envidvdnew_envinIdent.Map.merge(funidboundfree->matchbound,freewith|Someid',_->ifIdent.equalidid'thenNoneelseSome(rebindidid')|None,Some_->Some(update_freeid)|None,None->None)lsinletnew_env=Ident.Map.fold(fun_idupdateenv->updateenv)env_updatesold_envinLevent(substsllam,{evtwithlev_env=new_env})|Lifused(id,e)->letid=tryIdent.Map.findidlwithNot_found->idinLifused(id,substsle)andsubst_listslli=List.map(substsl)liandsubst_declsl(id,exp)=(id,substslexp)andsubst_casesl(key,case)=(key,substslcase)andsubst_strcasesl(key,case)=(key,substslcase)andsubst_optsl=function|None->None|Somee->Some(substsle)insubstsIdent.Map.emptyinput_lamletrenameidmaplam=letupdate_envoldidvdenv=letnewid=Ident.Map.findoldididmapinEnv.add_valuenewidvdenvinlets=Ident.Map.map(funnew_id->Lvarnew_id)idmapinsubstupdate_envslamletduplicatelam=subst(fun__env->env)~freshen_bound_variables:trueIdent.Map.emptylamletshallow_mapf=function|Lvar_|Lmutvar_|Lconst_aslam->lam|Lapply{ap_func;ap_args;ap_loc;ap_tailcall;ap_inlined;ap_specialised}->Lapply{ap_func=fap_func;ap_args=List.mapfap_args;ap_loc;ap_tailcall;ap_inlined;ap_specialised;}|Lfunction{kind;params;return;body;attr;loc;}->Lfunction{kind;params;return;body=fbody;attr;loc;}|Llet(str,k,v,e1,e2)->Llet(str,k,v,fe1,fe2)|Lmutlet(k,v,e1,e2)->Lmutlet(k,v,fe1,fe2)|Lletrec(idel,e2)->Lletrec(List.map(fun(v,e)->(v,fe))idel,fe2)|Lprim(p,el,loc)->Lprim(p,List.mapfel,loc)|Lswitch(e,sw,loc)->Lswitch(fe,{sw_numconsts=sw.sw_numconsts;sw_consts=List.map(fun(n,e)->(n,fe))sw.sw_consts;sw_numblocks=sw.sw_numblocks;sw_blocks=List.map(fun(n,e)->(n,fe))sw.sw_blocks;sw_failaction=Option.mapfsw.sw_failaction;sw_names=sw.sw_names;},loc)|Lstringswitch(e,sw,default,loc)->Lstringswitch(fe,List.map(fun(s,e)->(s,fe))sw,Option.mapfdefault,loc)|Lstaticraise(i,args)->Lstaticraise(i,List.mapfargs)|Lstaticcatch(body,id,handler)->Lstaticcatch(fbody,id,fhandler)|Ltrywith(e1,v,e2)->Ltrywith(fe1,v,fe2)|Lifthenelse(e1,e2,e3)->Lifthenelse(fe1,fe2,fe3)|Lsequence(e1,e2)->Lsequence(fe1,fe2)|Lwhile(e1,e2)->Lwhile(fe1,fe2)|Lfor(v,e1,e2,dir,e3)->Lfor(v,fe1,fe2,dir,fe3)|Lassign(v,e)->Lassign(v,fe)|Lsend(k,m,o,el,loc)->Lsend(k,fm,fo,List.mapfel,loc)|Levent(l,ev)->Levent(fl,ev)|Lifused(v,e)->Lifused(v,fe)letmapf=letrecglam=f(shallow_mapglam)ing(* To let-bind expressions to variables *)letbind_with_value_kindstr(var,kind)expbody=matchexpwithLvarvar'whenIdent.samevarvar'->body|_->Llet(str,kind,var,exp,body)letbindstrvarexpbody=bind_with_value_kindstr(var,Pgenval)expbodyletnegate_integer_comparison=function|Ceq->Cne|Cne->Ceq|Clt->Cge|Cle->Cgt|Cgt->Cle|Cge->Cltletswap_integer_comparison=function|Ceq->Ceq|Cne->Cne|Clt->Cgt|Cle->Cge|Cgt->Clt|Cge->Cleletnegate_float_comparison=function|CFeq->CFneq|CFneq->CFeq|CFlt->CFnlt|CFnlt->CFlt|CFgt->CFngt|CFngt->CFgt|CFle->CFnle|CFnle->CFle|CFge->CFnge|CFnge->CFgeletswap_float_comparison=function|CFeq->CFeq|CFneq->CFneq|CFlt->CFgt|CFnlt->CFngt|CFle->CFge|CFnle->CFnge|CFgt->CFlt|CFngt->CFnlt|CFge->CFle|CFnge->CFnleletraise_kind=function|Raise_regular->"raise"|Raise_reraise->"reraise"|Raise_notrace->"raise_notrace"letmerge_inline_attributesattr1attr2=matchattr1,attr2with|Default_inline,_->Someattr2|_,Default_inline->Someattr1|_,_->ifattr1=attr2thenSomeattr1elseNoneletfunction_is_curriedfunc=matchfunc.kindwith|Curried->true|Tupled->falseletfind_exact_applicationkind~arityargs=matchkindwith|Curried->ifarity<>List.lengthargsthenNoneelseSomeargs|Tupled->beginmatchargswith|[Lprim(Pmakeblock_,tupled_args,_)]->ifarity<>List.lengthtupled_argsthenNoneelseSometupled_args|[Lconst(Const_block(_,_,const_args))]->ifarity<>List.lengthconst_argsthenNoneelseSome(List.map(funcst->Lconstcst)const_args)|_->Noneendletreset()=raise_count:=0