123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Rewriting on Terms} *)moduleT=TermmoduleFmt=CCFormatletsection=Util.Section.make"rewrite"letstat_term_rw=Util.mk_stat"rw.steps_term"letprof_term_rw=ZProf.make"rw.term"letstat_lit_rw=Util.mk_stat"rw.steps_lit"letprof_lit_rw=ZProf.make"rw.lit"(* do we rewrite literals of the form [t = u]? *)letallow_pos_eqn_rewrite_=reffalsetypeterm=Term.ttypeproof=Proof.steptypeterm_rule={term_head:ID.t;(* head symbol of LHS *)term_args:termlist;(* arguments *)term_arity:int;(* [length args] *)term_lhs:term;(* [lhs = head args] *)term_rhs:term;term_proof:proof;}typelit_rule={lit_lhs:Literal.t;lit_rhs:Literal.tlistlist;(* list of clauses *)lit_proof:proof;}letcompare_trr1r2=CCOrd.(T.comparer1.term_lhsr2.term_lhs<?>(T.compare,r1.term_rhs,r2.term_rhs))letcompare_lrr1r2=letopenCCOrd.InfixinLiteral.comparer1.lit_lhsr2.lit_lhs<?>(CCList.compare(CCList.compareLiteral.compare),r1.lit_rhs,r2.lit_rhs)moduleTR_set=CCSet.Make(structtypet=term_ruleletcompare=compare_trend)moduleLR_set=CCSet.Make(structtypet=lit_ruleletcompare=compare_lrend)typedefined_position=Defined_pos.ttypedefined_positions=defined_positionIArray.ttyperule=|T_ruleofterm_rule|L_ruleoflit_ruleletcompare_ruler1r2=letto_int=functionT_rule_->0|L_rule_->1inbeginmatchr1,r2with|T_ruler1,T_ruler2->compare_trr1r2|L_ruler1,L_ruler2->compare_lrr1r2|T_rule_,_|L_rule_,_->CCInt.compare(to_intr1)(to_intr2)endmoduleRule_set=CCSet.Make(structtypet=ruleletcompare=compare_ruleend)typerule_set=Rule_set.ttypedefined_cst={defined_id:ID.t;defined_ty:Type.t;defined_level:intoption;mutabledefined_rules:rule_set;(* set of rewrite rules.
invariant: all these rules have [term_head = defined_id]
or are equations of type [tau] with [head tau = defined_id] *)mutabledefined_positions:defined_positionslazy_t;(* metadata on positions *)}letpp_term_ruleoutr=Fmt.fprintfout"@[<2>@[%a@] :=@ @[%a@]@]"T.ppr.term_lhsT.ppr.term_rhsletpp_term_rulesout(s:term_ruleIter.t):unit=Fmt.(within"{""}"@@hvbox@@Util.pp_iterpp_term_rule)outsletpp_lit_ruleoutr=letpp_c=CCFormat.hvbox(Util.pp_list~sep:" ∨ "Literal.pp)inFormat.fprintfout"@[<2>@[%a@] :=@ [@[<v>%a@]]@]"Literal.ppr.lit_lhs(Util.pp_list~sep:"∧"pp_c)r.lit_rhsletpp_lit_rulesout(s:lit_ruleIter.t):unit=Format.fprintfout"{@[<hv>%a@]}"(Util.pp_iterpp_lit_rule)sletpp_ruleout=function|T_ruler->Format.fprintfout"(@[%a [T]@])"pp_term_ruler|L_rulel->Format.fprintfout"(@[%a [B]@])"pp_lit_rulelletpp_rule_setout(rs:rule_set):unit=Fmt.(within"{""}"@@hvbox@@Util.pp_iterpp_rule)out(Rule_set.to_iterrs)(** Annotation on IDs that are defined. *)exceptionPayload_defined_cstofdefined_cstletas_defined_cstid=ID.payload_findid~f:(function|Payload_defined_cstc->Somec|_->None)letis_defined_cstid=CCOpt.is_some(as_defined_cstid)moduleCst_=structtypet=defined_cstletrulest=t.defined_rulesletrules_seqt=Rule_set.to_iter(rulest)letrules_term_seqt:term_ruleIter.t=rules_seqt|>Iter.filter_map(function|T_rulet->Somet|_->None)letrules_lit_seqt:lit_ruleIter.t=rules_seqt|>Iter.filter_map(functionL_rulet->Somet|_->None)letdefined_positionst=Lazy.forcet.defined_positionslettyt=t.defined_tyletlevelt=CCOpt.get_or~default:0t.defined_levelletppout(t:t):unit=Fmt.fprintfout"(@[defined_id@ :ty %a @ :rules %a@ :positions %a@])"Type.pp(tyt)pp_rule_set(rulest)Defined_pos.Arr.pp(defined_positionst)letto_string=Fmt.to_stringppendtypepseudo_rule=ID.t*termlist*termlistIter.t(* LHS id, LHS args, sequence of occurrences of same ID's arguments on RHS *)(* compute position roles for a set of rules with the given terms as LHS *)letcompute_pos_gen(l:pseudo_rulelist):defined_positions=(* ID, number of arguments *)letid,n=matchlwith|[]->assertfalse|(id,args,_)::_->id,List.lengthargsinassert(l|>List.for_all(fun(id',args',_)->ID.equalidid'&&List.lengthargs'=n));(* now compute position roles *)letpos=Array.makenDefined_pos.P_invariantinbeginIter.of_listl|>Iter.flat_map(fun(_,args,rhs)->funyield->List.iteri(funisub->yield(rhs,i,sub))args)|>Iter.iter(fun(rhs,i,arg)->beginmatchT.viewargwith|T.Varx->(* if all occurrences of [r.id] on the RHS also have [x] at this
position, the position stays invariant, otherwise
it is an accumulator *)letis_invariant=rhs|>Iter.filter_map(funargs'->letlen=List.lengthargs'iniflen>ithenSome(List.nthargs'(len-i-1))elseNone)|>Iter.for_all(funsub->matchT.viewsubwith|T.Vary->HVar.equalType.equalxy|_->false)in(* position is accumulator *)ifnotis_invariant&&pos.(i)=Defined_pos.P_invariantthen(pos.(i)<-Defined_pos.P_accumulator;);|_->(* pattern, consider this as input *)pos.(i)<-Defined_pos.P_activeend)end;IArray.of_array_unsafeposmoduleTerm=structtyperule=term_rulemoduleRule=structtypet=term_ruleletlhsr=r.term_lhsletrhsr=r.term_rhslethead_idr=r.term_headletargsr=r.term_argsletarityr=r.term_aritylettyr=T.tyr.term_rhsletproofr=r.term_proofletas_lit(r:t):Literal.t=Literal.mk_eq(lhsr)(rhsr)letvarsr=T.vars(lhsr)letvars_lr=varsr|>T.VarSet.to_listletmake_headargsterm_lhsterm_rhsproof=letterm_proof=Proof.Step.definehead(Proof.Src.internal[])[Proof.Parent.fromproof]in{term_head=head;term_args=args;term_arity=List.lengthargs;term_lhs;term_rhs;term_proof}(* constant rule [id := rhs] *)letmake_const~proofidtyrhs:t=letlhs=T.const~tyidinassert(Type.equal(T.tyrhs)(T.tylhs));ifnot(T.VarSet.is_empty@@T.varsrhs)then(Util.invalid_argf"Rule.make_const %a %a:@ invalid rule, RHS contains variables"ID.ppidT.pprhs);make_id[]lhsrhsproof(* [id args := rhs] *)letmake~proofidtyargsrhs:t=Util.debugf~section1"Making rule for %a"(funk->kID.ppid);letlhs=T.app(T.const~tyid)argsinifnot(T.VarSet.subset(T.varsrhs)(T.varslhs))then(Util.invalid_argf"Rule.make_const %a %a:@ invalid rule, RHS contains variables"ID.ppidT.pprhs);make_idargslhsrhsproofletmake_rewritten~proof~rewrite_funidtyargsrhs:t=letproof,rhs=rewrite_funrhsinmake~proofidtyargsrhsletppoutr=pp_term_ruleoutrletconv_~ctxlhsrhs=letmoduleF=TypedSTerm.ForminF.eq(Term.Conv.to_simple_termctxlhs)(Term.Conv.to_simple_termctxrhs)|>F.close_forallletto_form~ctxr=conv_~ctx(lhsr)(rhsr)letcompare=compare_trlethashr=Hash.combine2(T.hash@@lhsr)(T.hash@@rhsr)letequalr1r2=comparer1r2=0letto_string=Fmt.to_stringppendmoduleSet=structincludeTR_setletppout(s:t)=pp_term_rulesout(to_iters)endtyperule_set=Set.t(* term rules for this ID, if any *)letrules_of_idid:ruleIter.t=beginmatchas_defined_cstidwith|None->Iter.empty|Somedcst->Cst_.rules_term_seqdcstendmoduleRule_inst_set=structincludeCCSet.Make(structtypet=term_rule*Subst.t*Scoped.scopeletcompare(t1,s1,sc1)(t2,s2,sc2)=letopenCCOrd.InfixinCCInt.comparesc1sc2<?>(Rule.compare,t1,t2)<?>(Subst.compare,s1,s2)end)letppout(s:t):unit=letpp_tripleout(r,subst,sc)=Fmt.fprintfout"(@[%a@ :with %a[%d]@])"pp_term_rulerSubst.ppsubstscinFmt.fprintfout"{@[<hv>%a@]}"(Util.pp_iterpp_triple)(to_iters)end(* TODO: {b long term}
use De Bruijn indices for rewrite rules, with RuleSet.t being a
decision tree (similar to pattern-matching compilation) on head symbols
+ equality constraints for non-linear rules.
Use the Term.DB case extensively... *)letnormalize_term_max_steps(t0:term):term*Rule_inst_set.t=assert(max_steps>=0);letset=refRule_inst_set.emptyinletsc_t=0in(* scope of variables of term being normalized *)letsc_r=1inletfuel=refmax_stepsin(* compute normal form of subterm. Tail-recursive.
@param k the continuation
@return [t'] where [t'] is the normal form of [t] *)letrecreducetk=lett=Lambda.snftinmatchT.viewtwith|_when!fuel=0->kt|T.Constid->(* pick a constant rule *)beginmatchrules_of_idid|>Iter.headwith|SomerwhenT.is_constr.term_lhs->(* reduce [rhs], but no variable can be bound *)assert(T.equaltr.term_lhs);letcur_sc_r=sc_rinset:=Rule_inst_set.add(r,Subst.empty,cur_sc_r)!set;Util.incr_statstat_term_rw;decrfuel;Util.debugf~section5"@[<2>rewrite `@[%a@]`@ using `@[%a@]`@]"(funk->kT.pptRule.ppr);reducer.term_rhsk|Some_->assert(Type.is_fun(T.tyt)||Type.is_forall(T.tyt));kt(* must be a partial application *)|None->ktend|T.App(f,l)->(* first, reduce subterms *)(* assert(l != 0) *)reduce_ll(funl'->lett'=ifT.same_lll'thentelseT.appfl'inletn_l=List.lengthl'inbeginmatchT.viewfwith|T.Constid->letfind_rule=rules_of_idid|>Iter.find_map(funr->tryletn_r=Rule.arityrinlett',l_rest=ifn_l=n_rthent',[]elseifn_r<n_lthen(letl1,l2=CCList.take_dropn_rl'inT.appfl1,l2)else(raiseExit;)inletsubst'=Unif.FO.matching~pattern:(r.term_lhs,sc_r)(t',sc_t)inletcur_sc_r=sc_rinSome(r,subst',cur_sc_r,l_rest)withUnif.Fail|Exit->None)inbeginmatchfind_rulewith|None->kt'|Some(r,subst,sc_r,l_rest)->(* rewrite [t = r.lhs\sigma] into [rhs] (and normalize [rhs],
which contain variables bound by [subst]) *)Util.debugf~section5"(@[<2>rewrite `@[%a@]`@ :using `@[%a@]`@ \
:with `@[%a@]`[%d]@ :rest [@[%a@]]@])"(funk->kT.ppt'Rule.pprSubst.ppsubstsc_r(Util.pp_list~sep:","T.pp)l_rest);set:=Rule_inst_set.add(r,subst,sc_r)!set;Util.incr_statstat_term_rw;decrfuel;(* NOTE: not efficient, will traverse [t'] fully *)letrhs=Subst.FO.applySubst.Renaming.nonesubst(r.term_rhs,sc_r)in(* add leftover arguments *)letrhs=T.apprhsl_restinreducerhskend|_->kt'end)|T.Fun(arg,body)->(* term rewrite rules, because [vars(rhs)⊆vars(lhs)], map
closed terms to closed terms, so we can safely rewrite under λ *)reducebody(funbody'->assert(Type.equal(T.tybody)(T.tybody'));lett=ifT.equalbodybody'thentelse(T.fun_argbody')inkt)|T.Var_|T.DB_->kt|T.AppBuiltin(_,[])->kt|T.AppBuiltin(b,l)->reduce_ll(funl'->lett'=ifT.same_lll'thentelseT.app_builtin~ty:(T.tyt)bl'inkt')(* reduce list *)andreduce_l(l:_list)k=matchlwith|[]->k[]|t::tail->reduce_ltail(funtail'->reducet(funt'->k(t'::tail')))inreducet0(funt->t,!set)letnormalize_term?(max_steps=3)(t:term):term*Rule_inst_set.t=ZProf.with_profprof_term_rw(normalize_term_max_steps)tletnormalize_term_fst?max_stepst=fst(normalize_term?max_stepst)letnarrow_term?(subst=Unif_subst.empty)~scope_rules:sc_r(t,sc_t):_Iter.t=lett=Lambda.snftinbeginmatchT.viewtwith|T.Const_->Iter.empty(* already normal form *)|T.App(f,_)->beginmatchT.viewfwith|T.Constid->(* try to match the rules of [id] *)rules_of_idid|>Iter.filter_map(funr->trySome(r,Unif.FO.unify_full~subst(r.term_lhs,sc_r)(t,sc_t))withUnif.Fail->None)|_->Iter.emptyend|T.Fun_|T.Var_|T.DB_|T.AppBuiltin_->Iter.emptyendendmoduleLit=structtyperule=lit_rulemoduleRule=structtypet=lit_ruleletrule=Proof.Rule.mk"rw.lit"letmake~prooflit_lhslit_rhs=letlit_proof=Proof.Step.esa~rule[Proof.Parent.fromproof]in{lit_lhs;lit_rhs;lit_proof}letlhsc=c.lit_lhsletrhsc=c.lit_rhsletproofc=c.lit_proof(* conversion into regular clauses *)letas_clauses(c:t):Literals.tlist=assert(not(Literal.is_constraint@@lhsc));List.map(funrhs_c->Array.of_list(Literal.negate(lhsc)::rhs_c))(rhsc)lethead_idc=matchlhscwith|Literal.Equation(lhs,_,_)aslitwhenLiteral.is_predicate_litlit->beginmatchT.viewlhswith|T.Constid->Someid|T.App(f,_)->beginmatchT.viewfwith|T.Constid->Someid|_->assertfalseend|_->assertfalseend|Literal.Equation_->None|_->assertfalseletis_equationalc=matchlhscwith|Literal.Equation_->true|_->falseletconv_~ctxlhsrhs=letmoduleF=TypedSTerm.Formin(* put variables of [lhs] first, so that that instances of [lhs := rhs]
resemble [forall vars(lhs). (lhs = (forall …. rhs))] *)letclose_forall_ordlhsf=letmoduleTT=TypedSTerminletvars_lhs=TT.free_vars_setlhsinletvars=TT.free_varsf|>List.sort(funv1v2->letc1=Var.Set.memvars_lhsv1inletc2=Var.Set.memvars_lhsv2inifc1=c2thenVar.comparev1v2elseifc1then-1else1)inF.forall_lvarsfinletconv_litlit=Literal.Conv.to_s_form~ctxlitinletlhs=conv_litlhsinF.equivlhs(rhs|>List.map(funl->List.mapconv_litl|>F.or_)|>F.and_)|>close_forall_ordlhsletto_form~ctxr=conv_~ctx(lhsr)(rhsr)letvarsr=Iter.cons(lhsr)(Iter.of_list(rhsr)|>Iter.flat_map_lCCFun.id)|>Iter.flat_mapLiteral.Seq.vars|>T.VarSet.of_iter|>T.VarSet.to_listletcomparer1r2:int=compare_lrr1r2letpp=pp_lit_ruleendmoduleSet=structincludeLR_setletadd_clausers=Util.debugf~section5"@[<2>add rewrite rule@ `@[%a@]`@]"(funk->kRule.ppr);addrsletppouts=pp_lit_rulesout(to_iters)end(* rules on equality *)leteq_rules_:Set.tref=refSet.emptyletadd_eq_rule(r:Rule.t):unit=matchRule.lhsrwith|Literal.Equation(t,u,sign)->letty=T.tytinifsign&¬!allow_pos_eqn_rewrite_&&T.is_vart&&T.is_varuthen((* ignore positive rules *)Util.debugf~section2"@[<2>ignore positive equational rewrite `%a`@]"(funk->kRule.ppr);)elseifType.is_constty||Type.is_apptythen(eq_rules_:=Set.addr!eq_rules_;)else(Util.invalid_argf"Rewrite.Lit.add_eq_rule:@ invalid equation type `@[%a@]`@ for rule `%a`"Type.pptyRule.ppr)|_->Util.invalid_argf"Rewrite.Lit.add_eq_rule:@ non-equational rule `%a`"Rule.ppr(* term rules for this ID, if any *)letrules_of_idid:ruleIter.t=beginmatchas_defined_cstidwith|None->Iter.empty|Somedcst->Cst_.rules_lit_seqdcstendletrules_of_litlit:ruleIter.t=matchlitwith|Literal.Equation(lhs,_,_)whenLiteral.is_predicate_litlit->beginmatchT.Classic.viewlhswith|T.Classic.App(id,_)->rules_of_idid|_->Iter.emptyend|Literal.Equation_->Set.to_iter!eq_rules_|_->Iter.empty(* find rules that can apply to this literal *)letstep_lit(lit:Literal.t)=rules_of_litlit|>Iter.find_map(funr->letsubsts=Literal.matching~pattern:(r.lit_lhs,1)(lit,0)inbeginmatchIter.headsubstswith|None->None|Some(subst,tags)->Some(r,subst,tags)end)(* try to rewrite this literal, returning a list of list of lits instead *)letnormalize_clause_(lits:Literals.t):_option=leteval_llrenamingsubst(l,sc)=List.map(List.map(funlit->Literal.apply_substrenamingsubst(lit,sc)))linletstep=CCArray.find_map_i(funilit->matchstep_litlitwith|None->None|Some(rule,subst,tags)->letclauses=rule.lit_rhsinUtil.debugf~section5"@[<2>lit rewrite `@[%a@]`@ :into `@[<v>%a@]`@ :with @[%a@]@ :rule `%a`@]"(funk->kLiteral.pplit(Util.pp_list(Fmt.hvbox(Util.pp_list~sep:" ∨ "Literal.pp)))clausesSubst.ppsubstRule.pprule);Util.incr_statstat_lit_rw;Some(i,clauses,subst,rule,tags))litsinbeginmatchstepwith|None->None|Some(i,clause_chunks,subst,rule,tags)->letrenaming=Subst.Renaming.create()in(* remove rewritten literal, replace by [clause_chunks], apply
substitution (clause_chunks might contain other variables!),
distribute to get a CNF again *)letlits=CCArray.except_idxlitsiinletlits=Literal.apply_subst_listrenamingsubst(lits,0)inletclause_chunks=eval_llrenamingsubst(clause_chunks,1)inletclauses=List.rev_map(funnew_lits->Array.of_list(new_lits@lits))clause_chunksinSome(clauses,rule,subst,1,renaming,tags)endletnormalize_clauselits=ZProf.with_profprof_lit_rwnormalize_clause_litsletnarrow_lit?(subst=Unif_subst.empty)~scope_rules:sc_r(lit,sc_lit)=rules_of_litlit|>Iter.flat_map(funr->Literal.unify~subst(r.lit_lhs,sc_r)(lit,sc_lit)|>Iter.map(fun(subst,tags)->r,subst,tags))endletpseudo_rule_of_rule(r:rule):pseudo_rule=matchrwith|T_ruler->letid=Term.Rule.head_idrinletargs=Term.Rule.argsrinletrhs=Term.Rule.rhsr|>T.Seq.subterms|>Iter.filter_map(funsub->matchT.Classic.viewsubwith|T.Classic.App(id',args')whenID.equalid'id->Someargs'|_->None)inid,args,rhs|L_ruler->letview_atomid(t:term)=matchT.Classic.viewtwith|T.Classic.App(id',args')whenID.equalid'id->Someargs'|_->Noneinletview_litid(lit:Literal.t)=matchlitwith|Equation(lhs,_,_)whenLiteral.is_predicate_litlit->view_atomidlhs|_->Noneinletfail()=Util.invalid_argf"cannot compute position for rule %a"Lit.Rule.pprinbeginmatchLit.Rule.lhsrwith|Equation(lhs,_,_)aslitwhenLiteral.is_predicate_litlit->beginmatchT.Classic.viewlhswith|T.Classic.App(id,args)->(* occurrences of literals with same [id] on RHS *)letrhs=Lit.Rule.rhsr|>Iter.of_list|>Iter.flat_mapIter.of_list|>Iter.filter_map(view_litid)inid,args,rhs|_->fail()end|Literal.True|Literal.False|Literal.Equation_->fail()endmoduleRule=structtypet=ruleletof_termt=T_ruletletof_litt=L_ruletletpp=pp_ruleletto_form?(ctx=Type.Conv.create())(r:rule):TypedSTerm.t=beginmatchrwith|T_ruler->Term.Rule.to_form~ctxr|L_ruler->Lit.Rule.to_form~ctxrendletto_form_subst?(ctx=Type.Conv.create())(sp:Subst.Projection.t)(r:rule):TypedSTerm.t*_=letmoduleTT=TypedSTerminlet{Subst.Projection.renaming;scope=sc;subst}=spinbeginmatchrwith|T_rule{term_lhs;term_rhs;_}->letlhs=Subst.FO.applyrenamingsubst(term_lhs,sc)inletrhs=Subst.FO.applyrenamingsubst(term_rhs,sc)inletf=Term.Rule.conv_~ctxlhsrhsinletinst=Subst.Projection.as_inst~ctxsp(T.vars_prefix_orderterm_lhs)inf,inst|L_rule({lit_lhs;lit_rhs;_}aslit_r)->letlhs=Literal.apply_substrenamingsubst(lit_lhs,sc)inletrhs=List.map(funl->Literal.apply_subst_listrenamingsubst(l,sc))lit_rhsinletinst=Subst.Projection.as_inst~ctxsp(Lit.Rule.varslit_r)inLit.Rule.conv_~ctxlhsrhs,instendletpp_zfoutr=TypedSTerm.ZF.ppout(to_formr)letpp_tptpoutr=TypedSTerm.TPTP_THF.ppout(to_formr)letpp_in=function|Output_format.O_normal->pp|Output_format.O_zf->pp_zf|Output_format.O_tptp->pp_tptp|Output_format.O_none->(fun__->())letproof=function|T_ruler->Term.Rule.proofr|L_ruler->Lit.Rule.proofrletcontains_skolems(t:term):bool=T.Seq.symbolst|>Iter.existsID.is_skolemletmake_lit~prooflit_lhslit_rhs=L_rule(Lit.Rule.make~prooflit_lhslit_rhs)letcompareab=matcha,bwith|T_ruler1,T_ruler2->Term.Rule.comparer1r2|L_ruler1,L_ruler2->Lit.Rule.comparer1r2|T_rule_,L_rule_->-1|L_rule_,T_rule_->1exceptionE_poftletres_tc:tProof.result_tc=Proof.Result.make_tc~to_exn:(funt->E_pt)~of_exn:(functionE_pp->Somep|_->None)~compare~flavor:(fun_->`Def)~pp_in~to_form:(fun~ctxr->to_form~ctxr)~to_form_subst:(fun~ctxsubstr->to_form_subst~ctxsubstr)()letas_proofr=Proof.S.mk(proofr)(Proof.Result.makeres_tcr)letlit_as_proof_parent_substrenamingsubst(r,sc):Proof.parent=letproof=Proof.S.mk(Lit.Rule.proofr)(Proof.Result.makeres_tc(L_ruler))inProof.Parent.from_substrenaming(proof,sc)substletset_as_proof_parents(s:Term.Rule_inst_set.t):Proof.parentlist=Term.Rule_inst_set.to_iters|>Iter.map(fun(r,subst,sc)->letproof=Proof.S.mk(Term.Rule.proofr)(Proof.Result.makeres_tc(T_ruler))inProof.Parent.from_substSubst.Renaming.none(proof,sc)subst)|>Iter.to_rev_listendletallcst_:Cst_.tlistref=ref[]moduleDefined_cst=structincludeCst_(* check the ID of this rule *)letcheck_id_trid(r:term_rule):unit=ifnot(ID.equalid(Term.Rule.head_idr))then(Util.invalid_argf"Rewrite_term.Defined_cst:@ rule %a@ should have id %a"Term.Rule.pprID.ppid)letcompute_posid(s:rule_set)=letpos=Rule_set.to_iters|>Iter.mappseudo_rule_of_rule|>Iter.to_rev_list|>compute_pos_geninUtil.debugf~section3"(@[<2>defined_pos %a@ :pos (@[<hv>%a@])@])"(funk->kID.ppid(Util.pp_iterDefined_pos.pp)(IArray.to_iterpos));posletcheck_rulesidrules=Rule_set.iter(function|T_ruler->check_id_tridr|_->())rules(* main builder *)letmake_levelidtyrules:t=check_rulesidrules;{defined_id=id;defined_level=level;defined_ty=ty;defined_rules=rules;defined_positions=lazy(compute_posidrules);}letdeclare?levelid(rules:rule_set):t=(* declare that [id] is a defined constant of level [l+1] *)Util.debugf~section2"@[<2>declare %a@ as defined constant@ :rules %a@]"(funk->kID.ppidpp_rule_setrules);letty=ifRule_set.is_emptyrulesthen(Util.invalid_argf"cannot declare %a as defined constant with empty set of rules"ID.ppid;);beginmatchRule_set.chooseruleswith|T_rules->Term.Rule.tys|L_rule_->Type.propendinletdcst=make_levelidtyrulesinID.set_payloadid(Payload_defined_cstdcst);CCList.Ref.pushallcst_dcst;dcstletadd_rule(dcst:t)(r:rule):unit=beginmatchrwith|T_ruler->check_id_trdcst.defined_idr;|L_rule_->()end;letrules=Rule_set.addr(rulesdcst)indcst.defined_rules<-rules;dcst.defined_positions<-lazy(compute_posdcst.defined_idrules);(* update positions *)()letadd_term_rule(dcst:t)(r:term_rule):unit=add_ruledcst(T_ruler)letadd_lit_rule(dcst:t)(r:lit_rule):unit=add_ruledcst(L_ruler)letadd_term_rule_ldcst=List.iter(add_term_ruledcst)letadd_lit_rule_ldcst=List.iter(add_lit_ruledcst)letadd_eq_rule=Lit.add_eq_ruleletadd_eq_rule_l=List.iteradd_eq_ruleletdeclare_or_addid(rule:rule):unit=matchas_defined_cstidwith|Somec->Util.debugf~section2"@[<2>add rule@ :to %a@ :rule %a@]"(funk->kID.ppidpp_rulerule);add_rulecrule|None->ignore(declare?level:Noneid(Rule_set.singletonrule))(* make a single rule [proj (C … x_i …) --> x_i] *)letmk_rule_proj_(p:Ind_ty.projector)proof:rule=leti=Ind_ty.projector_idxpinletid=Ind_ty.projector_idpinletcstor=Ind_ty.projector_cstorpinletty_proj=Ind_ty.projector_typin(* build the variable arguments *)letty_cstor=cstor.Ind_ty.cstor_tyinletn_ty_vars,_,_=Type.open_poly_funty_cstorinletty_vars=CCList.initn_ty_vars(funi->HVar.make~ty:Type.tTypei)inlet_,ty_args,_=Type.applyty_cstor(List.mapType.varty_vars)|>Type.open_poly_funinletvars=List.mapi(funity->HVar.make(i+n_ty_vars)~ty)ty_argsin(* the term [cstor … x_i …] *)lett=T.app_full(T.const~ty:ty_cstorcstor.Ind_ty.cstor_name)(List.mapType.varty_vars)(List.mapT.varvars)inletrhs=T.var(List.nthvarsi)inT_rule(Term.Rule.make~proofidty_proj(List.mapT.varty_vars@[t])rhs)letdeclare_proj~proof(p:Ind_ty.projector):unit=letp_id=Ind_ty.projector_idpinbeginmatchas_defined_cstp_idwith|Some_->Util.invalid_argf"cannot declare proj %a, already defined"ID.ppp_id|None->letrule=mk_rule_proj_pproofinUtil.debugf~section3"(@[declare-proj %a@ :rule %a@])"(funk->kID.ppp_idRule.pprule);ignore(declare?level:Nonep_id(Rule_set.singletonrule))end(* make a single rule [C (proj_1 x)…(proj_n x) --> x] *)letmk_rule_cstor_(c:Ind_ty.constructor)proof:rule=letc_id=c.Ind_ty.cstor_nameinletprojs=List.mapsndc.Ind_ty.cstor_argsinassert(projs<>[]);(* make type variables *)letc_ty=c.Ind_ty.cstor_tyinletn_ty_vars,_,_=Type.open_poly_func_tyinletty_vars=CCList.initn_ty_vars(funi->HVar.make~ty:Type.tTypei)in(* build LHS *)let_,_,ty_x=Type.applyc_ty(List.mapType.varty_vars)|>Type.open_poly_funinletx=HVar.make~ty:ty_xn_ty_varsinletargs=List.map(funproj->T.app_full(T.const~ty:(Ind_ty.projector_typroj)(Ind_ty.projector_idproj))(List.mapType.varty_vars)[T.varx])projsinletrhs=T.varxinT_rule(Term.Rule.make~proofc_idc_ty(List.mapT.varty_vars@args)rhs)letdeclare_cstor~proof(c:Ind_ty.constructor):unit=letc_id=c.Ind_ty.cstor_nameinifnot(CCList.is_emptyc.Ind_ty.cstor_args)then(beginmatchas_defined_cstc_idwith|Some_->Util.invalid_argf"cannot declare cstor %a, already defined"ID.ppc_id|None->letrule=mk_rule_cstor_cproofinUtil.debugf~section3"(@[declare-cstor %a@ :rule %a@])"(funk->kID.ppc_idRule.pprule);ignore(declare?level:Nonec_id(Rule_set.singletonrule):t)end)endletall_cstk=List.iterk!allcst_letall_rules=all_cst|>Iter.flat_mapDefined_cst.rules_seqlet()=Options.add_opts["--rw-pos-eqn",Arg.Setallow_pos_eqn_rewrite_," do rewriting on positive equations";"--no-rw-pos-eqn",Arg.Clearallow_pos_eqn_rewrite_," no rewriting on positive equations";]