1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323(**************************************************************************)(* *)(* 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=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_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.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_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