Skip to content

Commit 47c8bae

Browse files
authored
Merge pull request #94 from SkyLabsAI/janno/level-env
ltac2-extra: evar and LevelEnv improvements.
2 parents 238d10c + 8c44031 commit 47c8bae

File tree

6 files changed

+265
-84
lines changed

6 files changed

+265
-84
lines changed

ltac2-extra/plugin/tac2constr.ml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,30 @@ let evar_tag : _ Tac2core.map_tag =
3636
let define s =
3737
define Tac2expr.{ mltac_plugin = "sl.Constr"; mltac_tactic = s }
3838

39+
let collect_context ctx =
40+
let fn acc decl =
41+
let open Context.Named.Declaration in
42+
let binder =
43+
Context.make_annot (Names.Name.Name (get_id decl)) (get_relevance decl), get_type decl
44+
in
45+
(binder, get_value decl) :: acc
46+
in
47+
Context.Named.fold_inside fn ~init:[] ctx
48+
3949
(* [evar_context] returns the context of an evar, i.e. the context at the time
4050
it was defined. *)
4151
let _ =
42-
define "evar_context" (evar @-> eret (list (triple ident (option constr) constr))) @@ fun e _ sigma ->
52+
define "evar_context" (evar @-> eret (list (pair binder (option constr)))) @@ fun e _ sigma ->
4353
let (EvarInfo e) = Evd.find sigma e in
4454
let ctx = Evd.evar_context e in
45-
let fn acc decl =
46-
let open Context.Named.Declaration in
47-
(get_id decl, get_value decl, get_type decl) :: acc
48-
in
49-
Context.Named.fold_inside fn ~init:[] ctx
55+
collect_context ctx
56+
57+
(* [evar_filtered_context] returns the filtered context of an evar. *)
58+
let _ =
59+
define "evar_filtered_context" (evar @-> eret (list (pair binder (option constr)))) @@ fun e _ sigma ->
60+
let (EvarInfo e) = Evd.find sigma e in
61+
let ctx = Evd.evar_filtered_context e in
62+
collect_context ctx
5063

5164
(* [compare] must be kept in sync with whatever is used in [ConstrSet] and [ConstrMap] *)
5265
let _ =

ltac2-extra/tests/test_constr.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Module Evar_Test.
122122
match kind l with
123123
| Evar e inst =>
124124
let ctx := Evar.context e in
125-
let ids := List.map (fun (id, _, _) => id) ctx in
125+
let ids := List.map (fun (b, _) => Option.get (Binder.name b)) ctx in
126126
Control.assert_true (List.equal Ident.equal ids [@a; @b]);
127127
let inst := Array.to_list inst in
128128
(* printf "inst:"; *)

ltac2-extra/tests/test_level_env.v

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,53 +33,84 @@ Module Substitute.
3333
| _, _ => throw_invalid! "%a and %a disagree on having a value" RelDecl.pp a RelDecl.pp b
3434
end.
3535

36-
Goal True.
36+
Ltac2 test_env_with_let offset :=
37+
let make_rel i := make_rel (Int.add i offset) in
38+
let e := LevelEnv.empty_w_offset offset in
39+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @a) 'nat)) in
40+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @A) (make_app1 '(@eq nat 1) (make_rel 1)))) in
41+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @b) 'nat)) in
42+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @B) (make_app1 '(@eq nat 2) (make_rel 3)))) in
43+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @C) (make_app1 '(@eq nat 3) '3))) in
44+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @d) 'nat)) in
45+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @D) (make_app1 '(@eq nat 4) (make_rel 6)))) in
46+
(* printf "%a" LevelEnv.pp_named e; *)
47+
e.
48+
49+
Ltac2 test_env_wo_let offset :=
50+
let make_rel i := make_rel (Int.add i offset) in
51+
let e := LevelEnv.empty_w_offset offset in
52+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @a) 'nat)) in
53+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @A) (make_app1 '(@eq nat 1) (make_rel 1)))) in
54+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @b) 'nat)) in
55+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @B) (make_app1 '(@eq nat 2) (make_rel 3)))) in
56+
let e := LevelEnv.add_decl_level e (RelDecl.Def (Binder.make (Some @c) 'nat) '3) in
57+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @C) (make_app1 '(@eq nat 3) (make_rel 5)))) in
58+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @d) 'nat)) in
59+
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @D) (make_app1 '(@eq nat 4) (make_rel 7)))) in
60+
(* printf "%a" LevelEnv.pp_named e; *)
61+
e.
62+
63+
Ltac2 test_substitute_def offset :=
64+
let make_rel i := make_rel (Int.add i offset) in
3765
let (ref_env, ref_term) :=
38-
let e := LevelEnv.empty in
39-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @a) 'nat)) in
40-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @A) (make_app1 '(@eq nat 1) (make_rel 1)))) in
41-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @b) 'nat)) in
42-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @B) (make_app1 '(@eq nat 2) (make_rel 3)))) in
43-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @C) (make_app1 '(@eq nat 3) '3))) in
44-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @d) 'nat)) in
45-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @D) (make_app1 '(@eq nat 4) (make_rel 6)))) in
66+
let e := test_env_with_let offset in
4667
let t := make_app4 '@test (make_rel 1) (make_rel 3) '3 (make_rel 6) in
4768
(e, t)
4869
in
4970

5071
let (env, term) :=
51-
let e := LevelEnv.empty in
52-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @a) 'nat)) in
53-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @A) (make_app1 '(@eq nat 1) (make_rel 1)))) in
54-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @b) 'nat)) in
55-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @B) (make_app1 '(@eq nat 2) (make_rel 3)))) in
56-
let e := LevelEnv.add_decl_level e (RelDecl.Def (Binder.make (Some @c) 'nat) '3) in
57-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @C) (make_app1 '(@eq nat 3) (make_rel 5)))) in
58-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @d) 'nat)) in
59-
let e := LevelEnv.add_decl_level e (RelDecl.Assum (Binder.make (Some @D) (make_app1 '(@eq nat 4) (make_rel 7)))) in
72+
let e := test_env_wo_let offset in
6073
let t := make_app4 '@test (make_rel 1) (make_rel 3) (make_rel 5) (make_rel 7) in
61-
(* printf "%a" LevelEnv.pp_named e; *)
6274
let (e, subs) := LevelEnv.substitute_defs e in
6375
(* printf "%a" (pp_list pp_constr) subs; *)
64-
(e, substnl subs 0 t)
76+
(e, substnl subs offset t)
6577
in
6678
(* printf "%a" LevelEnv.pp_named ref_env; *)
6779
(* printf "%t" ref_term; *)
6880
(* printf "%a" LevelEnv.pp_named env; *)
6981
(* printf "%t" term; *)
7082
List.iter2 assert_rel_decl_eq (LevelEnv.to_list ref_env) (LevelEnv.to_list env);
71-
assert_constr_eq ref_term term
72-
.
83+
assert_constr_eq ref_term term.
84+
7385

86+
Goal True.
87+
Proof.
88+
test_substitute_def 0.
89+
test_substitute_def 1.
90+
test_substitute_def 2.
91+
test_substitute_def 3.
92+
test_substitute_def 4.
93+
test_substitute_def 5.
94+
test_substitute_def 6.
95+
test_substitute_def 7.
96+
exact I.
97+
Qed.
98+
99+
100+
Goal True.
101+
Proof.
102+
let e := test_env_with_let 1 in
103+
let (p,s) := LevelEnv.cut e 2 in
104+
let e' := LevelEnv.append p s in
105+
List.iter2 assert_rel_decl_eq (LevelEnv.to_list e) (LevelEnv.to_list e').
74106
exact I.
75107
Qed.
76108

77109
Goal True.
78110
intros.
79111
let e := LevelEnv.empty in
80112
let e := LevelEnv.add_decl_level e (RelDecl.Def (Binder.make (Some @c) 'nat) '3) in
81-
let (ev, inst) := make_evar_in_level_env true e 'nat in
82-
printf "%t" (make_evar ev inst);
113+
let (ev, _) := make_evar_in_level_env true e 'nat in
83114
Control.new_goal ev > [|exact &c] > [exact I].
84115
Qed.
85116

ltac2-extra/theories/internal/constr.v

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,25 @@ Module Constr.
143143
"ltac2_extensions" "restrict_evar".
144144

145145
(** See [Evd.evar_context].
146+
147+
WARNING: Ltac2 evar instances are always filtered.
148+
If you are working with those, you need [evar_filtered_context].
149+
150+
NOTE: The [binder]s returned are guaranteed to be named. The reason to
151+
return [binders] and not pairs of [ident] and [constr] is to correctly
152+
track the relevance of the binders.
153+
146154
NOTE: The context is returned from outermost to innermost binder, i.e.
147155
the same order as in [Control.hyps]. *)
148-
Ltac2 @ external context : evar -> (ident * constr option * constr) list :=
156+
Ltac2 @ external context : evar -> (binder * constr option) list :=
149157
"sl.Constr" "evar_context".
158+
159+
(** See [Evd.evar_filtered_context] and notes in [evar_context] above.
160+
161+
NOTE: The filtered context will have the same length as the Ltac2
162+
representation of the evar's instance. *)
163+
Ltac2 @ external filtered_context : evar -> (binder * constr option) list :=
164+
"sl.Constr" "evar_filtered_context".
150165
End Evar.
151166

152167
(** [subst_evars c] returns [Some c'], where [c'] is a copy of [c] where all

0 commit comments

Comments
 (0)