-
Notifications
You must be signed in to change notification settings - Fork 2
/
LtacTCExplicitCtx.v
76 lines (68 loc) · 2.5 KB
/
LtacTCExplicitCtx.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
(** * Recursing under binders with typeclasses, tracking variables with explicit contexts *)
Require Import Reify.ReifyCommon.
(** Points of note:
- We make sure to fill in all implicit arguments explicitly, to
minimize the number of evars generated; evars are one of the
main bottlenecks.
- In the [Hint] used to tie the recursive knot, we run [intros]
before binding any terms to avoid playing fast and loose with
binders, because we will sometimes be presented with goals with
unintroduced binders. If we did not call [intros] first,
instead binding [?var] and [?term] in the hint pattern rule,
they might contain unbound identifiers, causing reification to
fail when it tried to deal with them. *)
Module var_context.
Inductive var_context {var : Type} :=
| nil
| cons (n : nat) (v : var) (xs : var_context).
End var_context.
Class reify_helper_cls (var : Type) (term : nat)
(ctx : @var_context.var_context var)
:= do_reify_helper : @expr var.
Ltac reify_helper var term ctx :=
let reify_rec term := reify_helper var term ctx in
lazymatch ctx with
| context[var_context.cons term ?v _]
=> constr:(@Var var v)
| _
=>
lazymatch term with
| O => constr:(@NatO var)
| S ?x
=> let rx := reify_rec x in
constr:(@NatS var rx)
| ?x * ?y
=> let rx := reify_rec x in
let ry := reify_rec y in
constr:(@NatMul var rx ry)
| (dlet x := ?v in ?f)
=> let rv := reify_rec v in
let not_x := fresh (*x *)in (* don't try to preserve variable names; c.f. comments around ReifyCommon.refresh *)
let rf
:=
lazymatch
constr:(_ : forall (x : nat) (not_x : var),
@reify_helper_cls
var f (@var_context.cons var x not_x ctx))
with
| fun _ => ?f => f
| ?f => error_cant_elim_deps f
end in
constr:(@LetIn var rv rf)
| ?v
=> error_bad_term v
end
end.
Ltac reify var x :=
reify_helper var x (@var_context.nil var).
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 ().
Global Hint Extern 0 (@reify_helper_cls _ _ _)
=> (intros;
lazymatch goal with
| [ |- @reify_helper_cls ?var ?term ?ctx ]
=> let res := reify_helper var term ctx in
exact res
end) : typeclass_instances.