1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467(**************************************************************************)(* *)(* 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->"%%"endendmoduleExt_attrs=structlethas_attrs=function|{attrs_extension=_;attrs_before=[];attrs_after=[]}->false|_->truelethas_docea=List.exists~f:Attr.is_docea.attrs_before||List.exists~f:Attr.is_docea.attrs_afterendmoduleExp=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_function_|Pexp_ifthenelse_|Pexp_match_|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(_,Some_,_)|Pexp_function(_,_,Pfunction_cases_)|Pexp_match_|Pexp_try_);_},(Match|Let_match|Non_apply))|({pexp_desc=(Pexp_function(_,_,Pfunction_body_)|Pexp_let_|Pexp_letop_|Pexp_letexception_|Pexp_letmodule_|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)->false|Pmty_functor(_,t,true)->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(* one attribute list *)|Pstr_eval(_,atrs)|Pstr_recmodule({pmb_expr={pmod_attributes=atrs;_};_}::_)|Pstr_extension(_,atrs)->List.exists~f:Attr.is_docatrs|Pstr_open{popen_attributes=ea;_}|Pstr_class_type({pci_attributes=ea;_}::_)|Pstr_class({pci_attributes=ea;_}::_)|Pstr_modtype{pmtd_ext_attrs=ea;_}|Pstr_type(_,{ptype_attributes=ea;_}::_)|Pstr_value{pvbs_bindings={pvb_attributes=ea;_}::_;_}|Pstr_primitive{pval_attributes=ea;_}|Pstr_typext{ptyext_attributes=ea;_}->Ext_attrs.has_docea|Pstr_module{pmb_ext_attrs=ea;pmb_expr={pmod_attributes=attrs;_};_}|Pstr_include{pincl_mod={pmod_attributes=attrs;_};pincl_attributes=ea;_}|Pstr_exception{ptyexn_attributes=ea;ptyexn_constructor={pext_attributes=attrs;_};_}->Ext_attrs.has_docea||List.exists~f:Attr.is_docattrs|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)letrecallow_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_->true|(Pstr_extension((_,PStr[n1]),_attrs1),Pstr_extension((_,PStr[n2]),_attrs2))->allow_adjacent(n1,cI)(n2,cJ)|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_extension(_,atrs)->List.exists~f:Attr.is_docatrs|Psig_value{pval_attributes=ea;_}|Psig_type(_,{ptype_attributes=ea;_}::_)|Psig_typesubst({ptype_attributes=ea;_}::_)|Psig_typext{ptyext_attributes=ea;_}|Psig_open{popen_attributes=ea;_}|Psig_class_type({pci_attributes=ea;_}::_)|Psig_class({pci_attributes=ea;_}::_)|Psig_modtype{pmtd_ext_attrs=ea;_}|Psig_modtypesubst{pmtd_ext_attrs=ea;_}|Psig_modsubst{pms_ext_attrs=ea;_}->Ext_attrs.has_docea|Psig_include{pincl_mod={pmty_attributes=atrs;_};pincl_attributes=ea;_}|Psig_exception{ptyexn_attributes=ea;ptyexn_constructor={pext_attributes=atrs;_};_}|Psig_recmodule({pmd_type={pmty_attributes=atrs;_};pmd_ext_attrs=ea;_}::_)|Psig_module{pmd_ext_attrs=ea;pmd_type={pmty_attributes=atrs;_};_}->Ext_attrs.has_docea||(List.exists~f:Attr.is_doc)atrs|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=Ext_attrs.has_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=Ext_attrs.has_docitm.pmb_ext_attrsletis_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=Ext_attrs.has_docitm.pmd_ext_attrsletis_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=Ext_attrs.has_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|Cdofclass_declaration|Ctdofclass_type_declaration|Patofpattern|Expofexpression|Fpeofexpr_function_param|Fpcofclass_function_param|Vcofvalue_constraint|Lbofvalue_binding|Boofbinding_op|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|Fpep->Format.fprintffs"Fpe:@\n%a"Printast.expr_function_paramp|Fpcp->Format.fprintffs"Fpc:@\n%a"Printast.class_function_paramp|Vcc->Format.fprintffs"Vc:@\n%a"Printast.value_constraintc|Lbb->Format.fprintffs"Lb:@\n%a"Printast.value_bindingb|Bob->Format.fprintffs"Bo:@\n%a"Printast.binding_opb|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|Cdcd->Format.fprintffs"Cd:@\n%a"Printast.class_declarationcd|Ctdctd->Format.fprintffs"Ctd:@\n%a"Printast.class_type_declarationctd|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|_->falseletattrs_of_ext_attrsea=ea.attrs_before@ea.attrs_afterletattributes=function|Pld_->[]|Typx->x.ptyp_attributes|Tdx->attrs_of_ext_attrsx.ptype_attributes|Ctyx->x.pcty_attributes|Patx->x.ppat_attributes|Expx->x.pexp_attributes|Fpe_|Fpc_->[]|Vc_->[]|Lbx->attrs_of_ext_attrsx.pvb_attributes|Bo_->[]|Mbx->attrs_of_ext_attrsx.pmb_ext_attrs|Mdx->attrs_of_ext_attrsx.pmd_ext_attrs|Clx->x.pcl_attributes|Cdx->attrs_of_ext_attrsx.pci_attributes|Ctdx->attrs_of_ext_attrsx.pci_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|Fpex->x.pparam_loc|Fpcx->x.pparam_loc|Vc_->Location.none|Lbx->x.pvb_loc|Box->x.pbop_loc|Mbx->x.pmb_loc|Mdx->x.pmd_loc|Clx->x.pcl_loc|Cdx->x.pci_loc|Ctdx->x.pci_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=private{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_itemxtvalsub_fun_body:ctx:T.t->function_body->function_bodyxtend=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}letsub_fun_body~ctxast={ctx;ast}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_type{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)|_->falseinletcheck_class_expr{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)|_->falseinletcheck_value_constraint=function|Pvc_constraint{typ=typ';_}->typ'==typ|Pvc_coercion{ground;coercion}->coercion==typ||Option.existsground~f:(funx->x==typ)inletcheck_pvbpvb=Option.existspvb.pvb_constraint~f:check_value_constraintinletcheck_let_bindingslbs=List.existslbs.pvbs_bindings~f:check_pvbinletcheck_type_constraint=function|Pconstraintt->ft|Pcoerce(t1,t2)->Option.existst1~f||ft2inmatchctxwith|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_open(_,t1)->assert(t1==typ)|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_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(_,c,_)->Option.existsc~f:check_type_constraint))|Pexp_let(lbs,_,_)->assert(check_let_bindingslbs)|Pexp_function(_,Somet1,_)->assert(check_type_constraintt1)|_->assertfalse)|Fpe_|Fpc_->assertfalse|Vcc->assert(check_value_constraintc)|Lb_->assertfalse|Bo_->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)|Cdctx->assert(check_class_exprctx)|Ctdctx->assert(check_class_typectx)|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)|_->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_extension((_,PTypt),_)->assert(t==typ)|Pstr_extension(_,_)->assertfalse|Pstr_value{pvbs_bindings;_}->assert(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(_,tc,_))->Option.existstc~f:check_type_constraint|Pcf_method(_,_,Cfk_virtualt)->typ==t|Pcf_method(_,_,Cfk_concrete(_,(_,t),_))->Option.existst~f:check_value_constraint|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}=match(ctx:t)with|Exp_->assertfalse|Fpe_|Fpc_->assertfalse|Vc_->assertfalse|Lb_->assertfalse|Bo_->assertfalse|Mb_->assertfalse|Md_->assertfalse|Pld_->assertfalse|Str_->assertfalse|Sig_->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)|Cdctx->assert(Option.existsctx.pci_constraint~f:(funx->x==cty))|Ctdctx->assert(Option.existsctx.pci_constraint~f:(funx->x==cty)||ctx.pci_expr==cty)|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|Fpe_|Fpc_->assertfalse|Vc_->assertfalse|Lb_->assertfalse|Bo_->assertfalse|Mb_->assertfalse|Md_->assertfalse|Pld_->assertfalse|Str_->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)|Cdctx->assert(ctx.pci_expr==cl)|Ctd_->assertfalse|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_cases=List.exists~f:(func->c.pc_lhs==pat)inletcheck_binding{pvb_pat;pvb_body;_}=check_subpatpvb_pat||matchpvb_bodywith|Pfunction_body_->false|Pfunction_cases(cases,_,_)->check_casescasesinletcheck_bindingsl=List.existsl~f:check_bindinginletcheck_param_val(_,_,p)=p==patinletcheck_expr_function_paramparam=matchparam.pparam_descwith|Pparam_valx->check_param_valx|Pparam_newtype_->falseinletcheck_class_function_paramparam=check_param_valparam.pparam_descinletcheck_class_function_params=List.exists~f:check_class_function_paraminmatchctxwith|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_effect(p1,p2)->assert(p1==pat||p2==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_open_|Pexp_override_|Pexp_pack_|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_match(_,cases)|Pexp_try(_,cases)->assert(check_casescases)|Pexp_for(p,_,_,_,_)->assert(p==pat)|Pexp_function(params,_,body)->letcheck_body=matchbodywith|Pfunction_body_->false|Pfunction_cases(cases,_,_)->check_casescasesinassert(List.exists~f:check_expr_function_paramparams||check_body))|Fpectx->assert(check_expr_function_paramctx)|Fpcctx->assert(check_class_function_paramctx)|Vc_->assertfalse|Lbx->assert(check_bindingx)|Box->assert(x.pbop_pat==pat)|Mb_->assertfalse|Md_->assertfalse|Clctx->assert(matchctx.pcl_descwith|Pcl_fun(p,_)->check_class_function_paramsp|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|Cd_->assertfalse|Ctd_->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|_->falseinletcheck_param_val(_,e,_)=Option.existse~f:(funx->x==exp)inletcheck_expr_function_paramparam=matchparam.pparam_descwith|Pparam_valx->check_param_valx|Pparam_newtype_->falseinletcheck_class_function_paramparam=check_param_valparam.pparam_descinletcheck_class_function_params=List.exists~f:check_class_function_paraminletcheck_cases=List.exists~f:(function|{pc_guard=Someg;_}wheng==exp->true|{pc_rhs;_}whenpc_rhs==exp->true|_->false)inletcheck_fun_body=function|Pfunction_bodybody->body==exp|Pfunction_cases(cases,_,_)->check_casescasesinmatchctxwith|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_body;_}->check_fun_bodypvb_body)||e==exp)|Pexp_letop{let_;ands;body;loc_in=_}->letf{pbop_exp;_}=pbop_exp==expinassert(flet_||List.exists~fands||body==exp)|(Pexp_match(e,_)|Pexp_try(e,_))whene==exp->()|Pexp_match(_,cases)|Pexp_try(_,cases)->assert(check_casescases)|Pexp_function(params,_,body)->assert(List.exists~f:check_expr_function_paramparams||check_fun_bodybody)|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.existse1N~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_open(_,e)|Pexp_letopen(_,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:(fun(x,_)->fx))|Pexp_for(_,e1,e2,_,e3)->assert(e1==exp||e2==exp||e3==exp)|Pexp_overridee1N->assert(List.existse1N~f:snd_f))|Fpectx->assert(check_expr_function_paramctx)|Fpcctx->assert(check_class_function_paramctx)|Vc_->assertfalse|Lbx->assert(check_fun_bodyx.pvb_body)|Box->assert(x.pbop_exp==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_body;_}->check_fun_bodypvb_body))|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(param,e)->check_class_function_paramsparam||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_body;_}->check_fun_bodypvb_body)|Pcl_constraint_->false|Pcl_extension_->false|Pcl_open_->falseinassert(loopctx)|Cty_->assertfalse|Cd_->assertfalse|Ctd_->assertfalse|Ctf_->assertfalse|Clf{pcf_desc;_}->assert(letcheck_cfk=function|Cfk_concrete(_,_,e)->e==exp|Cfk_virtual_->falseinmatchpcf_descwith|Pcf_initializere->e==exp|Pcf_val(_,_,cfk)->check_cfkcfk|Pcf_method(_,_,cfk)->check_cfkcfk|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(_,c,eo)->Option.is_nonec&&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_|Ptyp_open_->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=Fpe_|Fpc_;ast=_}|{ctx=_;ast=Fpe_|Fpc_}|{ctx=Vc_;ast=_}|{ctx=_;ast=Vc_}|{ctx=Lb_;ast=_}|{ctx=_;ast=Lb_}|{ctx=Bo_;ast=_}|{ctx=_;ast=Bo_}|{ctx=Td_;ast=_}|{ctx=_;ast=Td_}|{ctx=Cd_;ast=_}|{ctx=_;ast=Cd_}|{ctx=Ctd_;ast=_}|{ctx=_;ast=Ctd_}|{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_|Ptyp_open_->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)|Fpe_|Fpc_->None|Vc_->None|Lb_->None|Bo_->None|Clc->(matchc.pcl_descwith|Pcl_apply_->SomeApply|Pcl_structure_->SomeApply|Pcl_let_->SomeLow|_->None)|Top|Pat_|Mty_|Mod_|Sig_|Str_|Tli_|Clf_|Ctf_|Rep|Mb_|Md_|Cd_|Ctd_->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|_->falseletparenze_pat_in_bindingsbindingspat=letparenze_pat_in_binding~pvb_constraint=(* Some patterns must be parenthesed when followed by a colon. *)(exposed_right_colonpat&&Option.is_somepvb_constraint)||matchpat.ppat_descwith|Ppat_construct(_,Some_)|Ppat_variant(_,Some_)|Ppat_cons_|Ppat_alias_|Ppat_or_->(* Add disambiguation parentheses that are not necessary. *)true|_->falseinList.existsbindings~f:(fun{pvb_pat;pvb_constraint;_}->(* [pat] appears on the left side of a binding. *)pvb_pat==pat&&parenze_pat_in_binding~pvb_constraint)(** [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)|Fpe{pparam_desc=Pparam_val(_,_,_);_},Ppat_cons_->true|Fpc{pparam_desc=_;_},Ppat_cons_->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|(Bo{pbop_typ=None;_},(Ppat_construct(_,Some_)|Ppat_cons_|Ppat_variant(_,Some_)|Ppat_or_|Ppat_alias_))->true|Bo{pbop_typ=Some_;_},(Ppat_any|Ppat_tuple_)->true|Exp{pexp_desc=Pexp_function(_,_,Pfunction_body_);_},Ppat_or_|(Exp{pexp_desc=Pexp_function(_,_,Pfunction_body_);_},(Ppat_construct_|Ppat_cons_|Ppat_lazy_|Ppat_tuple_|Ppat_variant_))->true|_,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_effect_|Ppat_or_|Ppat_lazy_|Ppat_tuple_|Ppat_variant_|Ppat_list_);_}|Exp{pexp_desc=Pexp_function(_,_,Pfunction_body_);_}),Ppat_alias_)|(Pat{ppat_desc=Ppat_lazy_;_},(Ppat_construct_|Ppat_cons_|Ppat_variant(_,Some_)|Ppat_or_))|(Pat{ppat_desc=(Ppat_construct_|Ppat_exception_|Ppat_effect_|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_|Pat_,Ppat_effect_|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_;_}|Bo_),(Ppat_exception_|Ppat_effect_))->true|(Str_|Exp_|Lb_),Ppat_lazy_->true|((Fpe_|Fpc_),(Ppat_tuple_|Ppat_construct_|Ppat_alias_|Ppat_variant_|Ppat_lazy_|Ppat_exception_|Ppat_effect_|Ppat_or_))|(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;_};_}),_)whenparenze_pat_in_bindingspvbs_bindingspat->true|(Lb{pvb_pat;_},(Ppat_construct(_,Some_)|Ppat_variant(_,Some_)|Ppat_cons_|Ppat_alias_|Ppat_or_))whenpvb_pat==pat->(* Disambiguation parentheses *)true|Lb{pvb_pat;pvb_constraint=Some_;_},_whenpvb_pat==pat&&exposed_right_colonpat->true|_->false(* Whether an expression in a let binding shouldn't be parenthesed,
bypassing the other Ast rules. *)letdont_parenze_exp_in_bindingsbindingsexp=matchexp.pexp_descwith|Pexp_function([],None,(Pfunction_cases_asfun_body))->(* [fun_body] is the body of the let binding and shouldn't be
parenthesed. [exp] is a synthetic expression constructed in the
formatting code. *)List.existsbindings~f:(fun{pvb_body;_}->pvb_body==fun_body)|_->falseletctx_sensitive_to_trailing_attributes=function|Lb_->false|_->trueletmarked_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_function(_,_,Pfunction_bodye)|Pexp_ifthenelse(_,Some(e,_))|Pexp_prefix(_,e)|Pexp_infix(_,_,e)|Pexp_lazye|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_function(_,_,Pfunction_cases(cases,_,_))|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_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(_,Some(e,_))|Pexp_prefix(_,e)|Pexp_infix(_,_,e)|Pexp_lazye|Pexp_open(_,e)|Pexp_letopen(_,e)|Pexp_function(_,_,Pfunction_bodye)|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_function(_,_,Pfunction_cases(cases,_,_))|Pexp_match(_,cases)|Pexp_try(_,cases)->List.itercases~f:(funcase->mark_parenzed_inner_nested_matchcase.pc_rhs);true|_->continuee)|Pexp_function(_,_,Pfunction_cases(cases,_,_))|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_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->_)(* Whether to parenze an expr on the RHS of a match/try/function case. *)andparenze_exp_in_match_casecasesexp=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(* Whether to parenze an expr on the RHS of a let binding.
[dont_parenze_exp_in_bindings] must have been checked before. *)andparenze_exp_in_bindingsbindingsexp=List.existsbindings~f:(fun{pvb_body;pvb_args;_}->matchpvb_bodywith|Pfunction_body({pexp_desc=Pexp_function([],None,Pfunction_cases_);_}aslet_body)whenlet_body==exp->(* Function with cases and no 'fun' keyword is in the body of a
binding, parentheses are needed if the binding also defines
arguments. *)not(List.is_emptypvb_args)|Pfunction_cases(cases,_,_)->parenze_exp_in_match_casecasesexp|_->false)(** [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|Lbpvb,_whendont_parenze_exp_in_bindings[pvb]exp->false|Exp{pexp_desc=Pexp_let({pvbs_bindings;_},_,_);_},_|Cl{pcl_desc=Pcl_let({pvbs_bindings;_},_,_);_},_whendont_parenze_exp_in_bindingspvbs_bindingsexp->false|Lbpvb,_whenparenze_exp_in_bindings[pvb]exp->true|Exp{pexp_desc=Pexp_let({pvbs_bindings;_},_,_);_},_|Cl{pcl_desc=Pcl_let({pvbs_bindings;_},_,_);_},_whenparenze_exp_in_bindingspvbs_bindingsexp->true|_,{pexp_desc=Pexp_infix_;pexp_attributes=_::_;_}whenctx_sensitive_to_trailing_attributesctx->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(_,Some(e,_));_},{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=Pexp_function(_,_,Pfunction_bodye);_},{pexp_desc=Pexp_function([],None,Pfunction_cases_);_})whene==exp->true|(Exp{pexp_desc=(Pexp_extension(_,PStr[{pstr_desc=Pstr_eval({pexp_desc=(Pexp_function(_,_,Pfunction_cases(cases,_,_))|Pexp_match(_,cases)|Pexp_try(_,cases));_},_);_}])|Pexp_function(_,_,Pfunction_cases(cases,_,_))|Pexp_match(_,cases)|Pexp_try(_,cases));_},_)->parenze_exp_in_match_casecasesexp|Exp{pexp_desc;_},_->(matchpexp_descwith|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(_,Some(els,_))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_constraint_|Pexp_field_);_}ase0))whene0==exp->false|Pexp_record(_,Somee0)whene0==exp->true|Pexp_overridefieldswhenList.existsfields~f:(fun(_,e0)->e0==exp)->exposed_right_expSequenceexp|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|_,expwhenctx_sensitive_to_trailing_attributesctx&&Exp.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