Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file Cover_set.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Cover Set} *)openLogtkmoduleT=TermmoduleFmt=CCFormat(** Use for reasoning by case during induction *)typecst=Ind_cst.ttypeterm=Term.ttypecase={case_top:cst;(* copy of the coverset's top constant *)case_term:Term.t;(* rhs *)case_kind:[`Base|`Rec];(* at least one sub-constant? *)case_sub:cstlist;(* set of sub-constants *)case_skolems:(ID.t*Type.t)list;(* set of other skolems *)}typet={cs_top:cst;(* inductive constant that is unique to that set *)cs_cases:caselist;(* cases that also are unique *)}(** {5 Inductive Case} *)moduleCase=structtypet=caseletequalab=Ind_cst.equala.case_topb.case_top&&T.equala.case_termb.case_termletcompareab=CCOrd.Infix.(Ind_cst.comparea.case_topb.case_top<?>(Term.compare,a.case_term,b.case_term))lethasha=Hash.combine2(Ind_cst.hasha.case_top)(T.hasha.case_term)letppoutc=Fmt.hovboxT.ppoutc.case_termletto_termc=c.case_termletto_litc=letlhs=Ind_cst.to_termc.case_topinLiteral.mk_eqlhs(to_termc)letsame_cstc1c2=Ind_cst.equalc1.case_topc2.case_topletis_recc=c.case_kind=`Recletis_basec=c.case_kind=`Baseletsub_constantsc=c.case_subletskolemsc=c.case_skolemsendlettopt=t.cs_toplettyt=Ind_cst.ty(topt)letcases?(which=`All)(set:t):caseIter.t=letseq=Iter.of_listset.cs_casesinbeginmatchwhichwith|`All->seq|`Base->Iter.filterCase.is_baseseq|`Rec->Iter.filterCase.is_recseqendletppout(set:t):unit=Format.fprintfout"(@[<hv2>coverset of type `@[%a@]`@ :top `%a`@ :cases [@[<hv>%a@]]@])"Type.pp(tyset)Ind_cst.pp(topset)(Util.pp_listCase.pp)set.cs_casesletskolems(c:t)=Iter.of_listc.cs_cases|>Iter.flat_map_lCase.skolemsletsub_constants(set:t)=Iter.of_listset.cs_cases|>Iter.flat_map_lCase.sub_constants(* type declarations required by [c] *)letdeclarations(set:t)=letdecl_of_cstc=Ind_cst.idc,Ind_cst.tycinletseq1=sub_constantsset|>Iter.mapdecl_of_cstandseq2=skolemssetandtop=decl_of_cstset.cs_topinIter.constop(Iter.appendseq1seq2)moduleState_=struct(* state for creating coverset *)typet={cst:Ind_cst.Cst_set.t;(* raw set of constants *)others:(ID.t*Type.t)list;(* non-inductive terms *)}letempty={cst=Ind_cst.Cst_set.empty;others=[];}(* state monad *)type'am=t->t*'a(* state monad inside a backtracking monad *)type'amm=t->(t*'a)listletfail:_mm=fun_->[]letyield:'a->'amm=funxst->[st,x]letyield_l:'alist->'amm=funlst->List.map(funx->st,x)llet(>>=):'amm->('a->'bm)->'bmm=funx_mmfst->letxs=x_mmstinList.map(fun(st,x)->fxst)xslet(>|=):'amm->('a->'b)->'bmm=funx_mmfst->letxs=x_mmstinList.map(fun(st,x)->st,fx)xslet(>>>=):'amm->('a->'bmm)->'bmm=funx_mmfst->letxs=x_mmstinCCList.flat_map(fun(st,x)->fxst)xslet(>>|=):'amm->('a->'b)->'bmm=funx_mmfst->letxs=x_mmstinList.map(fun(st,x)->st,fx)xsletget:tmm=funst->[st,st]letset:t->unitm=funst_->st,()(* modify the state: add [c] to the set of cases *)letadd_sub_casec:unitmm=get>>=funst->letst={stwithcst=Ind_cst.Cst_set.addcst.cst}insetstletadd_constantidty:unitmm=get>>=funst->letst={stwithothers=(id,ty)::st.others}insetstletrecmap_l:('a->'bmm)->'alist->'blistmm=funfl->matchlwith|[]->yield[]|x::tl->fx>>>=funx'->map_lftl>>>=funtl'->yield(x'::tl')letrun:'amm->t->'alist=funmst->List.mapsnd(mst)endletmake_coverset_~cover_set_depth~depth(ty:Type.t)(ity:Ind_ty.t):t=letopenState_in(* map variables from [ity] to this concrete type *)letscope=0inletcs_top=Ind_cst.make~depth~is_sub:falsetyin(* how to make a simple skolem *)letmk_skolemty:T.tmm=letid=Ind_cst.make_skolemtyinadd_constantidty>|=fun()->T.const~tyidin(* how to make a sub-constant of type [ty] and register it in [cs_top] *)letdecl_subty:T.tmm=ifInd_ty.is_inductive_typetythen(letsub=Ind_cst.make~depth:(depth+1)~is_sub:truetyinadd_sub_casesub>|=fun()->Ind_cst.to_termsub)elsemk_skolemtyin(* list of generators of:
- member of the coverset (one of the t such that cst=t)
- set of sub-constants of this term *)letrecmake(cs_depth:int)(subst:Subst.t):T.tmm=Util.debugf~section:Ind_ty.section5"(@[make_cover_set@ :ty %a@ :depth %d@ :subst %a@])"(funk->kInd_ty.ppitycs_depthSubst.ppsubst);(* leaves: fresh constants *)ifcs_depth=0then(letty=Subst.Ty.applySubst.Renaming.nonesubst(ity.Ind_ty.ty_pattern,scope)indecl_subty)else((* inner nodes or base cases: constructors *)yield_lity.Ind_ty.ty_constructors>>>=funcstor->letf=cstor.Ind_ty.cstor_nameinletty_f=cstor.Ind_ty.cstor_tyin(* apply to ground type parameters *)letty_params=List.map(funv->letv=Type.varvinSubst.Ty.applySubst.Renaming.nonesubst(v,scope))ity.Ind_ty.ty_varsinletty_f_applied=Type.applyty_fty_paramsinletty_params=List.mapT.of_tyty_paramsinletn_ty_params,ty_args_f,_=Type.open_poly_funty_f_appliedinassert(n_ty_params=0);ifty_args_f=[]then(ifcs_depth>0thenyield(T.app(T.const~ty:ty_ff)ty_params)(* only one answer : f *)elsefail)else((* make fresh type variables and apply *)map_l(make_of_ty(cs_depth-1))ty_args_f>>|=funargs->T.app(T.const~ty:ty_ff)(ty_params@args)))(* return a new term of type [ty] *)andmake_of_tydepthty:T.tmm=letsubst=trySome(Unif.Ty.matching_same_scope~pattern:ity.Ind_ty.ty_patternty~scope)withUnif.Fail->Noneinbeginmatchsubstwith|Somesubst->makedepthsubst(* previous case *)|None->decl_subty(* not an inductive sub-case, just create a skolem symbol *)endinletsubst=Unif.Ty.matching_same_scope~pattern:ity.Ind_ty.ty_patternty~scopein(* build the toplevel values, along with a list of sub-constants
to declare *)letmake_cases=letl=makecover_set_depthsubstinl>>>=funt->(* obtain the current set of sub-constants *)get>>>=funstate->letcase={case_top=cs_top;case_term=t;case_kind=ifInd_cst.Cst_set.is_emptystate.cstthen`Baseelse`Rec;case_sub=Ind_cst.Cst_set.elementsstate.cst;case_skolems=state.others;}inyieldcaseinletcs_cases=runmake_casesemptyin{cs_top;cs_cases}(* compute coverset on the fly, if need be *)letmake?(cover_set_depth=1)~depth(ty:Type.t):t=ifcover_set_depth<=0then(Util.invalid_argf"Cover_set.make: cover_set_depth=%d must be > 0"cover_set_depth;);beginmatchInd_ty.as_inductive_typetywith|Some(ity,_)->letset=make_coverset_~cover_set_depth~depthtyityinUtil.debugf~section:Ind_ty.section2"@[<2>new coverset:@ %a@]"(funk->kppset);Util.debugf~section:Ind_ty.section5"@[<2>sub-constants:@ @[<v>%a@]@]"(funk->letpp_caseoutcase=Format.fprintfout"@[<h>case %a: sub {@[<hv>%a@]}@]"Case.ppcase(Util.pp_listID.pp)(Case.sub_constantscase|>List.rev_mapInd_cst.id)ink(Util.pp_listpp_case)set.cs_cases);set|None->Util.errorf~where:"cover_set.make""type `@[%a@]`@ is not an inductive type"Type.pptyend