123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321moduleStyle=structtypet=|Loc|Error|Warning|Kwd|Id|Prompt|Hint|Details|Ok|Debug|Success|Ansi_stylesofAnsi_color.Style.tlistletto_dyn=letopenDyninfunction|Loc->variant"Loc"[]|Error->variant"Error"[]|Warning->variant"Warning"[]|Kwd->variant"Kwd"[]|Id->variant"Id"[]|Prompt->variant"Prompt"[]|Hint->variant"Hint"[]|Details->variant"Details"[]|Ok->variant"Ok"[]|Debug->variant"Debug"[]|Success->variant"Success"[]|Ansi_stylesl->variant"Ansi_styles"[listAnsi_color.Style.to_dynl];;letcomparet1t2:Ordering.t=matcht1,t2with|Loc,Loc->Eq|Loc,_->Lt|_,Loc->Gt|Error,Error->Eq|Error,_->Lt|_,Error->Gt|Warning,Warning->Eq|Warning,_->Lt|_,Warning->Gt|Kwd,Kwd->Eq|Kwd,_->Lt|_,Kwd->Gt|Id,Id->Eq|Id,_->Lt|_,Id->Gt|Prompt,Prompt->Eq|Prompt,_->Lt|_,Prompt->Gt|Hint,Hint->Eq|Hint,_->Lt|_,Hint->Gt|Details,Details->Eq|Details,_->Lt|_,Details->Gt|Ok,Ok->Eq|Ok,_->Lt|_,Ok->Gt|Debug,Debug->Eq|Debug,_->Lt|_,Debug->Gt|Success,Success->Eq|Success,_->Lt|_,Success->Gt|Ansi_styles_,Ansi_styles_->Eq;;endmoduleAnnots=structmoduleInfo=structmoduleId=structtype'at={id:'aType_eq.Id.t;name:string}modulePacked=structtype'aunpacked='attypet=Id:'aunpacked->tletequal(Id{id;name})(Idt)=Type_eq.Id.equalidt.id&&String.equalnamet.name;;lethash(Id{id;name})=Tuple.T2.hashType_eq.Id.hashString.hash(id,name)letto_dyn(Id{name;_})=Dyn.variant"Info.Id"[Dyn.stringname]endendtype'ainfo={id:'aId.t;to_dyn:'a->Dyn.t}typepacked_info=E:'ainfo->packed_infoletall:(Id.Packed.t,packed_info)Table.t=Table.create(moduleId.Packed)12(* morally, this should be ['a info], but we need all this circus to make
sure we don't store functions in the map's keys so that it remains
marshabllable *)type'at='aId.tletto_dyn:'a.'at->'a->Dyn.t=fun(typea)(info:at)(a:a)->let(Epacked)=Table.find_exnall(Id.Packed.Idinfo)inmatchType_eq.Id.sameinfo.idpacked.id.idwith|Someeq->packed.to_dyn(Type_eq.casteqa)|None->Code_error.raise"type id's disagree for the same name"["info.name",Dyn.stringinfo.name];;letcreate~nameto_dyn=lettype_id=Type_eq.Id.create()inletid={Id.id=type_id;name}inletinfo={id;to_dyn}inTable.add_exnall(Id.Packed.Idid)(Einfo);id;;endmoduleT=Univ_map.Make(Info)()moduleKey=structincludeT.Keyletcreate~nameto_dyn=create(Info.create~nameto_dyn)endinclude(T:Univ_map.Swithtypet=T.tandmoduleKey:=Key)lethas_embedded_location=Key.create~name:"has-embedded-location"Unit.to_dynletneeds_stack_trace=Key.create~name:"needs-stack-trace"Unit.to_dynletto_dynt=Dyn.Map(letf={T.fold=(fun(info:_Info.t)aacc->(Dyn.stringinfo.name,Info.to_dyninfoa)::acc)}inT.foldt~init:[]~f);;endmodulePrint_config=structtypet=Style.t->Ansi_color.Style.tlistletdefault:t=function|Loc->[`Bold]|Error->[`Bold;`Fg_red]|Warning->[`Bold;`Fg_magenta]|Kwd->[`Bold;`Fg_blue]|Id->[`Bold;`Fg_yellow]|Prompt->[`Bold;`Fg_green]|Hint->[`Italic]|Details->[`Dim]|Ok->[`Fg_green]|Debug->[`Underline;`Fg_bright_cyan]|Success->[`Bold;`Fg_green]|Ansi_stylesl->l;;endtypet={loc:Loc0.toption;paragraphs:Style.tPp.tlist;hints:Style.tPp.tlist;annots:Annots.t;context:stringoption;dir:stringoption}letcompare{loc;paragraphs;hints;annots;context=_;dir=_}t=letopenOrdering.Oinlet=()=Option.compareLoc0.compareloct.locinlet=()=List.compareparagraphst.paragraphs~compare:Poly.compareinlet=()=List.comparehintst.hints~compare:Poly.compareinPoly.compareannotst.annots;;letequalab=Ordering.is_eq(compareab)letmake?loc?prefix?(hints=[])?(annots=Annots.empty)?context?dirparagraphs=letparagraphs=matchprefix,paragraphswith|None,l->l|Somep,[]->[p]|Somep,x::l->Pp.concat~sep:Pp.space[p;x]::lin{loc;hints;paragraphs;annots;context;dir};;letpp{loc;paragraphs;hints;annots=_;context;dir=_}=letopenPp.Oinletparagraphs=matchhintswith|[]->paragraphs|_->List.appendparagraphs(List.maphints~f:(funhint->Pp.tagStyle.Hint(Pp.verbatim"Hint:")++Pp.space++hint))inletparagraphs=List.mapparagraphs~f:Pp.boxinletparagraphs=matchlocwith|None->paragraphs|Someloc->letstart=Loc0.startlocinletstop=Loc0.stoplocinletstart_c=start.pos_cnum-start.pos_bolinletstop_c=stop.pos_cnum-start.pos_bolinletlnum=ifstart.pos_lnum=stop.pos_lnumthenPrintf.sprintf"line %d"start.pos_lnumelsePrintf.sprintf"lines %d-%d"start.pos_lnumstop.pos_lnuminPp.box(Pp.tagStyle.Loc(Pp.textf"File %S, %s, characters %d-%d:"start.pos_fnamelnumstart_cstop_c))::paragraphsinletparagraphs=matchcontextwith|None|Some"default"|Some".sandbox"->paragraphs|Somecontext->Pp.box(Pp.tagStyle.Loc(Pp.textf"Context: %s"context))::paragraphsinPp.vbox(Pp.concat_mapparagraphs~sep:Pp.nop~f:(funpp->Pp.seqppPp.cut));;letprint?(config=Print_config.default)t=Ansi_color.print(Pp.map_tags(ppt)~f:config);;letprerr?(config=Print_config.default)t=Ansi_color.prerr(Pp.map_tags(ppt)~f:config);;(* As found here http://rosettacode.org/wiki/Levenshtein_distance#OCaml *)letlevenshtein_distancest=letm=String.lengthsandn=String.lengthtin(* for all i and j, d.(i).(j) will hold the Levenshtein distance between the
first i characters of s and the first j characters of t *)letd=Array.make_matrix~dimx:(m+1)~dimy:(n+1)0infori=0tomdo(* the distance of any first string to an empty second string *)d.(i).(0)<-idone;forj=0tondo(* the distance of any second string to an empty first string *)d.(0).(j)<-jdone;forj=1tondofori=1tomdoifs.[i-1]=t.[j-1]thend.(i).(j)<-d.(i-1).(j-1)(* no operation required *)elsed.(i).(j)<-min(d.(i-1).(j)+1)(* a deletion *)(min(d.(i).(j-1)+1)(* an insertion *)(d.(i-1).(j-1)+1)(* a substitution *))donedone;d.(m).(n);;letdid_you_means~candidates=letcandidates=List.filtercandidates~f:(funcandidate->letdistance=levenshtein_distancescandidatein0<distance&&distance<3)inmatchcandidateswith|[]->[]|l->[Pp.textf"did you mean %s?"(String.enumerate_orl)];;letto_stringt=letfull_error=Format.asprintf"%a"Pp.to_fmt(pp{twithloc=None})inmatchString.drop_prefix~prefix:"Error:"full_errorwith|None->full_error|Someerror->String.trimerror;;letis_loc_noneloc=matchlocwith|None->true|Someloc->loc=Loc0.none;;lethas_embedded_locationmsg=Annots.memmsg.annotsAnnots.has_embedded_locationlethas_locationmsg=(not(is_loc_nonemsg.loc))||has_embedded_locationmsgletneeds_stack_tracemsg=Annots.memmsg.annotsAnnots.needs_stack_traceletcommandcmd=(* CR-someday rgrinberg: this should be its own tag, but that might bring
some backward compat issues with rpc. *)Pp.concat[Pp.verbatim"'";Pp.tag(Style.Ansi_styles[`Underline])@@Pp.verbatimcmd;Pp.verbatim"'"];;letaligned_message~left:(left_tag,left_string)~right=letopenPp.Oinletleft_padded=Printf.sprintf"%12s"left_stringinPp.tagleft_tag(Pp.verbatimleft_padded)++Pp.char' '++right;;