123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547moduleO=Order_managedtypecursor=O.tinclude(structtype+'acell={offset:int;cursor:cursor;value:'a}letmake_celloffsetcursorvalue=assert(offset>=0);{offset;cursor;value}letshift_cellnc=ifn=0thencelsemake_cell(c.offset+n)c.cursorc.valueend:sigtype+'acell=private{offset:int;cursor:cursor;value:'a}valmake_cell:int->cursor->'a->'acellvalshift_cell:int->'acell->'acellend)moduleT=Mbt.Make(structtype'ameasurable='acelltypemeasure=intletempty=0letcatabc=a+b.offset+cend)type'at={root:O.t;tree:'aT.t;}letcreate()={root=O.root();tree=T.leaf;}letvalidatetcmsg=ifnot(O.same_ordert.rootc)theninvalid_argmsgletupdatetf=lettree,result=ft.treein{twithtree},resultletupdate'tf={twithtree=ft.tree}letcleart={twithtree=T.leaf}letcompare=O.compareletis_leaf=function|T.Leaf->true|T.Node_->falseletis_emptyt=is_leaft.treeletmembertc=letrecaux=function|T.Leaf->false|T.Node(_,l,cell,r,_)->leto=compareccell.cursorinifo=0thentrueelseifo<0thenauxlelseauxrinauxt.treeletfindtc=letrecaux=function|T.Leaf->raiseNot_found|T.Node(_,l,cell,r,_)->leto=compareccell.cursorinifo=0thencell.valueelseifo<0thenauxlelseauxrinauxt.treeletpositiontc0=letrectraversen=function|T.Leaf->raiseNot_found|T.Node(_,l,cell,r,_)->leto=comparec0cell.cursorinifo<0thentraversenlelseletn=n+T.measurel+cell.offsetinifo>0thentraversenrelsenintraverse0t.treeletrecshift_treen=function|T.Leaf->T.leaf|T.Node(_,T.Leaf,cell,r,_)->T.nodeT.leaf(shift_cellncell)r|T.Node(_,l,cell,r,_)->T.node(shift_treenl)cellrletshift_treentree=ifn=0thentreeelseshift_treentreeletrem_cursortc0=letrectraverse=function|T.Leaf->raiseNot_found|T.Node(_,l,cell,r,_)->leto=comparec0cell.cursorinifo<0thenletl,shift=traverselinT.nodel(shift_cellshiftcell)r,0elseifo>0thenletr,shift=traverserinT.nodelcellr,shiftelseifis_leafrthenl,cell.offsetelseT.joinl(shift_treecell.offsetr),0infst(updatettraverse)letput_cursort~atvalue=ifat<0theninvalid_arg"Trope.put_cursor: [at] must be >= 0";letrectraversebeforeat=function|T.Leaf->letcursor=O.afterbeforeinletcell=make_cellatcursorvalueinT.nodeT.leafcellT.leaf,cursor|T.Node(_,l,cell,r,_)->letpos=T.measurel+cell.offsetinifat<posthenletl,cursor=traversebeforeatlinT.nodel(make_cell(pos-T.measurel)cell.cursorcell.value)r,cursorelseletr,cursor=traversecell.cursor(at-pos)rinT.nodelcellr,cursorinupdatet(traverset.rootat)letinsert?left_oft~at~len=ifat<0theninvalid_arg"Trope.insert: [at] must be >= 0";iflen<0theninvalid_arg"Trope.insert: [len] must be >= 0";letright=(left_of:unitoption)=Noneinletrecauxn=function|T.Leaf->T.leaf,len|T.Node(_,l,cell,r,_)->letn0=T.measurel+cell.offsetinif(ifrightthenn<n0elsen<=n0)thenletl,shift=auxnlinT.nodel(shift_cellshiftcell)r,0elseletr,shift=aux(n-n0)rinT.nodelcellr,shiftinfst(updatet(auxat))letremove?left_oft~at~len=ifat<0theninvalid_arg"Trope.remove: [at] must be >= 0";iflen<0theninvalid_arg"Trope.remove: [len] must be >= 0";iflen=0thentelseletrecremlen=function|T.Leaf->T.leaf|T.Node(_,l,cell,r,_)->letn0=T.measurel+cell.offsetiniflen<=n0thenletl=remlenlinletcell=make_cell(n0-len-T.measurel)cell.cursorcell.valueinT.nodelcellrelseletlen=len-n0inletr=remlenrinrinletright=(left_of:unitoption)=Noneinletrecauxnlen=function|T.Leaf->T.leaf|T.Node(_,l,cell,r,_)->letn0=T.measurel+cell.offsetinifn+len<=n0thenletl=auxnlenlinletcell=make_cell(n0-len-T.measurel)cell.cursorcell.valueinT.nodelcellrelseif(ifrightthenn>=n0elsen>n0)thenT.nodelcell(aux(n-n0)lenr)else(* Splitting case *)letl=auxnlenlinletlen=len-(n0-n)inletr=shift_tree(n-T.measurel)(remlenr)inT.joinlrinupdate't(auxatlen)letcursor_after=O.afterletcursor_before=O.beforeletcursor_at_origint=O.aftert.rootletremove_betweentc1c2=validatetc1"Trope.remove_between: cursor not in buffer";validatetc2"Trope.remove_between: cursor not in buffer";ifc1==c2thentelseifcomparec1c2>0theninvalid_arg"Trope.remove_between: cursors must be in increaing order"elsebeginletreccut_left=function|T.Leaf->invalid_arg"Trope.remove_between: cursor not in buffer"|T.Node(_,l,cell,r,_)->letc1=comparec1cell.cursorinifc1<0thencut_leftlelseifc1>0thenT.nodelcell(cut_leftr)else(* c1 = 0 *)T.nodelcellT.leafinletreccut_right=function|T.Leaf->invalid_arg"Trope.remove_between: cursor not in buffer"|T.Node(_,l,cell,r,_)->letc2=comparec2cell.cursorinifc2>0thencut_rightrelseifc2<0thenT.node(cut_rightl)cellrelse(* c2 = 0 *)T.nodeT.leaf(make_cell0cell.cursorcell.value)rinletrecaux=function|T.Leaf->invalid_arg"Trope.remove_between: cursor not in buffer"|T.Node(_,l,cell,r,_)->letc1=comparec1cell.cursorandc2=comparec2cell.cursorinifc2<0thenT.node(auxl)cellrelseifc1>0thenT.nodelcell(auxr)elseifc1=0thenT.nodelcell(cut_rightr)elseifc2=0thenT.node(cut_leftl)(make_cell0cell.cursorcell.value)relse(* c1 < 0 && c2 > 0 *)T.join(cut_leftl)(cut_rightr)inupdate'tauxendletremove_aftertclen=validatetc"Trope.remove_after: cursor not in buffer";iflen<0theninvalid_arg"Trope.remove_after: len must be >= 0"elseiflen=0thentelseletrecremn=function|T.Leaf->T.leaf,n|T.Node(_,l,cell,r,_)->letn0=T.measurelinletn1=n0+cell.offsetinifn<=n0thenletl,shift=remnlinT.nodel(shift_cell(-shift)cell)r,0elseifn<=n1thenT.nodeT.leaf(make_cell(n1-n)cell.cursorcell.value)r,0elserem(n-n1)rinletrecseek=function|T.Leaf->invalid_arg"Trope.remove_after: cursor not in buffer"|T.Node(_,l,cell,r,_)->letc=compareccell.cursorinifc<0thenletl,shift=seeklinifshift>cell.offsetthenletr,shift=rem(shift-cell.offset)rinT.joinlr,shiftelseT.nodel(shift_cell(-shift)cell)r,0elseletr,shift=ifc=0thenremlenrelseseekrinT.nodelcellr,shiftinfst(updatetseek)letremove_beforetclen=validatetc"Trope.remove_before: cursor not in buffer";iflen<0theninvalid_arg"Trope.remove_before: len must be >= 0"elseiflen=0thentelseletrecremn=function|T.Leaf->T.leaf|T.Node(_,l,cell,r,_)->letn0=T.measurerinifn<=n0thenletr=remnrinT.nodelcellrelseletn=n-n0-cell.offsetinifn>0thenremnlelselinletrecseek=function|T.Leaf->invalid_arg"Trope.remove_before: cursor not in buffer"|T.Node(_,l,cell,r,_)->letc=compareccell.cursorinifc<0thenT.node(seekl)cellrelseifc=0theniflen<=cell.offsetthenletcell=shift_cell(-len)cellinT.nodelcellrelseletlen=len-cell.offsetinletn0=T.measureliniflen<=n0thenletl=remlenlinT.nodel(make_cell(n0-T.measurel-len)cell.cursorcell.value)relseT.nodeT.leaf(make_cell0cell.cursorcell.value)relseletn0=T.measurerinletr=seekrinletlen=len-(n0-T.measurer)inassert(len>=0);iflen=0thenT.nodelcellrelseiflen<=cell.offsetthenT.joinl(shift_tree(cell.offset-len)r)elseletlen=len-cell.offsetinletn0=T.measureliniflen<=n0thenletl=remlenlinT.joinl(shift_tree(n0-T.measurel-len)r)elserinupdate'tseekletinsert_beforetclen=validatetc"Trope.insert_before: cursor not in buffer";iflen<0theninvalid_arg"Trope.insert_before: len must be >= 0"elseiflen=0thentelseletrecaux=function|T.Leaf->invalid_arg"Trope.insert_before: cursor not in buffer"|T.Node(_,l,cell,r,_)->letc=compareccell.cursorinifc<0thenT.node(auxl)cellrelseifc>0thenT.nodelcell(auxr)elseT.nodel(shift_celllencell)rinupdate'tauxletinsert_aftertclen=validatetc"Trope.insert_after: cursor not in buffer";iflen<0theninvalid_arg"Trope.insert_after: len must be >= 0"elseiflen=0thentelseletrecaux=function|T.Leaf->invalid_arg"Trope.insert_after: cursor not in buffer"|T.Node(_,l,cell,r,_)astree->letc=compareccell.cursorinifc<0thenletl,shift=auxlinT.nodel(shift_cellshiftcell)r,0elseifc>0thenletr,shift=auxrinT.nodelcellr,shiftelseifis_leafrthentree,lenelseT.nodelcell(shift_treelenr),0infst(updatetaux)let_put_beforetc0value=validatetc0"Trope.put_before: cursor not in buffer";letauxt=letc=O.beforec0inletrecaux=function|T.Leaf->invalid_arg"Trope.put_before: cursor not in buffer"|T.Node(_,l,cell,r,_)->leti=comparec0cell.cursorinifi=0thenT.node(T.nodel(make_cellcell.offsetcvalue)T.leaf)(make_cell0cell.cursorcell.value)relseifi<0thenT.node(auxl)cellrelseT.nodelcell(auxr)inauxt,cinupdatetauxlet_put_aftertc0value=validatetc0"Trope.put_after: cursor not in buffer";letauxt=letc=O.afterc0inletrecaux=function|T.Leaf->invalid_arg"Trope.put_after: cursor not in buffer"|T.Node(_,l,cell,r,_)->leti=comparec0cell.cursorinifi=0thenT.node(T.nodelcellT.leaf)(make_cell0cvalue)relseifi<0thenT.node(auxl)cellrelseT.nodelcell(auxr)inauxt,cinupdatetauxletput_lefttcv=validatetc"Trope.put_left: cursor from different buffer";letrecaux=function|T.Leaf->T.nodeT.leaf(make_cell0cv)T.leaf|T.Node(_,l,cell,r,_)->leti=compareccell.cursorinifi=0thenT.nodel(make_cellcell.offsetcv)relseifi<0thenT.node(auxl)cellrelseT.nodelcell(auxr)intryupdate'tauxwithExit->tletput_righttcv=validatetc"Trope.put_right: cursor from different buffer";letrecauxpad=function|T.Leaf->T.nodeT.leaf(make_cellpadcv)T.leaf,0|T.Node(_,l,cell,r,_)->leti=compareccell.cursorinifi=0thenT.nodel(make_cellcell.offsetcv)r,padelseifi<0then(letl',pad'=auxcell.offsetlinT.nodel'(make_cellpad'cell.cursorcell.value)r,pad)elseletr',pad'=auxpadrinT.nodelcellr',pad'intryfst(updatet(aux0))withExit->tletfind_beforetn=letrecauxn=function|T.Leaf->None|T.Node(_,l,cell,r,_)->letn0=T.measurel+cell.offsetinifn<n0thenauxnlelsematchaux(n-n0)rwith|Some_asresult->result|None->Some(cell.cursor,cell.value)inauxnt.treeletfind_aftertn=letrecauxn=function|T.Leaf->None|T.Node(_,l,cell,r,_)->letn0=T.measurelinifn<=n0&¬(is_leafl)thenauxnlelseletn1=n0+cell.offsetinifn<=n1thenSome(cell.cursor,cell.value)elseaux(n-n1)rinauxnt.treeletseek_beforetc=validatetc"Trope.seek_before: cursor not in buffer";letrecaux=function|T.Leaf->None|T.Node(_,l,cell,r,_)->letc=compareccell.cursorinifc<=0thenauxlelsematchauxrwith|Some_asresult->result|None->Some(cell.cursor,cell.value)inauxt.treeletseek_aftertc=validatetc"Trope.seek_after: cursor not in buffer";letrecaux=function|T.Leaf->None|T.Node(_,l,cell,r,_)->letc=compareccell.cursorinifc>=0thenauxrelsematchauxlwith|Some_asresult->result|None->Some(cell.cursor,cell.value)inauxt.treeletto_listt=letrecauxaccn=function|T.Leaf->acc|T.Node(_,l,cell,r,_)->letn'=n+T.measurel+cell.offsetinletacc=auxaccn'rinaux((n',cell.cursor,cell.value)::acc)nlinaux[]0t.tree