coq-club AT inria.fr
Subject: The Coq mailing list
List archive
- From: Tej Chajed <tchajed AT mit.edu>
- To: coq-club <coq-club AT inria.fr>
- Subject: Re: [Coq-Club] help calling ltac1 function from ltac2
- Date: Sat, 15 Aug 2020 21:39:11 -0500
- Authentication-results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=tchajed AT mit.edu; spf=Pass smtp.mailfrom=tchajed AT mit.edu; spf=None smtp.helo=postmaster AT outgoing.mit.edu
- Ironport-phdr: 9a23:7KsPGhEulNpW4dlgpWXjDp1GYnF86YWxBRYc798ds5kLTJ7zpcWwAkXT6L1XgUPTWs2DsrQY0rSQ6vi4EjJZqb+681k6OKRWUBEEjchE1ycBO+WiTXPBEfjxciYhF95DXlI2t1uyMExSBdqsLwaK+i764jEdAAjwOhRoLerpBIHSk9631+ev8JHPfglEnjWwba5zIRmssAndqtUajYRjJ6os1xDEvmZGd+NKyG1yOFmdhQz85sC+/J5i9yRfpfcs/NNeXKv5Yqo1U6VWACwpPG4p6sLrswLDTRaU6XsHTmoWiBtIDBPb4xz8Q5z8rzH1tut52CmdIM32UbU5Uims4qt3VBPljjoMOjgk+2/Vl8NwlrpWrx2vpxN9w4DaboKbOudgcKzBZt4VX3ZNU9xLWiBdHo+xbY0CBPcBM+ZCqIn9okMDowWgCgmuGeji1D9IiWX03aIkzusqDAbL3BA8ENIOqnvUrsv6O7oJXOCwzanI0S/PYO1L1jfg8YXFdA0qrv6QU7xqa8XR1VUvGB3fjlWWsYHrMDeY2+cCvWWa4ORsSOaihnMnpg1toDWix9khh4vViowa1F3J9iF0zZgoKdC2SUN3fMCoHZtMui+VNYZ4TMEvTmd1syg0zb0GvIS0fCkMyJk/yB7fbuaIc4mM4h75SOmRJjJ4iGpleLO/nxay6lKsyu37Vsi61ltBsylLksHUu3wQ1BHf8MyKRuFj8kqiwzqDyh3f5vlaLUwokafXMZ0sz74qmpYNrEjOGjX6lUrogKKQa04q4PKn6/79bbXjvpKcN5F7igX5Mqk2ncy/HPg4MgcJX2ia/+S826fv/Uj4QLVWlPE5jLTWsI3CKcQaoK62HRNV354+5xu8FTur1M4UkWcEIV5fZR6LkpDlO1TUL/D5Cfe/jU6skDBux/3eIr3uHpXNIWLBkLj/YLlw8EtcyAsvzdxF+Z1bF6wBLOrpWkDtrNzYEgM5Mwuszun7D9V9z5oSVn6LAq+EK6zfqkSI5+IqI+mUfoAZojf9K/4/5/7vl3A1g1EdfbP6lacQPXu/B7FtJ1iTKS7nhc5EGmMXtCI/SvbrgRuMS2gASWy1WvcA6zNzI4KvD4rPDtSxi7yI3iq3NphXeiZLBk3aQiSgTJmNR/pZMHHaGcRmiDFRDeH9Gb9k7gmnsUrB85QiNvDdq38dtI6l2dRotbWKxEMCsAdsBsHY6FmjCmR9n2cGXTgzjfJ6oFA7x1ueg/Eh3q5oUOdL7vYMaT8UcJ7Ry+sjW4L1Rx7OedaPRxCjQ8ngDD0sHIo8
Here's a solution (perhaps more complicated than you were expecting):
Note a significant part of the nastiness comes from not having Ltac1.of_ident, please complain to Pierre-Marie Pedrot that this is a useful feature and workarounds for it are horrendous. Otherwise the complications are somewhat necessary due to a bunch of higher-order stuff that has to back and forth between the two languages.
From Ltac2 Require Import Ltac2.
Ltac2 hyploop (tac : ident -> unit) :=
let rec loop hs :=
match hs with
| h3 :: hs => match h3 with
| (h, _, _) => tac h; loop hs
end
| _ => ()
end in loop (Control.hyps ()).
(* ident_to_constr is a helper to serialize an identifier as a constr of type
[unit -> unit], which uses the ident as the binder *)
Ltac2 ident_to_constr (i:ident) :=
constr:(ltac2:(clear; intros $i; exact tt) : unit -> unit).
Ltac allhyps_fast tac :=
(* tac can't be called from Ltac2 because we can't convert an ident to an
Ltac1 dynamically typed value (the type Ltac1.t in Ltac2); instead, we will
call a variant that expects its argument as the binder of a constr *)
let tac_constr i_constr :=
lazymatch i_constr with
| fun i => _ => tac i
end in
(* at the outermost level, we're constructing hyploop using the ltac1-to-ltac2
FFI which allows passing an argument so we can pass tac (as [tac_constr]) to
it *)
let hyploop :=
ltac2:(t |- (* t is passed as an Ltac1 opaque object of type [Ltac1.t].
Remember that it's an Ltac1 tactic that takes a constr and returns
nothing. *)
(* we now convert the ident hyploop will pass us to an Ltac1
dynamically-typed bundle... *)
let ident_to_arg (i: ident) := Ltac1.of_constr (ident_to_constr i) in
(* And finally construct the higher-order argument to hyploop using
[Ltac1.apply], the most general way to call an Ltac1 function. The
third argument is a CPS tactic to use the result, but these tactics
passed to hyploop (thankfully) don't return anything. *)
let tac (i: ident) := Ltac1.apply t [ident_to_arg i] (fun _ => ()) in
hyploop tac) in
hyploop tac_constr.
Set Default Proof Mode "Classic".
Goal nat -> bool -> nat.
Proof.
intros x y.
allhyps_fast ltac:(fun i => let P := type of i in idtac i ":" P).
(* prints x : nat and y : bool, as expected *)
Abort.
On Sat, Aug 15, 2020 at 8:12 PM jonikelee AT gmail.com jonikelee AT gmail.com wrote:
I have the following Ltac2 function to iterate over hypotheses:
Ltac2 hyploop (tac : ident -> unit) :=
let rec loop hs :=
match hs with
| h3 :: hs => match h3 with
| (h, _, _) => tac h; loop hs
end
| _ => ()
end in loop (Control.hyps ()).
How do I call hyploop from Ltac1, passing in an Ltac1 function
for the tac argument?
Ltac allhyps_fast tac :=
ltac2:(hyploop ltac1:(????)).
- [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Tej Chajed, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Jim Fehrle, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Jason Gross, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Jim Fehrle, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/17/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/18/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Jason Gross, 08/18/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/18/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/17/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Jim Fehrle, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, jonikelee AT gmail.com, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Jason Gross, 08/16/2020
- Re: [Coq-Club] help calling ltac1 function from ltac2, Tej Chajed, 08/16/2020
Archive powered by MHonArc 2.6.19+.