aboutsummaryrefslogtreecommitdiff
path: root/src/Reflection/WfProofs.v
blob: 226172b5d103208448d5eb27f93cf3af23024f04 (plain)
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
Require Import Crypto.Reflection.Syntax.
Require Import Crypto.Util.Tactics Crypto.Util.Sigma Crypto.Util.Prod.

Local Open Scope ctype_scope.
Section language.
  Context (base_type_code : Type).
  Context (interp_base_type : base_type_code -> Type).
  Context (op : flat_type base_type_code -> flat_type base_type_code -> Type).

  Local Notation flat_type := (flat_type base_type_code).
  Local Notation type := (type base_type_code).
  Let Tbase := @Tbase base_type_code.
  Local Coercion Tbase : base_type_code >-> Syntax.flat_type.
  Let interp_type := interp_type interp_base_type.
  Let interp_flat_type := interp_flat_type_gen interp_base_type.
  Local Notation exprf := (@exprf base_type_code interp_base_type op).
  Local Notation expr := (@expr base_type_code interp_base_type op).
  Local Notation Expr := (@Expr base_type_code interp_base_type op).
  Local Notation wff := (@wff base_type_code interp_base_type op).

  Section with_var.
    Context {var1 var2 : base_type_code -> Type}.
    Local Hint Constructors Syntax.wff.
    Lemma wff_in_impl_Proper G0 G1 {t} e1 e2
      : @wff var1 var2 G0 t e1 e2
        -> (forall x, List.In x G0 -> List.In x G1)
        -> @wff var1 var2 G1 t e1 e2.
    Proof.
      intro wf; revert G1; induction wf;
        repeat match goal with
               | _ => setoid_rewrite List.in_app_iff
               | _ => progress intros
               | _ => progress simpl in *
               | [ |- wff _ _ _ ] => constructor
               | [ H : _ |- _ ] => apply H
               | _ => solve [ intuition eauto ]
               end.
    Qed.

    Local Hint Resolve List.in_app_or List.in_or_app.
    Local Hint Extern 1 => progress unfold List.In in *.
    Local Hint Resolve wff_in_impl_Proper.

    Lemma wff_SmartVar {t} x1 x2
      : @wff var1 var2 (flatten_binding_list base_type_code x1 x2) t (SmartVar x1) (SmartVar x2).
    Proof.
      unfold SmartVar.
      induction t; simpl; constructor; eauto.
    Qed.

    Local Hint Resolve wff_SmartVar.

    Lemma wff_Const_eta G {A B} v1 v2
      : @wff var1 var2 G (Prod A B) (Const v1) (Const v2)
        -> (@wff var1 var2 G A (Const (fst v1)) (Const (fst v2))
           /\ @wff var1 var2 G B (Const (snd v1)) (Const (snd v2))).
    Proof.
      intro wf.
      assert (H : Some v1 = Some v2).
      { refine match wf in @Syntax.wff _ _ _ _ _ G t e1 e2 return invert_Const e1 = invert_Const e2 with
               | WfConst _ _ _ => eq_refl
               | _ => eq_refl
               end. }
      inversion H; subst; repeat constructor.
    Qed.

    Definition wff_Const_eta_fst G {A B} v1 v2 H
      := proj1 (@wff_Const_eta G A B v1 v2 H).
    Definition wff_Const_eta_snd G {A B} v1 v2 H
      := proj2 (@wff_Const_eta G A B v1 v2 H).

    Local Hint Resolve wff_Const_eta_fst wff_Const_eta_snd.

    Lemma wff_SmartConst G {t t'} v1 v2 x1 x2
          (Hin : List.In (existT (fun t : base_type_code => (@exprf var1 t * @exprf var2 t)%type) t (x1, x2))
                         (flatten_binding_list base_type_code (SmartConst v1) (SmartConst v2)))
          (Hwf : @wff var1 var2 G t' (Const v1) (Const v2))
      : @wff var1 var2 G t x1 x2.
    Proof.
      induction t'. simpl in *.
      { intuition (inversion_sigma; inversion_prod; subst; eauto). }
      { unfold SmartConst in *; simpl in *.
        apply List.in_app_iff in Hin.
        intuition (inversion_sigma; inversion_prod; subst; eauto). }
    Qed.

    Local Hint Resolve wff_SmartConst.
  End with_var.
End language.