123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)moduletypeS=sigtype'atvalempty:'atvallength:'at->intvalpush_front:'a->'at->'atvalpush_back:'a->'at->'atvalpeek_front:'at->'avalpeek_back:'at->'avalpop_front:'at->'atvalpop_back:'at->'atvalmap_forward:('a->'b)->'at->'btvalmap_backward:('a->'b)->'at->'btvaliter_forward:('a->unit)->'at->unitvaliter_backward:('a->unit)->'at->unitvalfold_forward:('a->'b->'b)->'at->'b->'bvalfold_backward:('a->'b->'b)->'at->'b->'bvalto_seq_forward:'at->'aSeq.tvalto_seq_backward:'at->'aSeq.tend(** concatenates a list of Seq.t *)letrecand_then:'a.'aSeq.tlist->'aSeq.t=funl()->letopenSeqinmatchlwith|[]->Nil|[x]->x()|x::tl->(matchx()with|Nil->(and_thentl)()|Cons(a,next)->Cons(a,and_then(next::tl)))(** concatenates a Seq.t of Seq.t *)letrecflatten_seq:'a.'aSeq.tSeq.t->'aSeq.t=funs()->letopenSeqinmatchs()with|Nil->Nil|Cons(x,tl)->(matchx()with|Nil->(flatten_seqtl)()|Cons(a,next)->Cons(a,flatten_seq(fun()->Cons(next,tl))))moduleD:S=structtype'adigit=Zero|Oneof'a|Twoof'a*'a|Threeof'a*'a*'atype'aqueue=|Shallowof'adigit|Deepof'adigit*('a*'a)queue*'adigittype'at={length:int;queue:'aqueue}letqempty=ShallowZeroletdpush_frontx=function|Zero->Onex|Onea->Two(x,a)|Two(a,b)->Three(x,a,b)|Three_->assertfalseletdpush_backx=function|Zero->Onex|Onea->Two(a,x)|Two(a,b)->Three(a,b,x)|Three_->assertfalseletdpeek_front=function|Zero->raiseNot_found|Onea->a|Two(a,_)->a|Three(a,_,_)->aletdpeek_back=function|Zero->raiseNot_found|Onea->a|Two(_,a)->a|Three(_,_,a)->aletdpop_front=function|Zero->raiseNot_found|One_->Zero|Two(_,a)->Onea|Three(_,a,b)->Two(a,b)letdpop_back=function|Zero->raiseNot_found|One_->Zero|Two(a,_)->Onea|Three(a,b,_)->Two(a,b)letdmap_forwardf=function|Zero->Zero|Onea->leta=fainOnea|Two(a,b)->letb=fbinleta=fainTwo(a,b)|Three(a,b,c)->letc=fcinletb=fbinleta=fainThree(a,b,c)letdmap_backwardf=function|Zero->Zero|Onea->leta=fainOnea|Two(a,b)->leta=fainletb=fbinTwo(a,b)|Three(a,b,c)->leta=fainletb=fbinletc=fcinThree(a,b,c)letditer_forwardf=function|Zero->()|Onea->fa|Two(a,b)->fb;fa|Three(a,b,c)->fc;fb;faletditer_backwardf=function|Zero->()|Onea->fa|Two(a,b)->fa;fb|Three(a,b,c)->fa;fb;fcletrecdto_seq_forwardf=letopenSeqinfun()->matchfwith|Zero->Nil|Onea->Cons(a,dto_seq_forwardZero)|Two(a,b)->Cons(b,dto_seq_forward(Onea))|Three(a,b,c)->Cons(c,dto_seq_forward(Two(a,b)))letrecdto_seq_backwardf=letopenSeqinfun()->matchfwith|Zero->Nil|Onea->Cons(a,dto_seq_backwardZero)|Two(a,b)->Cons(a,dto_seq_backward(Oneb))|Three(a,b,c)->Cons(a,dto_seq_backward(Two(b,c)))letdfold_forwardftacc=matchtwith|Zero->acc|Onea->faacc|Two(a,b)->fa(fbacc)|Three(a,b,c)->fa(fb(fcacc))letdfold_backwardftacc=matchtwith|Zero->acc|Onea->faacc|Two(a,b)->fb(faacc)|Three(a,b,c)->fc(fb(faacc))letrecqpush_front:'a.'a->'aqueue->'aqueue=funxq->matchqwith|Shallowd->(matchdwith|Zero|One_|Two_->Shallow(dpush_frontxd)|Three(a,b,c)->Deep(Two(x,a),qempty,Two(b,c)))|Deep(f,m,r)->(matchfwith|Zero|One_|Two_->Deep(dpush_frontxf,m,r)|Three(a,b,c)->Deep(Two(x,a),qpush_front(b,c)m,r))letrecqpush_back:'a.'a->'aqueue->'aqueue=funxq->matchqwith|Shallowd->(matchdwith|Zero|One_|Two_->Shallow(dpush_backxd)|Three(a,b,c)->Deep(Two(a,b),qempty,Two(c,x)))|Deep(f,m,r)->(matchrwith|Zero|One_|Two_->Deep(f,m,dpush_backxr)|Three(a,b,c)->Deep(f,qpush_back(a,b)m,Two(c,x)))letqpeek_front=function|Shallowd->dpeek_frontd|Deep(f,_,_)->dpeek_frontfletqpeek_back=function|Shallowd->dpeek_backd|Deep(_,_,r)->dpeek_backrletrecqpop_front:'a.'aqueue->'aqueue=funt->matchtwith|Shallowd->Shallow(dpop_frontd)|Deep(f,m,r)->(matchfwith|Zero->assertfalse|One_->ifm=qemptythenShallowrelseleta,b=qpeek_frontminDeep(Two(a,b),qpop_frontm,r)|Two_|Three_->Deep(dpop_frontf,m,r))letrecqpop_back:'a.'aqueue->'aqueue=funt->matchtwith|Shallowd->Shallow(dpop_backd)|Deep(f,m,r)->(matchrwith|Zero->assertfalse|One_->ifm=qemptythenShallowfelseleta,b=qpeek_backminDeep(f,qpop_backm,Two(a,b))|Two_|Three_->Deep(f,m,dpop_backr))letrecqmap_forward:'a'b.('a->'b)->'aqueue->'bqueue=fungt->matchtwith|Shallowd->Shallow(dmap_forwardgd)|Deep(f,m,r)->letr=dmap_forwardgrinletm=qmap_forward(fun(x,y)->lety=gyinletx=gxin(x,y))minletf=dmap_forwardgfinDeep(f,m,r)letrecqmap_backward:'a'b.('a->'b)->'aqueue->'bqueue=fungt->matchtwith|Shallowd->Shallow(dmap_backwardgd)|Deep(f,m,r)->letf=dmap_backwardgfinletm=qmap_backward(fun(x,y)->letx=gxinlety=gyin(x,y))minletr=dmap_backwardgrinDeep(f,m,r)letrecqiter_forward:'a.('a->unit)->'aqueue->unit=fungt->matchtwith|Shallowd->diter_forwardgd|Deep(f,m,r)->diter_forwardgr;qiter_forward(fun(x,y)->gy;gx)m;diter_forwardgfletrecqiter_backward:'a.('a->unit)->'aqueue->unit=fungt->matchtwith|Shallowd->diter_backwardgd|Deep(f,m,r)->diter_backwardgf;qiter_backward(fun(x,y)->gx;gy)m;diter_backwardgrletrecqto_seq_forward:typeb.bqueue->bSeq.t=function|Shallowd->dto_seq_forwardd|Deep(f,m,r)->letseq_of_pairs=qto_seq_forwardminletseq_of_seqs=Seq.map(fun(a,b)()->Seq.(Cons(b,returna)))seq_of_pairsinand_then[dto_seq_forwardr;flatten_seqseq_of_seqs;dto_seq_forwardf]letrecqto_seq_backward:typeb.bqueue->bSeq.t=function|Shallowd->dto_seq_backwardd|Deep(f,m,r)->letseq_of_pairs=qto_seq_backwardminletseq_of_seqs=Seq.map(fun(a,b)()->Seq.(Cons(a,returnb)))seq_of_pairsinand_then[dto_seq_backwardf;flatten_seqseq_of_seqs;dto_seq_backwardr]letrecqfold_forward:'a'b.('a->'b->'b)->'aqueue->'b->'b=fungtacc->matchtwith|Shallowd->dfold_forwardgdacc|Deep(f,m,r)->dfold_forwardgf(qfold_forward(fun(x,y)acc->gx(gyacc))m(dfold_forwardgracc))letrecqfold_backward:'a'b.('a->'b->'b)->'aqueue->'b->'b=fungtacc->matchtwith|Shallowd->dfold_backwardgdacc|Deep(f,m,r)->dfold_backwardgr(qfold_backward(fun(x,y)acc->gy(gxacc))m(dfold_backwardgfacc))letempty={length=0;queue=qempty}letlengtht=t.lengthletpush_frontxt={length=t.length+1;queue=qpush_frontxt.queue}letpush_backxt={length=t.length+1;queue=qpush_backxt.queue}letpeek_frontt=qpeek_frontt.queueletpeek_backt=qpeek_backt.queueletpop_frontt={length=t.length-1;queue=qpop_frontt.queue}letpop_backt={length=t.length-1;queue=qpop_backt.queue}letmap_forwardft={twithqueue=qmap_forwardft.queue}letmap_backwardft={twithqueue=qmap_backwardft.queue}letiter_forwardft=qiter_forwardft.queueletiter_backwardft=qiter_backwardft.queueletto_seq_forwardt=qto_seq_forwardt.queueletto_seq_backwardt=qto_seq_backwardt.queueletfold_forwardftacc=qfold_forwardft.queueaccletfold_backwardftacc=qfold_backwardft.queueaccendtype'acompound=|Simpleof'aD.t|Compoundof'aD.t*'acompoundqueue*'aD.tand'aqueue=|Shallowof'aD.t|Deepof'aD.t*'acompoundqueue*'aD.t*'acompoundqueue*'aD.ttype'at={length:int;queue:'aqueue}letqempty=ShallowD.emptyletqpush_frontx=function|Shallowq->Shallow(D.push_frontxq)|Deep(f,a,m,b,r)->Deep(D.push_frontxf,a,m,b,r)letqpush_backx=function|Shallowq->Shallow(D.push_backxq)|Deep(f,a,m,b,r)->Deep(f,a,m,b,D.push_backxr)letqpeek_front=function|Shallowq->D.peek_frontq|Deep(f,_,_,_,_)->D.peek_frontfletqpeek_back=function|Shallowq->D.peek_backq|Deep(_,_,_,_,r)->D.peek_backrletsharefr=(D.pop_backf,D.push_front(D.peek_backf)(D.push_front(D.peek_frontr)D.empty),D.pop_frontr)letrecappend_leftt1t2=ift1=D.emptythent2elseappend_left(D.pop_backt1)(D.push_front(D.peek_backt1)t2)letrecappend_rightt1t2=ift2=D.emptythent1elseappend_right(D.push_back(D.peek_frontt2)t1)(D.pop_frontt2)letqappendt1t2=match(t1,t2)with|Shallowq1,Shallowq2->ifD.lengthq1<4thenShallow(append_leftq1q2)elseifD.lengthq2<4thenShallow(append_rightq1q2)elseletf,m,r=shareq1q2inDeep(f,qempty,m,qempty,r)|Shallowq,Deep(f,a,m,b,r)->ifD.lengthq<3thenDeep(append_leftqf,a,m,b,r)elseDeep(q,qpush_front(Simplef)a,m,b,r)|Deep(f,a,m,b,r),Shallowq->ifD.lengthq<3thenDeep(f,a,m,b,append_rightrq)elseDeep(f,a,m,qpush_back(Simpler)b,q)|Deep(f1,a1,m1,b1,r1),Deep(f2,a2,m2,b2,r2)->letr,m,f=sharer1f2inDeep(f1,qpush_back(Compound(m1,b1,r))a1,m,qpush_front(Compound(f,a2,m2))b2,r2)letreplace_frontx=function|Shallowq->Shallow(D.push_frontx(D.pop_frontq))|Deep(f,a,m,b,r)->Deep(D.push_frontx(D.pop_frontf),a,m,b,r)letrecqpop_front:'a.'aqueue->'aqueue=funt->matchtwith|Shallowq->Shallow(D.pop_frontq)|Deep(f,a,m,b,r)->ifD.lengthf>3thenDeep(D.pop_frontf,a,m,b,r)elseifa<>qemptythenmatchqpeek_frontawith|Simpleq->Deep(append_left(D.pop_frontf)q,qpop_fronta,m,b,r)|Compound(f',a',r')->Deep(append_left(D.pop_frontf)f',qappenda'(replace_front(Simpler')a),m,b,r)elseifb<>qemptythenmatchqpeek_frontbwith|Simpleq->Deep(append_left(D.pop_frontf)m,qempty,q,qpop_frontb,r)|Compound(f',a',r')->Deep(append_left(D.pop_frontf)m,qpush_front(Simplef')a',r',qpop_frontb,r)elseqappend(Shallow(append_left(D.pop_frontf)m))(Shallowr)letreplace_backx=function|Shallowq->Shallow(D.push_backx(D.pop_backq))|Deep(f,a,m,b,r)->Deep(f,a,m,b,D.push_backx(D.pop_backr))letrecqpop_back:'a.'aqueue->'aqueue=funt->matchtwith|Shallowq->Shallow(D.pop_backq)|Deep(f,a,m,b,r)->ifD.lengthr>3thenDeep(f,a,m,b,D.pop_backr)elseifb<>qemptythenmatchqpeek_backbwith|Simpleq->Deep(f,a,m,qpop_backb,append_rightq(D.pop_backr))|Compound(f',a',r')->Deep(f,a,m,qappend(replace_back(Simplef')b)a',append_rightr'(D.pop_backr))elseifa<>qemptythenmatchqpeek_backawith|Simpleq->Deep(f,qpop_backa,q,qempty,append_rightm(D.pop_backr))|Compound(f',a',r')->Deep(f,qpop_backa,f',qpush_back(Simpler')a',append_rightm(D.pop_backr))elseqappend(Shallowf)(Shallow(append_rightm(D.pop_backr)))letreccmap_forward:'a'b.('a->'b)->'acompound->'bcompound=fungt->matchtwith|Simpleq->Simple(D.map_forwardgq)|Compound(f,a,r)->letr=D.map_forwardgrinleta=qmap_forward(cmap_forwardg)ainletf=D.map_forwardgfinCompound(f,a,r)andqmap_forward:'a'b.('a->'b)->'aqueue->'bqueue=fungt->matchtwith|Shallowq->Shallow(D.map_forwardgq)|Deep(f,a,m,b,r)->letr=D.map_forwardgrinletb=qmap_forward(cmap_forwardg)binletm=D.map_forwardgminleta=qmap_forward(cmap_forwardg)ainletf=D.map_forwardgfinDeep(f,a,m,b,r)letreccmap_backward:'a'b.('a->'b)->'acompound->'bcompound=fungt->matchtwith|Simpleq->Simple(D.map_backwardgq)|Compound(f,a,r)->letf=D.map_backwardgfinleta=qmap_backward(cmap_backwardg)ainletr=D.map_backwardgrinCompound(f,a,r)andqmap_backward:'a'b.('a->'b)->'aqueue->'bqueue=fungt->matchtwith|Shallowq->Shallow(D.map_backwardgq)|Deep(f,a,m,b,r)->letf=D.map_backwardgfinleta=qmap_backward(cmap_backwardg)ainletm=D.map_backwardgminletb=qmap_backward(cmap_backwardg)binletr=D.map_backwardgrinDeep(f,a,m,b,r)letrecciter_forward:'a.('a->unit)->'acompound->unit=fungt->matchtwith|Simpleq->D.iter_forwardgq|Compound(f,a,r)->D.iter_forwardgr;qiter_forward(citer_forwardg)a;D.iter_forwardgfandqiter_forward:'a.('a->unit)->'aqueue->unit=fungt->matchtwith|Shallowq->D.iter_forwardgq|Deep(f,a,m,b,r)->D.iter_forwardgr;qiter_forward(citer_forwardg)b;D.iter_forwardgm;qiter_forward(citer_forwardg)a;D.iter_forwardgfletrecciter_backward:'a.('a->unit)->'acompound->unit=fungt->matchtwith|Simpleq->D.iter_backwardgq|Compound(f,a,r)->D.iter_backwardgf;qiter_backward(citer_backwardg)a;D.iter_backwardgrandqiter_backward:'a.('a->unit)->'aqueue->unit=fungt->matchtwith|Shallowq->D.iter_backwardgq|Deep(f,a,m,b,r)->D.iter_backwardgf;qiter_backward(citer_backwardg)a;D.iter_backwardgm;qiter_backward(citer_backwardg)b;D.iter_backwardgrletreccto_seq_forward:typec.ccompound->cSeq.t=function|Simpleq->D.to_seq_forwardq|Compound(f,a,r)->and_then[D.to_seq_forwardr;flatten_seq(Seq.mapcto_seq_forward(qto_seq_forwarda));D.to_seq_forwardf;]andqto_seq_forward:typeb.bqueue->bSeq.t=function|Shallowq->D.to_seq_forwardq|Deep(f,a,m,b,r)->and_then[D.to_seq_forwardr;flatten_seq(Seq.mapcto_seq_forward(qto_seq_forwardb));D.to_seq_forwardm;flatten_seq(Seq.mapcto_seq_forward(qto_seq_forwarda));D.to_seq_forwardf;]letreccto_seq_backward:typec.ccompound->cSeq.t=function|Simpleq->D.to_seq_backwardq|Compound(f,a,r)->and_then[D.to_seq_backwardf;flatten_seq(Seq.mapcto_seq_backward(qto_seq_backwarda));D.to_seq_backwardr;]andqto_seq_backward:typeb.bqueue->bSeq.t=function|Shallowq->D.to_seq_backwardq|Deep(f,a,m,b,r)->and_then[D.to_seq_backwardf;flatten_seq(Seq.mapcto_seq_backward(qto_seq_backwarda));D.to_seq_backwardm;flatten_seq(Seq.mapcto_seq_backward(qto_seq_backwardb));D.to_seq_backwardr;]letreccfold_forward:'a'b.('a->'b->'b)->'acompound->'b->'b=fungtacc->matchtwith|Simpleq->D.fold_forwardgqacc|Compound(f,a,r)->D.fold_forwardgf(qfold_forward(cfold_forwardg)a(D.fold_forwardgracc))andqfold_forward:'a'b.('a->'b->'b)->'aqueue->'b->'b=fungtacc->matchtwith|Shallowq->D.fold_forwardgqacc|Deep(f,a,m,b,r)->D.fold_forwardgf(qfold_forward(cfold_forwardg)a(D.fold_forwardgm(qfold_forward(cfold_forwardg)b(D.fold_forwardgracc))))letreccfold_backward:'a'b.('a->'b->'b)->'acompound->'b->'b=fungtacc->matchtwith|Simpleq->D.fold_backwardgqacc|Compound(f,a,r)->D.fold_backwardgr(qfold_backward(cfold_backwardg)a(D.fold_backwardgfacc))andqfold_backward:'a'b.('a->'b->'b)->'aqueue->'b->'b=fungtacc->matchtwith|Shallowq->D.fold_backwardgqacc|Deep(f,a,m,b,r)->D.fold_backwardgr(qfold_backward(cfold_backwardg)b(D.fold_backwardgm(qfold_backward(cfold_backwardg)a(D.fold_backwardgfacc))))letempty={length=0;queue=qempty}letlengtht=t.lengthletappendt1t2={length=t1.length+t2.length;queue=qappendt1.queuet2.queue}letpush_frontxt={length=t.length+1;queue=qpush_frontxt.queue}letpush_backxt={length=t.length+1;queue=qpush_backxt.queue}letpeek_frontt=trySome(qpeek_frontt.queue)withNot_found->Noneletpeek_backt=trySome(qpeek_backt.queue)withNot_found->Noneletpop_frontt=trySome{length=t.length-1;queue=qpop_frontt.queue}withNot_found->Noneletpop_backt=trySome{length=t.length-1;queue=qpop_backt.queue}withNot_found->Noneletmap_forwardft={twithqueue=qmap_forwardft.queue}letmap_backwardft={twithqueue=qmap_backwardft.queue}letiter_forwardft=qiter_forwardft.queueletiter_backwardft=qiter_backwardft.queueletto_seq_forwardt=qto_seq_forwardt.queueletto_seq_backwardt=qto_seq_backwardt.queueletfold_forwardftacc=qfold_forwardft.queueaccletfold_backwardftacc=qfold_backwardft.queueacc