|
| 1 | +Require Import RecordUpdate.RecordUpdate. |
| 2 | +From stdpp Require Import base list. |
| 3 | +From Stdlib.Strings Require Import String. |
| 4 | + |
| 5 | +From RichWasm Require Import layout syntax typing util. |
| 6 | +Set Bullet Behavior "Strict Subproofs". |
| 7 | + |
| 8 | +Definition type_error := string. |
| 9 | +Definition ok := unit. |
| 10 | +Definition type_checker_res := sum ok type_error. |
| 11 | + |
| 12 | +Definition ok_term : type_checker_res := inl (). |
| 13 | +Definition INR (s:string) : type_checker_res := inr s. |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +(* No matter how type_checker_res changes, this MUST stay the same *) |
| 18 | +Definition check_ok In (func: In -> type_checker_res) (i: In) : bool := |
| 19 | + match (func i) with |
| 20 | + | inl a => true |
| 21 | + | inr a => false |
| 22 | + end. |
| 23 | + |
| 24 | +Definition check_ok_output (res: type_checker_res) : bool := |
| 25 | + match res with |
| 26 | + | inl a => true |
| 27 | + | inr a => false |
| 28 | + end. |
| 29 | + |
| 30 | +(* This is only true if ok is kept at unit. Unfortunately most of the proofs |
| 31 | + rely on this. *) |
| 32 | +Lemma check_ok_true_to_prop In (func: In -> type_checker_res) (i:In) : |
| 33 | + check_ok In func i = true -> func i = ok_term. |
| 34 | +Proof. |
| 35 | + intros. unfold ok_term. |
| 36 | + destruct (func i) eqn:H'. |
| 37 | + - unfold ok in o. |
| 38 | + assert (o = tt) by (by destruct o). |
| 39 | + subst; auto. |
| 40 | + - unfold check_ok in H. |
| 41 | + rewrite H' in H. inversion H. |
| 42 | +Qed. |
| 43 | +Lemma check_ok_output_true_to_prop (res: type_checker_res) : |
| 44 | + check_ok_output res = true -> res = ok_term. |
| 45 | +Proof. |
| 46 | + intros. unfold ok_term. |
| 47 | + destruct (res) eqn:H'. |
| 48 | + - unfold ok in o. |
| 49 | + assert (o = tt) by (by destruct o). |
| 50 | + subst; auto. |
| 51 | + - unfold check_ok in H. |
| 52 | + simpl in H. |
| 53 | + inversion H. |
| 54 | +Qed. |
| 55 | + |
| 56 | +(* Helper function for converting between forall inductive hyp and foldr boolean version *) |
| 57 | +Lemma Forall_foldr_bool_to_prop A (Pprop : A -> Prop) (Pbool : A -> bool) (l : list A) : |
| 58 | + (Forall (λ x:A, (Pbool x = true) -> Pprop x) l) -> |
| 59 | + (foldr (λ x:A, andb (Pbool x)) true l) = true -> |
| 60 | + Forall Pprop l. |
| 61 | +Proof. |
| 62 | + intros HForall Hfoldr. |
| 63 | + apply Forall_fold_right. |
| 64 | + induction l; simpl; auto. |
| 65 | + - rewrite foldr_cons in Hfoldr; apply andb_prop in Hfoldr as [a_true l_true]. |
| 66 | + apply Forall_cons_1 in HForall; destruct HForall as [a_prop l_prop]. |
| 67 | + split; auto. |
| 68 | +Qed. |
| 69 | + |
| 70 | +(* Converting between _ = ok_term to check_ok = true *) |
| 71 | +Lemma equal_okterm_to_checkok In (func: In -> type_checker_res) (Pbool : In -> Prop) : |
| 72 | + forall i:In, |
| 73 | + ((func i = ok_term -> Pbool i) -> |
| 74 | + (check_ok In func i = true -> Pbool i)). |
| 75 | +Proof. |
| 76 | + intros. apply H. |
| 77 | + by apply check_ok_true_to_prop. |
| 78 | +Qed. |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | +(** WE BEGIN **) |
| 84 | + |
| 85 | + |
| 86 | +(* mem_ok *) |
| 87 | +Definition mem_ok_checker (k:kind_ctx) (mem:memory) : type_checker_res := |
| 88 | + match mem with |
| 89 | + | BaseM cm => ok_term |
| 90 | + | VarM m => |
| 91 | + if m <? k.(kc_mem_vars) then ok_term else INR "mem_ok error" |
| 92 | + end. |
| 93 | + |
| 94 | +Lemma mem_ok_checker_correct (k:kind_ctx) (mem:memory) : |
| 95 | + (mem_ok_checker k mem = ok_term) -> mem_ok k mem. |
| 96 | +Proof. |
| 97 | + intros. |
| 98 | + destruct mem. |
| 99 | + - apply OKVarM. |
| 100 | + simpl in H. |
| 101 | + destruct (n <? kc_mem_vars k) eqn:H'. |
| 102 | + + apply Nat.ltb_lt in H'. auto. |
| 103 | + + inversion H. |
| 104 | + - apply OKBaseM. |
| 105 | +Qed. |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | +(* rep_ok *) |
| 110 | +Fixpoint rep_ok_checker (k:kind_ctx) (rep:representation) : type_checker_res := |
| 111 | + match rep with |
| 112 | + | AtomR ι => ok_term |
| 113 | + | VarR r => if r <? k.(kc_rep_vars) then ok_term else INR "rep_ok error" |
| 114 | + | ProdR ρs => |
| 115 | + if (foldr (λ i:representation, andb (check_ok representation (rep_ok_checker k) i)) true ρs) |
| 116 | + then ok_term else INR "rep_ok error" |
| 117 | + | SumR ρs => |
| 118 | + if (foldr (λ i:representation, andb (check_ok representation (rep_ok_checker k) i)) true ρs) |
| 119 | + then ok_term else INR "rep_ok error" |
| 120 | + end. |
| 121 | + |
| 122 | +Lemma rep_ok_checker_correct (k:kind_ctx) (rep:representation) : |
| 123 | + (rep_ok_checker k rep = ok_term) -> rep_ok k rep. |
| 124 | +Proof. |
| 125 | + intros. |
| 126 | + induction rep using rep_ind. |
| 127 | + - apply OKVarR. |
| 128 | + simpl in H. |
| 129 | + destruct (idx <? kc_rep_vars k) eqn:H'. |
| 130 | + + apply Nat.ltb_lt in H'. auto. |
| 131 | + + inversion H. |
| 132 | + - apply OKSumR. |
| 133 | + simpl in H. |
| 134 | + destruct (foldr (λ i:representation, andb (check_ok representation (rep_ok_checker k) i)) true ρs) eqn:H'. |
| 135 | + + clear H. |
| 136 | + apply (Forall_impl _ (λ x, check_ok representation (rep_ok_checker k) x = true -> rep_ok k x)) in H0. |
| 137 | + * eapply Forall_foldr_bool_to_prop; [apply H0 | apply H']. |
| 138 | + * apply equal_okterm_to_checkok. |
| 139 | + + inversion H. |
| 140 | + - apply OKProdR. |
| 141 | + simpl in H. |
| 142 | + destruct (foldr (λ i:representation, andb (check_ok representation (rep_ok_checker k) i)) true ρs) eqn:H'. |
| 143 | + + clear H. |
| 144 | + apply (Forall_impl _ (λ x, check_ok representation (rep_ok_checker k) x = true -> rep_ok k x)) in H0. |
| 145 | + * eapply Forall_foldr_bool_to_prop; [apply H0 | apply H']. |
| 146 | + * apply equal_okterm_to_checkok. |
| 147 | + + inversion H. |
| 148 | + - apply OKAtomR. |
| 149 | +Qed. |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | +(* size_ok *) |
| 154 | +Fixpoint size_ok_checker (k:kind_ctx) (s:size) : type_checker_res := |
| 155 | + match s with |
| 156 | + | ConstS n => ok_term |
| 157 | + | VarS r => if r <? k.(kc_size_vars) then ok_term else INR "size_ok error" |
| 158 | + | RepS ρ => match (rep_ok_checker k ρ) with |
| 159 | + | inl _ => ok_term |
| 160 | + | err => err (* this allows propagation*) |
| 161 | + (* you could also just ret rep_ok_checker. Idk which would be |
| 162 | + better for future changeability. I'll do just ret later*) |
| 163 | + end |
| 164 | + | SumS σs => |
| 165 | + if (foldr (λ i:size, andb (check_ok size (size_ok_checker k) i)) true σs) |
| 166 | + then ok_term else INR "size_ok error" |
| 167 | + | ProdS σs => |
| 168 | + if (foldr (λ i:size, andb (check_ok size (size_ok_checker k) i)) true σs) |
| 169 | + then ok_term else INR "size_ok error" |
| 170 | + end. |
| 171 | + |
| 172 | +Lemma size_ok_checker_correct (k:kind_ctx) (s:size) : |
| 173 | + (size_ok_checker k s = ok_term) -> size_ok k s. |
| 174 | +Proof. |
| 175 | + intros. |
| 176 | + induction s using size_ind. |
| 177 | + - apply OKVarS. |
| 178 | + simpl in H. |
| 179 | + destruct (idx <? kc_size_vars k) eqn:H'. |
| 180 | + + apply Nat.ltb_lt in H'. auto. |
| 181 | + + inversion H. |
| 182 | + - apply OKSumS. |
| 183 | + simpl in H. |
| 184 | + destruct (foldr (λ i:size, andb (check_ok size (size_ok_checker k) i)) true σs) eqn:H'. |
| 185 | + + clear H. |
| 186 | + apply (Forall_impl _ (λ x, check_ok size (size_ok_checker k) x = true -> size_ok k x)) in H0. |
| 187 | + * eapply Forall_foldr_bool_to_prop; [apply H0 | apply H']. |
| 188 | + * apply equal_okterm_to_checkok. |
| 189 | + + inversion H. |
| 190 | + - apply OKProdS. |
| 191 | + simpl in H. |
| 192 | + destruct (foldr (λ i:size, andb (check_ok size (size_ok_checker k) i)) true σs) eqn:H'. |
| 193 | + + clear H. |
| 194 | + apply (Forall_impl _ (λ x, check_ok size (size_ok_checker k) x = true -> size_ok k x)) in H0. |
| 195 | + * eapply Forall_foldr_bool_to_prop; [apply H0 | apply H']. |
| 196 | + * apply equal_okterm_to_checkok. |
| 197 | + + inversion H. |
| 198 | + - apply OKRepS. |
| 199 | + simpl in H. |
| 200 | + destruct (rep_ok_checker k ρ) eqn:H'. |
| 201 | + + apply rep_ok_checker_correct. |
| 202 | + unfold ok in o. |
| 203 | + assert (o = tt) by (by destruct o). |
| 204 | + subst; auto. |
| 205 | + + inversion H. |
| 206 | + - apply OKConstS. |
| 207 | +Qed. |
| 208 | + |
| 209 | + |
| 210 | +(* kind_ok *) |
| 211 | +Definition kind_ok_checker (k:kind_ctx) (ki: kind) : type_checker_res := |
| 212 | + match ki with |
| 213 | + | (VALTYPE ρ χ δ) => rep_ok_checker k ρ |
| 214 | + | MEMTYPE σ δ => size_ok_checker k σ |
| 215 | + end. |
| 216 | + |
| 217 | +Lemma kind_ok_checker_correct (k:kind_ctx) (ki:kind) : |
| 218 | + (kind_ok_checker k ki = ok_term) -> kind_ok k ki. |
| 219 | +Proof. |
| 220 | + intros. |
| 221 | + destruct ki; simpl in H. |
| 222 | + - apply OKVALTYPE. |
| 223 | + apply rep_ok_checker_correct; auto. |
| 224 | + - apply OKMEMTYPE. |
| 225 | + apply size_ok_checker_correct; auto. |
| 226 | +Qed. |
0 commit comments