1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677(** A location within a file *)typet=|Nowhere|Simpleof{line:int;start:int;stop:int}|Multilineof{start:int*int;stop:int*int}(** A data structure to add location data *)type'aext={loc:t;data:'a}letppppf=function|Nowhere->()|Simple{line;start;stop}->Pp.fpppf"l%d.%d−%d"linestartstop|Multiline{start=(l1,c1);stop=(l2,c2)}->Pp.fpppf"l%d.%d−l%d.%d"l1c1l2c2letcreatelocdata={loc;data}letnowheredata={loc=Nowhere;data}letexpand=function|Nowhere->None|Simple{line;start;stop}->Some((line,start),(line,stop))|Multilinem->Some(m.start,m.stop)letcompress=function|Multiline{start;stop}whenfststart=fststop->Simple{line=fststart;start=sndstart;stop=sndstop}|(Simple_|Nowhere|Multiline_)asm->mletmergexy=compress@@matchexpandx,expandywith|None,None->Nowhere|Some(start,stop),None|None,Some(start,stop)|Some(start,_),Some(_,stop)->Multiline{start;stop}letkeep_onexy=matchx,ywith|Nowhere,x|x,Nowhere->x|Simple_asx,Multiline_|Multiline_,(Simple_asx)->x|Simplexasf,(Simpleyass)->ifx.start<y.startthenfelses|Multilinexasf,(Multilineyass)->ifx.start<=y.startthenfelsesletlistl=List.fold_left(funlocx->mergelocx.loc)Nowherelletfmapfx={xwithdata=fx.data}moduleSch=structopenSchematicletraw_sch=Sum["Nowhere",Void;"Simple",[Int;Int;Int];"Multiline",[[Int;Int];[Int;Int]]]lett=letopenTupleincustomraw_sch(function|Nowhere->CE|Simple{line;start;stop}->C(S(Z[line;start;stop]))|Multiline{start=l,c;stop=l',c'}->C(S(S(Z[[l;c];[l';c']]))))(function|CE->Nowhere|CSZ[line;start;stop]->Simple{line;start;stop}|CSSZ[[l;c];[l';c']]->Multiline{start=l,c;stop=l',c'}|_->.)letextinner=letopenTupleincustom[inner;t](funr->[r.data;r.loc])(fun[data;loc]->{data;loc})end