diff options
Diffstat (limited to 'theories/dynlang')
| -rw-r--r-- | theories/dynlang/equiv.v | 154 | ||||
| -rw-r--r-- | theories/dynlang/interp.v | 49 | ||||
| -rw-r--r-- | theories/dynlang/interp_proofs.v | 426 | ||||
| -rw-r--r-- | theories/dynlang/operational.v | 41 | ||||
| -rw-r--r-- | theories/dynlang/operational_props.v | 33 |
5 files changed, 703 insertions, 0 deletions
diff --git a/theories/dynlang/equiv.v b/theories/dynlang/equiv.v new file mode 100644 index 0000000..aa0b7f3 --- /dev/null +++ b/theories/dynlang/equiv.v | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | From mininix Require Export lambda.interp_proofs dynlang.interp_proofs. | ||
| 2 | From stdpp Require Import options. | ||
| 3 | |||
| 4 | Class Lift A B := lift : A → B. | ||
| 5 | Global Hint Mode Lift ! - : typeclass_instances. | ||
| 6 | Arguments lift {_ _ _} !_ /. | ||
| 7 | Notation "⌜ x ⌝" := (lift x) (at level 0). | ||
| 8 | Notation "⌜* x ⌝" := (fmap lift x) (at level 0). | ||
| 9 | |||
| 10 | Module lambda. | ||
| 11 | Global Instance lambda_expr_lift : Lift lambda.expr dynlang.expr := | ||
| 12 | fix go e := let _ : Lift _ _ := go in | ||
| 13 | match e with | ||
| 14 | | lambda.EString s => dynlang.EString s | ||
| 15 | | lambda.EId x => dynlang.EId ∅ (dynlang.EString x) | ||
| 16 | | lambda.EAbs x e => dynlang.EAbs (dynlang.EString x) ⌜e⌝ | ||
| 17 | | lambda.EApp e1 e2 => dynlang.EApp ⌜e1⌝ ⌜e2⌝ | ||
| 18 | end. | ||
| 19 | |||
| 20 | Global Instance lambda_thunk_lift : Lift lambda.thunk dynlang.thunk := | ||
| 21 | fix go t := let _ : Lift _ _ := go in | ||
| 22 | dynlang.Thunk ⌜*lambda.thunk_env t⌝ ⌜lambda.thunk_expr t⌝. | ||
| 23 | |||
| 24 | Global Instance lambda_val_lift : Lift lambda.val dynlang.val := λ v, | ||
| 25 | match v with | ||
| 26 | | lambda.VString s => dynlang.VString s | ||
| 27 | | lambda.VClo x E e => dynlang.VClo x ⌜*E⌝ ⌜e⌝ | ||
| 28 | end. | ||
| 29 | End lambda. | ||
| 30 | |||
| 31 | Lemma interp_open_lambda_dynlang E e mv n : | ||
| 32 | lambda.closed_env E → lambda.closed (dom E) e → | ||
| 33 | lambda.interp n E e = Res mv → | ||
| 34 | ∃ m, dynlang.interp m ⌜*E⌝ ⌜e⌝ = Res ⌜*mv⌝. | ||
| 35 | Proof. | ||
| 36 | revert E e mv. induction n as [|n IH]; [done|]; intros E e mv HE He Hinterp. | ||
| 37 | rewrite lambda.interp_S in Hinterp. destruct e as [s|z|ex e|e1 e2]; simplify_res. | ||
| 38 | - (* EString *) by exists 1. | ||
| 39 | - (* EId *) | ||
| 40 | apply elem_of_dom in He as [[Et et] Hz]. rewrite Hz /= in Hinterp. | ||
| 41 | apply lambda.closed_env_lookup in Hz as He; last done. | ||
| 42 | rewrite lambda.closed_thunk_eq/= in He. destruct He as [HEtclosed Hetclosed]. | ||
| 43 | apply IH in Hinterp as [m Hinterp]; [|done..]. | ||
| 44 | exists (S (S m)). rewrite !dynlang.interp_S /= -dynlang.interp_S. | ||
| 45 | rewrite lookup_empty /= right_id_L lookup_fmap Hz /=. | ||
| 46 | eauto using dynlang.interp_le with lia. | ||
| 47 | - (* EAbs *) by exists 2. | ||
| 48 | - (* EApp *) | ||
| 49 | destruct He as [He1 He2]. | ||
| 50 | destruct (lambda.interp _ _ e1) as [mw|] eqn:Hinterp1; simplify_res. | ||
| 51 | pose proof Hinterp1 as Hinterp1'. | ||
| 52 | apply lambda.interp_closed in Hinterp1' as Hmw; [|done..]. | ||
| 53 | eapply IH in Hinterp1 as [m1 Hinterp1]; [|done..]. | ||
| 54 | destruct mw as [w|]; simplify_res; last first. | ||
| 55 | { exists (S m1). by rewrite dynlang.interp_S /= Hinterp1. } | ||
| 56 | destruct (maybe3 lambda.VClo w) eqn:?; simplify_res; last first. | ||
| 57 | { exists (S m1). rewrite dynlang.interp_S /= Hinterp1 /=. by destruct w. } | ||
| 58 | destruct w; simplify_res. | ||
| 59 | apply IH in Hinterp as [m2 Hinterp2]. | ||
| 60 | + exists (S (m1 + m2)). rewrite dynlang.interp_S /=. | ||
| 61 | rewrite (dynlang.interp_le Hinterp1) /=; last lia. | ||
| 62 | rewrite fmap_insert /= in Hinterp2. | ||
| 63 | rewrite (dynlang.interp_le Hinterp2) /=; last lia. done. | ||
| 64 | + apply lambda.closed_env_insert; [by split|naive_solver]. | ||
| 65 | + rewrite dom_insert_L. set_solver. | ||
| 66 | Qed. | ||
| 67 | Lemma interp_lambda_dynlang e mv n : | ||
| 68 | lambda.closed ∅ e → | ||
| 69 | lambda.interp n ∅ e = Res mv → | ||
| 70 | ∃ m, dynlang.interp m ∅ ⌜e⌝ = Res ⌜*mv⌝. | ||
| 71 | Proof. intro. by apply interp_open_lambda_dynlang. Qed. | ||
| 72 | |||
| 73 | Lemma interp_open_dynlang_lambda E e mv n : | ||
| 74 | lambda.closed_env E → lambda.closed (dom E) e → | ||
| 75 | dynlang.interp n ⌜*E⌝ ⌜e⌝ = Res mv → | ||
| 76 | ∃ mw, lambda.interp n E e = Res mw ∧ mv = ⌜*mw⌝. | ||
| 77 | Proof. | ||
| 78 | revert E e mv. induction n as [|n IH]; [done|]; intros E e mv HE He Hinterp. | ||
| 79 | rewrite dynlang.interp_S in Hinterp. destruct e as [s|z|ex e|e1 e2]; simplify_res. | ||
| 80 | - (* EString *) rewrite lambda.interp_S /=. by eexists. | ||
| 81 | - (* EId *) | ||
| 82 | destruct n as [|n]; [done|]. | ||
| 83 | rewrite dynlang.interp_S /= -dynlang.interp_S in Hinterp. | ||
| 84 | apply elem_of_dom in He as [[Et et] Hz]. | ||
| 85 | pose proof (f_equal (fmap lift) Hz) as Hz'. | ||
| 86 | rewrite -lookup_fmap /= in Hz'. rewrite Hz' lookup_empty /= {Hz'} in Hinterp. | ||
| 87 | pose proof Hz as Hz'. | ||
| 88 | apply lambda.closed_env_lookup in Hz' as [HEt Het]; simpl in *; last done. | ||
| 89 | apply IH in Hinterp as (mw & Hinterp & ->); [|done..]. | ||
| 90 | exists mw. rewrite lambda.interp_S /= Hz /=. done. | ||
| 91 | - (* EAbs *) | ||
| 92 | destruct n as [|n]; [done|]. | ||
| 93 | rewrite dynlang.interp_S /= in Hinterp; simplify_res. | ||
| 94 | rewrite lambda.interp_S /=. by eexists. | ||
| 95 | - (* EApp *) | ||
| 96 | destruct He as [He1 He2]. | ||
| 97 | destruct (dynlang.interp _ _ _) as [mw1|] eqn:Hinterp1; simplify_res. | ||
| 98 | eapply IH in Hinterp1 as (mv1 & Hinterp1 & ->); [|done..]. | ||
| 99 | destruct mv1 as [v1|]; simplify_res; last first. | ||
| 100 | { exists None. by rewrite lambda.interp_S /= Hinterp1. } | ||
| 101 | destruct (maybe3 dynlang.VClo _) eqn:?; simplify_res; last first. | ||
| 102 | { exists None. rewrite lambda.interp_S /= Hinterp1 /=. by destruct v1. } | ||
| 103 | destruct v1; simplify_res. | ||
| 104 | change (dynlang.Thunk ⌜*E⌝ ⌜e2⌝) with ⌜lambda.Thunk E e2⌝ in Hinterp. | ||
| 105 | rewrite -fmap_insert in Hinterp. | ||
| 106 | apply lambda.interp_closed in Hinterp1 as Hmw; [|done..]. | ||
| 107 | apply IH in Hinterp as (mv2 & Hinterp2 & ->). | ||
| 108 | + exists mv2. rewrite lambda.interp_S /= Hinterp1 /=. done. | ||
| 109 | + apply lambda.closed_env_insert; [by split|]. naive_solver. | ||
| 110 | + rewrite dom_insert_L. set_solver. | ||
| 111 | Qed. | ||
| 112 | Lemma interp_dynlang_lambda e mv n : | ||
| 113 | lambda.closed ∅ e → | ||
| 114 | dynlang.interp n ∅ ⌜e⌝ = Res mv → | ||
| 115 | ∃ mw, lambda.interp n ∅ e = Res mw ∧ mv = ⌜*mw⌝. | ||
| 116 | Proof. intros. by apply interp_open_dynlang_lambda. Qed. | ||
| 117 | |||
| 118 | (* The following equivalences about the semantics trivially follow: *) | ||
| 119 | |||
| 120 | Theorem interp_equiv_ret_string e s : | ||
| 121 | lambda.closed ∅ e → | ||
| 122 | rtc lambda.step e (lambda.EString s) | ||
| 123 | ↔ rtc dynlang.step ⌜e⌝ (dynlang.EString s). | ||
| 124 | Proof. | ||
| 125 | intros. rewrite -lambda.interp_sound_complete_ret_string //. | ||
| 126 | rewrite -dynlang.interp_sound_complete_ret_string. split; intros [n Hinterp]. | ||
| 127 | + by apply interp_lambda_dynlang in Hinterp. | ||
| 128 | + apply interp_dynlang_lambda in Hinterp as ([[]|] & ?); naive_solver. | ||
| 129 | Qed. | ||
| 130 | |||
| 131 | Theorem interp_equiv_fail e : | ||
| 132 | lambda.closed ∅ e → | ||
| 133 | (∃ e', rtc lambda.step e e' ∧ lambda.stuck e') | ||
| 134 | ↔ (∃ e', rtc dynlang.step ⌜e⌝ e' ∧ dynlang.stuck e'). | ||
| 135 | Proof. | ||
| 136 | intros. rewrite -lambda.interp_sound_complete_fail //. | ||
| 137 | rewrite -dynlang.interp_sound_complete_fail. split; intros [n Hinterp]. | ||
| 138 | + by apply interp_lambda_dynlang in Hinterp. | ||
| 139 | + apply interp_dynlang_lambda in Hinterp as ([] & ?); naive_solver. | ||
| 140 | Qed. | ||
| 141 | |||
| 142 | Theorem interp_equiv_no_fuel e : | ||
| 143 | lambda.closed ∅ e → | ||
| 144 | all_loop lambda.step e ↔ all_loop dynlang.step ⌜e⌝. | ||
| 145 | Proof. | ||
| 146 | intros He. rewrite -lambda.interp_sound_complete_no_fuel; last done. | ||
| 147 | rewrite -dynlang.interp_sound_complete_no_fuel. split; intros Hnofuel n. | ||
| 148 | - destruct (dynlang.interp n ∅ _) as [mv|] eqn:Hinterp; [|done]. | ||
| 149 | apply interp_dynlang_lambda in Hinterp as (? & Hinterp & _); [|done]. | ||
| 150 | by rewrite Hnofuel in Hinterp. | ||
| 151 | - destruct (lambda.interp n ∅ _) as [mv|] eqn:Hinterp; [|done]. | ||
| 152 | apply interp_lambda_dynlang in Hinterp as [m Hinterp]; [|done..]. | ||
| 153 | by rewrite Hnofuel in Hinterp. | ||
| 154 | Qed. | ||
diff --git a/theories/dynlang/interp.v b/theories/dynlang/interp.v new file mode 100644 index 0000000..dcf6b95 --- /dev/null +++ b/theories/dynlang/interp.v | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | From mininix Require Export res dynlang.operational_props. | ||
| 2 | From stdpp Require Import options. | ||
| 3 | |||
| 4 | Module Import dynlang. | ||
| 5 | Export dynlang. | ||
| 6 | |||
| 7 | Inductive thunk := Thunk { thunk_env : gmap string thunk; thunk_expr : expr }. | ||
| 8 | Add Printing Constructor thunk. | ||
| 9 | Notation env := (gmap string thunk). | ||
| 10 | |||
| 11 | Inductive val := | ||
| 12 | | VString (s : string) | ||
| 13 | | VClo (x : string) (E : env) (e : expr). | ||
| 14 | |||
| 15 | Global Instance maybe_VString : Maybe VString := λ v, | ||
| 16 | if v is VString s then Some s else None. | ||
| 17 | Global Instance maybe_VClo : Maybe3 VClo := λ v, | ||
| 18 | if v is VClo x E e then Some (x, E, e) else None. | ||
| 19 | |||
| 20 | Definition interp1 (interp : env → expr → res val) (E : env) (e : expr) : res val := | ||
| 21 | match e with | ||
| 22 | | EString s => | ||
| 23 | mret (VString s) | ||
| 24 | | EId ds e => | ||
| 25 | v ← interp E e; | ||
| 26 | x ← Res $ maybe VString v; | ||
| 27 | t ← Res $ (E !! x) ∪ (Thunk ∅ <$> ds !! x); | ||
| 28 | interp (thunk_env t) (thunk_expr t) | ||
| 29 | | EAbs ex e => | ||
| 30 | v ← interp E ex; | ||
| 31 | x ← Res $ maybe VString v; | ||
| 32 | mret (VClo x E e) | ||
| 33 | | EApp e1 e2 => | ||
| 34 | v1 ← interp E e1; | ||
| 35 | '(x, E', e') ← Res (maybe3 VClo v1); | ||
| 36 | interp (<[x:=Thunk E e2]> E') e' | ||
| 37 | end. | ||
| 38 | |||
| 39 | Fixpoint interp (n : nat) (E : env) (e : expr) : res val := | ||
| 40 | match n with | ||
| 41 | | O => NoFuel | ||
| 42 | | S n => interp1 (interp n) E e | ||
| 43 | end. | ||
| 44 | |||
| 45 | Global Opaque interp. | ||
| 46 | |||
| 47 | End dynlang. | ||
| 48 | |||
| 49 | Add Printing Constructor dynlang.thunk. | ||
diff --git a/theories/dynlang/interp_proofs.v b/theories/dynlang/interp_proofs.v new file mode 100644 index 0000000..f18a91c --- /dev/null +++ b/theories/dynlang/interp_proofs.v | |||
| @@ -0,0 +1,426 @@ | |||
| 1 | From mininix Require Export dynlang.interp. | ||
| 2 | From stdpp Require Import options. | ||
| 3 | |||
| 4 | Module Import dynlang. | ||
| 5 | Export dynlang. | ||
| 6 | |||
| 7 | Lemma interp_S n : interp (S n) = interp1 (interp n). | ||
| 8 | Proof. done. Qed. | ||
| 9 | |||
| 10 | Fixpoint thunk_size (t : thunk) : nat := | ||
| 11 | S (map_sum_with thunk_size (thunk_env t)). | ||
| 12 | Definition env_size (E : env) : nat := | ||
| 13 | map_sum_with thunk_size E. | ||
| 14 | |||
| 15 | Lemma env_ind (P : env → Prop) : | ||
| 16 | (∀ E, map_Forall (λ i, P ∘ thunk_env) E → P E) → | ||
| 17 | ∀ E : env, P E. | ||
| 18 | Proof. | ||
| 19 | intros Pbs E. | ||
| 20 | induction (Nat.lt_wf_0_projected env_size E) as [E _ IH]. | ||
| 21 | apply Pbs, map_Forall_lookup=> y [E' e'] Hy. | ||
| 22 | apply (map_sum_with_lookup_le thunk_size) in Hy. | ||
| 23 | apply IH. by rewrite -Nat.le_succ_l. | ||
| 24 | Qed. | ||
| 25 | |||
| 26 | (** Correspondence to operational semantics *) | ||
| 27 | Definition subst_env' (thunk_to_expr : thunk → expr) (E : env) : expr → expr := | ||
| 28 | subst (thunk_to_expr <$> E). | ||
| 29 | Fixpoint thunk_to_expr (t : thunk) : expr := | ||
| 30 | subst_env' thunk_to_expr (thunk_env t) (thunk_expr t). | ||
| 31 | Notation subst_env := (subst_env' thunk_to_expr). | ||
| 32 | |||
| 33 | Lemma subst_env_eq e E : | ||
| 34 | subst_env E e = | ||
| 35 | match e with | ||
| 36 | | EString s => EString s | ||
| 37 | | EId ds e => EId ((thunk_to_expr <$> E) ∪ ds) (subst_env E e) | ||
| 38 | | EAbs ex e => EAbs (subst_env E ex) (subst_env E e) | ||
| 39 | | EApp e1 e2 => EApp (subst_env E e1) (subst_env E e2) | ||
| 40 | end. | ||
| 41 | Proof. by destruct e. Qed. | ||
| 42 | |||
| 43 | Lemma subst_env_alt E e : subst_env E e = subst (thunk_to_expr <$> E) e. | ||
| 44 | Proof. done. Qed. | ||
| 45 | |||
| 46 | (* Use the unfolding lemmas, don't rely on conversion *) | ||
| 47 | Opaque subst_env'. | ||
| 48 | |||
| 49 | Definition val_to_expr (v : val) : expr := | ||
| 50 | match v with | ||
| 51 | | VString s => EString s | ||
| 52 | | VClo x E e => EAbs (EString x) (subst_env E e) | ||
| 53 | end. | ||
| 54 | |||
| 55 | Lemma val_final v : final (val_to_expr v). | ||
| 56 | Proof. by destruct v. Qed. | ||
| 57 | |||
| 58 | Lemma subst_empty e : subst ∅ e = e. | ||
| 59 | Proof. induction e; f_equal/=; auto. by rewrite left_id_L. Qed. | ||
| 60 | |||
| 61 | Lemma subst_env_empty e : subst_env ∅ e = e. | ||
| 62 | Proof. rewrite subst_env_alt. apply subst_empty. Qed. | ||
| 63 | |||
| 64 | Lemma interp_le {n1 n2 E e mv} : | ||
| 65 | interp n1 E e = Res mv → n1 ≤ n2 → interp n2 E e = Res mv. | ||
| 66 | Proof. | ||
| 67 | revert n2 E e mv. | ||
| 68 | induction n1 as [|n1 IH]; intros [|n2] E e mv He ?; [by (done || lia)..|]. | ||
| 69 | rewrite interp_S in He; rewrite interp_S; destruct e; | ||
| 70 | repeat match goal with | ||
| 71 | | _ => case_match | ||
| 72 | | H : context [(_ <$> ?mx)] |- _ => destruct mx eqn:?; simplify_res | ||
| 73 | | H : ?r ≫= _ = _ |- _ => destruct r as [[]|] eqn:?; simplify_res | ||
| 74 | | H : _ <$> ?r = _ |- _ => destruct r as [[]|] eqn:?; simplify_res | ||
| 75 | | |- interp ?n ?E ?e ≫= _ = _ => erewrite (IH n E e) by (done || lia) | ||
| 76 | | _ => progress simplify_res | ||
| 77 | | _ => progress simplify_option_eq | ||
| 78 | end; eauto with lia. | ||
| 79 | Qed. | ||
| 80 | |||
| 81 | Lemma interp_agree {n1 n2 E e mv1 mv2} : | ||
| 82 | interp n1 E e = Res mv1 → interp n2 E e = Res mv2 → mv1 = mv2. | ||
| 83 | Proof. | ||
| 84 | intros He1 He2. apply (inj Res). destruct (total (≤) n1 n2). | ||
| 85 | - rewrite -He2. symmetry. eauto using interp_le. | ||
| 86 | - rewrite -He1. eauto using interp_le. | ||
| 87 | Qed. | ||
| 88 | |||
| 89 | Lemma subst_env_union E1 E2 e : | ||
| 90 | subst_env (E1 ∪ E2) e = subst_env E1 (subst_env E2 e). | ||
| 91 | Proof. | ||
| 92 | revert E1 E2. induction e; intros E1 E2; rewrite subst_env_eq /=. | ||
| 93 | - done. | ||
| 94 | - rewrite !(subst_env_eq (EId _ _)) IHe. f_equal. | ||
| 95 | by rewrite assoc_L map_fmap_union. | ||
| 96 | - rewrite !(subst_env_eq (EAbs _ _)) /=. f_equal; auto. | ||
| 97 | - rewrite !(subst_env_eq (EApp _ _)) /=. f_equal; auto. | ||
| 98 | Qed. | ||
| 99 | |||
| 100 | Lemma subst_env_insert E x e t : | ||
| 101 | subst_env (<[x:=t]> E) e = subst {[x:=thunk_to_expr t]} (subst_env E e). | ||
| 102 | Proof. | ||
| 103 | rewrite insert_union_singleton_l subst_env_union subst_env_alt. | ||
| 104 | by rewrite map_fmap_singleton. | ||
| 105 | Qed. | ||
| 106 | |||
| 107 | Lemma subst_env_insert_eq e1 e2 E1 E2 x E1' E2' e1' e2' : | ||
| 108 | subst_env E1 e1 = subst_env E2 e2 → | ||
| 109 | subst_env E1' e1' = subst_env E2' e2' → | ||
| 110 | subst_env (<[x:=Thunk E1' e1']> E1) e1 = subst_env (<[x:=Thunk E2' e2']> E2) e2. | ||
| 111 | Proof. intros He He'. by rewrite !subst_env_insert //= He' He. Qed. | ||
| 112 | |||
| 113 | Lemma interp_proper n E1 E2 e1 e2 mv : | ||
| 114 | subst_env E1 e1 = subst_env E2 e2 → | ||
| 115 | interp n E1 e1 = Res mv → | ||
| 116 | ∃ mw m, interp m E2 e2 = Res mw ∧ | ||
| 117 | val_to_expr <$> mv = val_to_expr <$> mw. | ||
| 118 | Proof. | ||
| 119 | revert n E1 E2 e1 e2 mv. induction n as [|n IHn]; [done|]. | ||
| 120 | intros E1 E2 e1 e2 mv Hsubst Hinterp. | ||
| 121 | rewrite 2!subst_env_eq in Hsubst. | ||
| 122 | rewrite interp_S in Hinterp. destruct e1, e2; simplify_res; try done. | ||
| 123 | - eexists (Some (VString _)), 1. by rewrite interp_S. | ||
| 124 | - destruct (interp n _ e1) as [mv1|] eqn:Hinterp'; simplify_eq/=. | ||
| 125 | eapply IHn in Hinterp' as (mw1 & m1 & Hinterp1 & ?); last done. | ||
| 126 | destruct mv1 as [v1|], mw1 as [w1|]; simplify_res; last first. | ||
| 127 | { exists None, (S m1). by rewrite interp_S /= Hinterp1. } | ||
| 128 | destruct (maybe VString v1) as [x|] eqn:Hv1; | ||
| 129 | simplify_res; last first. | ||
| 130 | { exists None, (S m1). split; [|done]. rewrite interp_S /= Hinterp1 /=. | ||
| 131 | destruct v1, w1; repeat destruct select base_lit; by simplify_eq/=. } | ||
| 132 | destruct v1, w1; repeat destruct select base_lit; simplify_eq/=. | ||
| 133 | assert (∀ (ds : stringmap expr) (E : env) x, | ||
| 134 | thunk_to_expr <$> (E !! x) ∪ (Thunk ∅ <$> ds !! x) | ||
| 135 | = ((thunk_to_expr <$> E) ∪ ds) !! x) as HE. | ||
| 136 | { intros ds' E x. rewrite lookup_union lookup_fmap. | ||
| 137 | repeat destruct (_ !! _); f_equal/=; by rewrite subst_env_empty. } | ||
| 138 | pose proof (f_equal (.!! s0) Hsubst) as Hs. rewrite -!HE {HE} in Hs. | ||
| 139 | destruct (E1 !! s0 ∪ _) as [[E1' e1']|], | ||
| 140 | (E2 !! s0 ∪ _) as [[E2' e2']|] eqn:HE2; simplify_res; last first. | ||
| 141 | { exists None, (S m1). rewrite interp_S /= Hinterp1 /=. by rewrite HE2. } | ||
| 142 | eapply IHn in Hinterp as (mw & m2 & Hinterp2 & ?); [|by eauto..]. | ||
| 143 | exists mw, (S (m1 `max` m2)). split; [|done]. rewrite interp_S /=. | ||
| 144 | rewrite (interp_le Hinterp1) /=; last lia. rewrite HE2 /=. | ||
| 145 | eauto using interp_le with lia. | ||
| 146 | - destruct (interp n _ _) as [mv1|] eqn:Hinterp'; simplify_eq/=. | ||
| 147 | eapply IHn in Hinterp' as (mw1 & m1 & Hinterp1 & ?); last done. | ||
| 148 | destruct mv1 as [v1|], mw1 as [w1|]; simplify_res; last first. | ||
| 149 | { exists None, (S m1). by rewrite interp_S /= Hinterp1. } | ||
| 150 | destruct (maybe VString _) eqn:Hstring; simplify_res; last first. | ||
| 151 | { exists None, (S m1). rewrite interp_S /= Hinterp1 /=. | ||
| 152 | by assert (maybe VString w1 = None) as -> by (by destruct v1, w1). } | ||
| 153 | destruct v1, w1; simplify_eq/=. | ||
| 154 | eexists (Some (VClo _ _ _)), (S m1). | ||
| 155 | rewrite interp_S /= Hinterp1 /=. split; [done|]. by do 2 f_equal/=. | ||
| 156 | - destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res. | ||
| 157 | eapply IHn in Hinterp' as (mw' & m1 & Hinterp1 & ?); last done. | ||
| 158 | destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first. | ||
| 159 | { exists None, (S m1). by rewrite interp_S /= Hinterp1. } | ||
| 160 | destruct (maybe3 VClo _) eqn:Hclo; simplify_res; last first. | ||
| 161 | { exists None, (S m1). rewrite interp_S /= Hinterp1 /=. | ||
| 162 | by assert (maybe3 VClo w' = None) as -> by (by destruct v', w'). } | ||
| 163 | destruct v', w'; simplify_eq/=. | ||
| 164 | eapply IHn with (E2 := <[x0:=Thunk E2 e2_2]> E0) in Hinterp | ||
| 165 | as (w & m2 & Hinterp2 & ?); last by apply subst_env_insert_eq. | ||
| 166 | exists w, (S (m1 `max` m2)). rewrite interp_S /=. | ||
| 167 | rewrite (interp_le Hinterp1) /=; last lia. | ||
| 168 | rewrite (interp_le Hinterp2) /=; last lia. done. | ||
| 169 | Qed. | ||
| 170 | |||
| 171 | Lemma subst_as_subst_env x e1 e2 : | ||
| 172 | subst {[x:=e2]} e1 = subst_env (<[x:=Thunk ∅ e2]> ∅) e1. | ||
| 173 | Proof. rewrite subst_env_insert //= !subst_env_empty //. Qed. | ||
| 174 | |||
| 175 | Lemma interp_subst n x e1 e2 mv : | ||
| 176 | interp n ∅ (subst {[x:=e2]} e1) = Res mv → | ||
| 177 | ∃ mw m, interp m (<[x:=Thunk ∅ e2]> ∅) e1 = Res mw ∧ | ||
| 178 | val_to_expr <$> mv = val_to_expr <$> mw. | ||
| 179 | Proof. | ||
| 180 | apply interp_proper. | ||
| 181 | by rewrite subst_env_empty subst_as_subst_env. | ||
| 182 | Qed. | ||
| 183 | |||
| 184 | Lemma interp_step e1 e2 n mv : | ||
| 185 | e1 --> e2 → | ||
| 186 | interp n ∅ e2 = Res mv → | ||
| 187 | ∃ mw m, interp m ∅ e1 = Res mw ∧ val_to_expr <$> mv = val_to_expr <$> mw. | ||
| 188 | Proof. | ||
| 189 | intros Hstep. revert mv n. | ||
| 190 | induction Hstep; intros mv n Hinterp. | ||
| 191 | - apply interp_subst in Hinterp as (w & [|m] & Hinterp & Hv); | ||
| 192 | simplify_eq/=; [|done..]. | ||
| 193 | exists w, (S (S (S m))). rewrite !interp_S /= -!interp_S. | ||
| 194 | eauto using interp_le with lia. | ||
| 195 | - exists mv, (S (S n)). rewrite !interp_S /= -interp_S. | ||
| 196 | rewrite lookup_empty left_id_L H /=. eauto using interp_le with lia. | ||
| 197 | - destruct n as [|n]; [done|rewrite interp_S /= in Hinterp]. | ||
| 198 | destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res. | ||
| 199 | apply IHHstep in Hinterp' as (mw' & m1 & Hinterp1 & ?); simplify_res. | ||
| 200 | destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first. | ||
| 201 | { exists None, (S m1). by rewrite interp_S /= Hinterp1. } | ||
| 202 | destruct (maybe VString _) eqn:Hstring; simplify_res; last first. | ||
| 203 | { exists None, (S m1). rewrite interp_S /= Hinterp1 /=. | ||
| 204 | by assert (maybe VString w' = None) as -> by (by destruct v', w'). } | ||
| 205 | destruct v', w'; simplify_eq/=. | ||
| 206 | eexists (Some (VClo _ _ _)), (S m1). rewrite !interp_S /=. | ||
| 207 | rewrite (interp_le Hinterp1) /=; last lia. done. | ||
| 208 | - destruct n as [|n]; [done|rewrite interp_S /= in Hinterp]. | ||
| 209 | destruct (interp n _ _) as [mv'|] eqn:Hinterp'; simplify_res. | ||
| 210 | apply IHHstep in Hinterp' as (mw' & m1 & Hinterp1 & ?); simplify_res. | ||
| 211 | destruct mv' as [v'|], mw' as [w'|]; simplify_res; last first. | ||
| 212 | { exists None, (S m1). by rewrite interp_S /= Hinterp1. } | ||
| 213 | destruct (maybe3 VClo _) eqn:Hclo; simplify_res; last first. | ||
| 214 | { exists None, (S m1). rewrite interp_S /= Hinterp1 /=. | ||
| 215 | by assert (maybe3 VClo w' = None) as -> by (by destruct v', w'). } | ||
| 216 | destruct v', w'; simplify_eq/=. | ||
| 217 | eapply interp_proper in Hinterp as (mw & m2 & Hinterp2 & Hv); | ||
| 218 | last apply subst_env_insert_eq; try done. | ||
| 219 | exists mw, (S (m1 `max` m2)). rewrite !interp_S /=. | ||
| 220 | rewrite (interp_le Hinterp1) /=; last lia. | ||
| 221 | by rewrite (interp_le Hinterp2) /=; last lia. | ||
| 222 | - destruct n as [|n]; [done|rewrite interp_S /= in Hinterp]. | ||
| 223 | destruct (interp n _ e1') as [mv1|] eqn:Hinterp1; simplify_eq/=. | ||
| 224 | apply IHHstep in Hinterp1 as (mw1 & m & Hinterp1 & Hw1). | ||
| 225 | destruct mv1 as [v1|], mw1 as [w1|]; simplify_res; last first. | ||
| 226 | { exists None, (S m). by rewrite interp_S /= Hinterp1. } | ||
| 227 | exists mv, (S (n `max` m)). split; [|done]. | ||
| 228 | rewrite interp_S /= (interp_le Hinterp1) /=; last lia. | ||
| 229 | assert (maybe VString w1 = maybe VString v1) as ->. | ||
| 230 | { destruct v1, w1; naive_solver. } | ||
| 231 | destruct (maybe VString v1); simplify_res; [|done]. | ||
| 232 | destruct (_ ∪ _); simplify_res; eauto using interp_le with lia. | ||
| 233 | Qed. | ||
| 234 | |||
| 235 | Lemma final_interp e : | ||
| 236 | final e → | ||
| 237 | ∃ w m, interp m ∅ e = mret w ∧ e = val_to_expr w. | ||
| 238 | Proof. | ||
| 239 | induction e as [| |[]|]; inv 1. | ||
| 240 | - eexists (VString _), 1. by rewrite interp_S /=. | ||
| 241 | - eexists (VClo _ _ _), 2. rewrite interp_S /=. split; [done|]. | ||
| 242 | by rewrite subst_env_empty. | ||
| 243 | Qed. | ||
| 244 | |||
| 245 | Lemma red_final_interp e : | ||
| 246 | red step e ∨ final e ∨ ∃ m, interp m ∅ e = mfail. | ||
| 247 | Proof. | ||
| 248 | induction e. | ||
| 249 | - (* ENat *) right; left. constructor. | ||
| 250 | - (* EId *) destruct IHe as [[??]|[Hfinal|[m Hinterp]]]. | ||
| 251 | + left. by repeat econstructor. | ||
| 252 | + apply final_interp in Hfinal as (w & m & Hinterp & ->). | ||
| 253 | destruct (maybe VString w) as [x|] eqn:Hw; last first. | ||
| 254 | { do 2 right. eexists (S m). rewrite interp_S /= Hinterp /=. | ||
| 255 | by rewrite Hw. } | ||
| 256 | destruct w; simplify_eq/=. | ||
| 257 | destruct (ds !! x) as [e|] eqn:Hx; last first. | ||
| 258 | { do 2 right. eexists (S m). rewrite interp_S /= Hinterp /=. | ||
| 259 | by rewrite Hx. } | ||
| 260 | left. by repeat econstructor. | ||
| 261 | + do 2 right. exists (S m). rewrite interp_S /= Hinterp. done. | ||
| 262 | - (* EAbs *) destruct IHe1 as [[??]|[Hfinal|[m Hinterp]]]. | ||
| 263 | + left. by repeat econstructor. | ||
| 264 | + apply final_interp in Hfinal as (w & m & Hinterp & ->). | ||
| 265 | destruct (maybe VString w) as [x|] eqn:Hw; last first. | ||
| 266 | { do 2 right. eexists (S m). rewrite interp_S /= Hinterp /=. | ||
| 267 | by rewrite Hw. } | ||
| 268 | destruct w; naive_solver. | ||
| 269 | + do 2 right. exists (S m). rewrite interp_S /= Hinterp. done. | ||
| 270 | - (* EApp *) destruct IHe1 as [[??]|[Hfinal|[m Hinterp]]]. | ||
| 271 | + left. by repeat econstructor. | ||
| 272 | + apply final_interp in Hfinal as (w & m & Hinterp & ->). | ||
| 273 | destruct (maybe3 VClo w) eqn:Hw. | ||
| 274 | { destruct w; simplify_eq/=. left. by repeat econstructor. } | ||
| 275 | do 2 right. exists (S m). by rewrite interp_S /= Hinterp /= Hw. | ||
| 276 | + do 2 right. exists (S m). by rewrite interp_S /= Hinterp. | ||
| 277 | Qed. | ||
| 278 | |||
| 279 | Lemma interp_complete e1 e2 : | ||
| 280 | e1 -->* e2 → | ||
| 281 | nf step e2 → | ||
| 282 | ∃ mw m, interp m ∅ e1 = Res mw ∧ | ||
| 283 | if mw is Some w then e2 = val_to_expr w else ¬final e2. | ||
| 284 | Proof. | ||
| 285 | intros Hsteps Hnf. induction Hsteps as [e|e1 e2 e3 Hstep _ IH]. | ||
| 286 | { destruct (red_final_interp e) as [?|[Hfinal|[m Hinterp]]]; [done|..]. | ||
| 287 | - apply final_interp in Hfinal as (w & m & ? & ?). | ||
| 288 | by exists (Some w), m. | ||
| 289 | - exists None, m. split; [done|]. intros Hfinal. | ||
| 290 | apply final_interp in Hfinal as (w & m' & ? & _). | ||
| 291 | by assert (mfail = mret w) by eauto using interp_agree. } | ||
| 292 | destruct IH as (mw & m & Hinterp & ?); try done. | ||
| 293 | eapply interp_step in Hinterp as (mw' & m' & ? & ?); last done. | ||
| 294 | destruct mw, mw'; naive_solver. | ||
| 295 | Qed. | ||
| 296 | |||
| 297 | Lemma interp_complete_ret e1 e2 : | ||
| 298 | e1 -->* e2 → final e2 → | ||
| 299 | ∃ w m, interp m ∅ e1 = mret w ∧ e2 = val_to_expr w. | ||
| 300 | Proof. | ||
| 301 | intros Hsteps Hfinal. apply interp_complete in Hsteps | ||
| 302 | as ([w|] & m & ? & ?); naive_solver eauto using final_nf. | ||
| 303 | Qed. | ||
| 304 | Lemma interp_complete_fail e1 e2 : | ||
| 305 | e1 -->* e2 → nf step e2 → ¬final e2 → | ||
| 306 | ∃ m, interp m ∅ e1 = mfail. | ||
| 307 | Proof. | ||
| 308 | intros Hsteps Hnf Hforce. | ||
| 309 | apply interp_complete in Hsteps as ([w|] & m & ? & ?); simplify_eq/=; try by eauto. | ||
| 310 | destruct Hforce. apply val_final. | ||
| 311 | Qed. | ||
| 312 | |||
| 313 | Lemma interp_sound_open E e n mv : | ||
| 314 | interp n E e = Res mv → | ||
| 315 | ∃ e', subst_env E e -->* e' ∧ | ||
| 316 | if mv is Some v then e' = val_to_expr v else stuck e'. | ||
| 317 | Proof. | ||
| 318 | revert E e mv. | ||
| 319 | induction n as [|n IH]; intros E e mv Hinterp; first done. | ||
| 320 | rewrite subst_env_eq. rewrite interp_S in Hinterp. | ||
| 321 | destruct e; simplify_res. | ||
| 322 | - (* EString *) by eexists. | ||
| 323 | - (* EId *) | ||
| 324 | destruct (interp _ _ _) as [mv1|] eqn:Hinterp1; simplify_res. | ||
| 325 | apply IH in Hinterp1 as (e1' & Hsteps1 & He1'). | ||
| 326 | destruct mv1 as [v1|]; simplify_res; last first. | ||
| 327 | { eexists; split; [by eapply SId_rtc|]. split; [|inv 1]. | ||
| 328 | intros [??]. destruct He1' as [Hnf []]. | ||
| 329 | inv_step; simpl; eauto. destruct Hnf; eauto. } | ||
| 330 | destruct (maybe VString _) as [x|] eqn:Hv1; simplify_res; last first. | ||
| 331 | { eexists; split; [by eapply SId_rtc|]. split; [|inv 1]. | ||
| 332 | intros [??]. destruct v1; inv_step. } | ||
| 333 | destruct v1; simplify_eq/=. | ||
| 334 | assert (thunk_to_expr <$> (E !! x) ∪ (Thunk ∅ <$> ds !! x) | ||
| 335 | = ((thunk_to_expr <$> E) ∪ ds) !! x). | ||
| 336 | { rewrite lookup_union lookup_fmap. | ||
| 337 | repeat destruct (_ !! _); f_equal/=; by rewrite subst_env_empty. } | ||
| 338 | destruct (_ ∪ _) as [[E' e']|] eqn:Hx; simplify_res. | ||
| 339 | * apply IH in Hinterp as (e'' & Hsteps & He''). | ||
| 340 | exists e''; split; [|done]. etrans; [by eapply SId_rtc|]. | ||
| 341 | eapply rtc_l; [|done]. by econstructor. | ||
| 342 | * eexists; split; [by eapply SId_rtc|]. split; [|inv 1]. | ||
| 343 | intros [? Hstep]. inv_step; simplify_eq/=; congruence. | ||
| 344 | - (* EAbs *) | ||
| 345 | destruct (interp _ _ _) as [mv1|] eqn:Hinterp1; simplify_res. | ||
| 346 | apply IH in Hinterp1 as (e1' & Hsteps1 & He1'). | ||
| 347 | destruct mv1 as [v1|]; simplify_res; last first. | ||
| 348 | { eexists; split; [by eapply SAbsL_rtc|]. split. | ||
| 349 | + intros [??]. destruct He1' as [Hnf []]. | ||
| 350 | inv_step; simpl; eauto. destruct Hnf; eauto. | ||
| 351 | + intros ?. destruct He1' as [_ []]. by destruct e1'. } | ||
| 352 | eexists; split; [by eapply SAbsL_rtc|]. | ||
| 353 | destruct (maybe VString _) as [x|] eqn:Hv1; simplify_res; last first. | ||
| 354 | { split; [|destruct v1; inv 1]. intros [??]. destruct v1; inv_step. } | ||
| 355 | by destruct v1; simplify_eq/=. | ||
| 356 | - (* EApp *) destruct (interp _ _ _) as [mv'|] eqn:Hinterp'; simplify_res. | ||
| 357 | apply IH in Hinterp' as (e' & Hsteps & He'); try done. | ||
| 358 | destruct mv' as [v'|]; simplify_res; last first. | ||
| 359 | { eexists; repeat split; [by apply SAppL_rtc| |inv 1]. | ||
| 360 | intros [e'' Hstep]. destruct He' as [Hnf Hfinal]. | ||
| 361 | inv Hstep; [by destruct Hfinal; constructor|]. destruct Hnf. eauto. } | ||
| 362 | destruct (maybe3 VClo v') eqn:?; simplify_res; last first. | ||
| 363 | { eexists; repeat split; [by apply SAppL_rtc| |inv 1]. | ||
| 364 | intros [e'' Hstep]. inv Hstep; destruct v'; by repeat inv_step. } | ||
| 365 | destruct v'; simplify_res. | ||
| 366 | apply IH in Hinterp as (e'' & Hsteps' & He''). | ||
| 367 | eexists; split; [|done]. etrans; [by apply SAppL_rtc|]. | ||
| 368 | eapply rtc_l; first by constructor. | ||
| 369 | rewrite subst_env_insert // in Hsteps'. | ||
| 370 | Qed. | ||
| 371 | |||
| 372 | Lemma interp_sound n e mv : | ||
| 373 | interp n ∅ e = Res mv → | ||
| 374 | ∃ e', e -->* e' ∧ if mv is Some v then e' = val_to_expr v else stuck e'. | ||
| 375 | Proof. | ||
| 376 | intros Hsteps%interp_sound_open; try done. | ||
| 377 | by rewrite subst_env_empty in Hsteps. | ||
| 378 | Qed. | ||
| 379 | |||
| 380 | (** Final theorems *) | ||
| 381 | Theorem interp_sound_complete_ret e v : | ||
| 382 | (∃ w n, interp n ∅ e = mret w ∧ val_to_expr v = val_to_expr w) | ||
| 383 | ↔ e -->* val_to_expr v. | ||
| 384 | Proof. | ||
| 385 | split. | ||
| 386 | - by intros (n & w & (e' & ? & ->)%interp_sound & ->). | ||
| 387 | - intros Hsteps. apply interp_complete_ret in Hsteps as ([] & ? & ? & ?); | ||
| 388 | eauto using val_final. | ||
| 389 | Qed. | ||
| 390 | |||
| 391 | Theorem interp_sound_complete_ret_string e s : | ||
| 392 | (∃ n, interp n ∅ e = mret (VString s)) ↔ e -->* EString s. | ||
| 393 | Proof. | ||
| 394 | split. | ||
| 395 | - by intros [n (e' & ? & ->)%interp_sound]. | ||
| 396 | - intros Hsteps. apply interp_complete_ret in Hsteps as ([] & ? & ? & ?); | ||
| 397 | simplify_eq/=; eauto. | ||
| 398 | Qed. | ||
| 399 | |||
| 400 | Theorem interp_sound_complete_fail e : | ||
| 401 | (∃ n, interp n ∅ e = mfail) ↔ ∃ e', e -->* e' ∧ stuck e'. | ||
| 402 | Proof. | ||
| 403 | split. | ||
| 404 | - by intros [n ?%interp_sound]. | ||
| 405 | - intros (e' & Hsteps & Hnf & Hforced). by eapply interp_complete_fail. | ||
| 406 | Qed. | ||
| 407 | |||
| 408 | Theorem interp_sound_complete_no_fuel e : | ||
| 409 | (∀ n, interp n ∅ e = NoFuel) ↔ all_loop step e. | ||
| 410 | Proof. | ||
| 411 | rewrite all_loop_alt. split. | ||
| 412 | - intros Hnofuel e' Hsteps. | ||
| 413 | destruct (red_final_interp e') as [|[|He']]; [done|..]. | ||
| 414 | + apply interp_complete_ret in Hsteps as (w & m & Hinterp & _); last done. | ||
| 415 | by rewrite Hnofuel in Hinterp. | ||
| 416 | + apply interp_sound_complete_fail in He' as (e'' & ? & [Hnf _]). | ||
| 417 | destruct (interp_complete e e'') as (mv & n & Hinterp & _); [by etrans|done|]. | ||
| 418 | by rewrite Hnofuel in Hinterp. | ||
| 419 | - intros Hred n. destruct (interp n ∅ e) as [mv|] eqn:Hinterp; [|done]. | ||
| 420 | apply interp_sound in Hinterp as (e' & Hsteps%Hred & Hstuck). | ||
| 421 | destruct mv as [v|]; simplify_eq/=. | ||
| 422 | + apply final_nf in Hsteps as []. apply val_final. | ||
| 423 | + by destruct Hstuck as [[] ?]. | ||
| 424 | Qed. | ||
| 425 | |||
| 426 | End dynlang. | ||
diff --git a/theories/dynlang/operational.v b/theories/dynlang/operational.v new file mode 100644 index 0000000..34cca7b --- /dev/null +++ b/theories/dynlang/operational.v | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | From mininix Require Export utils. | ||
| 2 | From stdpp Require Import options. | ||
| 3 | |||
| 4 | Module Import dynlang. | ||
| 5 | |||
| 6 | Inductive expr := | ||
| 7 | | EString (s : string) | ||
| 8 | | EId (ds : gmap string expr) (ex : expr) | ||
| 9 | | EAbs (ex e : expr) | ||
| 10 | | EApp (e1 e2 : expr). | ||
| 11 | |||
| 12 | Fixpoint subst (ds : gmap string expr) (e : expr) : expr := | ||
| 13 | match e with | ||
| 14 | | EString s => EString s | ||
| 15 | | EId ds' e => EId (ds ∪ ds') (subst ds e) | ||
| 16 | | EAbs ex e => EAbs (subst ds ex) (subst ds e) | ||
| 17 | | EApp e1 e2 => EApp (subst ds e1) (subst ds e2) | ||
| 18 | end. | ||
| 19 | |||
| 20 | Reserved Infix "-->" (right associativity, at level 55). | ||
| 21 | Inductive step : expr → expr → Prop := | ||
| 22 | | Sβ x e1 e2 : EApp (EAbs (EString x) e1) e2 --> subst {[x:=e2]} e1 | ||
| 23 | | SIdString ds x e : ds !! x = Some e → EId ds (EString x) --> e | ||
| 24 | | SAbsL ex1 ex1' e : ex1 --> ex1' → EAbs ex1 e --> EAbs ex1' e | ||
| 25 | | SAppL e1 e1' e2 : e1 --> e1' → EApp e1 e2 --> EApp e1' e2 | ||
| 26 | | SId ds e1 e1' : e1 --> e1' → EId ds e1 --> EId ds e1' | ||
| 27 | where "e1 --> e2" := (step e1 e2). | ||
| 28 | |||
| 29 | Infix "-->*" := (rtc step) (right associativity, at level 55). | ||
| 30 | |||
| 31 | Definition final (e : expr) : Prop := | ||
| 32 | match e with | ||
| 33 | | EString _ => True | ||
| 34 | | EAbs (EString _) _ => True | ||
| 35 | | _ => False | ||
| 36 | end. | ||
| 37 | |||
| 38 | Definition stuck (e : expr) : Prop := | ||
| 39 | nf step e ∧ ¬final e. | ||
| 40 | |||
| 41 | End dynlang. | ||
diff --git a/theories/dynlang/operational_props.v b/theories/dynlang/operational_props.v new file mode 100644 index 0000000..9e8028c --- /dev/null +++ b/theories/dynlang/operational_props.v | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | From mininix Require Export dynlang.operational. | ||
| 2 | From stdpp Require Import options. | ||
| 3 | |||
| 4 | Module Import dynlang. | ||
| 5 | Export dynlang. | ||
| 6 | |||
| 7 | (** Properties of operational semantics *) | ||
| 8 | Lemma step_not_final e1 e2 : e1 --> e2 → ¬final e1. | ||
| 9 | Proof. induction 1; simpl; repeat case_match; naive_solver. Qed. | ||
| 10 | Lemma final_nf e : final e → nf step e. | ||
| 11 | Proof. by intros ? [??%step_not_final]. Qed. | ||
| 12 | |||
| 13 | Lemma SAbsL_rtc ex1 ex1' e : ex1 -->* ex1' → EAbs ex1 e -->* EAbs ex1' e. | ||
| 14 | Proof. induction 1; econstructor; eauto using step. Qed. | ||
| 15 | Lemma SAppL_rtc e1 e1' e2 : e1 -->* e1' → EApp e1 e2 -->* EApp e1' e2. | ||
| 16 | Proof. induction 1; econstructor; eauto using step. Qed. | ||
| 17 | Lemma SId_rtc ds e1 e1' : e1 -->* e1' → EId ds e1 -->* EId ds e1'. | ||
| 18 | Proof. induction 1; econstructor; eauto using step. Qed. | ||
| 19 | |||
| 20 | Ltac inv_step := repeat | ||
| 21 | match goal with H : ?e --> _ |- _ => assert_fails (is_var e); inv H end. | ||
| 22 | |||
| 23 | Lemma step_det e d1 d2 : | ||
| 24 | e --> d1 → | ||
| 25 | e --> d2 → | ||
| 26 | d1 = d2. | ||
| 27 | Proof. | ||
| 28 | intros Hred1. revert d2. | ||
| 29 | induction Hred1; intros d2 Hred2; inv Hred2; try by inv_step; | ||
| 30 | f_equal; by apply IHHred1. | ||
| 31 | Qed. | ||
| 32 | |||
| 33 | End dynlang. | ||