-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathReifyCommon.v
119 lines (103 loc) · 3.95 KB
/
ReifyCommon.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
(** * Factored code common to many variants of reification *)
Require Import Reify.NamedTimers.
Require Export Reify.Common.
Require Export Reify.PHOAS.
Notation do_transitivity := false (only parsing).
(** We provide a tactic to run a tactic in a constr context. *)
Ltac crun tac :=
match goal with
| _ => tac
end.
(** Note: If you want to preserve variable names on reification, there
are many hoops to jump through. We write a [refresh] tactic which
permits preserving binder names at a nontrivial performance
overhead. *)
(** c.f. %\url{https://github.com/coq/coq/issues/5448}%,
%\url{https://github.com/coq/coq/issues/6315}%,
%\url{https://github.com/coq/coq/issues/6559}% *)
Ltac require_same_var n1 n2 :=
let c1 := constr:(fun n1 n2 : Set => ltac:(exact n1)) in
let c2 := constr:(fun n1 n2 : Set => ltac:(exact n2)) in
first [ constr_eq c1 c2
| fail 1 "Not the same var:" n1 "and" n2 "(via constr_eq" c1 c2 ")" ].
Ltac is_same_var n1 n2 :=
match goal with
| _ => let __ := match goal with _ => require_same_var n1 n2 end in
true
| _ => false
end.
Ltac is_underscore v :=
let v' := fresh v in
let v' := fresh v' in
is_same_var v v'.
(** Note that [fresh_tac] must be [ltac:(fun n => fresh n)];
c.f. %\url{https://github.com/coq/coq/issues/6559}% *)
Ltac refresh n fresh_tac :=
let n_is_underscore := is_underscore n in
let n' := lazymatch n_is_underscore with
| true => fresh
| false => fresh_tac n
end in
let n' := fresh_tac n' in
n'.
(** However, this comes at a significant cost in speed, so we do not
try to preserve variable names, and this tactic is unused in our
benchmark. *)
Ltac Reify_of reify x :=
constr:(fun var : Type => ltac:(let v := reify var x in exact v)).
Ltac if_doing_trans tac :=
let do_trans := constr:(do_transitivity) in
lazymatch do_trans with
| true => tac ()
| false => idtac
end.
(** We ask for dummy arguments for most things, because it is good
practice to indicate that this tactic should not be run at the
call-site (when it's passed to another tactic), but at the
use-site. *)
Ltac do_Reify_rhs_of_cps_with_denote Reify_cps Denote _ :=
let v := lazymatch goal with |- ?LHS = ?v => v end in
let __ := crun ltac:(restart_timer "norm reif") in
let __ := crun ltac:(restart_timer "actual reif") in
Reify_cps v ltac:(
fun rv
=> let __ := crun ltac:(finish_timing ("Tactic call") "actual reif") in
let __ := crun ltac:(restart_timer "eval lazy") in
let rv := (eval lazy in rv) in
let __ := crun ltac:(finish_timing ("Tactic call") "eval lazy") in
let __ := crun ltac:(finish_timing ("Tactic call") "norm reif") in
time "lazy beta iota" lazy beta iota;
if_doing_trans
ltac:(fun _
=> time "transitivity (Denote rv)"
transitivity (Denote rv))).
Ltac do_Reify_rhs_of_cps Reify_cps _ :=
do_Reify_rhs_of_cps_with_denote Reify_cps Denote ().
Ltac do_Reify_rhs_of_with_denote Reify Denote _ :=
do_Reify_rhs_of_cps_with_denote
ltac:(fun v tac => let rv := Reify v in tac rv) Denote ().
Ltac do_Reify_rhs_of Reify _ :=
do_Reify_rhs_of_with_denote Reify Denote ().
Ltac post_Reify_rhs _ :=
[ > ..
| if_doing_trans ltac:(fun _ => lazy [Denote denote]; reflexivity) ].
Ltac Reify_rhs_of_cps Reify_cps _ :=
do_Reify_rhs_of_cps Reify_cps (); post_Reify_rhs ().
Ltac Reify_rhs_of Reify _ :=
do_Reify_rhs_of Reify (); post_Reify_rhs ().
Ltac error_cant_elim_deps f :=
let __ := match goal with
| _ => idtac "Failed to eliminate functional dependencies in" f
end in
constr:(I : I).
Ltac error_bad_function f :=
let __ := match goal with
| _ => idtac "Bad let-in function" f
end in
constr:(I : I).
Ltac error_bad_term term :=
let __ := match goal with
| _ => idtac "Unrecognized term:" term
end in
let ret := constr:(term : I) in
constr:(I : I).