123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284openTypesmoduleTake=structtype('a,'b,'c)action=|Recof'alist|Skip|Accumof'blist|Stop_and_keep|Stop_and_accumof'blist*'coptionletuntil~classifyitems=letrecloopacc=function|[]->(List.revacc,None,[])|b::rest->(matchclassifybwith|Skip->loopaccrest|Recx->loopacc(x@rest)|Accumv->loop(List.rev_appendvacc)rest|Stop_and_keep->(List.revacc,None,b::rest)|Stop_and_accum(v,e)->(List.rev_appendaccv,e,rest))inloop[]itemsendmoduleRewire=structtype('a,'h)action=Recof'a|Skip|Headingof'h*intletwalk~classify~nodeitems=letrecloopcurrent_levelaccl=matchlwith|[]->(List.revacc,[])|b::rest->(matchclassifybwith|Skip->loopcurrent_levelaccrest|Recl->loopcurrent_levelacc(l@rest)|Heading(h,level)->iflevel>current_levelthenletchildren,rest=looplevel[]restinloopcurrent_level(nodehchildren::acc)restelse(List.revacc,l))inlettrees,rest=loop(-1)[]itemsinassert(rest=[]);treesendmoduleToc:sigtypet=onelistandone={url:Url.t;text:Inline.t;children:t}valcompute:Url.Path.t->on_sub:(Include.status->bool)->Item.tlist->tend=structtypet=onelistandone={url:Url.t;text:Inline.t;children:t}letclassify~on_sub(i:Item.t):_Rewire.action=matchiwith|Text_|Declaration_->Skip|Include{content={status;content;_};_}->ifon_substatusthenReccontentelseSkip|Heading{label=None;_}->Skip|Heading{label=Somelabel;level;title}->Heading((label,title),level)letnodemkurl(anchor,text)children={url=mkurlanchor;text;children}letcomputepage~on_subt=letmkurlanchor={Url.Anchor.page;anchor;kind=`LeafPage}inRewire.walk~classify:(classify~on_sub)~node:(nodemkurl)tendmoduleSubpages:sigvalcompute:Page.t->Subpage.tlistend=structletrecwalk_documentedsrc(l:DocumentedSrc.t)=Utils.flatmapl~f:(function|DocumentedSrc.Code_->[]|Documented_->[]|Nested{code;_}->walk_documentedsrccode|Subpagep->[p]|Alternative(Expansionr)->walk_documentedsrcr.expansion)letrecwalk_items(l:Item.tlist)=Utils.flatmapl~f:(function|Item.Text_->[]|Heading_->[]|Declaration{content;_}->walk_documentedsrccontent|Includei->walk_itemsi.content.content)letcompute(p:Page.t)=walk_items(p.header@p.items)endmoduleShift=structtypestate={englobing_level:int;current_level:int}letstart={englobing_level=0;current_level=0}letshiftstx=letlevel=st.englobing_level+xin({stwithcurrent_level=level},level)letenter{current_level;_}i={englobing_level=current_level+i;current_level}letrecwalk_documentedsrc~on_subshift_state(l:DocumentedSrc.t)=matchlwith|[]->[]|((Code_|Documented_)ash)::rest->h::walk_documentedsrc~on_subshift_staterest|Nestedds::rest->letds={dswithcode=walk_documentedsrc~on_subshift_stateds.code}inNestedds::walk_documentedsrc~on_subshift_staterest|Subpagesubp::rest->letsubp=subpage~on_subshift_statesubpinSubpagesubp::walk_documentedsrc~on_subshift_staterest|Alternative(Expansionr)::rest->letexpansion=walk_documentedsrc~on_subshift_stater.expansioninAlternative(Expansion{rwithexpansion})::walk_documentedsrc~on_subshift_staterestandsubpage~on_subshift_state(subp:Subpage.t)=matchon_sub(`Pagesubp)with|None->subp|Somei->letshift_state=entershift_stateiinletpage=subp.contentinletcontent={pagewithheader=walk_item~on_subshift_statepage.header;items=walk_item~on_subshift_statepage.items;}in{subpwithcontent}andinclude_~on_subshift_state(subp:Include.t)=matchon_sub(`Includesubp)with|None->subp|Somei->letshift_state=entershift_stateiinletcontent=walk_item~on_subshift_statesubp.contentin{subpwithcontent}andwalk_item~on_subshift_state(l:Item.tlist)=matchlwith|[]->[]|Heading{label;level;title}::rest->letshift_state,level=shiftshift_statelevelinItem.Heading{label;level;title}::walk_item~on_subshift_staterest|Includesubp::rest->letcontent=include_~on_subshift_statesubp.contentinletsubp={subpwithcontent}inItem.Includesubp::walk_item~on_subshift_staterest|Declarationdecl::rest->letdecl={declwithcontent=walk_documentedsrc~on_subshift_statedecl.content;}inDeclarationdecl::walk_item~on_subshift_staterest|Texttxt::rest->Texttxt::walk_item~on_subshift_staterestletcompute~on_subi=letshift_state=startinwalk_item~on_subshift_stateiendmoduleHeadings:sigvalfold:('a->Heading.t->'a)->'a->Page.t->'a(** Fold over every headings, follow subpages, nested documentedsrc and
expansions. *)valfoldmap:('a->Heading.t->'a*Heading.t)->'a->Page.t->'a*Page.tend=structletfold=letrecw_pagefaccpage=w_itemsf(w_itemsfaccpage.Page.header)page.itemsandw_itemsfaccts=List.fold_left(w_itemf)acctsandw_itemfacc=function|Headingh->facch|Text_->acc|Declarationt->w_documentedsrcfacct.Item.content|Includet->w_itemsfacct.Item.content.contentandw_documentedsrcfacct=List.fold_left(w_documentedsrc_onef)acctandw_documentedsrc_onefacc=function|DocumentedSrc.Code_|Documented_->acc|Nestedt->w_documentedsrcfacct.code|Subpagesp->w_pagefaccsp.content|Alternative(Expansionexp)->w_documentedsrcfaccexp.expansioninw_pageletrecfoldmap_leftfaccrlst=function|[]->(acc,List.revrlst)|hd::tl->letacc,hd=facchdinfoldmap_leftfacc(hd::rlst)tlletfoldmap_leftfacclst=foldmap_leftfacc[]lstletfoldmap=letrecw_pagefaccpage=letacc,header=w_itemsfaccpage.Page.headerinletacc,items=w_itemsfaccpage.itemsin(acc,{pagewithheader;items})andw_itemsfaccitems=foldmap_left(w_itemf)accitemsandw_itemfacc=function|Headingh->letacc,h=facchin(acc,Headingh)|Text_asx->(acc,x)|Declarationt->letacc,content=w_documentedsrcfacct.contentin(acc,Declaration{twithcontent})|Includet->letacc,content=w_itemsfacct.Item.content.contentin(acc,Include{twithcontent={t.contentwithcontent}})andw_documentedsrcfacct=foldmap_left(w_documentedsrc_onef)acctandw_documentedsrc_onefacc=function|(Code_|Documented_)asx->(acc,x)|Nestedt->letacc,code=w_documentedsrcfacct.codein(acc,Nested{twithcode})|Subpagesp->letacc,content=w_pagefaccsp.contentin(acc,Subpage{spwithcontent})|Alternative(Expansionexp)->letacc,expansion=w_documentedsrcfaccexp.expansionin(acc,Alternative(Expansion{expwithexpansion}))inw_pageendmoduleLabels:sigvaldisambiguate_page:Page.t->Page.t(** Colliding labels are allowed in the model but don't make sense in
generators because we need to link to everything (eg. the TOC).
Post-process the doctree, add a "_N" suffix to dupplicates, the first
occurence is unchanged. Iterate through subpages. *)end=structmoduleStringMap=Map.Make(String)letrecmake_label_uniquelabelsdilabel=letlabel'=label^"_"in(* start at [_2]. *)letnew_label=label'^string_of_int(di+1)in(* If the label is still ambiguous after suffixing, add an extra '_'. *)ifStringMap.memnew_labellabelsthenmake_label_uniquelabelsdilabel'elsenew_labelletdisambiguate_pagepage=(* Perform two passes, we need to know every labels before allocating new
ones. *)letlabels=Headings.fold(funacch->matchh.labelwithSomel->StringMap.addl0acc|None->acc)StringMap.emptypageinHeadings.foldmap(funacch->matchh.labelwith|Somel->letd_index=StringMap.findlaccinleth=ifd_index=0thenhelseletlabel=Some(make_label_uniqueaccd_indexl)in{hwithlabel}in(StringMap.addl(d_index+1)acc,h)|None->(acc,h))labelspage|>sndend