99(*********************************************************************** *)
1010
1111Require Import Ltac2.Init.
12- Require Ltac2.Ind.
12+ Require Ltac2.Ind Ltac2.Array .
1313
1414Ltac2 @ 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
3535Ltac2 @ 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+
3841End Binder.
3942
4043Module Unsafe.
@@ -73,6 +76,12 @@ Ltac2 Type kind := [
7376
7477Ltac2 @ 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+
7685Ltac2 @ external make : kind -> constr := "coq-core.plugins.ltac2" "constr_make".
7786
7887Ltac2 @ external check : constr -> constr result := "coq-core.plugins.ltac2" "constr_check".
@@ -123,6 +132,142 @@ Module Case.
123132
124133End 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+
126271End Unsafe.
127272
128273Module Cast.
0 commit comments