123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144moduleU=Unif_substmoduleT=TermmoduleH=HVarmoduleS=SubstmoduleIntSet=PUnif.IntSetmodulePUP=PragUnifParamsletelim_vars=refIntSet.emptyletident_vars=refIntSet.emptymoduleMake(S:sigvalst:Flex_state.tend)=structmoduleSU=SolidUnif.Make(S)letget_opk=Flex_state.get_exnkS.stletdelay_res=resletiter_rule?(flex_same=false)~counter~scopetudepth=JP_unif.iterate~flex_same~scope~countertu[]|>OSeq.map(CCOpt.map(funs->U.substs,depth+1))letimit_rule~counter~scopetudepth=JP_unif.imitate~scope~countertu[]|>OSeq.map(funx->Some(U.substx,depth+1))leths_proj_flex_rigid~counter~scope~flexudepth=letflex_var=T.as_var_exn(T.head_termflex)inletflex_hd_id=HVar.idflex_varinifIntSet.memflex_hd_id!ident_varsthenOSeq.emptyelseletprojections=PUnif.proj_hs~counter~scope~flexuinletsimp_projs,func_projs=CCList.partition(funsub->letbinding,_=Subst.FO.derefsub(T.head_termflex,scope)inlet_,body=T.open_funbindinginT.is_bvarbody)projectionsinletsimp_projs=CCList.map(funs->Some(s,depth))simp_projsinletfunc_projs=CCList.map(funs->Some(s,depth+1))func_projsinOSeq.append(OSeq.of_listsimp_projs)(ifCCList.is_emptyfunc_projsthenOSeq.emptyelsedelaydepth(OSeq.of_listfunc_projs))letproj_rule~counter~scopestdepth=letmaybe_projectu=letflex_hd_id=HVar.id(T.as_var_exn(T.head_termu))inifIntSet.memflex_hd_id!ident_varsthenOSeq.emptyelseJP_unif.project_onesided~scope~counteruinOSeq.append(maybe_projects)(maybe_projectt)|>OSeq.map(funx->Some(U.substx,depth+1))letident_rule~counter~scopetudepth=JP_unif.identify~scope~countertu[]|>OSeq.map(funx->letsubst=U.substxin(* variable introduced by identification *)letsubs_t=T.of_term_unsafe(fst(snd(List.hd(Subst.to_listsubst))))inletnew_var,_=T.as_app(snd(T.open_funsubs_t))inletnew_var_id=HVar.id(T.as_var_exnnew_var)in(* remembering that we introduced this var in identification *)ident_vars:=IntSet.addnew_var_id!ident_vars;Some(subst,depth+1))letrenamer~countert0st1s=letlhs,rhs,unifscope,us=U.FO.rename_to_new_scope~countert0st1sinlhs,rhs,unifscope,U.substusletdeciders~counter()=letpattern=ifget_opPUP.k_pattern_deciderthen[funstsub->[U.subst@@PatternUnif.unify_scoped~subst:(U.of_substsub)~counterst]]else[]inletsolid=ifget_opPUP.k_solid_deciderthen[funstsub->List.mapU.subst@@SU.unify_scoped~subst:(U.of_substsub)~counterst]else[]inletfixpoint=ifget_opPUP.k_fixpoint_deciderthen[funstsub->[U.subst@@FixpointUnif.unify_scoped~subst:(U.of_substsub)~counterst]]else[]infixpoint@pattern@solid(* pattern @ fixpoint @ solid *)lethead_classifiers=matchT.view@@T.head_termswith|T.Varx->`Flexx|_->`Rigidletoracle~counter~scope(s,_)(t,_)depth=lethd_t,hd_s=T.head_terms,T.head_termtinifT.is_varhd_t&&T.is_varhd_s&&T.equalhd_shd_t&&IntSet.mem(HVar.id@@T.as_var_exnhd_t)!elim_varsthen(OSeq.empty)else(matchhead_classifiers,head_classifiertwith|`Flexx,`FlexywhenHVar.equalType.equalxy->(* eliminate + iter *)delaydepth@@OSeq.append(OSeq.map(funx->Somex)@@PUnif.elim_subsets_rule~max_elims:None~elim_vars~counter~scopestdepth)(delaydepth@@iter_rule~flex_same:true~counter~scopestdepth)|`Flex_,`Flex_->(* all rules *)letproj_ident=OSeq.append(proj_rule~counter~scopestdepth)(delaydepth@@(ident_rule~counter~scopestdepth))inOSeq.appendproj_ident(delaydepth@@iter_rule~counter~scopestdepth)|`Flex_,`Rigid|`Rigid,`Flex_->letflex,rigid=ifTerm.is_var(T.head_terms)thens,telset,sin(* let delay_fr imit =
if depth > 4 then OSeq.append (OSeq.take (depth*2) (OSeq.repeat None)) imit else imit in *)OSeq.append(imit_rule~counter~scopestdepth)(hs_proj_flex_rigid~counter~scope~flexrigiddepth)|_->assertfalse)letunify_scoped=letcounter=ref0inletmoduleJPFullParams=structexceptionNotInFragment=PatternUnif.NotInFragmentexceptionNotUnifiable=PatternUnif.NotUnifiabletypeflag_type=intletflex_state=S.stletinit_flag=(0:flag_type)letidentify_scope=renamer~counterletfrag_algs=deciders~counterletpb_oraclest(f:flag_type)_scope=oracle~counter~scopestfletoracle_composer=Flex_state.get_exnPUP.k_oracle_composerS.stendinletmoduleJPFull=UnifFramework.Make(JPFullParams)in(funxy->elim_vars:=IntSet.empty;ident_vars:=IntSet.empty;OSeq.map(CCOpt.mapUnif_subst.of_subst)(JPFull.unify_scopedxy))end