123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227(******************************************************************************)(* This file is part of Waterproof-lib. *)(* *)(* Waterproof-lib is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as published by *)(* the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* Waterproof-lib is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public License *)(* along with Waterproof-lib. If not, see <https://www.gnu.org/licenses/>. *)(* *)(******************************************************************************)(** Functions that should be available from Ltac2 can be made available from here
*)moduleTac2ffi=Ltac2_plugin.Tac2ffimoduleTac2env=Ltac2_plugin.Tac2envmoduleTac2expr=Ltac2_plugin.Tac2expropenLtac2_plugin.Tac2externalsopenProofviewopenTac2expropenTac2ffiopenLtac2_plugin.Tac2valopenExceptionsopenHint_dataset_declarationsopenWaterproveopenWp_evarsopenUnfold_framework(** Creates a name used to define the function interface *)letpname(s:string):ml_tactic_name={mltac_plugin="rocq-runtime.plugins.coq-waterproof";mltac_tactic=s}letdefines=Ltac2_plugin.Tac2externals.define(pnames)(** Comes from [coq/plugins/ltac2/tac2tactics.ml] *)letthaw(f:(unit,'a)fun1):'atactic=f()(** Comes from [coq/plugins/ltac2/tac2tactics.ml] *)letdelayed_of_tactic(tac:'atactic)(env:Environ.env)(sigma:Evd.evar_map):(Evd.evar_map*'a)=let_,pv=Proofview.initsigma[]inletname,poly=Names.Id.of_string"ltac2_delayed",falseinletc,pv,_,_,_=Proofview.apply~name~polyenvtacpvinlet_,sigma=Proofview.proofviewpvin(sigma,c)(**
Utility function to cast OCaml types into Ltac2-compatibles types
Comes from [coq/plugins/ltac2/tac2tactics.ml]
*)letdelayed_of_thunk(tac:(unit,'a)fun1)(env:Environ.env)(sigma:Evd.evar_map):(Evd.evar_map*'a)=delayed_of_tactic(thawtac)envsigma(** Converts a ['a repr] into a [(unit -> 'a) repr] *)letthunk(r:'arepr):(unit,'a)fun1repr=fun1unitr(** Converts a {! Hint_dataset_declarations.database_type} into a [valexpr] *)letof_database_type(database_type:database_type):valexpr=matchdatabase_typewith|Main->ValInt0|Decidability->ValInt1|Shorten->ValInt2(** Converts a [valexpr] into a {! Hint_dataset_declarations.database_type} *)letto_database_type(value:valexpr):database_type=matchvaluewith|ValIntn->letdatabase_type=matchnwith|0->Main|1->Decidability|2->Shorten|_->throw(CastError"cannot cast something an [int] greater than 3 into a [database_type]")indatabase_type|_->throw(CastError"cannot cast something different than an [int] into a [database_type]")letdatabase_type=make_reprof_database_typeto_database_type(** Converts a {! Feedback.level} into a [valexpr] *)letof_feedback_level(feedback_lvl:Feedback.level):valexpr=matchfeedback_lvlwith|Debug->ValInt0|Info->ValInt1|Notice->ValInt2|Warning->ValInt3|Error->ValInt4(** Converts a [valexpr] into a {! Feedback.level} *)letto_feedback_level(value:valexpr):Feedback.level=matchvaluewith|ValIntn->letfeedback_lvl=matchnwith|0->Feedback.Debug|1->Info|2->Notice|3->Warning|4->Error|_->throw(CastError"cannot cast an [int] outside {0, 1, 2, 3, 4} into a [Feedback.level]")infeedback_lvl|_->throw(CastError"cannot cast something different from an [int] into a [Feedback.level]")letof_unfold_action=function|Unfold(s,gr)->of_block(0,[|of_strings;of_referencegr|])|Apply(s,c)->of_block(1,[|of_strings;of_constrc|])|Rewrite(s,c)->of_block(2,[|of_strings;of_constrc|])letto_unfold_action=letopenLtac2_plugin.Tac2valinfunction|ValBlk(0,[|s;gr|])->Unfold(to_strings,to_referencegr)|ValBlk(1,[|s;c|])->Apply(to_strings,to_constrc)|ValBlk(2,[|s;c|])->Rewrite(to_strings,to_constrc)|_->assertfalseletunfold_action=make_reprof_unfold_actionto_unfold_action(** Pack the conversion functions for feedback levels into a representation *)letfeedback_level=make_reprof_feedback_levelto_feedback_level(* Exports {! Waterprove.waterprove} to Ltac2 *)let()=define"waterprove"(int@->bool@->(list(thunkconstr))@->liststring@->database_type@->tacunit)@@fundepthshieldlemsdbsdatabase_type->beginwaterprovedepth~shield(List.map(funlem->delayed_of_thunklem)lems)dbsdatabase_typeend(* Exports {! Waterprove.rwaterprove} to Ltac2 *)let()=define"rwaterprove"(int@->bool@->(list(thunkconstr))@->liststring@->database_type@->listconstr@->listconstr@->tacunit)@@fundepthshieldlemsdbsdatabase_typemust_useforbidden->beginrwaterprovedepth~shield(List.map(funlem->delayed_of_thunklem)lems)dbsdatabase_typemust_useforbiddenendlet()=define"warn_external"(pp@->tacunit)@@warnlet()=define"notice_external"(pp@->tacunit)@@noticelet()=define"throw_external"(pp@->tacunit)@@errlet()=define"inform_external"(pp@->tacunit)@@informlet()=define"message_external"(feedback_level@->pp@->(tacunit))@@messagelet()=define"refine_goal_with_evar_external"(string@->tacunit)@@refine_goal_with_evarlet()=define"blank_evars_in_term_external"(constr@->tac(listevar))@@blank_evars_in_termlet()=define"get_print_hypothesis_flag_external"(unit@->retbool)@@fun()->!print_hypothesis_helplet()=define"get_redirect_errors_flag_external"(unit@->retbool)@@fun()->!redirect_errorslet()=define"get_last_warning_external"(unit@->ret(optionpp))@@get_last_warninglet()=define"get_feedback_log_external"(feedback_level@->ret(listpp))@@funinput->!(feedback_loginput)let()=define"extract_def_external"(string@->ret(optionreference))@@extract_deflet()=define"find_unfold_by_ref_external"(reference@->ret(listunfold_action))@@find_unfold_actions_by_reflet()=define"find_unfold_by_str_external"(string@->ret(listunfold_action))@@find_unfold_actions_by_strlet()=define"get_unfold_references_external"(unit@->ret(listreference))@@get_all_referenceslet()=define"shortest_string_of_global_external"(reference@->retstring)@@shortest_string_of_globallet()=define"check_feedback_level_Ltac2_to_Ocaml_external"(feedback_level@->int@->retbool)@@check_feedback_level_Ltac2_to_Ocamllet()=define"feedback_level_round_trip_external"(feedback_level@->retfeedback_level)@@funinput->input(** TODO: This can be removed in a later version of Rocq, probably 9.2,
because it has then been integrated in Ltac2. *)let()=define"message_of_lconstr"(constr@->tacpp)@@func->Ltac2_plugin.Tac2core.pf_apply@@funenvsigma->Proofview.tclUNIT(Printer.pr_leconstr_envenvsigmac)