Last active
December 22, 2017 18:31
-
-
Save JasonGross/e3d55b61a26e038020870df825cd0896 to your computer and use it in GitHub Desktop.
ltac_slow_fresh.v
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Global Set Implicit Arguments. | |
Reserved Notation "'dlet' x .. y := v 'in' f" | |
(at level 200, x binder, y binder, f at level 200, format "'dlet' x .. y := v 'in' '//' f"). | |
Reserved Notation "'elet' x := v 'in' f" | |
(at level 200, f at level 200, format "'elet' x := v 'in' '//' f"). | |
Definition Let_In {A P} (v : A) (f : forall x : A, P x) : P v | |
:= let x := v in f x. | |
Notation "'dlet' x .. y := v 'in' f" := (Let_In v (fun x => .. (fun y => f) .. )). | |
Inductive expr {var : Type} : Type := | |
| NatO : expr | |
| NatS : expr -> expr | |
| LetIn (v : expr) (f : var -> expr) | |
| Var (v : var) | |
| NatMul (x y : expr). | |
Bind Scope expr_scope with expr. | |
Delimit Scope expr_scope with expr. | |
Infix "*" := NatMul : expr_scope. | |
Notation "'elet' x := v 'in' f" := (LetIn v (fun x => f%expr)) : expr_scope. | |
Notation "$$ x" := (Var x) (at level 9, format "$$ x") : expr_scope. | |
Fixpoint denote (e : @expr nat) : nat | |
:= match e with | |
| NatO => O | |
| NatS x => S (denote x) | |
| LetIn v f => dlet x := denote v in denote (f x) | |
| Var v => v | |
| NatMul x y => denote x * denote y | |
end. | |
Definition Expr := forall var, @expr var. | |
Definition Denote (e : Expr) := denote (e _). | |
Set Primitive Projections. | |
Record prod A B := pair { fst : A ; snd : B }. | |
Add Printing Let prod. | |
Arguments pair {A B} _ _. | |
Arguments fst {A B} _. | |
Arguments snd {A B} _. | |
Notation "x * y" := (prod x y) : type_scope. | |
Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope. | |
(* cf COQBUG(https://github.com/coq/coq/issues/5448), COQBUG(https://github.com/coq/coq/issues/6315) *) | |
Ltac refresh n := | |
let n' := fresh n in | |
let n' := fresh n in | |
n'. | |
Ltac Reify_of reify x := | |
constr:(fun var : Type => ltac:(let v := reify var x in exact v)). | |
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). | |
Ltac reify var term := | |
let reify_rec term := reify var term in | |
lazymatch term with | |
| fst (?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 := refresh x in | |
let not_x2 := refresh not_x in | |
let not_x3 := refresh not_x2 in | |
let rf | |
:= | |
lazymatch | |
constr:( | |
fun (not_x : nat) (not_x2 : var) | |
=> match @fst nat var (@pair nat var not_x not_x2) return @expr var with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return] *) | |
| x | |
=> match f return @expr var with | |
| not_x3 | |
=> ltac:(let fx := (eval cbv delta [not_x3 x] in not_x3) in | |
clear x not_x3; | |
let rf := reify_rec fx in | |
exact rf) | |
end | |
end) | |
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 x := Reify_of reify x. | |
Fixpoint big (a : nat) (sz : nat) : nat | |
:= match sz with | |
| O => a | |
| S sz' => dlet a' := a * a in big a' sz' | |
end. | |
Notation sz := 300 (only parsing). | |
Goal True. | |
Time do 200 | |
time (idtac; | |
let v := constr:(ltac:(assert (exists e, e = big 1 sz); | |
[ eexists; | |
lazy [big]; | |
let x := match goal with |- _ = ?RHS => RHS end in | |
let rv := Reify x in | |
transitivity (Denote rv); | |
[ | lazy [Denote denote]; reflexivity ]; | |
reflexivity | |
| exact I ])) in | |
idtac). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Global Set Implicit Arguments. | |
Reserved Notation "'dlet' x .. y := v 'in' f" | |
(at level 200, x binder, y binder, f at level 200, format "'dlet' x .. y := v 'in' '//' f"). | |
Reserved Notation "'elet' x := v 'in' f" | |
(at level 200, f at level 200, format "'elet' x := v 'in' '//' f"). | |
Definition Let_In {A P} (v : A) (f : forall x : A, P x) : P v | |
:= let x := v in f x. | |
Notation "'dlet' x .. y := v 'in' f" := (Let_In v (fun x => .. (fun y => f) .. )). | |
Inductive expr {var : Type} : Type := | |
| NatO : expr | |
| NatS : expr -> expr | |
| LetIn (v : expr) (f : var -> expr) | |
| Var (v : var) | |
| NatMul (x y : expr). | |
Bind Scope expr_scope with expr. | |
Delimit Scope expr_scope with expr. | |
Infix "*" := NatMul : expr_scope. | |
Notation "'elet' x := v 'in' f" := (LetIn v (fun x => f%expr)) : expr_scope. | |
Notation "$$ x" := (Var x) (at level 9, format "$$ x") : expr_scope. | |
Fixpoint denote (e : @expr nat) : nat | |
:= match e with | |
| NatO => O | |
| NatS x => S (denote x) | |
| LetIn v f => dlet x := denote v in denote (f x) | |
| Var v => v | |
| NatMul x y => denote x * denote y | |
end. | |
Definition Expr := forall var, @expr var. | |
Definition Denote (e : Expr) := denote (e _). | |
Set Primitive Projections. | |
Record prod A B := pair { fst : A ; snd : B }. | |
Add Printing Let prod. | |
Arguments pair {A B} _ _. | |
Arguments fst {A B} _. | |
Arguments snd {A B} _. | |
Notation "x * y" := (prod x y) : type_scope. | |
Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope. | |
(* cf COQBUG(https://github.com/coq/coq/issues/5448), COQBUG(https://github.com/coq/coq/issues/6315) *) | |
Ltac refresh n := | |
let n' := fresh n in | |
let n' := fresh n in | |
n'. | |
Ltac Reify_of reify x := | |
constr:(fun var : Type => ltac:(let v := reify var x in exact v)). | |
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). | |
Ltac reify var term := | |
let reify_rec term := reify var term in | |
lazymatch term with | |
| fst (?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 := refresh x in | |
let not_x2 := refresh not_x in | |
let not_x3 := refresh not_x2 in | |
let rf | |
:= | |
lazymatch | |
constr:( | |
fun (not_x : nat) (not_x2 : var) | |
=> match fst (not_x, not_x2) return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *) | |
| x | |
=> match f return _ with | |
| not_x3 | |
=> ltac:(let fx := (eval cbv delta [not_x3 x] in not_x3) in | |
let rf := reify_rec fx in | |
exact rf) | |
end | |
end) | |
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 x := Reify_of reify x. | |
Module var_context. | |
Inductive var_context {var : Type} := nil | cons (n : nat) (v : var) (xs : var_context). | |
End var_context. | |
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 := refresh x in | |
let not_x2 := refresh not_x in | |
let not_x3 := refresh not_x2 in | |
let rf | |
:= | |
lazymatch | |
constr:( | |
fun (x : nat) (not_x : var) | |
=> match f, @var_context.cons var x not_x ctx return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *) | |
| not_x2, not_x3 | |
=> ltac:(let fx := (eval cbv delta [not_x2] in not_x2) in | |
let ctx := (eval cbv delta [not_x3] in not_x3) in | |
let rf := reify_helper var fx ctx in | |
exact rf) | |
end) | |
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 reify2 var x := | |
reify_helper var x (@var_context.nil var). | |
Ltac Reify2 x := Reify_of reify2 x. | |
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 := refresh x in | |
let not_x2 := refresh not_x in | |
let not_x3 := refresh not_x2 in | |
let rf | |
:= | |
lazymatch | |
constr:( | |
fun (x : nat) (not_x : var) | |
=> match f return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *) | |
| not_x2 | |
=> ltac:(let fx := (eval cbv delta [not_x2] in not_x2) in | |
let ctx := constr:(@var_context.cons var x not_x ctx) in | |
let rf := reify_helper' var fx ctx in | |
exact rf) | |
end) | |
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 reify2' var x := | |
reify_helper' var x (@var_context.nil var). | |
Ltac Reify2' x := Reify_of reify2' x. | |
Definition var_for {var : Type} (n : nat) (v : var) := False. | |
Ltac reify3 var term := | |
let reify_rec term := reify3 var term in | |
lazymatch goal with | |
| [ H : var_for 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 := refresh x in | |
let not_x2 := refresh not_x in | |
let rf | |
:= | |
lazymatch | |
constr:( | |
fun (x : nat) (not_x : var) (_ : @var_for var x not_x) | |
=> match f return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *) | |
| not_x2 | |
=> ltac:(let fx := (eval cbv delta [not_x2] in not_x2) in | |
let rf := reify_rec fx in | |
exact rf) | |
end) | |
with | |
| fun _ v' _ => @?f v' => f | |
| ?f => error_cant_elim_deps f | |
end in | |
constr:(@LetIn var rv rf) | |
| ?v | |
=> error_bad_term v | |
end | |
end. | |
Ltac Reify3 x := Reify_of reify3 x. | |
Fixpoint big (a : nat) (sz : nat) : nat | |
:= match sz with | |
| O => a | |
| S sz' => dlet a' := a * a in big a' sz' | |
end. | |
Notation sz := 200 (only parsing). | |
Goal exists e, e = big 1 sz. | |
Time eexists; cbv [big]. | |
Time let x := match goal with |- _ = ?RHS => RHS end in | |
let rv := Reify x in | |
(*transitivity (Denote rv)*) | |
idtac. (* 3.03 s *) | |
Time let x := match goal with |- _ = ?RHS => RHS end in | |
let rv := Reify2 x in | |
(*transitivity (Denote rv)*) | |
idtac. (* 2.3 s *) | |
Time let x := match goal with |- _ = ?RHS => RHS end in | |
let rv := Reify2' x in | |
(*transitivity (Denote rv)*) | |
idtac. (* 1.5 s *) | |
Time let x := match goal with |- _ = ?RHS => RHS end in | |
let rv := Reify3 x in | |
(*transitivity (Denote rv)*) | |
idtac. (* 1.4 s *) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment