123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470(************************************************************************)(* * The Rocq Prover / The Rocq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openUtilopenConstropenNamesopenPatternletdebug=CDebug.create~name:"dnet-decomp"()(* Discrimination nets with bounded depth.
See the module dn.ml for further explanations.
Eduardo (5/8/97). *)letdnet_depth=ref8typeterm_label=|GRLabelofGlobRef.t|ProjLabelofProjection.Repr.t*int(** [ProjLabel (p, n)] represents a possibly partially applied projection [p]
with [n] arguments missing to be fully applied. [n] is always zero for
labels derived from [Proj] terms but can be greater than zero for labels
derived from compatibility constants. *)|ProdLabel|SortLabel|CaseLabel|LamLabelletcompare_term_labelt1t2=matcht1,t2with|GRLabelgr1,GRLabelgr2->GlobRef.UserOrd.comparegr1gr2|ProjLabel(p1,n1),ProjLabel(p2,n2)->letc=Int.comparen1n2inifc<>0thencelse(Projection.Repr.UserOrd.comparep1p2)|_->Stdlib.comparet1t2(** OK *)letpr_term_label(l:term_label)=letopenPpinmatchlwith|GRLabelgr->str"GRLabel("++GlobRef.printgr++str")"|ProjLabel(proj,i)->str"ProjLabel("++Projection.Repr.printproj++str", "++inti++str")"|ProdLabel->str"ProdLabel"|SortLabel->str"SortLabel"|CaseLabel->str"CaseLabel"|LamLabel->str"LamLabel"type'reslookup_res='resDn.lookup_res=Labelof'res|Nothing|Everythingletpr_lookup_respr_resr=letopenPpinmatchrwith|Labellbl->str"Label("++hv2(pr_reslbl)++str")"|Nothing->str"Nothing"|Everything->str"Everything"(* let eta_reduce = Reductionops.shrink_eta *)letevaluable_constantcenvts=(* This is a hack to work around a broken Print Module implementation, see
bug #2668. *)(ifEnviron.mem_constantcenvthenEnviron.evaluable_constantcenvelsetrue)&&(matchtswithNone->true|Somets->Structures.PrimitiveProjections.is_transparent_constanttsc)letevaluable_namedidenvts=(tryEnviron.evaluable_namedidenvwithNot_found->true)&&(matchtswithNone->true|Somets->TransparentState.is_transparent_variabletsid)letevaluable_projectionp_envts=(matchtswithNone->true|Somets->TransparentState.is_transparent_projectiontsp)letdecomp_constant(c:Names.Constant.t)(args:'alist):(Names.Projection.Repr.t*int)option*'alist=matchStructures.PrimitiveProjections.find_optcwith|None->(None,args)|Somep->letn_args_needed=Names.Projection.Repr.nparsp+1in(* +1 for the record value itself *)letn_args_given=List.lengthargsinletn_args_missing=max(n_args_needed-n_args_given)0inletn_args_drop=min(n_args_needed-1)n_args_givenin(* we do not drop the record value from the stack *)(Some(p,n_args_missing),List.skipnn_args_dropargs)letlabel_of_opaque_constantcstack=matchdecomp_constantcstackwith|(None,stack)->(GRLabel(ConstRefc),stack)|(Some(p,i),stack)->(ProjLabel(p,i),stack)typeconstr_res=(term_label*partial_constrlist)lookup_resandpartial_constr=|ConstrofEConstr.t|PartialConstrofconstr_resletrecpr_constr_respr_constr(cr:constr_res)=letopenPpinletpr_partial_constr(pc:partial_constr)=matchpcwith|Constrc->str"Constr("++hv2(pr_constrc)++str")"|PartialConstrpc->str"PartialConstr(["++hv2(pr_constr_respr_constrpc)++str"])"inletaux(lbl,pcs)=pr_term_labellbl++str","++prlist_with_sep(fun()->str",")pr_partial_constrpcsinpr_lookup_resauxcrletdecomp_lambda_constrenvsigmatsdecomp:EConstr.t->EConstr.t->constr_res=letresdsp=matchdswith|[]->assertfalse|ty::ds->letacc=Label(LamLabel,[Constrty;p])inletfnaccty=(Label(LamLabel,[Constrty;PartialConstracc]))inletres=List.fold_leftfnaccdsinresinletrecdecomp_appcstack=letk=EConstr.kindsigmacinmatchkwith|App(f,args)->decomp_appf(Array.to_listargs@stack)|Const(c,_)->(k,decomp_constantcstack)|Proj(p,b,c)->(k,(Some(Projection.reprp,0),c::stack))|_->(k,(None,stack))inletrecgonumdsdsp:constr_res=matchdecomp_appp[]with|(Lambda(_,ty,c),(None,[]))->letds=ty::dsingo(numds+1)dsc|(_,(None,[]))->(* this is neither a lambda nor an application *)beginmatchdecomp[]pwith|_whends=[]->assertfalse|Label_->(* there are left-over lambdas and the body is discriminating *)resds(Constrp)|Nothing|Everything->Everythingend|(_asf,(None,args))->(* this is an application whose head [f] is not a projection *)letnargs=List.lengthargsinletn=minnumdsnargsinletds=List.skipnndsinletargs=List.firstn(nargs-n)argsinletp=EConstr.mkApp(EConstr.of_kindf,Array.of_listargs)inletp=EConstr.Vars.lift(-n)pinbeginmatchdecomp[]pwith|_ascwhends=[]->c(* no more remaining lambdas *)|Label_->resds(Constrp)|Nothing|Everything->Everythingend|(_,(Some(p,_),_))whenevaluable_projectionpenvts->Everything|(_,(Some(p,args_missing),args))->(* We have [num_params + |args| - args_missing] virtual arguments left. *)letparams=Projection.Repr.nparspinletnargs=List.lengthargsinlettotal_nargs=params+nargs-args_missinginletn=minnumdstotal_nargsinletds=List.skipnndsinletargs=List.firstn(max0(nargs-n))argsinletargs=List.map(func->Constrc)argsinletargs_missing=args_missing+(max0(n-nargs))inletp=Label(ProjLabel(p,args_missing),args)inbeginmatchdswith|[]->p|_->resds(PartialConstrp)endinfunty->go1[ty](* The pattern view functions below try to overapproximate βι-neutral terms up
to η-conversion. Some historical design choices are still incorrect w.r.t. to
this specification. TODO: try to make them follow the spec. *)letconstr_val_discrenvsigmatst:constr_res=(* Should we perform weak βι here? *)letopenGlobRefinletrecdecomp(stack:partial_constrlist)(t:EConstr.t):constr_res=debugPp.(fun()->str"constr_val_discr.decomp input: "++Printer.pr_leconstr_envenvsigmat);letout=matchEConstr.kindsigmatwith|App(f,l)->decomp(Array.fold_right(funal->Constra::l)lstack)f|Proj(p,_,c)whenevaluable_projection(Projection.reprp)envts->Everything|Proj(p,_,c)->letp=Environ.QProjection.canonizeenvpinLabel(ProjLabel(Projection.reprp,0),Constrc::stack)|Cast(c,_,_)->decompstackc|Const(c,_)whenevaluable_constantcenvts->Everything|Const(c,_)->letc=Environ.QConstant.canonizeenvcinLabel(label_of_opaque_constantcstack)|Ind(ind_sp,_)->letind_sp=Environ.QInd.canonizeenvind_spinLabel(GRLabel(IndRefind_sp),stack)|Construct(cstr_sp,_)->letcstr_sp=Environ.QConstruct.canonizeenvcstr_spinLabel(GRLabel(ConstructRefcstr_sp),stack)|Varidwhenevaluable_namedidenvts->Everything|Varid->Label(GRLabel(VarRefid),stack)|Prod(n,d,c)->Label(ProdLabel,[Constrd;Constrc])|Lambda(_,d,c)whenList.is_emptystack->decomp_lambda_constrenvsigmatsdecompdc|Lambda_->Everything|Sort_->Label(SortLabel,[])|Evar_->Everything|Case(_,_,_,_,_,c,_)->beginmatchdecompstackcwith|Label(GRLabel(ConstructRef_),_)->Everything(* over-approximating w.r.t. [fMATCH] *)|(Label_|Nothing)asres->Label(CaseLabel,PartialConstrres::stack)|Everything->Everythingend|Rel_|Meta_|LetIn_|Fix_|CoFix_|Int_|Float_|String_|Array_->NothingindebugPp.(fun()->str"constr_val_discr.decomp output: "++pr_constr_res(Printer.pr_leconstr_envenvsigma)out);outanddecomp_partial(stack:partial_constrlist)(t:partial_constr):constr_res=matchtwith|Constrt->decompstackt|PartialConstrres->resindecomp_partial[]ttypepat_res=(term_label*partial_patlist)optionandpartial_pat=|Patternofconstr_pattern|PartialPatofpat_resletrecpr_pat_respr_pat(cr:pat_res)=letopenPpinletpr_partial_pat(pc:partial_pat)=matchpcwith|Patternc->str"Pattern("++hv2(pr_patc)++str")"|PartialPatpc->str"PartialPat(["++hv2(pr_pat_respr_patpc)++str"])"inletaux(lbl,pcs)=pr_term_labellbl++str","++prlist_with_sep(fun()->str",")pr_partial_patpcsinmatchcrwith|Somex->str"Some("++hv2(auxx)++str")"|None->str"None"letdecomp_lambda_patenvtsdecomp:constr_pattern->constr_pattern->pat_res=letresdsp=matchdswith|[]->assertfalse|ty::ds->letacc=Some(LamLabel,[Patternty;p])inletfnaccty=Some(LamLabel,[Patternty;PartialPatacc])inletres=List.fold_leftfnaccdsinresinletrecdecomp_apppstack=matchpwith|PApp(f,args)->decomp_appf(Array.to_listargs@stack)|PRef(ConstRefc)->(p,decomp_constantcstack)|PProj(pr,c)->(p,(Some(Projection.reprpr,0),c::stack))|_->(p,(None,stack))inletrecgonumdsdsp:pat_res=matchdecomp_appp[]with|(PLambda(_,ty,c),(None,[]))->letds=ty::dsingo(numds+1)dsc|(_,(None,[]))->(* this is neither a lambda nor an application *)beginmatchdecomp[]pwith|_whends=[]->assertfalse|Some_->(* there are left-over lambdas and the body is discriminating *)resds(Patternp)|None->Noneend|(_asf,(None,args))->(* this is an application whose head [f] is not a projection *)letnargs=List.lengthargsinletn=minnumdsnargsinletds=List.skipnndsinletargs=List.firstn(nargs-n)argsinletp=PApp(f,Array.of_listargs)inletp=Patternops.lift_pattern(-n)pinbeginmatchdecomp[]pwith|_ascwhends=[]->c(* no more remaining lambdas *)|Some_->(* there are left-over lambdas and the body is discriminating *)resds(Patternp)|None->Noneend|(_,(Some(p,_),_))whenevaluable_projectionpenvts->None|(_,(Some(p,args_missing),args))->(* We have [num_params + |args| - args_missing] virtual arguments left. *)letparams=Projection.Repr.nparspinletnargs=List.lengthargsinlettotal_nargs=params+nargs-args_missinginletn=minnumdstotal_nargsinletds=List.skipnndsinletargs=List.firstn(max0(nargs-n))argsinletargs=List.map(func->Patternc)argsinletargs_missing=args_missing+(max0(n-nargs))inletp=(Some(ProjLabel(p,args_missing),args))inbeginmatchdswith|[]->p|_->resds(PartialPatp)endinfunty->go1[ty]letconstr_pat_discrenvtsp:pat_res=letopenGlobRefinletrecdecomp(stack:partial_patlist)(p:constr_pattern):pat_res=debugPp.(fun()->str"constr_pat_discr.decomp input: "++Printer.pr_lconstr_pattern_envenvEvd.emptyp);letout=matchpwith|PApp(f,args)->decomp((Array.map_to_list(funp->Patternp)args)@stack)f|PProj(p,c)whenevaluable_projection(Projection.reprp)envts->None|PProj(p,c)->letp=Environ.QProjection.canonizeenvpinSome(ProjLabel(Projection.reprp,0),Patternc::stack)|PRef((IndRef_)asref)|PRef((ConstructRef_)asref)->letref=Environ.QGlobRef.canonizeenvrefinSome(GRLabelref,stack)|PRef(VarRefv)whenevaluable_namedvenvts->None|PRef((VarRef_)asref)->Some(GRLabelref,stack)|PRef(ConstRefc)whenevaluable_constantcenvts->None|PRef(ConstRefc)->letc=Environ.QConstant.canonizeenvcinSome(label_of_opaque_constantcstack)|PVarvwhenevaluable_namedvenvts->None|PVarv->Some(GRLabel(VarRefv),stack)|PProd(_,d,c)whenstack=[]->Some(ProdLabel,[Patternd;Patternc])|PLambda(_,d,c)whenList.is_emptystack->decomp_lambda_patenvtsdecompdc|PSortswhenstack=[]->Some(SortLabel,[])|PCase(_,_,p,_)|PIf(p,_,_)->beginmatchdecompstackpwith|Some(GRLabel(ConstructRef_),_)->None(* over-approximating w.r.t. [fMATCH] *)|Some_asres->Some(CaseLabel,PartialPatres::stack)|None->Noneend|_->NoneindebugPp.(fun()->str"constr_pat_discr.decomp output: "++pr_pat_res(Printer.pr_lconstr_pattern_envenvEvd.empty)out);outanddecomp_partial(stack:partial_patlist)(t:partial_pat):pat_res=matchtwith|Patternp->decompstackp|PartialPatres->resindecomp_partial[]pletconstr_pat_discr_syntacticenvp=letopenGlobRefinletrecdecomp(stack:partial_patlist)(p:constr_pattern):pat_res=debugPp.(fun()->str"constr_pat_discr_syntactic.decomp input: "++Printer.pr_lconstr_pattern_envenvEvd.emptyp);letout=matchpwith|PApp(f,args)->decomp((Array.map_to_list(funp->Patternp)args)@stack)f|PProj(p,c)->letp=Environ.QProjection.canonizeenvpinSome(ProjLabel(Names.Projection.reprp,0),Patternc::stack)|PRef((IndRef_)asref)|PRef((ConstructRef_)asref)->letref=Environ.QGlobRef.canonizeenvrefinSome(GRLabelref,stack)|PRef((VarRef_)asref)->Some(GRLabelref,stack)|PRef(ConstRefc)->letc=Environ.QConstant.canonizeenvcinSome(label_of_opaque_constantcstack)|PVarv->Some(GRLabel(VarRefv),stack)|PProd(_,d,c)whenstack=[]->Some(ProdLabel,[Patternd;Patternc])|PLambda(_,d,c)whenList.is_emptystack->decomp_lambda_patenv(SomeTransparentState.full)decompdc|PSortswhenstack=[]->Some(SortLabel,[])|PCase(_,_,p,_)|PIf(p,_,_)->Some(CaseLabel,Patternp::stack)|_->NoneindebugPp.(fun()->str"constr_pat_discr_syntactic.decomp output: "++pr_pat_res(Printer.pr_lconstr_pattern_envenvEvd.empty)out);outanddecomp_partial(stack:partial_patlist)(t:partial_pat):pat_res=matchtwith|Patternp->decompstackp|PartialPatres->resindecomp_partial[]pletbounded_constr_pat_discrenvst(t,depth)=ifInt.equaldepth0thenNoneelsematchconstr_pat_discrenvsttwith|None->None|Some(c,l)->Some(c,List.map(func->(c,depth-1))l)letbounded_constr_pat_discr_syntacticenv(t,depth)=ifInt.equaldepth0thenNoneelsematchconstr_pat_discr_syntacticenvtwith|None->None|Some(c,l)->Some(c,List.map(func->(c,depth-1))l)letbounded_constr_val_discrenvstsigma(t,depth)=ifInt.equaldepth0thenNothingelsematchconstr_val_discrenvsigmasttwith|Label(c,l)->Label(c,List.map(func->(c,depth-1))l)|Nothing->Nothing|Everything->EverythingmoduleMake=functor(Z:Map.OrderedType)->structmoduleY=structtypet=term_labelletcompare=compare_term_labelendmoduleDn=Dn.Make(Y)(Z)typet=Dn.ttypepattern=Dn.patternletpatternenvstpat=Dn.pattern(bounded_constr_pat_discrenvst)(Patternpat,!dnet_depth)letpattern_syntacticenvpat=Dn.pattern(bounded_constr_pat_discr_syntacticenv)(Patternpat,!dnet_depth)letconstr_patternenvsigmastpat=letmkp=matchbounded_constr_val_discrenvstsigmapwith|Labell->Somel|Everything|Nothing->NoneinDn.patternmk(Constrpat,!dnet_depth)letempty=Dn.emptyletadd=Dn.addletrmv=Dn.rmvletlookupenvsigmastdnt=Dn.lookupdn(bounded_constr_val_discrenvstsigma)(Constrt,!dnet_depth)end