123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202(* elpi: embedded lambda prolog interpreter *)(* license: GNU Lesser General Public License Version 2.1 or later *)(* ------------------------------------------------------------------------- *)moduleArray=struct(* Main code taken from OCaml-bazaar, Library General
Public License version 2. *)type'at='adatarefand'adata=|Arrayof'aarray|Diffofint*'a*'at[@@derivingshow]letempty()=ref@@Array[||](* `reroot t` ensures that `t` becomes an `Array` node.
This is written in CPS to avoid any stack overflow. *)letrecrerootktk=match!twith|Array_->k()|Diff(i,v,t')->rerootkt'(fun()->(match!t'with|Arrayaasn->letv'=a.(i)ina.(i)<-v;t:=n;t':=Diff(i,v',t)|Diff_->assertfalse);k())letreroott=rerootkt(fun()->())letgetti=match!twith|Arraya->a.(i)|Diff_->reroott;(match!twithArraya->a.(i)|Diff_->assertfalse)letsettiv=reroott;match!twith|Arrayaasn->letold=a.(i)inifold==vthentelse(a.(i)<-v;letres=refnint:=Diff(i,old,res);res)|Diff_->assertfalse(* New code, all bugs are mine ;-) *)letextendlenta=letdata=reroott;match!twithArrayx->x|Diff_->assertfalseinletnewlength=2*(max1len)inifnewlength>Sys.max_array_lengththenbeginPrintf.eprintf"bl: too many items: %d > %d (max array length)"newlengthSys.max_array_length;exit1end;letnewdata=Array.makenewlengthainiflen>0thenArray.blitdata0newdata0len;ref@@Arraynewdataletshift_righttilen=letrecshifttj=ifj<ithentelseshift(sett(j+1)(gettj))(j-1)inshiftt(i+len-1)letshift_lefttilen=letrecshifttj=ifj=len-1thentelseshift(settj(gett(j+1)))(j+1)inshifttiletreclengtht=match!twithDiff(_,_,x)->lengthx|Arraya->Array.lengthaletof_listl=ref@@Array(Array.of_listl)endtype'at=|BArrayof{len:int;data:'aArray.t}|BConsof'a*'at[@@derivingshow]letempty()=BArray{len=0;data=Array.empty()}letextendklendataak=letnewdata=Array.extendlendataainBArray{len=len+1;data=knewdata}letextendlendataa=extendklendataa(funx->x)letconsheadtail=BCons(head,tail)letrecrconseltl=matchlwith|BCons(x,xs)->BCons(x,rconseltxs)|BArray{len;data}whenlen<Array.lengthdata->BArray{len=len+1;data=Array.setdatalenelt}|BArray{len;data}->extendlendataeltletrecreplacefx=function|BCons(head,tail)whenfhead->BCons(x,tail)|BCons(head,tail)->BCons(head,replacefxtail)|BArray{len;data}asa->letrecauxi=ifi<lentheniffdata.(i)thenBArray{len;data=Array.setdataix}elseaux(i+1)elseainaux0letrecremovef=function|BCons(head,tail)whenfhead->tail|BCons(head,tail)->BCons(head,removeftail)|BArray{len;data}asa->letrecauxi=ifi<lentheniffdata.(i)thenBArray{len=len-1;data=Array.shift_leftdatailen}elseaux(i+1)elseainaux0letrecinsertfx=function|BCons(head,tail)whenfhead>0->BCons(head,BCons(x,tail))|BCons(head,tail)->BCons(head,insertfxtail)|BArray{len;data}->letrecauxi=ifi<lentheniffdata.(i)>0theniflen<Array.lengthdatathenbeginletdata=Array.shift_rightdatai(len-i)inBArray{len=len+1;data=Array.setdataix}endelseextendklendatax(fundata->letdata=Array.shift_rightdatai(len-i)inArray.setdataix)elseaux(i+1)elseiflen<Array.lengthdatathenbeginBArray{len=len+1;data=Array.setdatalenx}endelseextendklendatax(fundata->Array.setdatalenx)inaux0type'ascan='at*intletto_scanx=x,0letis_empty(x,n)=matchxwith|BArray{len}->len=n|BCons_->falseletnext(x,n)=matchxwith|BArray{len;data}->assert(n<len);data.(n),(x,n+1)|BCons(a,xs)->a,(xs,n)(* ocaml >= 4.14
let[@tail_mod_cons] rec to_list_aux i len data =
if i = len then []
else data.(i) :: to_list_aux (i+1) len data *)letrecto_list_auxilendataacc=ifi=lenthenList.revaccelseto_list_aux(i+1)lendata(data.(i)::acc)letrecto_list=function|BCons(x,xs)->x::to_listxs|BArray{len;data}->to_list_aux0lendata[]letto_list(x,n)=ifn=0thento_listxelsematchxwith|BCons_->assertfalse|BArray{len;data}->to_list_auxnlendata[]letof_listl=letdata=Array.of_listlinBArray{len=Array.lengthdata;data},0letlength(x,i)=letrecauxi=function|BCons(_,l)->aux(i+1)l|BArray{len}->i+leninaux(-i)x