123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609(** Parser-level abstract syntax. *)openLplibopenBaseopenExtraopenCommonopenPosopenCore(** Representation of a (located) identifier. *)typep_ident=strloc(** [notin id idopts] checks that [id] does not occur in [idopts]. *)letcheck_notin:string->p_identoptionlist->unit=funid->letrecnotin=function|[]->()|None::idopts->notinidopts|Some{elt=id';pos}::idopts->ifid'=idthenError.fatalpos"%s already used."idelsenotinidoptsinnotin(** [are_distinct idopts] checks that the elements of [idopts] of the form
[Some _] are pairwise distinct. *)letreccheck_distinct:p_identoptionlist->unit=function|[]->()|None::idopts->check_distinctidopts|Some{elt=id;_}::idopts->check_notinididopts;check_distinctidopts(** Identifier of a metavariable. *)typep_meta_ident=intloc(** Representation of a module name. *)typep_path=Path.tloc(** Representation of a possibly qualified (and located) identifier. *)typep_qident=Term.qidentloc(** Parser-level (located) term representation. *)typep_term=p_term_auxlocandp_term_aux=|P_Type(** TYPE constant. *)|P_Idenofp_qident*bool(** Identifier. The boolean indicates whether
the identifier is prefixed by "@". *)|P_Wild(** Underscore. *)|P_Metaofp_meta_ident*p_termarray(** Meta-variable with explicit substitution. *)|P_Pattofp_identoption*p_termarrayoption(** Pattern. *)|P_Applofp_term*p_term(** Application. *)|P_Arroofp_term*p_term(** Arrow. *)|P_Abstofp_paramslist*p_term(** Abstraction. *)|P_Prodofp_paramslist*p_term(** Product. *)|P_LLetofp_ident*p_paramslist*p_termoption*p_term*p_term(** Let. *)|P_NLitofint(** Natural number literal. *)|P_Wrapofp_term(** Term between parentheses. *)|P_Explofp_term(** Term between curly brackets. *)(** Parser-level representation of a function argument. The boolean is true if
the argument is marked as implicit (i.e., between curly braces). *)andp_params=p_identoptionlist*p_termoption*bool(** [nb_params ps] returns the number of parameters in a list of parameters
[ps]. *)letnb_params:p_paramslist->int=List.fold_left(funacc(ps,_,_)->acc+List.lengthps)0(** [get_impl_params_list l] gives the implicitness of [l]. *)letget_impl_params_list:p_paramslist->boollist=List.concat_map(fun(idopts,_,b)->List.map(fun_->b)idopts)(** [get_impl_term t] gives the implicitness of [t]. *)letrecget_impl_term:p_term->boollist=funt->get_impl_term_auxt.eltandget_impl_term_aux:p_term_aux->boollist=funt->matchtwith|P_LLet(_,_,_,_,t)->get_impl_termt|P_Prod([],t)|P_Abst([],t)->get_impl_termt|P_Prod((ys,_,b)::xs,t)->List.map(fun_->b)ys@get_impl_term_aux(P_Prod(xs,t))|P_Abst((ys,_,b)::xs,t)->List.map(fun_->b)ys@get_impl_term_aux(P_Abst(xs,t))|P_Arro(_,t)->false::get_impl_termt|P_Wrap(t)->get_impl_termt|_->[](** [p_get_args t] is like {!val:Core.Term.get_args} but on syntax-level
terms. *)letp_get_args:p_term->p_term*p_termlist=funt->letrecp_get_argstacc=matcht.eltwith|P_Appl(t,u)->p_get_argst(u::acc)|_->t,accinp_get_argst[](** Parser-level rewriting rule representation. *)typep_rule_aux=p_term*p_termtypep_rule=p_rule_auxloc(** Parser-level inductive type representation. *)typep_inductive_aux=p_ident*p_term*(p_ident*p_term)listtypep_inductive=p_inductive_auxloc(** Module to create p_term's with no positions. *)moduleP=struct(** [qiden p s] builds a [P_Iden] "@p.s". *)letqiden:Path.t->string->p_term=funps->Pos.none(P_Iden(Pos.none(p,s),true))(** [iden s] builds a [P_Iden] "@s". *)letiden:string->p_term=qiden[](** [var v] builds a [P_Iden] from [Bindlib.name_of v]. *)letvar:Term.tvar->p_term=funv->iden(Bindlib.name_ofv)(** [patt s ts] builds a [P_Patt] "$s[ts]". *)letpatt:string->p_termarrayoption->p_term=funsts->Pos.none(P_Patt(Some(Pos.nones),ts))(** [patt0 s] builds a [P_Patt] "$s". *)letpatt0:string->p_term=funs->pattsNone(** [appl t u] builds [P_Appl(t, u)]. *)letappl:p_term->p_term->p_term=funtu->Pos.none(P_Appl(t,u))(** [appl_list t ts] iterates [appl]. *)letappl_list:p_term->p_termlist->p_term=List.fold_leftappl(** [wild] builds a [P_Wild]. *)letwild=Pos.noneP_Wild(** [appl_wild t n] applies [t] to [n] underscores. *)letrecappl_wild:p_term->int->p_term=funti->ifi<=0thentelseappl_wild(appltwild)(i-1)(** [abst idopt t] builds a [P_Abst] over [t]. *)letabst:p_identoption->p_term->p_term=funidoptt->Pos.none(P_Abst([[idopt],None,false],t))(** [abst_list] iterates [abst]. *)letabst_list:p_identoptionlist->p_term->p_term=funidoptst->List.fold_rightabstidoptstletrule:p_term->p_term->p_rule=funlr->Pos.none(l,r)end(** Rewrite patterns as in Coq/SSReflect. See "A Small Scale
Reflection Extension for the Coq system", by Georges Gonthier,
Assia Mahboubi and Enrico Tassi, INRIA Research Report 6455, 2016,
@see <http://hal.inria.fr/inria-00258384>, section 8, p. 48. *)type('term,'binder)rw_patt=|Rw_Termof'term|Rw_InTermof'term|Rw_InIdInTermof'binder|Rw_IdInTermof'binder|Rw_TermInIdInTermof'term*'binder|Rw_TermAsIdInTermof'term*'bindertypep_rw_patt=(p_term,p_ident*p_term)rw_pattloc(** Parser-level representation of an assertion. *)typep_assertion=|P_assert_typingofp_term*p_term(** The given term should have the given type. *)|P_assert_convofp_term*p_term(** The two given terms should be convertible. *)(** Parser-level representation of a query command. *)typep_query_aux=|P_query_verboseofint(** Sets the verbosity level. *)|P_query_debugofbool*string(** Toggles logging functions described by string according to boolean. *)|P_query_flagofstring*bool(** Sets the boolean flag registered under the given name (if any). *)|P_query_assertofbool*p_assertion(** Assertion (must fail if boolean is [true]). *)|P_query_inferofp_term*Eval.strat(** Type inference command. *)|P_query_normalizeofp_term*Eval.strat(** Normalisation command. *)|P_query_proverofstring(** Set the prover to use inside a proof. *)|P_query_prover_timeoutofint(** Set the timeout of the prover (in seconds). *)|P_query_printofp_qidentoption(** Print information about a symbol or the current goals. *)|P_query_proofterm(** Print the current proof term (possibly containing open goals). *)typep_query=p_query_auxloc(** Parser-level representation of a tactic. *)typep_tactic_aux=|P_tac_admit|P_tac_applyofp_term|P_tac_assumeofp_identoptionlist|P_tac_fail|P_tac_generalizeofp_ident|P_tac_haveofp_ident*p_term|P_tac_induction|P_tac_queryofp_query|P_tac_refineofp_term|P_tac_refl|P_tac_rewriteofbool*p_rw_pattoption*p_term(* The boolean indicates if the equation is applied from left to right. *)|P_tac_simplofp_qidentoption|P_tac_solve|P_tac_sym|P_tac_why3ofstringoptiontypep_tactic=p_tactic_auxloc(** [is_destructive t] says whether tactic [t] changes the current goal. *)letis_destructive{elt;_}=matcheltwithP_tac_have_->false|_->true(** Parser-level representation of a proof. *)typep_subproof=p_proofsteplistandp_proofstep=Tacticofp_tactic*p_subprooflisttypep_proof=p_subprooflisttypep_proof_end_aux=|P_proof_end(** The proof is done and fully checked. *)|P_proof_admitted(** Give up current state and admit the theorem. *)|P_proof_abort(** Abort the proof (theorem not admitted). *)typep_proof_end=p_proof_end_auxloc(** Parser-level representation of modifiers. *)typep_modifier_aux=|P_mstratofTerm.match_strat(** pattern matching strategy *)|P_expoofTerm.expo(** visibility of symbol outside its modules *)|P_propofTerm.prop(** symbol properties: constant, definable, ... *)|P_opaq(** opacity *)typep_modifier=p_modifier_auxlocletis_prop{elt;_}=matcheltwithP_prop(_)->true|_->falseletis_opaq{elt;_}=matcheltwithP_opaq->true|_->falseletis_expo{elt;_}=matcheltwithP_expo(_)->true|_->falseletis_mstrat{elt;_}=matcheltwithP_mstrat(_)->true|_->false(** Parser-level representation of symbol declarations. *)typep_symbol={p_sym_mod:p_modifierlist(** modifiers *);p_sym_nam:p_ident(** symbol name *);p_sym_arg:p_paramslist(** arguments before ":" *);p_sym_typ:p_termoption(** symbol type *);p_sym_trm:p_termoption(** symbol definition *);p_sym_prf:(p_proof*p_proof_end)option(** proof script *);p_sym_def:bool(** is it a definition ? *)}(** Parser-level representation of a single command. *)typep_command_aux=|P_requireofbool*p_pathlist(* "require open" if the boolean is true *)|P_require_asofp_path*p_ident|P_openofp_pathlist|P_symbolofp_symbol|P_rulesofp_rulelist|P_inductiveofp_modifierlist*p_paramslist*p_inductivelist|P_builtinofstring*p_qident|P_notationofp_qident*Sign.notation|P_unif_ruleofp_rule|P_queryofp_query(** Parser-level representation of a single (located) command. *)typep_command=p_command_auxloc(** Top level AST returned by the parser. *)typeast=p_commandStream.t(** Equality functions on the syntactic expressions ignoring positions. *)leteq_p_ident:p_identeq=funi1i2->i1.elt=i2.eltleteq_p_meta_ident:p_meta_identeq=funi1i2->i1.elt=i2.eltleteq_p_qident:p_qidenteq=funq1q2->q1.elt=q2.eltleteq_p_path:p_patheq=funm1m2->m1.elt=m2.eltletreceq_p_term:p_termeq=fun{elt=t1;_}{elt=t2;_}->matcht1,t2with|P_Type,P_Type|P_Wild,P_Wild->true|P_Iden(q1,b1),P_Iden(q2,b2)->eq_p_qidentq1q2&&b1=b2|P_Meta(i1,ts1),P_Meta(i2,ts2)->eq_p_meta_identi1i2&&Array.eqeq_p_termts1ts2|P_Patt(io1,ts1),P_Patt(io2,ts2)->Option.eqeq_p_identio1io2&&Option.eq(Array.eqeq_p_term)ts1ts2|P_Appl(t1,u1),P_Appl(t2,u2)|P_Arro(t1,u1),P_Arro(t2,u2)->eq_p_termt1t2&&eq_p_termu1u2|P_Abst(xs1,t1),P_Abst(xs2,t2)|P_Prod(xs1,t1),P_Prod(xs2,t2)->List.eqeq_p_paramsxs1xs2&&eq_p_termt1t2|P_LLet(i1,xs1,a1,t1,u1),P_LLet(i2,xs2,a2,t2,u2)->eq_p_identi1i2&&List.eqeq_p_paramsxs1xs2&&Option.eqeq_p_terma1a2&&eq_p_termt1t2&&eq_p_termu1u2|P_Wrapt1,P_Wrapt2|P_Explt1,P_Explt2->eq_p_termt1t2|P_NLitn1,P_NLitn2->n1=n2|_,_->falseandeq_p_params:p_paramseq=fun(i1,ao1,b1)(i2,ao2,b2)->List.eq(Option.eqeq_p_ident)i1i2&&Option.eqeq_p_termao1ao2&&b1=b2leteq_p_rule:p_ruleeq=fun{elt=(l1,r1);_}{elt=(l2,r2);_}->eq_p_terml1l2&&eq_p_termr1r2leteq_p_inductive:p_inductiveeq=leteq_cons(i1,t1)(i2,t2)=eq_p_identi1i2&&eq_p_termt1t2infun{elt=(i1,t1,l1);_}{elt=(i2,t2,l2);_}->List.eqeq_cons((i1,t1)::l1)((i2,t2)::l2)leteq_p_rw_patt:p_rw_patteq=fun{elt=r1;_}{elt=r2;_}->matchr1,r2with|Rw_Termt1,Rw_Termt2|Rw_InTermt1,Rw_InTermt2->eq_p_termt1t2|Rw_InIdInTerm(i1,t1),Rw_InIdInTerm(i2,t2)|Rw_IdInTerm(i1,t1),Rw_IdInTerm(i2,t2)->eq_p_identi1i2&&eq_p_termt1t2|Rw_TermInIdInTerm(t1,(i1,u1)),Rw_TermInIdInTerm(t2,(i2,u2))|Rw_TermAsIdInTerm(t1,(i1,u1)),Rw_TermAsIdInTerm(t2,(i2,u2))->eq_p_termt1t2&&eq_p_identi1i2&&eq_p_termu1u2|_,_->falseleteq_p_assertion:p_assertioneq=funa1a2->matcha1,a2with|P_assert_typing(t1,u1),P_assert_typing(t2,u2)|P_assert_conv(t1,u1),P_assert_conv(t2,u2)->eq_p_termt1t2&&eq_p_termu1u2|_,_->falseleteq_p_query:p_queryeq=fun{elt=q1;_}{elt=q2;_}->matchq1,q2with|P_query_assert(b1,a1),P_query_assert(b2,a2)->b1=b2&&eq_p_assertiona1a2|P_query_infer(t1,c1),P_query_infer(t2,c2)|P_query_normalize(t1,c1),P_query_normalize(t2,c2)->eq_p_termt1t2&&c1=c2|P_query_provers1,P_query_provers2->s1=s2|P_query_prover_timeoutt1,P_query_prover_timeoutt2->t1=t2|P_query_printio1,P_query_print(io2)->Option.eqeq_p_qidentio1io2|P_query_verbosen1,P_query_verbosen2->n1=n2|P_query_debug(b1,s1),P_query_debug(b2,s2)->b1=b2&&s1=s2|P_query_proofterm,P_query_proofterm->true|_,_->falseleteq_p_tactic:p_tacticeq=fun{elt=t1;_}{elt=t2;_}->matcht1,t2with|P_tac_applyt1,P_tac_applyt2|P_tac_refinet1,P_tac_refinet2->eq_p_termt1t2|P_tac_have(i1,t1),P_tac_have(i2,t2)->eq_p_identi1i2&&eq_p_termt1t2|P_tac_assumexs1,P_tac_assumexs2->List.eq(Option.eqeq_p_ident)xs1xs2|P_tac_rewrite(b1,p1,t1),P_tac_rewrite(b2,p2,t2)->b1=b2&&Option.eqeq_p_rw_pattp1p2&&eq_p_termt1t2|P_tac_queryq1,P_tac_queryq2->eq_p_queryq1q2|P_tac_why3so1,P_tac_why3so2->so1=so2|P_tac_simplq1,P_tac_simplq2->Option.eqeq_p_qidentq1q2|P_tac_generalizei1,P_tac_generalizei2->eq_p_identi1i2|P_tac_admit,P_tac_admit|P_tac_induction,P_tac_induction|P_tac_solve,P_tac_solve|P_tac_fail,P_tac_fail|P_tac_refl,P_tac_refl|P_tac_sym,P_tac_sym->true|_,_->falseletreceq_p_subproof:p_subproofeq=funsp1sp2->List.eqeq_p_proofstepsp1sp2andeq_p_proofstep:p_proofstepeq=funps1ps2->matchps1,ps2with|Tactic(t1,spl1),Tactic(t2,spl2)->eq_p_tactict1t2&&List.eqeq_p_subproofspl1spl2leteq_p_proof:p_proofeq=List.eqeq_p_subproofleteq_p_sym_prf:(p_proof*p_proof_end)eq=fun(p1,pe1)(p2,pe2)->pe1.elt=pe2.elt&&eq_p_proofp1p2leteq_p_symbol:p_symboleq=fun{p_sym_mod=p_sym_mod1;p_sym_nam=p_sym_nam1;p_sym_arg=p_sym_arg1;p_sym_typ=p_sym_typ1;p_sym_trm=p_sym_trm1;p_sym_prf=p_sym_prf1;p_sym_def=p_sym_def1}{p_sym_mod=p_sym_mod2;p_sym_nam=p_sym_nam2;p_sym_arg=p_sym_arg2;p_sym_typ=p_sym_typ2;p_sym_trm=p_sym_trm2;p_sym_prf=p_sym_prf2;p_sym_def=p_sym_def2}->p_sym_mod1=p_sym_mod2&&eq_p_identp_sym_nam1p_sym_nam2&&List.eqeq_p_paramsp_sym_arg1p_sym_arg2&&Option.eqeq_p_termp_sym_typ1p_sym_typ2&&Option.eqeq_p_termp_sym_trm1p_sym_trm2&&Option.eqeq_p_sym_prfp_sym_prf1p_sym_prf2&&p_sym_def1=p_sym_def2(** [eq_command c1 c2] tells whether [c1] and [c2] are the same commands. They
are compared up to source code positions. *)leteq_p_command:p_commandeq=fun{elt=c1;_}{elt=c2;_}->matchc1,c2with|P_require(b1,l1),P_require(b2,l2)->b1=b2&&List.eqeq_p_pathl1l2|P_openl1,P_openl2->List.eqeq_p_pathl1l2|P_require_as(m1,i1),P_require_as(m2,i2)->eq_p_pathm1m2&&eq_p_identi1i2|P_symbols1,P_symbols2->eq_p_symbols1s2|P_rules(r1),P_rules(r2)->List.eqeq_p_ruler1r2|P_inductive(m1,xs1,l1),P_inductive(m2,xs2,l2)->m1=m2&&List.eqeq_p_paramsxs1xs2&&List.eqeq_p_inductivel1l2|P_builtin(s1,q1),P_builtin(s2,q2)->s1=s2&&eq_p_qidentq1q2|P_notation(i1,n1),P_notation(i2,n2)->eq_p_qidenti1i2&&n1=n2|P_unif_ruler1,P_unif_ruler2->eq_p_ruler1r2|P_query(q1),P_query(q2)->eq_p_queryq1q2|_,_->false(** [fold_proof f acc p] recursively builds a value of type ['a] by starting
from [acc] and by applying [f] to every tactic of [p]. *)letfold_proof:('a->p_tactic->int->'a)->'a->p_proof->'a=funf->letrecsubproofasp=List.fold_leftproofstepaspandproofstepa(Tactic(t,spl))=List.fold_leftsubproof(fat(List.lengthspl))splinList.fold_leftsubproof(** [fold_idents f a ast] allows to recursively build a value of type ['a]
starting from [a] and by applying [f] on each identifier occurring in [ast]
corresponding to a function symbol: variables (term variables or assumption
names) are excluded.
NOTE: This function is incomplete if an assumption name hides a function
symbol. Example:
symbol A:TYPE;
symbol a:A;
symbol p:((A->A)->A->A)->A :=
begin
assume h
apply h
// proof of A->A
assume a
apply a // here a is an assumption
// proof of A
apply a // here a is a function symbol
end; *)letfold_idents:('a->p_qident->'a)->'a->p_commandlist->'a=funf->letadd_idopt:StrSet.t->p_identoption->StrSet.t=funvsidopt->matchidoptwith|None->vs|Someid->StrSet.addid.eltvsinletadd_idopts=List.fold_leftadd_idoptinletrecfold_term_vars:StrSet.t->'a->p_term->'a=funvsa{elt;pos}->matcheltwith|P_Iden({elt=(mp,s);_}asqid,_)->ifmp=[]&&StrSet.memsvsthenaelsefaqid|P_Type|P_Wild|P_Patt(_,None)|P_NLit_->a|P_Meta(_,ts)|P_Patt(_,Somets)->Array.fold_left(fold_term_varsvs)ats|P_Appl(t,u)|P_Arro(t,u)->fold_term_varsvs(fold_term_varsvsat)u|P_Abst((idopts,Somet,_)::args_list,u)|P_Prod((idopts,Somet,_)::args_list,u)->fold_term_vars(add_idoptsvsidopts)(fold_term_varsvsat)(Pos.makepos(P_Abst(args_list,u)))|P_Abst((idopts,None,_)::args_list,u)|P_Prod((idopts,None,_)::args_list,u)->fold_term_vars(add_idoptsvsidopts)a(Pos.makepos(P_Abst(args_list,u)))|P_Abst([],t)|P_Prod([],t)|P_Wrapt|P_Explt->fold_term_varsvsat|P_LLet(id,(idopts,None,_)::args_list,u,v,w)->fold_term_vars(add_idoptsvsidopts)a(Pos.makepos(P_LLet(id,args_list,u,v,w)))|P_LLet(id,(idopts,Somet,_)::args_list,u,v,w)->fold_term_vars(add_idoptsvsidopts)(fold_term_varsvsat)(Pos.makepos(P_LLet(id,args_list,u,v,w)))|P_LLet(id,[],None,v,w)->fold_term_vars(StrSet.addid.eltvs)(fold_term_varsvsav)w|P_LLet(id,[],Someu,v,w)->fold_term_vars(StrSet.addid.eltvs)(fold_term_varsvs(fold_term_varsvsau)v)winletfold_term:'a->p_term->'a=fold_term_varsStrSet.emptyinletfold_rule:'a->p_rule->'a=funa{elt=(l,r);_}->fold_term(fold_termal)rinletfold_rw_patt_vars:StrSet.t->'a->p_rw_patt->'a=funvsap->matchp.eltwith|Rw_Termt|Rw_InTermt->fold_term_varsvsat|Rw_InIdInTerm(id,t)|Rw_IdInTerm(id,t)->fold_term_vars(StrSet.addid.eltvs)at|Rw_TermInIdInTerm(t,(id,u))|Rw_TermAsIdInTerm(t,(id,u))->fold_term_vars(StrSet.addid.eltvs)(fold_term_varsvsat)uinletfold_query_vars:StrSet.t->'a->p_query->'a=funvsaq->matchq.eltwith|P_query_verbose_|P_query_debug(_,_)|P_query_flag(_,_)|P_query_prover_|P_query_prover_timeout_|P_query_printNone|P_query_proofterm->a|P_query_assert(_,P_assert_typing(t,u))|P_query_assert(_,P_assert_conv(t,u))->fold_term_varsvs(fold_term_varsvsat)u|P_query_infer(t,_)|P_query_normalize(t,_)->fold_term_varsvsat|P_query_print(Someqid)->faqidinletfold_tactic:StrSet.t*'a->p_tactic->StrSet.t*'a=fun(vs,a)t->matcht.eltwith|P_tac_refinet|P_tac_applyt|P_tac_rewrite(_,None,t)->(vs,fold_term_varsvsat)|P_tac_rewrite(_,Somep,t)->(vs,fold_term_varsvs(fold_rw_patt_varsvsap)t)|P_tac_queryq->(vs,fold_query_varsvsaq)|P_tac_assumeidopts->(add_idoptsvsidopts,a)|P_tac_have(id,t)->(StrSet.addid.eltvs,fold_term_varsvsat)|P_tac_simpl(Someqid)->(vs,faqid)|P_tac_simplNone|P_tac_admit|P_tac_refl|P_tac_sym|P_tac_why3_|P_tac_solve|P_tac_fail|P_tac_generalize_|P_tac_induction->(vs,a)inletfold_inductive_vars:StrSet.t->'a->p_inductive->'a=funvsa{elt=(id,t,cons_list);_}->letfold_consa(_,t)=fold_term_varsvsatinList.fold_leftfold_consa((id,t)::cons_list)inletfold_sym_prf:'a->(p_proof*p_proof_end)->'a=funa(p,_)->letfat_=fold_tacticatinsnd(fold_prooff(StrSet.empty,a)p)inletfold_args:StrSet.t*'a->p_params->StrSet.t*'a=fun(vs,a)(idopts,tyopt,_)->add_idoptsvsidopts,matchtyoptwith|None->a|Somet->fold_term_varsvsatinletfold_command:'a->p_command->'a=funa{elt;pos}->matcheltwith|P_require(_,_)|P_require_as(_,_)|P_open_->a|P_queryq->fold_query_varsStrSet.emptyaq|P_builtin(_,qid)|P_notation(qid,_)->faqid|P_unif_ruler->fold_rulear|P_rulesrs->List.fold_leftfold_rulears|P_inductive(_,xs,ind_list)->letvs,a=List.fold_leftfold_args(StrSet.empty,a)xsinList.fold_left(fold_inductive_varsvs)aind_list|P_symbol{p_sym_nam;p_sym_arg;p_sym_typ;p_sym_trm;p_sym_prf;_}->letd=Pos.noneP_Typeinlett=matchp_sym_trmwithSomet->t|None->dinOption.foldfold_sym_prf(fold_terma(Pos.makepos(P_LLet(p_sym_nam,p_sym_arg,p_sym_typ,t,d))))p_sym_prfinList.fold_leftfold_command