123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144(**************************************************************************)(* *)(* 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. *)(* *)(**************************************************************************)typet=PidentofIdent.t|Pdotoft*string|Papplyoft*t|Pextra_tyoft*extra_tyandextra_ty=|Pcstr_tyofstring|Pext_tyletrecsamep1p2=p1==p2||match(p1,p2)with(Pidentid1,Pidentid2)->Ident.sameid1id2|(Pdot(p1,s1),Pdot(p2,s2))->s1=s2&&samep1p2|(Papply(fun1,arg1),Papply(fun2,arg2))->samefun1fun2&&samearg1arg2|(Pextra_ty(p1,t1),Pextra_ty(p2,t2))->letsame_extra=matcht1,t2with|(Pcstr_tys1,Pcstr_tys2)->s1=s2|(Pext_ty,Pext_ty)->true|((Pcstr_ty_|Pext_ty),_)->falseinsame_extra&&samep1p2|(_,_)->falseletreccomparep1p2=ifp1==p2then0elsematch(p1,p2)with(Pidentid1,Pidentid2)->Ident.compareid1id2|(Pdot(p1,s1),Pdot(p2,s2))->leth=comparep1p2inifh<>0thenhelseString.compares1s2|(Papply(fun1,arg1),Papply(fun2,arg2))->leth=comparefun1fun2inifh<>0thenhelsecomparearg1arg2|(Pextra_ty(p1,t1),Pextra_ty(p2,t2))->leth=compare_extrat1t2inifh<>0thenhelsecomparep1p2|(Pident_,(Pdot_|Papply_|Pextra_ty_))|(Pdot_,(Papply_|Pextra_ty_))|(Papply_,Pextra_ty_)->-1|((Pextra_ty_|Papply_|Pdot_),Pident_)|((Pextra_ty_|Papply_),Pdot_)|(Pextra_ty_,Papply_)->1andcompare_extrat1t2=match(t1,t2)withPcstr_tys1,Pcstr_tys2->String.compares1s2|(Pext_ty,Pext_ty)->0|(Pcstr_ty_,Pext_ty)->-1|(Pext_ty,Pcstr_ty_)->1letrecfind_free_optids=functionPidentid->List.find_opt(Ident.sameid)ids|Pdot(p,_)|Pextra_ty(p,_)->find_free_optidsp|Papply(p1,p2)->beginmatchfind_free_optidsp1with|None->find_free_optidsp2|Some_asres->resendletexists_freeidsp=matchfind_free_optidspwith|None->false|_->trueletrecscope=functionPidentid->Ident.scopeid|Pdot(p,_)|Pextra_ty(p,_)->scopep|Papply(p1,p2)->Int.max(scopep1)(scopep2)letkfalse_=falseletrecname?(paren=kfalse)=functionPidentid->Ident.nameid|Pdot(p,s)|Pextra_ty(p,Pcstr_tys)->name~parenp^ifparensthen".( "^s^" )"else"."^s|Papply(p1,p2)->name~parenp1^"("^name~parenp2^")"|Pextra_ty(p,Pext_ty)->name~parenpletrecprintppf=function|Pidentid->Ident.print_with_scopeppfid|Pdot(p,s)|Pextra_ty(p,Pcstr_tys)->Format.fprintfppf"%a.%s"printps|Papply(p1,p2)->Format.fprintfppf"%a(%a)"printp1printp2|Pextra_ty(p,Pext_ty)->printppfpletrechead=functionPidentid->id|Pdot(p,_)|Pextra_ty(p,_)->headp|Papply_->assertfalseletflatten=letrecflattenacc=function|Pidentid->`Ok(id,acc)|Pdot(p,s)|Pextra_ty(p,Pcstr_tys)->flatten(s::acc)p|Papply_->`Contains_apply|Pextra_ty(p,Pext_ty)->flattenaccpinfunt->flatten[]tletheadsp=letrecheadspacc=matchpwith|Pidentid->id::acc|Pdot(p,_)|Pextra_ty(p,_)->headspacc|Papply(p1,p2)->headsp1(headsp2acc)inheadsp[]letreclast=function|Pidentid->Ident.nameid|Pdot(_,s)|Pextra_ty(_,Pcstr_tys)->s|Papply(_,p)|Pextra_ty(p,Pext_ty)->lastpletis_constructor_typathp=matchpwith|Pident_|Pdot_|Papply_->false|Pextra_ty_->truemoduleT=structtypenonrect=tletcompare=compareendmoduleSet=Set.Make(T)moduleMap=Map.Make(T)