-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLtacPrimUncurry.v
72 lines (63 loc) · 2.74 KB
/
LtacPrimUncurry.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
(** * Ltac-based reification, using uncurrying to reucurse under binders *)
Require Import Reify.ReifyCommon.
Require Import Reify.PrimPair.
(** Points of note:
- We use primitive projections for pairing to speed up typing.
- Because we track variables by pairing [nat] binders with fresh
[var] nodes, we use a [phantom] axiom of type [nat] to fill in
the now-unused [nat] binder after reification.
- We make sure to fill in all implicit arguments explicitly, to
minimize the number of evars generated; evars are one of the
main bottlenecks.
- We make use of a trick from "%[coqdev]% beta1 and zeta1
reduction"%\footnote{\url{https://sympa.inria.fr/sympa/arc/coqdev/2016-01/msg00060.html}}%
to bind names with a single-branch [match] statement without
incurring extra β or ζ reductions.
- We give the [return] clause on the [match] statement explicitly
to work around
%\url{https://github.com/coq/coq/issues/6252\#issuecomment-347041995}%
and prevent extra backtracking, as well as preventing extra evar
allocation. *)
Axiom phantom : nat.
Ltac reify var term :=
let reify_rec term := reify var term in
lazymatch term with
| (fun args : ?T => O)
=> constr:(fun args : T => @NatO var)
| (fun args : ?T => S (@?x args))
=> let rx := reify_rec x in
constr:(fun args : T => @NatS var (rx args))
| fun args : ?T => @?x args * @?y args
=> let rx := reify_rec x in
let ry := reify_rec y in
constr:(fun args : T => @NatMul var (rx args) (ry args))
| (fun args : ?T => dlet x := @?v args in ?f)
=> let rv := reify_rec v in
let args2 := fresh (*args *)in (* don't try to preserve variable names; c.f. comments around ReifyCommon.refresh *)
let rf :=
reify_rec
(fun args2 : (nat * var) * T
=> match @snd (nat * var) T args2,
@fst nat var (@fst (nat * var) T args2)
return nat
with
| args, x => f
end) in
constr:(fun args : T
=> @LetIn
var
(rv args)
(fun x : var
=> rf (@pair (nat * var) T (@pair nat var phantom x) args)))
| (fun args : ?T => @fst ?A ?B (@fst ?C ?D ?args'))
=> constr:(fun args : T => @Var var (@snd A B (@fst C D args')))
| (fun args : ?T => _) (* error case *)
=> error_bad_term term
| ?v
=> let rv := reify_rec (fun dummy : unit => v) in
(eval lazy beta iota delta [fst snd] in (rv tt))
end.
Ltac Reify x := Reify_of reify x.
Ltac do_Reify_rhs _ := do_Reify_rhs_of Reify ().
Ltac post_Reify_rhs _ := ReifyCommon.post_Reify_rhs ().
Ltac Reify_rhs _ := Reify_rhs_of Reify ().