123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156# 1 "typing/signature_group.ml"(**************************************************************************)(* *)(* OCaml *)(* *)(* Florian Angeletti, projet Cambium, Inria Paris *)(* *)(* 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. *)(* *)(**************************************************************************)(** Fold on a signature by syntactic group of items *)(** Classes and class types generate ghosts signature items, we group them
together before printing *)typesig_item={src:Types.signature_item;post_ghosts:Types.signature_itemlist(** ghost classes types are post-declared *);}letflattenx=x.src::x.post_ghoststypecore_rec_group=|Not_recofsig_item|Rec_groupofsig_itemlistletrec_items=function|Not_recx->[x]|Rec_groupx->x(** Private row types are manifested as a sequence of definitions
preceding a recursive group, we collect them and separate them from the
syntactic recursive group. *)typerec_group={pre_ghosts:Types.signature_itemlist;group:core_rec_group}letnext_group=function|[]->None|src::q->letghosts,q=matchsrcwith|Types.Sig_class_->(* a class declaration for [c] is followed by the ghost
declarations of class type [c], and types [c] and [#c] *)beginmatchqwith|ct::t::ht::q->[ct;t;ht],q|_->assertfalseend|Types.Sig_class_type_->(* a class type declaration for [ct] is followed by the ghost
declarations of types [ct] and [#ct] *)beginmatchqwith|t::ht::q->[t;ht],q|_->assertfalseend|Types.(Sig_module_|Sig_value_|Sig_type_|Sig_typext_|Sig_modtype_)->[],qinSome({src;post_ghosts=ghosts},q)letrecursive_sigitem=function|Types.Sig_type(ident,_,rs,_)|Types.Sig_class(ident,_,rs,_)|Types.Sig_class_type(ident,_,rs,_)|Types.Sig_module(ident,_,_,rs,_)->Some(ident,rs)|Types.(Sig_value_|Sig_modtype_|Sig_typext_)->Noneletnextx=letcons_grouppregroupq=letgroup=Rec_group(List.revgroup)inSome({pre_ghosts=List.revpre;group},q)inletrecnot_in_groupprel=matchnext_grouplwith|None->assert(pre=[]);None|Some(elt,q)->matchrecursive_sigitemelt.srcwith|Some(id,_)whenBtype.is_row_name(Ident.nameid)->not_in_group(elt.src::pre)q|None|Some(_,Types.Trec_not)->letsgroup={pre_ghosts=List.revpre;group=Not_recelt}inSome(sgroup,q)|Some(id,Types.(Trec_first|Trec_next))->in_group~pre~ids:[id]~group:[elt]qandin_group~pre~ids~grouprem=matchnext_groupremwith|None->cons_grouppregroup[]|Some(elt,next)->matchrecursive_sigitemelt.srcwith|Some(id,Types.Trec_next)->in_group~pre~ids:(id::ids)~group:(elt::group)next|None|Some(_,Types.(Trec_not|Trec_first))->cons_grouppregroupreminnot_in_group[]xletseql=Seq.unfoldnextlletiterfl=Seq.iterf(seql)letfoldfaccl=Seq.fold_leftfacc(seql)letupdate_rec_nextrsrem=matchrswith|Types.Trec_next->rem|Types.(Trec_first|Trec_not)->matchremwith|Types.Sig_type(id,decl,Trec_next,priv)::rem->Types.Sig_type(id,decl,rs,priv)::rem|Types.Sig_module(id,pres,mty,Trec_next,priv)::rem->Types.Sig_module(id,pres,mty,rs,priv)::rem|_->remtypein_place_patch={ghosts:Types.signature;replace_by:Types.signature_itemoption;}letreplace_in_placefsg=letrecnext_groupfbeforesignature=matchnextsignaturewith|None->None|Some(item,sg)->core_groupf~before~ghosts:item.pre_ghosts~before_group:[](rec_itemsitem.group)~sgandcore_groupf~before~ghosts~before_groupcurrent~sg=letcommitghosts=before_group@List.rev_appendghostsbeforeinmatchcurrentwith|[]->next_groupf(commitghosts)sg|a::q->matchf~ghostsa.srcwith|Some(info,{ghosts;replace_by})->letafter=List.concat_mapflattenq@sginletafter=matchrecursive_sigitema.src,replace_bywith|None,_|_,Some_->after|Some(_,rs),None->update_rec_nextrsafterinletbefore=matchreplace_bywith|None->commitghosts|Somex->x::commitghostsinletsg=List.rev_appendbeforeafterinSome(info,sg)|None->letbefore_group=List.rev_appenda.post_ghosts(a.src::before_group)incore_groupf~before~ghosts~before_groupq~sginnext_groupf[]sg