12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324(**************************************************************************)(* *)(* OCamlFormat *)(* *)(* Copyright (c) Facebook, Inc. and its affiliates. *)(* *)(* This source code is licensed under the MIT license found in *)(* the LICENSE file in the root directory of this source tree. *)(* *)(**************************************************************************)(** Abstract syntax tree term *)openMigrate_astopenExtended_asttypecmt_checker={cmts_before:Location.t->bool;cmts_within:Location.t->bool;cmts_after:Location.t->bool}letcmts_betweens{cmts_before;cmts_after;_}loc1loc2=(cmts_afterloc1&&Source.ends_linesloc1)||cmts_beforeloc2let(init,register_reset,leading_nested_match_parens,parens_ite,ocaml_version,ocp_indent_compat)=letl=ref[]inletleading_nested_match_parens=reffalseinletparens_ite=reffalseinletocaml_version=refOcaml_version.sys_versioninletocp_indent_compat=reffalseinletregisterf=l:=f::!linletinit(conf:Conf.t)=leading_nested_match_parens:=conf.fmt_opts.leading_nested_match_parens.v;parens_ite:=conf.fmt_opts.parens_ite.v;ocaml_version:=conf.opr_opts.ocaml_version.v;ocp_indent_compat:=conf.fmt_opts.ocp_indent_compat.v;List.iter!l~f:(funf->f())in(init,register,leading_nested_match_parens,parens_ite,ocaml_version,ocp_indent_compat)(** [fit_margin c x] returns [true] if and only if [x] does not exceed 1/3 of
the margin. *)letfit_margin(c:Conf.t)x=x*3<c.fmt_opts.margin.v(** [longident_fit_margin c x] returns [true] if and only if [x] does not
exceed 2/3 of the margin. *)letlongident_fit_margin(c:Conf.t)x=x*3<c.fmt_opts.margin.v*2letlongident_is_simplecx=letreclengthx=matchxwith|Longident.Lidentx->String.lengthx|Ldot(x,y)->lengthx+1+String.lengthy|Lapply(x,y)->lengthx+lengthy+3inlongident_fit_marginc(lengthx)(** 'Classes' of expressions which are parenthesized differently. *)typecls=Let_match|Match|Non_apply|Sequence|Then|ThenElse(** Predicates recognizing special symbol identifiers. *)moduleToken=structletis_infix=function|Parser.AMPERAMPER|AMPERSAND|ANDOP_|BAR|BARBAR|COLON|COLONCOLON|COLONEQUAL|DOTDOT|DOTOP_|EQUAL|GREATER|HASHOP_|INFIXOP0_|INFIXOP1_|INFIXOP2_|INFIXOP3_|INFIXOP4_|LESS|LESSMINUS|LETOP_|MINUS|MINUSDOT|MINUSGREATER|PERCENT|PLUS|PLUSDOT|PLUSEQ|SLASH|STAR->true|_->falseendmoduleAttr=structmoduleKey=structtypet=Regular|Item|Floatingletto_string=function|Regular->"@"|Item->"@@"|Floating->"@@@"endletis_doc=function|{attr_name={Location.txt="ocaml.doc"|"ocaml.text";_};_}->true|_->falseendmoduleExt=structmoduleKey=structtypet=Regular|Itemletto_string=functionRegular->"%"|Item->"%%"endendmoduleExp=structletlocationx=x.pexp_loclettest_id~f=function|{pexp_desc=Pexp_ident{txt=i;_};_}->fi|_->falseletis_prefix=test_id~f:Std_longident.is_prefixletis_infix=test_id~f:Std_longident.is_infixletis_monadic_binding=test_id~f:Std_longident.is_monadic_bindingletis_symbol=test_id~f:Std_longident.is_symbolletis_sequenceexp=matchexp.pexp_descwith|Pexp_sequence_->true|Pexp_extension(ext,PStr[{pstr_desc=Pstr_eval(({pexp_desc=Pexp_sequence_;_}ase),[]);_}])whenSource.extension_using_sugar~name:ext~payload:e.pexp_loc->true|_->falselethas_trailing_attributes{pexp_desc;pexp_attributes;_}=matchpexp_descwith|Pexp_fun_|Pexp_function_|Pexp_ifthenelse_|Pexp_match_|Pexp_newtype_|Pexp_try_->false|_->List.existspexp_attributes~f:(Fn.nonAttr.is_doc)letrecis_trivialexp=matchexp.pexp_descwith|Pexp_constant{pconst_desc=Pconst_string(_,_,None);_}->true|Pexp_constant_|Pexp_field_|Pexp_ident_|Pexp_send_->true|Pexp_construct(_,exp)->Option.for_allexp~f:is_trivial|Pexp_prefix(_,e)->is_triviale|Pexp_apply({pexp_desc=Pexp_ident{txt=Lident"not";_};_},[(_,e1)])->is_triviale1|Pexp_variant(_,None)->true|Pexp_array[]|Pexp_list[]->true|Pexp_array[x]|Pexp_list[x]->is_trivialx|_->falseletrecexposed_lefte=matche.pexp_descwith|Pexp_prefix_->true|Pexp_apply(op,_)->exposed_leftop|Pexp_field(e,_)->exposed_lefte|_->false(** [mem_cls cls exp] holds if [exp] is in the named class of expressions
[cls]. *)letmem_clsclsast=match(ast,cls)with|{pexp_desc=Pexp_ifthenelse(_,None);_},(Non_apply|ThenElse)|{pexp_desc=Pexp_ifthenelse_;_},Non_apply|({pexp_desc=Pexp_sequence_;_},(Non_apply|Sequence|Then|ThenElse))|({pexp_desc=(Pexp_function_|Pexp_match_|Pexp_try_|Pexp_fun(_,_,_,{pexp_desc=Pexp_constraint_;_}));_},(Match|Let_match|Non_apply))|({pexp_desc=(Pexp_fun_|Pexp_let_|Pexp_letop_|Pexp_letexception_|Pexp_letmodule_|Pexp_newtype_|Pexp_open_|Pexp_letopen_);_},(Let_match|Non_apply))->true|_->falseendmodulePat=structletlocationx=x.ppat_locletis_any=function{ppat_desc=Ppat_any;_}->true|_->falseletis_simple{ppat_desc;_}=matchppat_descwith|Ppat_any|Ppat_constant_|Ppat_var_|Ppat_variant(_,None)|Ppat_construct(_,None)->true|(Ppat_variant(_,Somep)|Ppat_construct(_,Some([],p)))whenis_anyp->true|Ppat_consplwhenList.for_allpl~f:is_any->true|_->falselethas_trailing_attributes{ppat_desc;ppat_attributes;_}=matchppat_descwith|Ppat_construct(_,None)|Ppat_constant_|Ppat_any|Ppat_var_|Ppat_variant(_,None)|Ppat_record_|Ppat_array_|Ppat_list_|Ppat_type_|Ppat_unpack_|Ppat_extension_|Ppat_open_|Ppat_interval_->false|_->List.existsppat_attributes~f:(Fn.nonAttr.is_doc)endletdoc_atrs?(acc=[])atrs=letdocs,rev_atrs=List.foldatrs~init:(acc,[])~f:(fun(docs,rev_atrs)atr->letopenAsttypesinmatchatrwith|{attr_name={txt=("ocaml.doc"|"ocaml.text")astxt;loc={loc_ghost=true;_}};attr_payload=PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant{pconst_desc=Pconst_string(doc,_,None);_};pexp_loc=loc;pexp_attributes=[];_},[]);_}];_}->(match(txt,docs)with|"ocaml.doc",(_,false)::_->(* cannot put two doc comment next to each other *)(docs,atr::rev_atrs)|_->(({txt=doc;loc},String.equal"ocaml.text"txt)::docs,rev_atrs))|_->(docs,atr::rev_atrs))inletdocs=matchdocswith[]->None|l->Some(List.revl)in(docs,List.revrev_atrs)letrecmty_is_simplex=matchx.pmty_descwith|Pmty_ident_|Pmty_alias_|Pmty_signature[]->true|Pmty_signature(_::_)|Pmty_with(_,_::_::_)|Pmty_extension_|Pmty_functor(_,_)->false|Pmty_gen(_,t)->mty_is_simplet|Pmty_typeofe->mod_is_simplee|Pmty_with(t,([]|[_]))->mty_is_simpletandmod_is_simplex=matchx.pmod_descwith|Pmod_ident_|Pmod_unpack_|Pmod_structure[]|Pmod_hole->true|Pmod_structure(_::_)|Pmod_extension_|Pmod_functor(_,_)->false|Pmod_constraint(e,t)->mod_is_simplee&&mty_is_simplet|Pmod_apply(a,b)->mod_is_simplea&&mod_is_simpleb|Pmod_apply_unit(a,_)->mod_is_simpleamoduleMty=structletis_simple=mty_is_simplelethas_trailing_attributes{pmty_attributes;_}=List.existspmty_attributes~f:(Fn.nonAttr.is_doc)endmoduleMod=structletis_simple=mod_is_simplelethas_trailing_attributes{pmod_attributes;_}=List.existspmod_attributes~f:(Fn.nonAttr.is_doc)endmoduleCty=structletrecis_simplex=matchx.pcty_descwith|Pcty_constr_|Pcty_signature{pcsig_fields=[];_}->true|Pcty_signature{pcsig_fields=_::_;_}|Pcty_open_|Pcty_extension_->false|Pcty_arrow(_,t)->is_simpletendmoduleCl=structletrecis_simplex=matchx.pcl_descwith|Pcl_constr_|Pcl_structure{pcstr_fields=[];_}->true|Pcl_structure{pcstr_fields=_::_;_}|Pcl_let_|Pcl_open_|Pcl_extension_->false|Pcl_apply(e,_)|Pcl_fun(_,_,_,e)->is_simplee|Pcl_constraint(e,t)->is_simplee&&Cty.is_simplet(** [mem_cls cls cl] holds if [cl] is in the named class of expressions
[cls]. *)letmem_clsclsast=match(ast,cls)with|{pcl_desc=Pcl_fun_;_},Non_apply->true|_->falseendmoduleTyd=structletis_simplex=matchx.ptype_kindwith|Ptype_abstract|Ptype_open->true|Ptype_variant_|Ptype_record_->falseendmoduleStructure_item=structlethas_docitm=matchitm.pstr_descwith|Pstr_attributeatr->Attr.is_docatr|Pstr_eval(_,atrs)|Pstr_value{pvbs_bindings={pvb_attributes=atrs;_}::_;_}|Pstr_primitive{pval_attributes=atrs;_}|Pstr_type(_,{ptype_attributes=atrs;_}::_)|Pstr_typext{ptyext_attributes=atrs;_}|Pstr_recmodule({pmb_expr={pmod_attributes=atrs;_};_}::_)|Pstr_modtype{pmtd_attributes=atrs;_}|Pstr_open{popen_attributes=atrs;_}|Pstr_extension(_,atrs)|Pstr_class_type({pci_attributes=atrs;_}::_)|Pstr_class({pci_attributes=atrs;_}::_)->List.exists~f:Attr.is_docatrs|Pstr_include{pincl_mod={pmod_attributes=atrs1;_};pincl_attributes=atrs2;_}|Pstr_exception{ptyexn_attributes=atrs1;ptyexn_constructor={pext_attributes=atrs2;_};_}|Pstr_module{pmb_attributes=atrs1;pmb_expr={pmod_attributes=atrs2;_};_}->List.exists~f:Attr.is_docatrs1||List.exists~f:Attr.is_docatrs2|Pstr_value{pvbs_bindings=[];_}|Pstr_type(_,[])|Pstr_recmodule[]|Pstr_class_type[]|Pstr_class[]->falseletis_simple(itm,(c:Conf.t))=matchc.fmt_opts.module_item_spacing.vwith|`Compact|`Preserve->Location.is_single_lineitm.pstr_locc.fmt_opts.margin.v|`Sparse->(matchitm.pstr_descwith|Pstr_include{pincl_mod=me;_}|Pstr_module{pmb_expr=me;_}->letrecis_simple_modme=matchme.pmod_descwith|Pmod_apply(me1,me2)->is_simple_modme1&&is_simple_modme2|Pmod_functor(_,me)|Pmod_apply_unit(me,_)->is_simple_modme|Pmod_identi->longident_is_simpleci.txt|_->falseinis_simple_modme|Pstr_open{popen_expr={pmod_desc=Pmod_identi;_};_}->longident_is_simpleci.txt|_->false)letallow_adjacent(itmI,cI)(itmJ,cJ)=matchConf.(cI.fmt_opts.module_item_spacing.v,cJ.fmt_opts.module_item_spacing.v)with|`Compact,`Compact->(match(itmI.pstr_desc,itmJ.pstr_desc)with|Pstr_eval_,Pstr_eval_|Pstr_value_,Pstr_value_|Pstr_primitive_,Pstr_primitive_|(Pstr_type_|Pstr_typext_),(Pstr_type_|Pstr_typext_)|Pstr_exception_,Pstr_exception_|((Pstr_module_|Pstr_recmodule_|Pstr_open_|Pstr_include_),(Pstr_module_|Pstr_recmodule_|Pstr_open_|Pstr_include_))|Pstr_modtype_,Pstr_modtype_|Pstr_class_,Pstr_class_|Pstr_class_type_,Pstr_class_type_|Pstr_attribute_,Pstr_attribute_|Pstr_extension_,Pstr_extension_->true|_->false)|_->trueletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.pstr_loci2.pstr_loc||has_doci1||has_doci2||matchConf.(c1.fmt_opts.module_item_spacing.v,c2.fmt_opts.module_item_spacing.v)with|`Preserve,`Preserve->Source.empty_line_betweensi1.pstr_loc.loc_endi2.pstr_loc.loc_start|_->(not(is_simple(i1,c1)))||(not(is_simple(i2,c2)))||not(allow_adjacent(i1,c1)(i2,c2))endmoduleSignature_item=structlethas_docitm=matchitm.psig_descwith|Psig_attributeatr->Attr.is_docatr|Psig_value{pval_attributes=atrs;_}|Psig_type(_,{ptype_attributes=atrs;_}::_)|Psig_typesubst({ptype_attributes=atrs;_}::_)|Psig_typext{ptyext_attributes=atrs;_}|Psig_modtype{pmtd_attributes=atrs;_}|Psig_modtypesubst{pmtd_attributes=atrs;_}|Psig_modsubst{pms_attributes=atrs;_}|Psig_open{popen_attributes=atrs;_}|Psig_extension(_,atrs)|Psig_class_type({pci_attributes=atrs;_}::_)|Psig_class({pci_attributes=atrs;_}::_)->List.exists~f:Attr.is_docatrs|Psig_recmodule({pmd_type={pmty_attributes=atrs1;_};pmd_attributes=atrs2;_}::_)|Psig_include{pincl_mod={pmty_attributes=atrs1;_};pincl_attributes=atrs2;_}|Psig_exception{ptyexn_attributes=atrs1;ptyexn_constructor={pext_attributes=atrs2;_};_}|Psig_module{pmd_attributes=atrs1;pmd_type={pmty_attributes=atrs2;_};_}->List.exists~f:Attr.is_docatrs1||List.exists~f:Attr.is_docatrs2|Psig_type(_,[])|Psig_typesubst[]|Psig_recmodule[]|Psig_class_type[]|Psig_class[]->falseletis_simple(itm,(c:Conf.t))=matchc.fmt_opts.module_item_spacing.vwith|`Compact|`Preserve->Location.is_single_lineitm.psig_locc.fmt_opts.margin.v|`Sparse->(matchitm.psig_descwith|Psig_open{popen_expr=i;_}|Psig_module{pmd_type={pmty_desc=Pmty_aliasi;_};_}|Psig_modsubst{pms_manifest=i;_}->longident_is_simpleci.txt|_->false)letallow_adjacent(itmI,cI)(itmJ,cJ)=matchConf.(cI.fmt_opts.module_item_spacing.v,cJ.fmt_opts.module_item_spacing.v)with|`Compact,`Compact->(match(itmI.psig_desc,itmJ.psig_desc)with|Psig_value_,Psig_value_|((Psig_type_|Psig_typesubst_|Psig_typext_),(Psig_type_|Psig_typesubst_|Psig_typext_))|Psig_exception_,Psig_exception_|((Psig_module_|Psig_modsubst_|Psig_recmodule_|Psig_open_|Psig_include_),(Psig_module_|Psig_modsubst_|Psig_recmodule_|Psig_open_|Psig_include_))|Psig_modtype_,Psig_modtype_|Psig_class_,Psig_class_|Psig_class_type_,Psig_class_type_|Psig_attribute_,Psig_attribute_|Psig_extension_,Psig_extension_->true|_->false)|_->trueletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.psig_loci2.psig_loc||has_doci1||has_doci2||matchConf.(c1.fmt_opts.module_item_spacing.v,c2.fmt_opts.module_item_spacing.v)with|`Preserve,`Preserve->Source.empty_line_betweensi1.psig_loc.loc_endi2.psig_loc.loc_start|_->(not(is_simple(i1,c1)))||(not(is_simple(i2,c2)))||not(allow_adjacent(i1,c1)(i2,c2))endmoduleLb=structlethas_docitm=List.exists~f:Attr.is_docitm.pvb_attributesletis_simple(i,(c:Conf.t))=Poly.(c.fmt_opts.module_item_spacing.v=`Compact)&&Location.is_single_linei.pvb_locc.fmt_opts.margin.vletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.pvb_loci2.pvb_loc||has_doci1||has_doci2||(not(is_simple(i1,c1)))||not(is_simple(i2,c2))endmoduleMb=structlethas_docitm=List.exists~f:Attr.is_docitm.pmb_attributesletis_simple(i,(c:Conf.t))=Poly.(c.fmt_opts.module_item_spacing.v=`Compact)&&Location.is_single_linei.pmb_locc.fmt_opts.margin.vletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.pmb_loci2.pmb_loc||has_doci1||has_doci2||(not(is_simple(i1,c1)))||not(is_simple(i2,c2))endmoduleMd=structlethas_docitm=List.exists~f:Attr.is_docitm.pmd_attributesletis_simple(i,(c:Conf.t))=Poly.(c.fmt_opts.module_item_spacing.v=`Compact)&&Location.is_single_linei.pmd_locc.fmt_opts.margin.vletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.pmd_loci2.pmd_loc||has_doci1||has_doci2||(not(is_simple(i1,c1)))||not(is_simple(i2,c2))endmoduleTd=structlethas_docitm=List.exists~f:Attr.is_docitm.ptype_attributesletis_simple(i,(c:Conf.t))=matchc.fmt_opts.module_item_spacing.vwith|`Compact|`Preserve->Location.is_single_linei.ptype_locc.fmt_opts.margin.v|`Sparse->falseletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.ptype_loci2.ptype_loc||has_doci1||has_doci2||matchConf.(c1.fmt_opts.module_item_spacing.v,c2.fmt_opts.module_item_spacing.v)with|`Preserve,`Preserve->Source.empty_line_betweensi1.ptype_loc.loc_endi2.ptype_loc.loc_start|_->(not(is_simple(i1,c1)))||not(is_simple(i2,c2))endmoduleClass_field=structlethas_docitm=List.exists~f:Attr.is_docitm.pcf_attributes||matchitm.pcf_descwith|Pcf_attributeatr->Attr.is_docatr|_->falseletis_simple(itm,(c:Conf.t))=matchc.fmt_opts.module_item_spacing.vwith|`Compact|`Preserve->Location.is_single_lineitm.pcf_locc.fmt_opts.margin.v|`Sparse->falseletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.pcf_loci2.pcf_loc||has_doci1||has_doci2||matchConf.(c1.fmt_opts.module_item_spacing.v,c2.fmt_opts.module_item_spacing.v)with|`Preserve,`Preserve->Source.empty_line_betweensi1.pcf_loc.loc_endi2.pcf_loc.loc_start|_->(not(is_simple(i1,c1)))||not(is_simple(i2,c2))endmoduleClass_type_field=structlethas_docitm=List.exists~f:Attr.is_docitm.pctf_attributes||matchitm.pctf_descwith|Pctf_attributeatr->Attr.is_docatr|_->falseletis_simple(itm,(c:Conf.t))=matchc.fmt_opts.module_item_spacing.vwith|`Compact|`Preserve->Location.is_single_lineitm.pctf_locc.fmt_opts.margin.v|`Sparse->falseletbreak_betweenscc(i1,c1)(i2,c2)=cmts_betweenscci1.pctf_loci2.pctf_loc||has_doci1||has_doci2||matchConf.(c1.fmt_opts.module_item_spacing.v,c2.fmt_opts.module_item_spacing.v)with|`Preserve,`Preserve->Source.empty_line_betweensi1.pctf_loc.loc_endi2.pctf_loc.loc_start|_->(not(is_simple(i1,c1)))||not(is_simple(i2,c2))endtypetoplevel_item=[`Itemofstructure_item|`Directiveoftoplevel_directive](** Ast terms of various forms. *)moduleT=structtypet=|Pldofpayload|Typofcore_type|Tdoftype_declaration|Ctyofclass_type|Patofpattern|Expofexpression|Lbofvalue_binding|Mbofmodule_binding|Mdofmodule_declaration|Clofclass_expr|Mtyofmodule_type|Modofmodule_expr|Sigofsignature_item|Strofstructure_item|Clfofclass_field|Ctfofclass_type_field|Tlioftoplevel_item|Top|Repletdumpfs=function|Pldl->Format.fprintffs"Pld:@\n%a"Printast.payloadl|Typt->Format.fprintffs"Typ:@\n%a"Printast.core_typet|Tdt->Format.fprintffs"Td:@\n%a"Printast.type_declarationt|Patp->Format.fprintffs"Pat:@\n%a"Printast.patternp|Expe->Format.fprintffs"Exp:@\n%a"Printast.expressione|Lbb->Format.fprintffs"Lb:@\n%a"Printast.value_bindingb|Mbm->Format.fprintffs"Mb:@\n%a"Printast.module_bindingm|Mdm->Format.fprintffs"Md:@\n%a"Printast.module_declarationm|Clcl->Format.fprintffs"Cl:@\n%a"Printast.class_exprcl|Mtymt->Format.fprintffs"Mty:@\n%a"Printast.module_typemt|Ctycty->Format.fprintffs"Cty:@\n%a"Printast.class_typecty|Modm->Format.fprintffs"Mod:@\n%a"Printast.module_exprm|Sigs->Format.fprintffs"Sig:@\n%a"Printast.signature_items|Strs|Tli(`Items)->Format.fprintffs"Str:@\n%a"Printast.structure_items|Clfclf->Format.fprintffs"Clf:@\n%a@\n"Printast.class_fieldclf|Ctfctf->Format.fprintffs"Ctf:@\n%a@\n"Printast.class_type_fieldctf|Tli(`Directived)->Format.fprintffs"Dir:@\n%a"Printast.top_phrase(Ptop_dird)|Top->Format.pp_print_stringfs"Top"|Rep->Format.pp_print_stringfs"Rep"endincludeTletis_top=functionTop->true|_->falseletattributes=function|Pld_->[]|Typx->x.ptyp_attributes|Tdx->x.ptype_attributes|Ctyx->x.pcty_attributes|Patx->x.ppat_attributes|Expx->x.pexp_attributes|Lbx->x.pvb_attributes|Mbx->x.pmb_attributes|Mdx->x.pmd_attributes|Clx->x.pcl_attributes|Mtyx->x.pmty_attributes|Modx->x.pmod_attributes|Sig_->[]|Str_->[]|Clfx->x.pcf_attributes|Ctfx->x.pctf_attributes|Top->[]|Tli_->[]|Rep->[]letlocation=function|Pld_->Location.none|Typx->x.ptyp_loc|Tdx->x.ptype_loc|Ctyx->x.pcty_loc|Patx->x.ppat_loc|Expx->x.pexp_loc|Lbx->x.pvb_loc|Mbx->x.pmb_loc|Mdx->x.pmd_loc|Clx->x.pcl_loc|Mtyx->x.pmty_loc|Modx->x.pmod_loc|Sigx->x.psig_loc|Strx->x.pstr_loc|Clfx->x.pcf_loc|Ctfx->x.pctf_loc|Tli(`Itemx)->x.pstr_loc|Tli(`Directivex)->x.pdir_loc|Top->Location.none|Rep->Location.noneletbreak_between_modulesscc(i1,c1)(i2,c2)=lethas_docitm=List.exists~f:Attr.is_doc(attributesitm)inletis_simple(itm,(c:Conf.t))=Location.is_single_line(locationitm)c.fmt_opts.margin.vincmts_betweenscc(locationi1)(locationi2)||has_doci1||has_doci2||(not(is_simple(i1,c1)))||not(is_simple(i2,c2))letbreak_betweenscc(i1,c1)(i2,c2)=match(i1,i2)with|Stri1,Stri2->Structure_item.break_betweenscc(i1,c1)(i2,c2)|Sigi1,Sigi2->Signature_item.break_betweenscc(i1,c1)(i2,c2)|Lbi1,Lbi2->Lb.break_betweenscc(i1,c1)(i2,c2)|Mbi1,Mbi2->Mb.break_betweenscc(i1,c1)(i2,c2)|Mdi1,Mdi2->Md.break_betweenscc(i1,c1)(i2,c2)|Mty_,Mty_->break_between_modulesscc(i1,c1)(i2,c2)|Mod_,Mod_->break_between_modulesscc(i1,c1)(i2,c2)|Tli(`Itemi1),Tli(`Itemi2)->Structure_item.break_betweenscc(i1,c1)(i2,c2)|Tli(`Directive_),Tli(`Directive_)|Tli_,Tli_->true(* always break between an item and a directive *)|Clfi1,Clfi2->Class_field.break_betweenscc(i1,c1)(i2,c2)|Ctfi1,Ctfi2->Class_type_field.break_betweenscc(i1,c1)(i2,c2)|Tdi1,Tdi2->Td.break_betweenscc(i1,c1)(i2,c2)|_->assertfalse(** Term-in-context, [{ctx; ast}] records that [ast] is (considered to be) an
immediate sub-term of [ctx] as assumed by the operations in
[Requires_sub_terms]. *)modulerecIn_ctx:sigtype'axt={ctx:T.t;ast:'a}valsub_ast:ctx:T.t->T.t->T.txtvalsub_typ:ctx:T.t->core_type->core_typextvalsub_td:ctx:T.t->type_declaration->type_declarationxtvalsub_cty:ctx:T.t->class_type->class_typextvalsub_pat:ctx:T.t->pattern->patternxtvalsub_exp:ctx:T.t->expression->expressionxtvalsub_cl:ctx:T.t->class_expr->class_exprxtvalsub_cf:ctx:T.t->class_field->class_fieldxtvalsub_ctf:ctx:t->class_type_field->class_type_fieldxtvalsub_mty:ctx:T.t->module_type->module_typextvalsub_mod:ctx:T.t->module_expr->module_exprxtvalsub_md:ctx:T.t->module_declaration->module_declarationxtvalsub_mb:ctx:T.t->module_binding->module_bindingxtvalsub_sig:ctx:T.t->signature_item->signature_itemxtvalsub_str:ctx:T.t->structure_item->structure_itemxtend=structopenRequires_sub_termstype'axt={ctx:T.t;ast:'a}letsub_ast~ctxast={ctx;ast}letsub_typ~ctxtyp=checkparenze_typ{ctx;ast=typ}letsub_td~ctxtd={ctx;ast=td}letsub_cty~ctxcty={ctx;ast=cty}letsub_pat~ctxpat=checkparenze_pat{ctx;ast=pat}letsub_exp~ctxexp=checkparenze_exp{ctx;ast=exp}letsub_cl~ctxcl={ctx;ast=cl}letsub_cf~ctxcf={ctx;ast=cf}letsub_ctf~ctxctf={ctx;ast=ctf}letsub_mty~ctxmty={ctx;ast=mty}letsub_mod~ctxmod_={ctx;ast=mod_}letsub_md~ctxmd={ctx;ast=md}letsub_mb~ctxmb={ctx;ast=mb}letsub_sig~ctxsig_={ctx;ast=sig_}letsub_str~ctxstr={ctx;ast=str}end(** Operations determining precedence and necessary parenthesization of terms
based on their super-terms. *)andRequires_sub_terms:sigvalis_simple:Conf.t->(expressionIn_ctx.xt->int)->expressionIn_ctx.xt->boolvalexposed_right_exp:cls->expression->boolvalprec_ast:T.t->Prec.toptionvalparenze_typ:core_typeIn_ctx.xt->boolvalparenze_mty:module_typeIn_ctx.xt->boolvalparenze_mod:module_exprIn_ctx.xt->boolvalparenze_cty:class_typeIn_ctx.xt->boolvalparenze_cl:class_exprIn_ctx.xt->boolvalparenze_pat:patternIn_ctx.xt->boolvalparenze_exp:expressionIn_ctx.xt->boolvalparenze_nested_exp:expressionIn_ctx.xt->boolend=structopenIn_ctx(* This module uses physical equality extensively to detect sub-terms. *)let(==)=Base.phys_equalletdumpctxastfs=Format.fprintffs"ast: %a@\nctx: %a@\n"T.dumpastT.dumpctxletassert_no_raise~f~dumpx=assert(tryignore(fx);truewithexc->letbt=Stdlib.Printexc.get_backtrace()indumpxFormat.err_formatter;Format.eprintf"%s%!"bt;raiseexc)(** Predicates to check the claimed sub-term relation. *)letcheck_typ{ctx;ast=typ}=letftI=typ==tIinletfst_f(tI,_)=typ==tIinletsnd_f(_,tI)=typ==tIinletcheck_cstr=function|Pcstr_tuplet1N->List.existst1N~f|Pcstr_record(_,ld1N)->List.existsld1N~f:(fun{pld_type;_}->typ==pld_type)inletcheck_ext{pext_kind;_}=matchpext_kindwith|Pext_decl(_,cstr,t0)->check_cstrcstr||Option.existst0~f|_->falseinletcheck_typext{ptyext_params;ptyext_constructors;_}=List.existsptyext_params~f:fst_f||List.existsptyext_constructors~f:check_extinletcheck_typexn{ptyexn_constructor;_}=check_extptyexn_constructorinletcheck_class_typel=List.existsl~f:(fun{pci_expr={pcty_desc;_};pci_params;_}->List.existspci_params~f:(fun(t,_)->t==typ)||matchpcty_descwith|Pcty_constr(_,l)->List.existsl~f:(funx->x==typ)|Pcty_arrow(t,_)->List.existst~f:(funx->x.pap_type==typ)|_->false)inletcheck_pvbpvb=matchpvb.pvb_constraintwith|Some(Pvc_constraint{typ=typ';_})->typ'==typ|Some(Pvc_coercion{ground;coercion})->coercion==typ||Option.existsground~f:(funx->x==typ)|None->falseinletcheck_let_bindingslbs=List.existslbs.pvbs_bindings~f:check_pvbinmatchctxwith|Pld(PTypt1)->assert(typ==t1)|Pld_->assertfalse|Typctx->(matchctx.ptyp_descwith|Ptyp_extension_->()|Ptyp_any|Ptyp_var_->assertfalse|Ptyp_alias(t1,_)|Ptyp_poly(_,t1)->assert(typ==t1)|Ptyp_arrow(t,t2)->assert(List.existst~f:(funx->typ==x.pap_type)||typ==t2)|Ptyp_tuplet1N|Ptyp_constr(_,t1N)->assert(List.existst1N~f)|Ptyp_variant(r1N,_,_)->assert(List.existsr1N~f:(function|{prf_desc=Rtag(_,_,t1N);_}->List.existst1N~f|{prf_desc=Rinheritt1;_}->typ==t1))|Ptyp_package(_,it1N)->assert(List.existsit1N~f:snd_f)|Ptyp_object(fields,_)->assert(List.existsfields~f:(function|{pof_desc=Otag(_,t1);_}->typ==t1|{pof_desc=Oinheritt1;_}->typ==t1))|Ptyp_class(_,l)->assert(List.existsl~f))|Td{ptype_params;ptype_cstrs;ptype_kind;ptype_manifest;_}->assert(List.existsptype_params~f:fst_f||List.existsptype_cstrs~f:(fun(t1,t2,_)->typ==t1||typ==t2)||(matchptype_kindwith|Ptype_variantcd1N->List.existscd1N~f:(fun{pcd_args;pcd_res;_}->check_cstrpcd_args||Option.existspcd_res~f)|Ptype_recordld1N->List.existsld1N~f:(fun{pld_type;_}->typ==pld_type)|_->false)||Option.existsptype_manifest~f)|Cty{pcty_desc;_}->assert(matchpcty_descwith|Pcty_constr(_,l)->List.existsl~f|Pcty_arrow(t,_)->List.existst~f:(funx->x.pap_type==typ)|Pcty_open_->false|Pcty_extension_->false|Pcty_signature{pcsig_self;_}->Option.existspcsig_self~f)|Patctx->(matchctx.ppat_descwith|Ppat_constraint(_,t1)->assert(typ==t1)|Ppat_extension(_,PTypt)->assert(typ==t)|Ppat_unpack(_,Some(_,l))->assert(List.existsl~f:(fun(_,t)->typ==t))|Ppat_record(l,_)->assert(List.existsl~f:(fun(_,t,_)->Option.existst~f))|_->assertfalse)|Expctx->(matchctx.pexp_descwith|Pexp_pack(_,Some(_,it1N))->assert(List.existsit1N~f:snd_f)|Pexp_constraint(_,t1)|Pexp_coerce(_,None,t1)|Pexp_poly(_,Somet1)|Pexp_extension(_,PTypt1)->assert(typ==t1)|Pexp_coerce(_,Somet1,t2)->assert(typ==t1||typ==t2)|Pexp_letexception(ext,_)->assert(check_extext)|Pexp_object_->assertfalse|Pexp_record(en1,_)->assert(List.existsen1~f:(fun(_,(t1,t2),_)->Option.existst1~f||Option.existst2~f))|Pexp_let(lbs,_)->assert(check_let_bindingslbs)|_->assertfalse)|Lb_->assertfalse|Mb_->assertfalse|Md_->assertfalse|Cl{pcl_desc;_}->assert(matchpcl_descwith|Pcl_constr(_,l)->List.existsl~f|Pcl_constraint_->false|Pcl_let(lbs,_)->check_let_bindingslbs|Pcl_apply_->false|Pcl_fun_->false|Pcl_open_->false|Pcl_extension_->false|Pcl_structure_->false)|Mty_->assertfalse|Modctx->(matchctx.pmod_descwith|Pmod_unpack(_,ty1,ty2)->letf(_,cstrs)=List.existscstrs~f:(fun(_,x)->fx)inassert(Option.existsty1~f||Option.existsty2~f)|_->assertfalse)|Sigctx->(matchctx.psig_descwith|Psig_value{pval_type=t1;_}->assert(typ==t1)|Psig_type(_,_)->assertfalse|Psig_typesubst_->assertfalse|Psig_typexttypext->assert(check_typexttypext)|Psig_exceptionext->assert(check_typexnext)|Psig_class_typel->assert(check_class_typel)|Psig_classl->assert(check_class_typel)|_->assertfalse)|Strctx->(matchctx.pstr_descwith|Pstr_primitive{pval_type=t1;_}->assert(typ==t1)|Pstr_type(_,_)->assertfalse|Pstr_typexttypext->assert(check_typexttypext)|Pstr_exceptionext->assert(check_typexnext)|Pstr_classl->assert(List.existsl~f:(fun{pci_expr={pcl_desc;_};pci_params;_}->List.existspci_params~f:(fun(t,_)->t==typ)||matchpcl_descwith|Pcl_constr(_,l)->List.existsl~f:(funx->x==typ)|_->false))|Pstr_class_typel->assert(check_class_typel)|Pstr_extension((_,PTypt),_)->assert(t==typ)|Pstr_extension(_,_)->assertfalse|Pstr_value{pvbs_bindings;_}->letcheck_pvbpvb=matchpvb.pvb_constraintwith|Some(Pvc_constraint{typ=typ';_})->typ'==typ|Some(Pvc_coercion{ground;coercion})->coercion==typ||Option.existsground~f:(funx->x==typ)|None->falseinassert(List.existspvbs_bindings~f:check_pvb)|_->assertfalse)|Clf{pcf_desc;_}->assert(matchpcf_descwith|Pcf_inherit(_,_,_)->false|Pcf_val(_,_,Cfk_virtualt)->typ==t|Pcf_val(_,_,Cfk_concrete(_,{pexp_desc=Pexp_constraint(_,t);_}))->typ==t|Pcf_val(_,_,Cfk_concrete_)->false|Pcf_method(_,_,Cfk_virtualt)->typ==t|Pcf_method(_,_,Cfk_concrete(_,{pexp_desc=Pexp_constraint(_,t);_}))->typ==t|Pcf_method(_,_,Cfk_concrete(_,{pexp_desc=Pexp_poly(e,topt);_}))->letrecloop=function|{pexp_desc=Pexp_newtype(_,e);_}->loope|{pexp_desc=Pexp_constraint(_,t);_}->t==typ|{pexp_desc=Pexp_fun(_,_,_,e);_}->loope|_->falsein(matchtoptwithNone->false|Somet->typ==t)||loope|Pcf_method(_,_,Cfk_concrete_)->false|Pcf_constraint(t1,t2)->t1==typ||t2==typ|Pcf_initializer_|Pcf_attribute_|Pcf_extension_->false)|Ctf{pctf_desc;_}->assert(matchpctf_descwith|Pctf_constraint(t1,t2)->t1==typ||t2==typ|Pctf_val(_,_,t)->t==typ|Pctf_method(_,_,t)->t==typ|Pctf_inherit_->false|Pctf_attribute_->false|Pctf_extension_->false)|Top|Tli_|Rep->assertfalseletassert_check_typxtyp=letdump{ctx;ast=typ}=dumpctx(Typtyp)inassert_no_raise~f:check_typ~dumpxtypletcheck_cty{ctx;ast=cty}=letcheck_class_typel=List.existsl~f:(fun{pci_expr;_}->letrecloopx=x==cty||matchx.pcty_descwithPcty_arrow(_,x)->loopx|_->falseinlooppci_expr)inmatch(ctx:t)with|Exp_->assertfalse|Lb_->assertfalse|Mb_->assertfalse|Md_->assertfalse|Pld_->assertfalse|Strctx->(matchctx.pstr_descwith|Pstr_class_typel->assert(check_class_typel)|Pstr_classl->assert(List.existsl~f:(fun{pci_expr;_}->letrecloopx=matchx.pcl_descwith|Pcl_fun(_,_,_,x)->loopx|Pcl_constraint(_,x)->x==cty|_->falseinlooppci_expr))|_->assertfalse)|Sigctx->(matchctx.psig_descwith|Psig_class_typel->assert(check_class_typel)|Psig_classl->assert(check_class_typel)|_->assertfalse)|Cty{pcty_desc;_}->(matchpcty_descwith|Pcty_arrow(_,t)->assert(t==cty)|Pcty_signature_->assertfalse|Pcty_open(_,t)->assert(t==cty)|Pcty_constr_->assertfalse|Pcty_extension_->assertfalse)|Top->assertfalse|Tli_->assertfalse|Typ_->assertfalse|Td_->assertfalse|Pat_->assertfalse|Clctx->assert(matchctx.pcl_descwith|Pcl_fun(_,_,_,_)->false|Pcl_constr_->false|Pcl_structure_->false|Pcl_apply_->false|Pcl_let(_,_)->false|Pcl_constraint(_,x)->x==cty|Pcl_extension_->false|Pcl_open_->false)|Clf_->assertfalse|Ctf{pctf_desc;_}->assert(matchpctf_descwith|Pctf_inheritt->t==cty|Pctf_val_->false|Pctf_method_->false|Pctf_constraint_->false|Pctf_attribute_->false|Pctf_extension_->false)|Mty_->assertfalse|Mod_->assertfalse|Rep->assertfalseletassert_check_ctyxcty=letdump{ctx;ast=cty}=dumpctx(Ctycty)inassert_no_raise~f:check_cty~dumpxctyletcheck_cl{ctx;ast=cl}=match(ctx:t)with|Exp_->assertfalse|Lb_->assertfalse|Mb_->assertfalse|Md_->assertfalse|Pld_->assertfalse|Strctx->(matchctx.pstr_descwith|Pstr_classl->assert(List.existsl~f:(fun{pci_expr;_}->letrecloopx=cl==x||matchx.pcl_descwith|Pcl_fun(_,_,_,x)->loopx|Pcl_constraint(x,_)->loopx|_->falseinlooppci_expr))|_->assertfalse)|Sig_->assertfalse|Cty_->assertfalse|Top->assertfalse|Tli_->assertfalse|Typ_->assertfalse|Td_->assertfalse|Pat_->assertfalse|Cl{pcl_desc;_}->assert(matchpcl_descwith|Pcl_structure_->false|Pcl_fun(_,_,_,x)->x==cl|Pcl_apply(x,_)->x==cl|Pcl_let(_,x)->x==cl|Pcl_constraint(x,_)->x==cl|Pcl_open(_,x)->x==cl|Pcl_constr_->false|Pcl_extension_->false)|Clf{pcf_desc;_}->assert(matchpcf_descwithPcf_inherit(_,x,_)->x==cl|_->false)|Ctf_->assertfalse|Mty_->assertfalse|Mod_->assertfalse|Rep->assertfalseletassert_check_clxcl=letdump{ctx;ast=cl}=dumpctx(Clcl)inassert_no_raise~f:check_cl~dumpxclletcheck_pat{ctx;ast=pat}=letcheck_extensions=functionPPat(p,_)->p==pat|_->falseinletcheck_subpatppat=ppat==pat||matchppat.ppat_descwith|Ppat_constraint(p,_)->p==pat|_->falseinletcheck_bindingsl=List.existsl~f:(fun{pvb_pat;_}->check_subpatpvb_pat)inmatchctxwith|Pld(PPat(p1,_))->assert(p1==pat)|Pld_->assertfalse|Typctx->(matchctx.ptyp_descwith|Ptyp_extension(_,ext)->assert(check_extensionsext)|_->assertfalse)|Td_->assertfalse|Patctx->(letfpI=pI==patinmatchctx.ppat_descwith|Ppat_arrayp1N|Ppat_listp1N|Ppat_tuplep1N|Ppat_consp1N->assert(List.existsp1N~f)|Ppat_record(p1N,_)->assert(List.existsp1N~f:(fun(_,_,x)->Option.existsx~f))|Ppat_orl->assert(List.exists~f:(funp->p==pat)l)|Ppat_alias(p1,_)|Ppat_constraint(p1,_)|Ppat_construct(_,Some(_,p1))|Ppat_exceptionp1|Ppat_lazyp1|Ppat_open(_,p1)|Ppat_variant(_,Somep1)->assert(p1==pat)|Ppat_extension(_,ext)->assert(check_extensionsext)|Ppat_any|Ppat_constant_|Ppat_construct(_,None)|Ppat_interval_|Ppat_type_|Ppat_unpack_|Ppat_var_|Ppat_variant(_,None)->assertfalse)|Expctx->(matchctx.pexp_descwith|Pexp_apply_|Pexp_array_|Pexp_list_|Pexp_assert_|Pexp_coerce_|Pexp_constant_|Pexp_constraint_|Pexp_construct_|Pexp_field_|Pexp_ident_|Pexp_ifthenelse_|Pexp_lazy_|Pexp_letexception_|Pexp_letmodule_|Pexp_new_|Pexp_newtype_|Pexp_open_|Pexp_override_|Pexp_pack_|Pexp_poly_|Pexp_record_|Pexp_send_|Pexp_sequence_|Pexp_setfield_|Pexp_setinstvar_|Pexp_tuple_|Pexp_unreachable|Pexp_variant_|Pexp_while_|Pexp_hole|Pexp_beginend_|Pexp_parens_|Pexp_cons_|Pexp_letopen_|Pexp_indexop_access_|Pexp_prefix_|Pexp_infix_->assertfalse|Pexp_extension(_,ext)->assert(check_extensionsext)|Pexp_object{pcstr_self;_}->assert(Option.exists~f:(funself_->self_==pat)pcstr_self)|Pexp_let({pvbs_bindings;_},_)->assert(check_bindingspvbs_bindings)|Pexp_letop{let_;ands;_}->letf{pbop_pat;_}=check_subpatpbop_patinassert(flet_||List.exists~fands)|Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases)->assert(List.existscases~f:(function|{pc_lhs;_}whenpc_lhs==pat->true|_->false))|Pexp_for(p,_,_,_,_)|Pexp_fun(_,_,p,_)->assert(p==pat))|Lbx->assert(x.pvb_pat==pat)|Mb_->assertfalse|Md_->assertfalse|Clctx->assert(matchctx.pcl_descwith|Pcl_fun(_,_,p,_)->p==pat|Pcl_constr_->false|Pcl_structure{pcstr_self;_}->Option.exists~f:(funself_->self_==pat)pcstr_self|Pcl_apply_->false|Pcl_let({pvbs_bindings;_},_)->check_bindingspvbs_bindings|Pcl_constraint_->false|Pcl_extension(_,ext)->check_extensionsext|Pcl_open_->false)|Cty_->assertfalse|Mty_|Mod_|Sig_->assertfalse|Strstr->(matchstr.pstr_descwith|Pstr_value{pvbs_bindings;_}->assert(check_bindingspvbs_bindings)|Pstr_extension((_,ext),_)->assert(check_extensionsext)|_->assertfalse)|Clf{pcf_desc;_}->assert(matchpcf_descwith|Pcf_initializer_->false|Pcf_val(_,_,_)->false|Pcf_method(_,_,_)->false|Pcf_extension(_,PPat(p,_))->p==pat|Pcf_extension(_,_)->false|Pcf_inherit_->false|Pcf_constraint_->false|Pcf_attribute_->false)|Ctf_->assertfalse|Top|Tli_|Rep->assertfalseletassert_check_patxpat=letdump{ctx;ast=pat}=dumpctx(Patpat)inassert_no_raise~f:check_pat~dumpxpatletcheck_exp{ctx;ast=exp}=letcheck_extensions=function|PPat(_,Somee)->e==exp|PStr[{pstr_desc=Pstr_eval(e,_);_}]->e==exp|_->falseinmatchctxwith|Pld(PPat(_,Somee1))->assert(e1==exp)|Pld_->assertfalse|Expctx->(letfeI=eI==expinletsnd_f(_,eI)=eI==expinmatchctx.pexp_descwith|Pexp_extension(_,ext)->assert(check_extensionsext)|Pexp_constant_|Pexp_ident_|Pexp_new_|Pexp_pack_|Pexp_unreachable|Pexp_hole->assertfalse|Pexp_object_->assertfalse|Pexp_let({pvbs_bindings;_},e)->assert(List.existspvbs_bindings~f:(fun{pvb_expr;_}->pvb_expr==exp)||e==exp)|Pexp_letop{let_;ands;body}->letf{pbop_exp;_}=pbop_exp==expinassert(flet_||List.exists~fands||body==exp)|(Pexp_match(e,_)|Pexp_try(e,_))whene==exp->()|Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases)->assert(List.existscases~f:(function|{pc_guard=Someg;_}wheng==exp->true|{pc_rhs;_}whenpc_rhs==exp->true|_->false))|Pexp_fun(_,default,_,body)->assert(Option.value_mapdefault~default:false~f||body==exp)|Pexp_indexop_access{pia_lhs;pia_kind=Builtinidx;pia_rhs;_}->assert(pia_lhs==exp||idx==exp||Option.value_mappia_rhs~default:false~f)|Pexp_indexop_access{pia_lhs;pia_kind=Dotop(_,_,idx);pia_rhs;_}->assert(pia_lhs==exp||List.exists~fidx||Option.value_mappia_rhs~default:false~f)|Pexp_prefix(_,e)->assert(fe)|Pexp_infix(_,e1,e2)->assert(fe1||fe2)|Pexp_apply(_e0,_e1N)->()(* FAIL *)(* assert (e0 == exp || List.exists e1N ~f:snd_f) *)|Pexp_tuplee1N|Pexp_arraye1N|Pexp_liste1N|Pexp_conse1N->assert(List.existse1N~f)|Pexp_construct(_,e)|Pexp_variant(_,e)->assert(Option.existse~f)|Pexp_record(e1N,e0)->assert(Option.existse0~f||List.existse1N~f:(fun(_,_,e)->Option.existse~f))|Pexp_asserte|Pexp_beginende|Pexp_parense|Pexp_constraint(e,_)|Pexp_coerce(e,_,_)|Pexp_field(e,_)|Pexp_lazye|Pexp_letexception(_,e)|Pexp_letmodule(_,_,_,e)|Pexp_newtype(_,e)|Pexp_open(_,e)|Pexp_letopen(_,e)|Pexp_poly(e,_)|Pexp_send(e,_)|Pexp_setinstvar(_,e)->assert(e==exp)|Pexp_sequence(e1,e2)->assert(e1==exp||e2==exp)|Pexp_setfield(e1,_,e2)|Pexp_while(e1,e2)->assert(e1==exp||e2==exp)|Pexp_ifthenelse(eN,e)->assert(List.existseN~f:(funx->fx.if_cond||fx.if_body)||Option.existse~f)|Pexp_for(_,e1,e2,_,e3)->assert(e1==exp||e2==exp||e3==exp)|Pexp_overridee1N->assert(List.existse1N~f:snd_f))|Lbx->assert(x.pvb_expr==exp)|Mb_->assertfalse|Md_->assertfalse|Strstr->(matchstr.pstr_descwith|Pstr_eval(e0,_)->assert(e0==exp)|Pstr_value{pvbs_bindings;_}->assert(List.existspvbs_bindings~f:(fun{pvb_expr;_}->pvb_expr==exp))|Pstr_extension((_,ext),_)->assert(check_extensionsext)|Pstr_primitive_|Pstr_type_|Pstr_typext_|Pstr_exception_|Pstr_module_|Pstr_recmodule_|Pstr_modtype_|Pstr_open_|Pstr_class_|Pstr_class_type_|Pstr_include_|Pstr_attribute_->assertfalse)|Mod{pmod_desc=Pmod_unpack(e1,_,_);_}->assert(e1==exp)|Clctx->letrecloopctx=matchctx.pcl_descwith|Pcl_fun(_,eopt,_,e)->Option.existseopt~f:(fune->e==exp)||loope|Pcl_constr_->false|Pcl_structure_->false|Pcl_apply(_,l)->List.existsl~f:(fun(_,e)->e==exp)|Pcl_let({pvbs_bindings;_},_)->List.existspvbs_bindings~f:(fun{pvb_expr;_}->pvb_expr==exp)|Pcl_constraint_->false|Pcl_extension_->false|Pcl_open_->falseinassert(loopctx)|Cty_->assertfalse|Ctf_->assertfalse|Clf{pcf_desc;_}->assert(matchpcf_descwith|Pcf_initializere->e==exp|Pcf_val(_,_,Cfk_concrete(_,e))->letrecloopx=x==exp||matchxwith|{pexp_desc=Pexp_constraint(e,_);_}->loope|_->falseinloope|Pcf_val(_,_,Cfk_virtual_)->false|Pcf_method(_,_,Cfk_concrete(_,{pexp_desc=Pexp_poly(e,_);_}))|Pcf_method(_,_,Cfk_concrete(_,e))->letrecloopx=x==exp||matchxwith|{pexp_desc=Pexp_newtype(_,e);_}->loope|{pexp_desc=Pexp_constraint(e,_);_}->loope|{pexp_desc=Pexp_fun(_,_,_,e);_}->loope|_->falseinloope|Pcf_method(_,_,Cfk_virtual_)->false|Pcf_extension(_,ext)->check_extensionsext|Pcf_inherit_->false|Pcf_constraint_->false|Pcf_attribute_->false)|Mod_|Top|Tli_|Typ_|Pat_|Mty_|Sig_|Td_|Rep->assertfalseletassert_check_expxexp=letdump{ctx;ast=exp}=dumpctx(Expexp)inassert_no_raise~f:check_exp~dumpxexpletrecis_simple(c:Conf.t)width({ast=exp;_}asxexp)=letctx=Expexpinmatchexp.pexp_descwith|Pexp_constant_->Exp.is_trivialexp|Pexp_field_|Pexp_ident_|Pexp_send_|Pexp_construct(_,None)|Pexp_variant(_,None)->true|Pexp_consl->List.for_alll~f:(fune->is_simplecwidth(sub_exp~ctxe))&&fit_marginc(widthxexp)|Pexp_construct(_,Somee0)|Pexp_variant(_,Somee0)->Exp.is_triviale0|Pexp_arraye1N|Pexp_liste1N|Pexp_tuplee1N->List.for_alle1N~f:Exp.is_trivial&&fit_marginc(widthxexp)|Pexp_record(e1N,e0)->Option.for_alle0~f:Exp.is_trivial&&List.for_alle1N~f:(fun(_,(ct1,ct2),eo)->Option.is_nonect1&&Option.is_nonect2&&Option.for_alleo~f:Exp.is_trivial)&&fit_marginc(widthxexp)|Pexp_indexop_access{pia_lhs;pia_kind;pia_rhs=None;_}->Exp.is_trivialpia_lhs&&(matchpia_kindwith|Builtinidx->Exp.is_trivialidx|Dotop(_,_,idx)->List.for_allidx~f:Exp.is_trivial)&&fit_marginc(widthxexp)|Pexp_prefix(_,e)->Exp.is_triviale&&fit_marginc(widthxexp)|Pexp_infix({txt=":=";_},_,_)->false|Pexp_infix(_,e1,e2)->Exp.is_triviale1&&Exp.is_triviale2&&fit_marginc(widthxexp)|Pexp_apply(e0,e1N)->Exp.is_triviale0&&List.for_alle1N~f:(snd>>Exp.is_trivial)&&fit_marginc(widthxexp)|Pexp_extension(_,PStr[{pstr_desc=Pstr_eval(e0,[]);_}])->is_simplecwidth(sub_exp~ctxe0)|Pexp_extension(_,(PStr[]|PTyp_))->true|_->false(** [prec_ctx {ctx; ast}] is the precedence of the context of [ast] within
[ctx], where [ast] is an immediate sub-term (modulo syntactic sugar) of
[ctx]. Also returns whether [ast] is the left, right, or neither child
of [ctx]. Meaningful for binary operators, otherwise returns [None]. *)letprec_ctxctx=letopenPrecinletopenAssocinletis_tuple_lvl1_in_constructorty=function|{pcd_args=Pcstr_tuplet1N;_}->List.existst1N~f:(phys_equalty)|_->falseinletis_tuple_lvl1_in_ext_constructorty=function|{pext_kind=Pext_decl(_,Pcstr_tuplet1N,_);_}->List.existst1N~f:(phys_equalty)|_->falseinletconstructor_cxt_prec_of_inner=function|{ptyp_desc=Ptyp_arrow_;_}->Some(Apply,Non)|{ptyp_desc=Ptyp_tuple_;_}->Some(InfixOp3,Non)|_->Noneinmatchctxwith|{ctx=Td{ptype_kind=Ptype_variantv;_};ast=Typ({ptyp_desc=Ptyp_arrow_|Ptyp_tuple_;_}astyp)}whenList.existsv~f:(is_tuple_lvl1_in_constructortyp)->constructor_cxt_prec_of_innertyp|{ctx=(Str{pstr_desc=Pstr_typext{ptyext_constructors=l;_};_}|Sig{psig_desc=Psig_typext{ptyext_constructors=l;_};_});ast=Typ({ptyp_desc=Ptyp_arrow_|Ptyp_tuple_;_}astyp);_}whenList.existsl~f:(is_tuple_lvl1_in_ext_constructortyp)->constructor_cxt_prec_of_innertyp|{ctx=(Str{pstr_desc=Pstr_exception{ptyexn_constructor=constr;_};_}|Sig{psig_desc=Psig_exception{ptyexn_constructor=constr;_};_}|Exp{pexp_desc=Pexp_letexception(constr,_);_});ast=Typ({ptyp_desc=Ptyp_tuple_|Ptyp_arrow_;_}astyp)}whenis_tuple_lvl1_in_ext_constructortypconstr->constructor_cxt_prec_of_innertyp|{ctx=Str_;ast=Typ_;_}->None|{ctx=Typ{ptyp_desc;_};ast=Typtyp;_}->(matchptyp_descwith|Ptyp_arrow(t,_)->letassoc=ifList.existst~f:(funx->x.pap_type==typ)thenLeftelseRightinSome(MinusGreater,assoc)|Ptyp_tuple_->Some(InfixOp3,Non)|Ptyp_alias_->Some(As,Non)|Ptyp_constr(_,_::_::_)->Some(Comma,Non)|Ptyp_constr_->Some(Apply,Non)|Ptyp_any|Ptyp_var_|Ptyp_object_|Ptyp_class_|Ptyp_variant_|Ptyp_poly_|Ptyp_package_|Ptyp_extension_->None)|{ctx=Cty{pcty_desc;_};ast=Typtyp;_}->(matchpcty_descwith|Pcty_constr(_,_::_::_)->Some(Comma,Non)|Pcty_arrow(t,_)->letassoc=ifList.existst~f:(funx->x.pap_type==typ)thenLeftelseRightinSome(MinusGreater,assoc)|_->None)|{ctx=Cty{pcty_desc;_};ast=Ctytyp;_}->(matchpcty_descwith|Pcty_arrow(_,t2)->Some(MinusGreater,ift2==typthenRightelseLeft)|_->None)|{ast=Cty_;_}->None|{ast=Typ_;_}->None|{ctx=Exp{pexp_desc;_};ast=Expexp}->(matchpexp_descwith|Pexp_tuple(e0::_)->Some(Comma,ifexp==e0thenLeftelseRight)|Pexp_consl->Some(ColonColon,ifexp==List.last_exnlthenRightelseLeft)|Pexp_construct({txt=Lident"[]";_},Some{pexp_desc=Pexp_tuple[_;_];_})->Some(Semi,Non)|Pexp_array_|Pexp_list_->Some(Semi,Non)|Pexp_construct(_,Some_)|Pexp_assert_|Pexp_lazy_|Pexp_variant(_,Some_)->Some(Apply,Non)|Pexp_indexop_access{pia_lhs=lhs;pia_rhs=rhs;_}->(iflhs==expthenSome(Dot,Left)elsematchrhswith|Someewhene==exp->Some(LessMinus,Right)|_->Some(Low,Left))|Pexp_prefix({txt=i;loc},_)->(matchiwith|"~-"|"~-."|"~+"|"~+."->ifloc.loc_end.pos_cnum-loc.loc_start.pos_cnum=String.lengthi-1thenSome(UMinus,Non)elseSome(High,Non)|_->(matchi.[0]with|'!'|'?'|'~'->Some(High,Non)|_->Some(Apply,Non)))|Pexp_infix({txt=i;_},e1,_)->(letchild=ife1==expthenLeftelseRightinmatch(i.[0],i)with|_,":="->Some(ColonEqual,child)|_,("or"|"||")->Some(BarBar,child)|_,("&"|"&&")->Some(AmperAmper,child)|('='|'<'|'>'|'|'|'&'|'$'),_|_,"!="->Some(InfixOp0,child)|('@'|'^'),_->Some(InfixOp1,child)|('+'|'-'),_->Some(InfixOp2,child)|'*',_whenString.(i<>"*")&&Char.(i.[1]='*')->Some(InfixOp4,child)|('*'|'/'|'%'),_|_,("lor"|"lxor"|"mod"|"land")->Some(InfixOp3,child)|_,("lsl"|"lsr"|"asr")->Some(InfixOp4,child)|'#',_->Some(HashOp,child)|_->Some(Apply,child))|Pexp_apply_->Some(Apply,Non)|Pexp_setfield(e0,_,_)whene0==exp->Some(Dot,Left)|Pexp_setfield(_,_,e0)whene0==exp->Some(LessMinus,Non)|Pexp_setinstvar_->Some(LessMinus,Non)|Pexp_field_->Some(Dot,Left)(* We use [Dot] so [x#y] has the same precedence as [x.y], it is
different to what is done in the parser, but it is intended. *)|Pexp_send_->Some(Dot,Left)|_->None)|{ctx=Cl{pcl_desc;_};ast=Cl_|Exp_}->(matchpcl_descwithPcl_apply_->Some(Apply,Non)|_->None)|{ctx=Exp_;ast=(Pld_|Top|Tli_|Pat_|Cl_|Mty_|Mod_|Sig_|Str_|Clf_|Ctf_|Rep|Mb_|Md_)}|{ctx=Lb_;ast=_}|{ctx=_;ast=Lb_}|{ctx=Td_;ast=_}|{ctx=_;ast=Td_}|{ctx=Cl_;ast=(Pld_|Top|Tli_|Pat_|Mty_|Mod_|Sig_|Str_|Clf_|Ctf_|Rep|Mb_|Md_)}|{ctx=(Pld_|Top|Tli_|Typ_|Cty_|Pat_|Mty_|Mod_|Sig_|Str_|Clf_|Ctf_|Rep|Mb_|Md_);ast=(Pld_|Top|Tli_|Pat_|Exp_|Cl_|Mty_|Mod_|Sig_|Str_|Clf_|Ctf_|Rep|Mb_|Md_)}->None(** [prec_ast ast] is the precedence of [ast]. Meaningful for binary
operators, otherwise returns [None]. *)letrecprec_ast=letopenPrecinfunction|Pld_->None|Typ{ptyp_desc;_}->(matchptyp_descwith|Ptyp_package_->SomeLow|Ptyp_arrow_->SomeMinusGreater|Ptyp_tuple_->SomeInfixOp3|Ptyp_alias_->SomeAs|Ptyp_any|Ptyp_var_|Ptyp_constr_|Ptyp_object_|Ptyp_class_|Ptyp_variant_|Ptyp_poly_|Ptyp_extension_->None)|Td_->None|Cty{pcty_desc;_}->(matchpcty_descwithPcty_arrow_->SomeMinusGreater|_->None)|Exp{pexp_desc;_}->(matchpexp_descwith|Pexp_tuple_->SomeComma|Pexp_cons_->SomeColonColon|Pexp_construct(_,Some_)->SomeApply|Pexp_constant{pconst_desc=Pconst_integer(i,_)|Pconst_float(i,_);_}->(matchi.[0]with'-'|'+'->SomeUMinus|_->SomeAtomic)|Pexp_indexop_access{pia_rhs=rhs;_}->(matchrhswithSome_->SomeLessMinus|_->SomeDot)|Pexp_prefix({txt=i;loc;_},_)->(matchiwith|"~-"|"~-."|"~+."|"~+"->ifloc.loc_end.pos_cnum-loc.loc_start.pos_cnum=String.lengthi-1thenSomeUMinuselseSomeHigh|"!="->SomeApply|_->(matchi.[0]with'!'|'?'|'~'->SomeHigh|_->SomeApply))|Pexp_infix({txt=i;_},_,_)->(match(i.[0],i)with|_,":="->SomeColonEqual|_,("or"|"||")->SomeBarBar|_,("&"|"&&")->SomeAmperAmper|('='|'<'|'>'|'|'|'&'|'$'),_|_,"!="->SomeInfixOp0|('@'|'^'),_->SomeInfixOp1|('+'|'-'),_->SomeInfixOp2|'*',_whenString.(i<>"*")&&Char.(i.[1]='*')->SomeInfixOp4|('*'|'/'|'%'),_|_,("lor"|"lxor"|"mod"|"land")->SomeInfixOp3|_,("lsl"|"lsr"|"asr")->SomeInfixOp4|'#',_->SomeHashOp|_->SomeApply)|Pexp_apply_->SomeApply|Pexp_assert_|Pexp_lazy_|Pexp_for_|Pexp_variant(_,Some_)|Pexp_while_|Pexp_new_|Pexp_object_->SomeApply|Pexp_extension(ext,PStr[{pstr_desc=Pstr_eval(e,_);_}])whenSource.extension_using_sugar~name:ext~payload:e.pexp_loc->prec_ast(Expe)|Pexp_setfield_->SomeLessMinus|Pexp_setinstvar_->SomeLessMinus|Pexp_field_->SomeDot|Pexp_send_->SomeDot|_->None)|Lb_->None|Clc->(matchc.pcl_descwith|Pcl_apply_->SomeApply|Pcl_structure_->SomeApply|_->None)|Top|Pat_|Mty_|Mod_|Sig_|Str_|Tli_|Clf_|Ctf_|Rep|Mb_|Md_->None(** [ambig_prec {ctx; ast}] holds when [ast] is ambiguous in its context
[ctx], indicating that [ast] should be parenthesized. Meaningful for
binary operators, otherwise returns [None] if [ctx] has no precedence
or [Some None] if [ctx] does but [ast] does not. *)letambig_prec({ast;_}asxast)=matchprec_ctxxastwith|Some(prec_ctx,which_child)->(matchprec_astastwith|Someprec_ast->letambiguous=matchPrec.compareprec_ctxprec_astwith|0->(* which child and associativity match: no parens *)(* which child and assoc conflict: add parens *)Assoc.equalwhich_childNon||not(Assoc.equal(Assoc.of_precprec_ast)which_child)(* add parens only when the context has a higher prec than ast *)|cmp->cmp>=0inifambiguousthen`Ambiguouselse`Non_ambiguous|None->`No_prec_ast)|None->`No_prec_ctx(** [parenze_typ {ctx; ast}] holds when type [ast] should be parenthesized
in context [ctx]. *)letparenze_typ({ctx;ast=typ}asxtyp)=assert_check_typxtyp;matchxtypwith|{ast={ptyp_desc=Ptyp_package_;_};_}->true|{ast={ptyp_desc=Ptyp_alias_;_};ctx=Typ_}->true|{ast={ptyp_desc=Ptyp_arrow_|Ptyp_tuple_;_};ctx=Typ{ptyp_desc=Ptyp_class_;_}}->true|{ast={ptyp_desc=Ptyp_alias_;_};ctx=(Str{pstr_desc=Pstr_typext_;_}|Sig{psig_desc=Psig_typext_;_})}->true|{ast={ptyp_desc=Ptyp_alias_;_};ctx=Td{ptype_kind=Ptype_variantl;_}}whenList.existsl~f:(func->matchc.pcd_argswith|Pcstr_tuplel->List.existsl~f:(phys_equaltyp)|_->false)->true|{ast={ptyp_desc=Ptyp_alias_|Ptyp_arrow_|Ptyp_tuple_;_};ctx=(Str{pstr_desc=Pstr_exception_;_}|Sig{psig_desc=Psig_exception_;_})}->true|_->(matchambig_prec(sub_ast~ctx(Typtyp))with|`Ambiguous->true|_->false)(** [parenze_cty {ctx; ast}] holds when class type [ast] should be
parenthesized in context [ctx]. *)letparenze_cty({ctx;ast=cty}asxcty)=assert_check_ctyxcty;matchambig_prec(sub_ast~ctx(Ctycty))with|`Ambiguous->true|_->false(** [parenze_mty {ctx; ast}] holds when module type [ast] should be
parenthesized in context [ctx]. *)letparenze_mty{ctx;ast=mty}=Mty.has_trailing_attributesmty||match(ctx,mty.pmty_desc)with|Mty{pmty_desc=Pmty_with_;_},Pmty_with_->true|_->false(** [parenze_mod {ctx; ast}] holds when module expr [ast] should be
parenthesized in context [ctx]. *)letparenze_mod{ctx;ast=m}=Mod.has_trailing_attributesm||match(ctx,m.pmod_desc)with(* The RHS of an application is always parenthesized already. *)|Mod{pmod_desc=Pmod_apply(_,x);_},Pmod_functor_whenm==x->false|Mod{pmod_desc=Pmod_apply_|Pmod_apply_unit_;_},Pmod_functor_->true|_->false(* Whether a pattern should be parenthesed if followed by a [:]. *)letexposed_right_colonpat=matchpat.ppat_descwith(* Some patterns that are always parenthesed are not mentionned here:
Ppat_constraint, Ppat_unpack *)|Ppat_tuple_->true|_->false(** [parenze_pat {ctx; ast}] holds when pattern [ast] should be
parenthesized in context [ctx]. *)letparenze_pat({ctx;ast=pat}asxpat)=assert_check_patxpat;Pat.has_trailing_attributespat||match(ctx,pat.ppat_desc)with|Pat{ppat_desc=Ppat_conspl;_},Ppat_cons_whenList.last_exnpl==pat->false|Pat{ppat_desc=Ppat_cons_;_},inner->(matchinnerwith|Ppat_cons_->true|Ppat_construct_|Ppat_record_|Ppat_variant_->false|_->true)|Pat{ppat_desc=Ppat_construct_;_},Ppat_cons_->true|_,Ppat_constraint(_,{ptyp_desc=Ptyp_poly_;_})->false|(Exp{pexp_desc=Pexp_letop_;_},(Ppat_construct(_,Some_)|Ppat_cons_|Ppat_variant(_,Some_)|Ppat_or_|Ppat_alias_|Ppat_constraint({ppat_desc=Ppat_any;_},_)))->true|(Exp{pexp_desc=Pexp_letop_;_},Ppat_constraint({ppat_desc=Ppat_tuple_;_},_))->false|_,Ppat_constraint_|_,Ppat_unpack_|(Pat{ppat_desc=(Ppat_alias_|Ppat_array_|Ppat_list_|Ppat_constraint_|Ppat_construct_|Ppat_variant_);_},Ppat_tuple_)|((Pat{ppat_desc=(Ppat_construct_|Ppat_exception_|Ppat_or_|Ppat_lazy_|Ppat_tuple_|Ppat_variant_|Ppat_list_);_}|Exp{pexp_desc=Pexp_fun_;_}),Ppat_alias_)|(Pat{ppat_desc=Ppat_lazy_;_},(Ppat_construct_|Ppat_cons_|Ppat_variant(_,Some_)|Ppat_or_))|(Pat{ppat_desc=(Ppat_construct_|Ppat_exception_|Ppat_tuple_|Ppat_variant_|Ppat_list_);_},Ppat_or_)|Pat{ppat_desc=Ppat_lazy_;_},Ppat_tuple_|Pat{ppat_desc=Ppat_tuple_;_},Ppat_tuple_|Pat_,Ppat_lazy_|Pat_,Ppat_exception_|Exp{pexp_desc=Pexp_fun_;_},Ppat_or_|Cl{pcl_desc=Pcl_fun_;_},Ppat_variant(_,Some_)|Cl{pcl_desc=Pcl_fun_;_},Ppat_tuple_|Cl{pcl_desc=Pcl_fun_;_},Ppat_construct_|Cl{pcl_desc=Pcl_fun_;_},Ppat_alias_|Cl{pcl_desc=Pcl_fun_;_},Ppat_lazy_|Exp{pexp_desc=Pexp_letop_;_},Ppat_exception_|(Exp{pexp_desc=Pexp_fun_;_},(Ppat_construct_|Ppat_cons_|Ppat_lazy_|Ppat_tuple_|Ppat_variant_))->true|(Str_|Exp_),Ppat_lazy_->true|(Pat{ppat_desc=Ppat_construct_|Ppat_variant_;_},(Ppat_construct(_,Some_)|Ppat_cons_|Ppat_variant(_,Some_)))->true|_,Ppat_var_whenList.is_emptypat.ppat_attributes->false|((Exp{pexp_desc=Pexp_let({pvbs_bindings;_},_);_}|Str{pstr_desc=Pstr_value{pvbs_bindings;_};_}),pat_desc)->(matchpat_descwith|Ppat_construct(_,Some_)|Ppat_variant(_,Some_)|Ppat_cons_|Ppat_alias_|Ppat_constraint_|Ppat_lazy_|Ppat_or_->(* Add disambiguation parentheses that are not necessary. *)true|_whenexposed_right_colonpat->(* Some patterns must be parenthesed when followed by a colon. *)letpvb=List.find_exnpvbs_bindings~f:(funpvb->pvb.pvb_pat==pat)inOption.is_somepvb.pvb_constraint|_->false)|_->falseletmarked_parenzed_inner_nested_match=letmemo=Hashtbl.Poly.create()inregister_reset(fun()->Hashtbl.clearmemo);memo(** [exposed cls exp] holds if there is a right-most subexpression of [exp]
which satisfies [Exp.mem_cls cls] and is not parenthesized. *)letrecexposed_right_exp=(* exponential without memoization *)letmemo=Hashtbl.Poly.create()inregister_reset(fun()->Hashtbl.clearmemo);funclsexp->letexposed_()=letcontinuesubexp=(not(parenze_exp(sub_exp~ctx:(Expexp)subexp)))&&exposed_right_expclssubexpinmatchexp.pexp_descwith|Pexp_asserte|Pexp_construct(_,Somee)|Pexp_fun(_,_,_,e)|Pexp_ifthenelse(_,Somee)|Pexp_prefix(_,e)|Pexp_infix(_,_,e)|Pexp_lazye|Pexp_newtype(_,e)|Pexp_open(_,e)|Pexp_letopen(_,e)|Pexp_sequence(_,e)|Pexp_setfield(_,_,e)|Pexp_setinstvar(_,e)|Pexp_variant(_,Somee)->continuee|Pexp_consl->continue(List.last_exnl)|Pexp_ifthenelse(eN,None)->continue(List.last_exneN).if_body|Pexp_extension(ext,PStr[{pstr_desc=Pstr_eval(({pexp_attributes=[];_}ase),_);_}])whenSource.extension_using_sugar~name:ext~payload:e.pexp_loc->continuee|Pexp_let(_,e)|Pexp_letop{body=e;_}|Pexp_letexception(_,e)|Pexp_letmodule(_,_,_,e)->(matchclswithMatch|Then|ThenElse->continuee|_->false)|Pexp_match_whenmatchclswithThen->true|_->false->false|Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases)->continue(List.last_exncases).pc_rhs|Pexp_apply(_,args)->continue(snd(List.last_exnargs))|Pexp_tuplees->continue(List.last_exnes)|Pexp_array_|Pexp_list_|Pexp_coerce_|Pexp_constant_|Pexp_constraint_|Pexp_construct(_,None)|Pexp_extension_|Pexp_field_|Pexp_for_|Pexp_ident_|Pexp_new_|Pexp_object_|Pexp_override_|Pexp_pack_|Pexp_poly_|Pexp_record_|Pexp_send_|Pexp_unreachable|Pexp_variant(_,None)|Pexp_hole|Pexp_while_|Pexp_beginend_|Pexp_parens_|Pexp_indexop_access_->falseinExp.mem_clsclsexp||Hashtbl.find_or_addmemo(cls,exp)~default:exposed_andexposed_right_cl=letmemo=Hashtbl.Poly.create()inregister_reset(fun()->Hashtbl.clearmemo);funclscl->letexposed_()=matchcl.pcl_descwith|Pcl_apply(_,args)->letexp=snd(List.last_exnargs)in(not(parenze_exp(sub_exp~ctx:(Clcl)exp)))&&exposed_right_expclsexp|Pcl_fun(_,_,_,e)->(not(parenze_cl(sub_cl~ctx:(Clcl)e)))&&exposed_right_clclse|_->falseinCl.mem_clsclscl||Hashtbl.find_or_addmemo(cls,cl)~default:exposed_andmark_parenzed_inner_nested_matchexp=letexposed_()=letcontinuesubexp=ifnot(parenze_exp(sub_exp~ctx:(Expexp)subexp))thenmark_parenzed_inner_nested_matchsubexp;falseinmatchexp.pexp_descwith|Pexp_asserte|Pexp_construct(_,Somee)|Pexp_ifthenelse(_,Somee)|Pexp_prefix(_,e)|Pexp_infix(_,_,e)|Pexp_lazye|Pexp_newtype(_,e)|Pexp_open(_,e)|Pexp_letopen(_,e)|Pexp_fun(_,_,_,e)|Pexp_sequence(_,e)|Pexp_setfield(_,_,e)|Pexp_setinstvar(_,e)|Pexp_variant(_,Somee)->continuee|Pexp_consl->continue(List.last_exnl)|Pexp_let(_,e)|Pexp_letop{body=e;_}|Pexp_letexception(_,e)|Pexp_letmodule(_,_,_,e)->continuee|Pexp_ifthenelse(eN,None)->continue(List.last_exneN).if_body|Pexp_extension(ext,PStr[{pstr_desc=Pstr_eval(e,_);_}])whenSource.extension_using_sugar~name:ext~payload:e.pexp_loc->(matche.pexp_descwith|Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases)->List.itercases~f:(funcase->mark_parenzed_inner_nested_matchcase.pc_rhs);true|_->continuee)|Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases)->List.itercases~f:(funcase->mark_parenzed_inner_nested_matchcase.pc_rhs);true|Pexp_indexop_access{pia_rhs=rhs;_}->(matchrhswithSomee->continuee|None->false)|Pexp_apply(_,args)->continue(snd(List.last_exnargs))|Pexp_tuplees->continue(List.last_exnes)|Pexp_array_|Pexp_list_|Pexp_coerce_|Pexp_constant_|Pexp_constraint_|Pexp_construct(_,None)|Pexp_extension_|Pexp_field_|Pexp_for_|Pexp_ident_|Pexp_new_|Pexp_object_|Pexp_override_|Pexp_pack_|Pexp_poly_|Pexp_record_|Pexp_send_|Pexp_unreachable|Pexp_variant(_,None)|Pexp_hole|Pexp_while_|Pexp_beginend_|Pexp_parens_->falseinHashtbl.find_or_addmarked_parenzed_inner_nested_matchexp~default:exposed_|>(ignore:bool->_)(** [parenze_exp {ctx; ast}] holds when expression [ast] should be
parenthesized in context [ctx]. *)andparenze_exp({ctx;ast=exp}asxexp)=letparenze()=letis_right_infix_argctx_descexp=matchctx_descwith|Pexp_infix(_,_,e2)whene2==exp&&Option.value_map~default:false(prec_astctx)~f:(funp->Prec.comparepApply<0)->true|Pexp_tuplee1N->List.last_exne1N==xexp.ast|_->falseinmatchambig_prec(sub_ast~ctx(Expexp))with|`No_prec_ctx->false(* ctx not apply *)|`Ambiguous->true(* exp is apply and ambig *)|_->(matchctxwith|Exp{pexp_desc;_}->ifis_right_infix_argpexp_descexpthenExp.is_sequenceexpelseexposed_right_expNon_applyexp|_->exposed_right_expNon_applyexp)inletrecifthenelsepexp_desc=matchpexp_descwith|Pexp_extension(ext,PStr[{pstr_desc=Pstr_eval(e,_);_}])whenSource.extension_using_sugar~name:ext~payload:e.pexp_loc->ifthenelsee.pexp_desc|Pexp_let_|Pexp_match_|Pexp_try_->true|_->falseinletexp_in_sequencelhsrhsexp=match(lhs.pexp_desc,exp.pexp_attributes)with|(Pexp_match_|Pexp_try_),_::_whenlhs==exp->true|_,_::_->false|(Pexp_extension(_,PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_sequence_;_},[]);_}]),_)whenlhs==exp->true|_whenlhs==exp->exposed_right_expLet_matchexp|_whenrhs==exp->false|_->failwith"exp must be lhs or rhs from the parent expression"inassert_check_expxexp;Hashtbl.findmarked_parenzed_inner_nested_matchexp|>Option.value~default:false||match(ctx,exp)with|Str{pstr_desc=Pstr_eval_;_},_->false|_,{pexp_desc=Pexp_infix_;pexp_attributes=_::_;_}->true|(Str{pstr_desc=Pstr_value{pvbs_rec=Nonrecursive;pvbs_bindings=[{pvb_pat={ppat_desc=Ppat_any;_};_}];_};_},_)->false(* Object fields do not require parens, even with trailing attributes *)|Exp{pexp_desc=Pexp_object_;_},_->false|_,{pexp_desc=Pexp_object_;pexp_attributes=[];_}whenOcaml_version.(compare!ocaml_versionReleases.v4_14_0>=0)->false|(Exp{pexp_desc=Pexp_construct({txt=id;_},_);_},{pexp_attributes=_::_;_})whenStd_longident.is_infixid->true|Exp_,ewhenExp.is_symbole||Exp.is_monadic_bindinge->true|Exp{pexp_desc=Pexp_cons_;_},{pexp_attributes=_::_;_}->true|Exp{pexp_desc=Pexp_extension_;_},{pexp_desc=Pexp_tuple_;_}->false|Pld_,{pexp_desc=Pexp_tuple_;_}->false|Cl{pcl_desc=Pcl_apply_;_},_->parenze()|Clf_,_->parenze()|Exp{pexp_desc=Pexp_ifthenelse(eN,_);_},{pexp_desc;_}when!parens_ite&&List.existseN~f:(funx->x.if_body==exp)&&ifthenelsepexp_desc->true|Exp{pexp_desc=Pexp_ifthenelse(_,Somee);_},{pexp_desc;_}when!parens_ite&&e==exp&&ifthenelsepexp_desc->true|(Exp{pexp_desc=Pexp_infix(_,_,e1);_},{pexp_desc=Pexp_apply({pexp_desc=Pexp_ident{txt=Lident"not";_};_},_);_})whennot(e1==exp)->true|(Exp{pexp_desc=Pexp_apply(e,_);_},{pexp_desc=Pexp_construct_|Pexp_cons_|Pexp_variant_;_})whene==exp->true|(Exp{pexp_desc=Pexp_apply(e,_::_);_},{pexp_desc=Pexp_prefix_;pexp_attributes=_::_;_})whene==exp->true|(Exp{pexp_desc=Pexp_indexop_access{pia_lhs=lhs;_};_},{pexp_desc=Pexp_construct_|Pexp_cons_;_})whenlhs==exp->true|Exp{pexp_desc=Pexp_indexop_access{pia_kind=Builtinidx;_};_},_whenidx==exp->false|(Exp{pexp_desc=Pexp_constraint(e,_)|Pexp_coerce(e,_,_);_},{pexp_desc=Pexp_tuple_|Pexp_match_|Pexp_try_;_})whene==exp&&!ocp_indent_compat->true|(Exp{pexp_desc=Pexp_indexop_access{pia_kind=Dotop(_,_,[idx]);pia_paren=Paren;_};_},_)whenidx==exp&¬(Exp.is_sequenceidx)->false|(Exp{pexp_desc=Pexp_prefix(_,e);_},{pexp_desc=(Pexp_indexop_access{pia_lhs=x;_}|Pexp_infix(_,x,_)|Pexp_apply(_,[(_,x);_]));_})whene==exp&&Exp.exposed_leftx->true(* Integers without suffixes must be parenthesised on the lhs of an
indexing operator *)|(Exp{pexp_desc=Pexp_indexop_access{pia_lhs=lhs;_};_},{pexp_desc=Pexp_constant{pconst_desc=Pconst_integer(_,None);_};_})whenexp==lhs->true|(Exp{pexp_desc=Pexp_field(e,_);_},{pexp_desc=Pexp_construct_|Pexp_cons_;_})whene==exp->true|Exp{pexp_desc;_},_->(matchpexp_descwith|Pexp_extension(_,PStr[{pstr_desc=Pstr_eval({pexp_desc=(Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases));_},_);_}])|Pexp_functioncases|Pexp_match(_,cases)|Pexp_try(_,cases)->if!leading_nested_match_parensthenList.itercases~f:(fun{pc_rhs;_}->mark_parenzed_inner_nested_matchpc_rhs);List.existscases~f:(fun{pc_rhs;_}->pc_rhs==exp)&&exposed_right_expMatchexp|Pexp_ifthenelse(eN,_)whenList.existseN~f:(funx->x.if_cond==exp)->false|Pexp_ifthenelse(eN,None)when(List.last_exneN).if_body==exp->exposed_right_expThenexp|Pexp_ifthenelse(eN,_)whenList.existseN~f:(funx->x.if_body==exp)->exposed_right_expThenElseexp|Pexp_ifthenelse(_,Someels)whenels==exp->Exp.is_sequenceexp|Pexp_apply(({pexp_desc=Pexp_new_;_}asexp2),_)whenexp2==exp->false|Pexp_apply(({pexp_desc=Pexp_extension(_,PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_new_;_},[]);_}]);_}asexp2),_)whenexp2==exp->false|Pexp_record(flds,_)whenList.existsflds~f:(fun(_,_,e0)->Option.existse0~f:(funx->x==exp))->exposed_right_expNon_applyexp(* Non_apply is perhaps pessimistic *)|Pexp_record(_,Some({pexp_desc=Pexp_prefix_;_}ase0))whene0==exp->(* don't put parens around [!e] in [{ !e with a; b }] *)false|Pexp_record(_,Some({pexp_desc=(Pexp_ident_|Pexp_constant_|Pexp_record_|Pexp_field_);_}ase0))whene0==exp->false|Pexp_record(_,Somee0)whene0==exp->true|Pexp_sequence(lhs,rhs)->exp_in_sequencelhsrhsexp|Pexp_apply(_,args)whenList.existsargs~f:(fun(_,e0)->match(e0.pexp_desc,e0.pexp_attributes)with|Pexp_list_,_::_whene0==exp->true|Pexp_array_,_::_whene0==exp->true|_->false)->true|_->(matchexp.pexp_descwith|Pexp_list_|Pexp_array_->false|_->Exp.has_trailing_attributesexp||parenze()))|_,{pexp_desc=Pexp_list_;_}->false|_,{pexp_desc=Pexp_array_;_}->false|_,expwhenExp.has_trailing_attributesexp->true|_->false(** [parenze_cl {ctx; ast}] holds when class expr [ast] should be
parenthesized in context [ctx]. *)andparenze_cl({ctx;ast=cl}asxcl)=assert_check_clxcl;matchambig_prec(sub_ast~ctx(Clcl))with|`No_prec_ctx->false|`Ambiguous->true|_->exposed_right_clNon_applyclletparenze_nested_exp{ctx;ast=exp}=letinfix_precast=matchastwith|Exp{pexp_desc=Pexp_infix_;_}->prec_astast|Exp{pexp_desc=Pexp_apply(e,_);_}whenExp.is_infixe->prec_astast|Exp{pexp_desc=Pexp_cons_;_}->prec_astast|_->Nonein(* Make the precedence explicit for infix operators *)match(infix_precctx,infix_prec(Expexp))with|Some(InfixOp0|ColonEqual),_|_,Some(InfixOp0|ColonEqual)->(* special case for refs update and all InfixOp0 to reduce parens
noise *)false|None,_|_,None->false|Somep1,Somep2->not(Prec.equalp1p2)endincludeIn_ctxincludeRequires_sub_terms