Skip to content

Commit 4352c71

Browse files
Merge PR #18764: Add some Ltac2.Constr.Unsafe combinators
Reviewed-by: ppedrot Ack-by: JasonGross Co-authored-by: ppedrot <[email protected]>
2 parents 171bfc6 + 1a22936 commit 4352c71

File tree

3 files changed

+153
-1
lines changed

3 files changed

+153
-1
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- **Added:**
2+
open recursion combinators in `Ltac2.Constr.Unsafe`
3+
(`#18764 <https://github.com/coq/coq/pull/18764>`_,
4+
by Gaëtan Gilbert).

plugins/ltac2/tac2core.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,9 @@ let () =
830830
let () =
831831
define "constr_binder_type" (repr_ext val_binder @-> ret constr) @@ fun (_, ty) -> ty
832832

833+
let () =
834+
define "constr_binder_relevance" (repr_ext val_binder @-> ret relevance) @@ fun (na, _) -> na.binder_relevance
835+
833836
let () =
834837
define "constr_has_evar" (constr @-> tac bool) @@ fun c ->
835838
Proofview.tclEVARMAP >>= fun sigma ->

user-contrib/Ltac2/Constr.v

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
(************************************************************************)
1010

1111
Require Import Ltac2.Init.
12-
Require Ltac2.Ind.
12+
Require Ltac2.Ind Ltac2.Array.
1313

1414
Ltac2 @ external type : constr -> constr := "coq-core.plugins.ltac2" "constr_type".
1515
(** Return the type of a term *)
@@ -35,6 +35,9 @@ Ltac2 @ external name : binder -> ident option := "coq-core.plugins.ltac2" "cons
3535
Ltac2 @ external type : binder -> constr := "coq-core.plugins.ltac2" "constr_binder_type".
3636
(** Retrieve the type of a binder. *)
3737

38+
Ltac2 @ external relevance : binder -> relevance := "coq-core.plugins.ltac2" "constr_binder_relevance".
39+
(** Retrieve the relevance of a binder. *)
40+
3841
End Binder.
3942

4043
Module Unsafe.
@@ -73,6 +76,12 @@ Ltac2 Type kind := [
7376

7477
Ltac2 @ external kind : constr -> kind := "coq-core.plugins.ltac2" "constr_kind".
7578

79+
Ltac2 rec kind_nocast c :=
80+
match kind c with
81+
| Cast c _ _ => kind_nocast c
82+
| k => k
83+
end.
84+
7685
Ltac2 @ external make : kind -> constr := "coq-core.plugins.ltac2" "constr_make".
7786

7887
Ltac2 @ external check : constr -> constr result := "coq-core.plugins.ltac2" "constr_check".
@@ -123,6 +132,142 @@ Module Case.
123132

124133
End Case.
125134

135+
(** Open recursion combinators *)
136+
137+
Local Ltac2 iter_invert (f : constr -> unit) (ci : case_invert) : unit :=
138+
match ci with
139+
| NoInvert => ()
140+
| CaseInvert indices => Array.iter f indices
141+
end.
142+
143+
(** [iter f c] iters [f] on the immediate subterms of [c]; it is
144+
not recursive and the order with which subterms are processed is
145+
not specified *)
146+
Ltac2 iter (f : constr -> unit) (c : constr) : unit :=
147+
match kind c with
148+
| Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _
149+
| Constructor _ _ | Uint63 _ | Float _ => ()
150+
| Cast c _ t => f c; f t
151+
| Prod b c => f (Binder.type b); f c
152+
| Lambda b c => f (Binder.type b); f c
153+
| LetIn b t c => f (Binder.type b); f t; f c
154+
| App c l => f c; Array.iter f l
155+
| Evar _ l => Array.iter f l
156+
| Case _ x iv y bl =>
157+
match x with (x,_) => f x end;
158+
iter_invert f iv;
159+
f y;
160+
Array.iter f bl
161+
| Proj _p _ c => f c
162+
| Fix _ _ tl bl =>
163+
Array.iter (fun b => f (Binder.type b)) tl;
164+
Array.iter f bl
165+
| CoFix _ tl bl =>
166+
Array.iter (fun b => f (Binder.type b)) tl;
167+
Array.iter f bl
168+
| Array _u t def ty =>
169+
f ty; Array.iter f t; f def
170+
end.
171+
172+
(** [iter_with_binders g f n c] iters [f n] on the immediate
173+
subterms of [c]; it carries an extra data [n] (typically a lift
174+
index) which is processed by [g] (which typically add 1 to [n]) at
175+
each binder traversal; it is not recursive and the order with which
176+
subterms are processed is not specified *)
177+
Ltac2 iter_with_binders (g : 'a -> binder -> 'a) (f : 'a -> constr -> unit) (n : 'a) (c : constr) : unit :=
178+
match kind c with
179+
| Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _
180+
| Constructor _ _ | Uint63 _ | Float _ => ()
181+
| Cast c _ t => f n c; f n t
182+
| Prod b c => f n (Binder.type b); f (g n b) c
183+
| Lambda b c => f n (Binder.type b); f (g n b) c
184+
| LetIn b t c => f n (Binder.type b); f n t; f (g n b) c
185+
| App c l => f n c; Array.iter (f n) l
186+
| Evar _ l => Array.iter (f n) l
187+
| Case _ x iv y bl =>
188+
match x with (x,_) => f n x end;
189+
iter_invert (f n) iv;
190+
f n y;
191+
Array.iter (f n) bl
192+
| Proj _p _ c => f n c
193+
| Fix _ _ tl bl =>
194+
Array.iter (fun b => f n (Binder.type b)) tl;
195+
let n := Array.fold_left g n tl in
196+
Array.iter (f n) bl
197+
| CoFix _ tl bl =>
198+
Array.iter (fun b => f n (Binder.type b)) tl;
199+
let n := Array.fold_left g n tl in
200+
Array.iter (f n) bl
201+
| Array _u t def ty =>
202+
f n ty;
203+
Array.iter (f n) t;
204+
f n def
205+
end.
206+
207+
Local Ltac2 binder_map (f : constr -> constr) (b : binder) : binder :=
208+
Binder.unsafe_make (Binder.name b) (Binder.relevance b) (f (Binder.type b)).
209+
210+
Local Ltac2 map_invert (f : constr -> constr) (iv : case_invert) : case_invert :=
211+
match iv with
212+
| NoInvert => NoInvert
213+
| CaseInvert indices => CaseInvert (Array.map f indices)
214+
end.
215+
216+
(** [map f c] maps [f] on the immediate subterms of [c]; it is
217+
not recursive and the order with which subterms are processed is
218+
not specified *)
219+
Ltac2 map (f : constr -> constr) (c : constr) : constr :=
220+
match kind c with
221+
| Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _
222+
| Constructor _ _ | Uint63 _ | Float _ => c
223+
| Cast c k t =>
224+
let c := f c
225+
with t := f t in
226+
make (Cast c k t)
227+
| Prod b c =>
228+
let b := binder_map f b
229+
with c := f c in
230+
make (Prod b c)
231+
| Lambda b c =>
232+
let b := binder_map f b
233+
with c := f c in
234+
make (Lambda b c)
235+
| LetIn b t c =>
236+
let b := binder_map f b
237+
with t := f t
238+
with c := f c in
239+
make (LetIn b t c)
240+
| App c l =>
241+
let c := f c
242+
with l := Array.map f l in
243+
make (App c l)
244+
| Evar e l =>
245+
let l := Array.map f l in
246+
make (Evar e l)
247+
| Case info x iv y bl =>
248+
let x := match x with (x,x') => (f x, x') end
249+
with iv := map_invert f iv
250+
with y := f y
251+
with bl := Array.map f bl in
252+
make (Case info x iv y bl)
253+
| Proj p r c =>
254+
let c := f c in
255+
make (Proj p r c)
256+
| Fix structs which tl bl =>
257+
let tl := Array.map (binder_map f) tl
258+
with bl := Array.map f bl in
259+
make (Fix structs which tl bl)
260+
| CoFix which tl bl =>
261+
let tl := Array.map (binder_map f) tl
262+
with bl := Array.map f bl in
263+
make (CoFix which tl bl)
264+
| Array u t def ty =>
265+
let ty := f ty
266+
with t := Array.map f t
267+
with def := f def in
268+
make (Array u t def ty)
269+
end.
270+
126271
End Unsafe.
127272

128273
Module Cast.

0 commit comments

Comments
 (0)