aboutsummaryrefslogtreecommitdiff
path: root/src/Reflection/Reify.v
diff options
context:
space:
mode:
authorGravatar Jason Gross <jgross@mit.edu>2017-01-11 21:02:50 -0500
committerGravatar Jason Gross <jasongross9@gmail.com>2017-03-01 11:45:47 -0500
commit6b3048c37ad348dc88ecc03ef892ecfb121bfa7f (patch)
tree351e5438c5664ab0caf08b9d5054f296ff4aa2ee /src/Reflection/Reify.v
parent80dc66a34fbf031bfac1214ccbb3bb1dcdef3d39 (diff)
Switch to fully uncurried form for reflection
This will eventually make a number of proofs easier. Unfortunately, the correctness lemmas for AddCoordinates and LadderStep no longer work (because of different arities), and there's a proof in Experiments/Ed25519 that I've admitted. The correctness lemmas will be easy to re-add when we have a more general version that handle arbitrary type shapes.
Diffstat (limited to 'src/Reflection/Reify.v')
-rw-r--r--src/Reflection/Reify.v86
1 files changed, 60 insertions, 26 deletions
diff --git a/src/Reflection/Reify.v b/src/Reflection/Reify.v
index 9b3c70d49..99518657b 100644
--- a/src/Reflection/Reify.v
+++ b/src/Reflection/Reify.v
@@ -81,16 +81,21 @@ Ltac reify_flat_type T :=
=> let v := reify_base_type T in
constr:(@Tbase _ v)
end.
-Ltac reify_type T :=
+Ltac reify_input_type T :=
let dummy := debug_enter_reify_type T in
lazymatch T with
| (?A -> ?B)%type
- => let a := reify_base_type A in
- let b := reify_type B in
+ => let a := reify_flat_type A in
+ let b := reify_input_type B in
constr:(@Arrow _ a b)
- | _
- => let v := reify_flat_type T in
- constr:(@Tflat _ v)
+ end.
+Ltac reify_type T :=
+ let dummy := debug_enter_reify_type T in
+ lazymatch T with
+ | (?A -> ?B)%type
+ => let a := reify_flat_type A in
+ let b := reify_flat_type B in
+ constr:(@Syntax.Arrow _ a b)
end.
Ltac reifyf_var x mkVar :=
@@ -140,6 +145,8 @@ Ltac reifyf base_type_code interp_base_type op var e :=
let mkConst T ex := constr:(Const (base_type_code:=base_type_code) (interp_base_type:=interp_base_type) (op:=op) (var:=var) (t:=T) ex) in
let mkOp T retT op_code args := constr:(Op (base_type_code:=base_type_code) (interp_base_type:=interp_base_type) (op:=op) (var:=var) (t1:=T) (tR:=retT) op_code args) in
let mkMatchPair tC ex eC := constr:(MatchPair (base_type_code:=base_type_code) (interp_base_type:=interp_base_type) (op:=op) (var:=var) (tC:=tC) ex eC) in
+ let mkFst ex := constr:(Fst (base_type_code:=base_type_code) (interp_base_type:=interp_base_type) (op:=op) (var:=var) ex) in
+ let mkSnd ex := constr:(Snd (base_type_code:=base_type_code) (interp_base_type:=interp_base_type) (op:=op) (var:=var) ex) in
let reify_tag := constr:(@exprf base_type_code interp_base_type op var) in
let dummy := debug_enter_reifyf e in
lazymatch e with
@@ -172,10 +179,20 @@ Ltac reifyf base_type_code interp_base_type op var e :=
with fun _ v _ => @?C v => C end
| match ?ev with pair a b => @?eC a b end =>
let dummy := debug_reifyf_case "matchpair" in
- let t := (let T := match type of eC with _ -> _ -> ?T => T end in reify_flat_type T) in
+ let T := type of eC in
+ let t := (let T := match (eval cbv beta in T) with _ -> _ -> ?T => T end in reify_flat_type T) in
let v := reify_rec ev in
let C := reify_rec eC in
- mkMatchPair t v C
+ let ret := mkMatchPair t v C in
+ ret
+ | @fst ?A ?B ?ev =>
+ let dummy := debug_reifyf_case "fst" in
+ let v := reify_rec ev in
+ mkFst v
+ | @snd ?A ?B ?ev =>
+ let dummy := debug_reifyf_case "snd" in
+ let v := reify_rec ev in
+ mkSnd v
| ?x =>
let dummy := debug_reifyf_case "generic" in
let t := lazymatch type of x with ?t => reify_flat_type t end in
@@ -256,14 +273,14 @@ Ltac reify_abs base_type_code interp_base_type op var e :=
let dummy := debug_enter_reify_abs e in
lazymatch e with
| (fun x : ?T => ?C) =>
- let t := reify_base_type T in
+ let t := reify_flat_type T in
(* Work around Coq 8.5 and 8.6 bug *)
(* <https://coq.inria.fr/bugs/show_bug.cgi?id=4998> *)
(* Avoid re-binding the Gallina variable referenced by Ltac [x] *)
(* even if its Gallina name matches a Ltac in this tactic. *)
let maybe_x := fresh x in
let not_x := fresh x in
- lazymatch constr:(fun (x : T) (not_x : var (Tbase t)) (_ : reify_var_for_in_is base_type_code x (Tbase t) not_x) =>
+ lazymatch constr:(fun (x : T) (not_x : var t) (_ : reify_var_for_in_is base_type_code x t not_x) =>
(_ : reify_abs reify_tag C)) (* [C] here is an open term that references "x" by name *)
with fun _ v _ => @?C v => mkAbs t C end
| ?x =>
@@ -280,29 +297,44 @@ Ltac Reify' base_type_code interp_base_type op e :=
end.
Ltac Reify base_type_code interp_base_type op make_const e :=
let r := Reify' base_type_code interp_base_type op e in
+ let r := lazymatch type of r with
+ | forall var, exprf _ _ _ _ => constr:(fun var => Abs (src:=Unit) (fun _ => r var))
+ | _ => r
+ end in
constr:(@InputSyntax.Compile base_type_code interp_base_type op make_const _ r).
-Ltac lhs_of_goal := lazymatch goal with |- ?R ?LHS ?RHS => LHS end.
-Ltac rhs_of_goal := lazymatch goal with |- ?R ?LHS ?RHS => RHS end.
+Ltac rhs_of_goal :=
+ lazymatch goal with
+ | [ |- ?R ?LHS ?RHS ] => RHS
+ | [ |- forall x, ?R (@?LHS x) (@?RHS x) ] => RHS
+ end.
+
+Ltac transitivity_tt term :=
+ first [ transitivity term
+ | transitivity (term tt)
+ | let x := fresh in intro x; transitivity (term x); revert x ].
Ltac Reify_rhs_gen Reify prove_interp_compile_correct interp_op try_tac :=
let rhs := rhs_of_goal in
let RHS := Reify rhs in
let RHS' := (eval vm_compute in RHS) in
- transitivity (Syntax.Interp interp_op RHS');
+ transitivity_tt (Syntax.Interp interp_op RHS');
[
- | transitivity (Syntax.Interp interp_op RHS);
+ | transitivity_tt (Syntax.Interp interp_op RHS);
[ lazymatch goal with
| [ |- ?R ?x ?y ]
=> cut (x = y)
+ | [ |- forall k, ?R (?x k) (?y k) ]
+ => cut (x = y)
end;
[ let H := fresh in
intro H; rewrite H; reflexivity
| apply f_equal; vm_compute; reflexivity ]
- | etransitivity; (* first we strip off the [InputSyntax.Compile]
- bit; Coq is bad at inferring the type, so we
- help it out by providing it *)
- [ prove_interp_compile_correct ()
+ | intros; etransitivity; (* first we strip off the [InputSyntax.Compile]
+ bit; Coq is bad at inferring the type, so we
+ help it out by providing it *)
+ [ cbv [InputSyntax.compilet];
+ prove_interp_compile_correct ()
| try_tac
ltac:(fun _
=> (* now we unfold the interpretation function,
@@ -311,7 +343,7 @@ Ltac Reify_rhs_gen Reify prove_interp_compile_correct interp_op try_tac :=
functions that we're parameterized over. *)
abstract (
lazymatch goal with
- | [ |- ?R (@InputSyntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op ?t ?e) _ ]
+ | [ |- appcontext[@InputSyntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op ?t ?e] ]
=> let interp_base_type' := (eval hnf in interp_base_type) in
let interp_op' := (eval hnf in interp_op) in
change interp_base_type with interp_base_type';
@@ -320,13 +352,15 @@ Ltac Reify_rhs_gen Reify prove_interp_compile_correct interp_op try_tac :=
cbv iota beta delta [InputSyntax.Interp interp_type interp_type_gen interp_type_gen_hetero interp_flat_type interp interpf]; reflexivity)) ] ] ].
Ltac prove_compile_correct :=
- fun _ => lazymatch goal with
- | [ |- @Syntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op (@Tflat _ ?t) (@Compile _ _ _ ?make_const _ ?e) = _ ]
- => apply (fun pf => @InputSyntax.Compile_flat_correct base_type_code interp_base_type op make_const interp_op pf t e)
- | [ |- interp_type_gen_rel_pointwise _ (@Syntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op ?t (@Compile _ _ _ ?make_const _ ?e)) _ ]
- => apply (fun pf => @InputSyntax.Compile_correct base_type_code interp_base_type op make_const interp_op pf t e)
- end;
- let T := fresh in intro T; destruct T; reflexivity.
+ fun _ => intros;
+ lazymatch goal with
+ | [ |- @Syntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op _ (@Compile _ _ _ ?make_const (InputSyntax.Arrow ?src (Tflat ?dst)) ?e) ?x = _ ]
+ => apply (fun pf => @InputSyntax.Compile_correct base_type_code interp_base_type op make_const interp_op pf src dst e x);
+ let T := fresh in intro T; destruct T; reflexivity
+ | [ |- @Syntax.Interp ?base_type_code ?interp_base_type ?op ?interp_op _ (@Compile _ _ _ ?make_const (Tflat ?T) ?e) ?x = _ ]
+ => apply (fun pf => @InputSyntax.Compile_flat_correct_flat base_type_code interp_base_type op make_const interp_op pf T e x);
+ let T := fresh in intro T; destruct T; reflexivity
+ end.
Ltac Reify_rhs base_type_code interp_base_type op make_const interp_op :=
Reify_rhs_gen