123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374(**************************************************************************)(* *)(* OCaml *)(* *)(* Ulysse Gérard, Thomas Refis, Tarides *)(* *)(* Copyright 2021 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. *)(* *)(**************************************************************************)moduleUid=structtypet=|Compilation_unitofstring|Itemof{comp_unit:string;id:int;from:Unit_info.intf_or_impl}|Internal|PredefofstringincludeIdentifiable.Make(structtypenonrect=tletequal(x:t)y=x=yletcompare(x:t)y=comparexylethash(x:t)=Hashtbl.hashxletpp_intf_or_implfmt=function|Unit_info.Intf->Format.pp_print_stringfmt"[intf]"|Unit_info.Impl->()letprintfmt=function|Internal->Format.pp_print_stringfmt"<internal>"|Predefname->Format.fprintffmt"<predef:%s>"name|Compilation_units->Format.pp_print_stringfmts|Item{comp_unit;id;from}->Format.fprintffmt"%a%s.%d"pp_intf_or_implfromcomp_unitidletoutputoct=letfmt=Format.formatter_of_out_channelocinprintfmttend)letid=Local_store.s_ref(-1)letreinit()=id:=(-1)letget_current_stamp()=!idletrestore_stampi=id:=iletstamp_of_uid=function|Item{id;_}->Someid|_->Noneletmk~current_unit=letcomp_unit,from=letopenUnit_infoinmatchcurrent_unitwith|None->"",Impl|Someui->modnameui,kinduiinincrid;Item{comp_unit;id=!id;from}letof_compilation_unit_idid=ifnot(Ident.persistentid)thenMisc.fatal_errorf"Types.Uid.of_compilation_unit_id %S"(Ident.nameid);Compilation_unit(Ident.nameid)letof_predef_idid=ifnot(Ident.is_predefid)thenMisc.fatal_errorf"Types.Uid.of_predef_id %S"(Ident.nameid);Predef(Ident.nameid)letinternal_not_actually_unique=Internalletfor_actual_declaration=function|Item_->true|_->falseendmoduleSig_component_kind=structtypet=|Value|Type|Constructor|Label|Module|Module_type|Extension_constructor|Class|Class_typeletto_string=function|Value->"value"|Type->"type"|Constructor->"constructor"|Label->"label"|Module->"module"|Module_type->"module type"|Extension_constructor->"extension constructor"|Class->"class"|Class_type->"class type"letcan_appear_in_types=function|Value|Extension_constructor->false|Type|Constructor|Label|Module|Module_type|Class|Class_type->trueendmoduleItem=structmoduleT=structtypet=string*Sig_component_kind.tletcompare=compareletname(name,_)=nameletkind(_,kind)=kindletmakestrns=str,nsletvalueid=Ident.nameid,Sig_component_kind.Valuelettype_id=Ident.nameid,Sig_component_kind.Typeletconstrid=Ident.nameid,Sig_component_kind.Constructorletlabelid=Ident.nameid,Sig_component_kind.Labelletmodule_id=Ident.nameid,Sig_component_kind.Moduleletmodule_typeid=Ident.nameid,Sig_component_kind.Module_typeletextension_constructorid=Ident.nameid,Sig_component_kind.Extension_constructorletclass_id=Ident.nameid,Sig_component_kind.Classletclass_typeid=Ident.nameid,Sig_component_kind.Class_typeletprintfmt(name,ns)=Format.fprintffmt"%S[%s]"name(Sig_component_kind.to_stringns)endincludeTmoduleMap=Map.Make(T)endtypevar=Ident.ttypet={uid:Uid.toption;desc:desc;approximated:bool}anddesc=|Varofvar|Absofvar*t|Appoft*t|StructoftItem.Map.t|Aliasoft|Leaf|Projoft*Item.t|Comp_unitofstring|Errorofstringletprintfmtt=letprint_uid_opt=Format.pp_print_option(funfmt->Format.fprintffmt"<%a>"Uid.print)inletrecauxfmt{uid;desc}=matchdescwith|Varid->Format.fprintffmt"%s%a"(Ident.nameid)print_uid_optuid|Abs(id,t)->letreccollect_idents=function|{uid=None;desc=Abs(id,t)}->let(ids,body)=collect_identstinid::ids,body|body->([],body)inlet(other_idents,body)=collect_identstinletpp_identsfmtidents=letidents_names=List.mapIdent.nameidentsinletpp_sepfmt()=Format.fprintffmt",@ "inFormat.pp_print_list~pp_sepFormat.pp_print_stringfmtidents_namesinFormat.fprintffmt"Abs@[%a@,(@[%a,@ @[%a@]@])@]"print_uid_optuidpp_idents(id::other_idents)auxbody|App(t1,t2)->Format.fprintffmt"@[%a(@,%a)%a@]"auxt1auxt2print_uid_optuid|Leaf->Format.fprintffmt"<%a>"(Format.pp_print_optionUid.print)uid|Proj(t,item)->beginmatchuidwith|None->Format.fprintffmt"@[%a@ .@ %a@]"auxtItem.printitem|Someuid->Format.fprintffmt"@[(%a@ .@ %a)<%a>@]"auxtItem.printitemUid.printuidend|Comp_unitname->Format.fprintffmt"CU %s"name|Structmap->letprint_mapfmt=Item.Map.iter(funitemt->Format.fprintffmt"@[<hv 2>%a ->@ %a;@]@,"Item.printitemauxt)inifItem.Map.is_emptymapthenFormat.fprintffmt"@[<hv>{%a}@]"print_uid_optuidelseFormat.fprintffmt"{@[<v>%a@,%a@]}"print_uid_optuidprint_mapmap|Aliast->Format.fprintffmt"Alias@[(@[<v>%a@,%a@])@]"print_uid_optuidauxt|Errors->Format.fprintffmt"Error %s"sinift.approximatedthenFormat.fprintffmt"@[(approx)@ %a@]@;"auxtelseFormat.fprintffmt"@[%a@]@;"auxtletrecstrip_head_aliases=function|{desc=Aliast;_}->strip_head_aliasest|t->tletfresh_var?(name="shape-var")uid=letvar=Ident.create_localnameinvar,{uid=Someuid;desc=Varvar;approximated=false}letfor_unnamed_functor_param=Ident.create_local"()"letvaruidid={uid=Someuid;desc=Varid;approximated=false}letabs?uidvarbody={uid;desc=Abs(var,body);approximated=false}letstr?uidmap={uid;desc=Structmap;approximated=false}letalias?uidt={uid;desc=Aliast;approximated=false}letleafuid={uid=Someuid;desc=Leaf;approximated=false}letapproxt={twithapproximated=true}letproj?uidtitem=matcht.descwith|Leaf->(* When stuck projecting in a leaf we propagate the leaf
as a best effort *)approxt|Structmap->begintryItem.Map.finditemmapwithNot_found->approxt(* ill-typed program *)end|_->{uid;desc=Proj(t,item);approximated=false}letapp?uidf~arg={uid;desc=App(f,arg);approximated=false}letdecompose_abst=matcht.descwith|Abs(x,t)->Some(x,t)|_->Noneletdummy_mod={uid=None;desc=StructItem.Map.empty;approximated=false}letof_path~find_shape~namespacepath=(* We need to handle the following cases:
Path of constructor:
M.t.C
Path of label:
M.t.lbl
Path of label of inline record:
M.t.C.lbl *)letrecaux:Sig_component_kind.t->Path.t->t=funns->function|Pidentid->find_shapensid|Pdot(path,name)->letnamespace:Sig_component_kind.t=match(ns:Sig_component_kind.t)with|Constructor->Type|Label->Type|_->Moduleinproj(auxnamespacepath)(name,ns)|Papply(p1,p2)->app(auxModulep1)~arg:(auxModulep2)|Pextra_ty(path,extra)->beginmatchextrawithPcstr_tyname->proj(auxTypepath)(name,Constructor)|Pext_ty->auxExtension_constructorpathendinauxnamespacepathletfor_persistent_units={uid=Some(Uid.of_compilation_unit_id(Ident.create_persistents));desc=Comp_units;approximated=false}letleaf_for_unpack={uid=None;desc=Leaf;approximated=false}letset_uid_if_nonetuid=matcht.uidwith|None->{twithuid=Someuid}|_->tmoduleMap=structtypeshape=ttypenonrect=tItem.Map.tletempty=Item.Map.emptyletaddtitemshape=Item.Map.additemshapetletadd_valuetiduid=Item.Map.add(Item.valueid)(leafuid)tletadd_value_projtidshape=letitem=Item.valueidinItem.Map.additem(projshapeitem)tletadd_typetidshape=Item.Map.add(Item.type_id)shapetletadd_type_projtidshape=letitem=Item.type_idinItem.Map.additem(projshapeitem)tletadd_constrtidshape=Item.Map.add(Item.constrid)shapetletadd_constr_projtidshape=letitem=Item.constridinItem.Map.additem(projshapeitem)tletadd_labeltiduid=Item.Map.add(Item.labelid)(leafuid)tletadd_label_projtidshape=letitem=Item.labelidinItem.Map.additem(projshapeitem)tletadd_moduletidshape=Item.Map.add(Item.module_id)shapetletadd_module_projtidshape=letitem=Item.module_idinItem.Map.additem(projshapeitem)tletadd_module_typetiduid=Item.Map.add(Item.module_typeid)(leafuid)tletadd_module_type_projtidshape=letitem=Item.module_typeidinItem.Map.additem(projshapeitem)tletadd_extconstidshape=Item.Map.add(Item.extension_constructorid)shapetletadd_extcons_projtidshape=letitem=Item.extension_constructoridinItem.Map.additem(projshapeitem)tletadd_classtiduid=Item.Map.add(Item.class_id)(leafuid)tletadd_class_projtidshape=letitem=Item.class_idinItem.Map.additem(projshapeitem)tletadd_class_typetiduid=Item.Map.add(Item.class_typeid)(leafuid)tletadd_class_type_projtidshape=letitem=Item.class_typeidinItem.Map.additem(projshapeitem)tend