123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160(** {1 Inductive Constants and Cases}
Skolem constants of an inductive type, coversets, etc. required for
inductive reasoning. *)openLogtkmoduleT=TermexceptionInvalidDeclofstringexceptionNotAnInductiveConstantofID.tlet()=letspf=CCFormat.sprintfinPrintexc.register_printer(function|InvalidDeclmsg->Some(spf"@[<2>invalid declaration:@ %s@]"msg)|NotAnInductiveConstantid->Some(spf"%a is not an inductive constant"ID.ppid)|_->None)letinvalid_declm=raise(InvalidDeclm)letinvalid_declfm=CCFormat.ksprintfm~f:invalid_decltypet={cst_id:ID.t;cst_args:Type.tlist;cst_ty:Type.t;(* [cst_ty = cst_id cst_args] *)cst_ity:Ind_ty.t;(* the corresponding inductive type *)cst_is_sub:bool;(* sub-constant? *)cst_depth:int;(* how many induction lead to this one? *)}exceptionPayload_cstoft(** {5 Inductive Constants} *)letto_termc=Term.const~ty:c.cst_tyc.cst_idletidc=c.cst_idlettyc=c.cst_tyletequalab=ID.equala.cst_idb.cst_idletcompareab=ID.comparea.cst_idb.cst_idlethasha=ID.hasha.cst_idmoduleCst_set=CCSet.Make(structtypet_=ttypet=t_letcompare=compareend)letdepthc=c.cst_depthletsame_typec1c2=Type.equalc1.cst_tyc2.cst_tyletppoutc=ID.ppoutc.cst_idleton_new_cst=Signal.create()letid_as_cstid=ID.payload_findid~f:(function|Payload_cstc->Somec|_->None)letid_as_cst_exnid=matchid_as_cstidwith|None->raise(NotAnInductiveConstantid)|Somec->cletid_is_cstid=matchid_as_cstidwithSome_->true|_->falseletis_subc=c.cst_is_subletid_is_subid=id_as_cstid|>CCOpt.map_or~default:falseis_sub(** {5 Creation of Coverset and Cst} *)letn_=ref0letmake_skolemty:ID.t=letc=ID.makef"#%s_%d"(Type.manglety)!n_inincrn_;(* declare as a skolem *)letk=ifInd_ty.is_inductive_typetythenID.K_indelseID.K_normalinID.set_payloadc(ID.Attr_skolemk);c(* declare new constant *)letdeclare~depth~is_subidty=Util.debugf~section:Ind_ty.section2"@[<2>declare new inductive symbol@ `@[%a : %a@]`@ :depth %d :is_sub %B@]"(funk->kID.ppidType.pptydepthis_sub);assert(not(id_is_cstid));assert(Type.is_groundty);(* constant --> not polymorphic *)letity,args=matchInd_ty.as_inductive_typetywith|Some(t,l)->t,l|None->invalid_declf"cannot declare a constant of type %a"Type.pptyin(* build coverset and constant, mutually recursive *)letcst={cst_id=id;cst_ty=ty;cst_depth=depth;cst_ity=ity;cst_args=args;cst_is_sub=is_sub;}inID.set_payloadid(Payload_cstcst)~can_erase:(function|ID.Attr_skolemID.K_ind->true(* special case: promotion from skolem to inductive const *)|_->false);(* return *)Signal.sendon_new_cstcst;cstletmake?(depth=0)~is_sub(ty:Type.t):t=letid=make_skolemtyindeclare~depth~is_subidtyletdominates(c1:t)(c2:t):bool=c1.cst_depth<c2.cst_depth(** {2 Inductive Skolems} *)typeind_skolem=ID.t*Type.tletind_skolem_compare=CCOrd.pairID.compareType.compareletind_skolem_equalab=ind_skolem_compareab=0letid_is_ind_skolem(id:ID.t)(ty:Type.t):bool=letn_tyvars,ty_args,ty_ret=Type.open_poly_funtyinn_tyvars=0&&ty_args=[](* constant *)&&Ind_ty.is_inductive_typety_ret&&Ind_ty.is_recursive(Ind_ty.as_inductive_type_exnty_ret|>fst)&&Type.is_groundty&&(id_is_cstid||(not(Ind_ty.is_constructorid)&¬(Rewrite.is_defined_cstid)))letind_skolem_depth(id:ID.t):int=matchid_as_cstidwith|None->0|Somec->depthc(* find inductive constant candidates in terms *)letfind_ind_skolemst:ind_skolemIter.t=T.Seq.subtermst|>Iter.filter_map(funt->matchT.viewtwith|T.Constid->letty=T.tytinifid_is_ind_skolemidtythen(letn_tyvars,ty_args,_=Type.open_poly_funtyinassert(n_tyvars=0&&ty_args=[]);Some(id,ty))elseNone|_->None)