From 1b8b58ccb1abd2b6b864913265244b97153e2698 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Wed, 2 Mar 2016 14:43:40 +0100
Subject: [PATCH] get rid of substitution in Case (use lambdas); introduce
 Match as derived form that involves binders

---
 heap_lang/derived.v      | 15 +++++++++++++++
 heap_lang/lang.v         | 20 +++++++++-----------
 heap_lang/lifting.v      | 16 ++++++++--------
 heap_lang/notation.v     |  2 +-
 heap_lang/substitution.v | 13 +++++--------
 5 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/heap_lang/derived.v b/heap_lang/derived.v
index 83bc65ae5..196ddf4f7 100644
--- a/heap_lang/derived.v
+++ b/heap_lang/derived.v
@@ -9,6 +9,7 @@ Notation LamV x e := (RecV BAnom x e).
 Notation LetCtx x e2 := (AppRCtx (LamV x e2)).
 Notation SeqCtx e2 := (LetCtx BAnom e2).
 Notation Skip := (Seq (Lit LitUnit) (Lit LitUnit)).
+Notation Match e0 x1 e1 x2 e2 := (Case e0 (Lam x1 e1) (Lam x2 e2)).
 
 Section derived.
 Context {Σ : rFunctor}.
@@ -34,6 +35,20 @@ Proof. intros ?. by rewrite -wp_let. Qed.
 Lemma wp_skip E Φ : ▷ Φ (LitV LitUnit) ⊑ || Skip @ E {{ Φ }}.
 Proof. rewrite -wp_seq // -wp_value //. Qed.
 
+Lemma wp_match_inl E e0 v0 x1 e1 x2 e2 Φ :
+  to_val e0 = Some v0 →
+  ▷ || subst' e1 x1 v0 @ E {{ Φ }} ⊑ || Match (InjL e0) x1 e1 x2 e2 @ E {{ Φ }}.
+Proof.
+  intros. rewrite -wp_case_inl // -[X in _ ⊑ X]later_intro. by apply wp_let.
+Qed.
+
+Lemma wp_match_inr E e0 v0 x1 e1 x2 e2 Φ :
+  to_val e0 = Some v0 →
+  ▷ || subst' e2 x2 v0 @ E {{ Φ }} ⊑ || Match (InjR e0) x1 e1 x2 e2 @ E {{ Φ }}.
+Proof.
+  intros. rewrite -wp_case_inr // -[X in _ ⊑ X]later_intro. by apply wp_let.
+Qed.
+
 Lemma wp_le E (n1 n2 : Z) P Φ :
   (n1 ≤ n2 → P ⊑ ▷ Φ (LitV (LitBool true))) →
   (n2 < n1 → P ⊑ ▷ Φ (LitV (LitBool false))) →
diff --git a/heap_lang/lang.v b/heap_lang/lang.v
index 918b18564..db52de949 100644
--- a/heap_lang/lang.v
+++ b/heap_lang/lang.v
@@ -36,7 +36,7 @@ Inductive expr :=
   (* Sums *)
   | InjL (e : expr)
   | InjR (e : expr)
-  | Case (e0 : expr) (x1 : binder) (e1 : expr) (x2 : binder) (e2 : expr)
+  | Case (e0 : expr) (e1 : expr) (e2 : expr)
   (* Concurrency *)
   | Fork (e : expr)
   (* Heap *)
@@ -107,7 +107,7 @@ Inductive ectx_item :=
   | SndCtx
   | InjLCtx
   | InjRCtx
-  | CaseCtx (x1 : binder) (e1 : expr) (x2 : binder) (e2 : expr)
+  | CaseCtx (e1 : expr) (e2 : expr)
   | AllocCtx
   | LoadCtx
   | StoreLCtx (e2 : expr)
@@ -132,7 +132,7 @@ Definition fill_item (Ki : ectx_item) (e : expr) : expr :=
   | SndCtx => Snd e
   | InjLCtx => InjL e
   | InjRCtx => InjR e
-  | CaseCtx x1 e1 x2 e2 => Case e x1 e1 x2 e2
+  | CaseCtx e1 e2 => Case e e1 e2
   | AllocCtx => Alloc e
   | LoadCtx => Load e
   | StoreLCtx e2 => Store e e2
@@ -160,10 +160,8 @@ Fixpoint subst (e : expr) (x : string) (v : val) : expr :=
   | Snd e => Snd (subst e x v)
   | InjL e => InjL (subst e x v)
   | InjR e => InjR (subst e x v)
-  | Case e0 x1 e1 x2 e2 =>
-     Case (subst e0 x v)
-       x1 (if decide (BNamed x ≠ x1) then subst e1 x v else e1)
-       x2 (if decide (BNamed x ≠ x2) then subst e2 x v else e2)
+  | Case e0 e1 e2 =>
+     Case (subst e0 x v) (subst e1 x v) (subst e2 x v)
   | Fork e => Fork (subst e x v)
   | Loc l => Loc l
   | Alloc e => Alloc (subst e x v)
@@ -213,12 +211,12 @@ Inductive head_step : expr → state → expr → state → option expr → Prop
   | SndS e1 v1 e2 v2 σ :
      to_val e1 = Some v1 → to_val e2 = Some v2 →
      head_step (Snd (Pair e1 e2)) σ e2 σ None
-  | CaseLS e0 v0 x1 e1 x2 e2 σ :
+  | CaseLS e0 v0 e1 e2 σ :
      to_val e0 = Some v0 →
-     head_step (Case (InjL e0) x1 e1 x2 e2) σ (subst' e1 x1 v0) σ None
-  | CaseRS e0 v0 x1 e1 x2 e2 σ :
+     head_step (Case (InjL e0) e1 e2) σ (App e1 e0) σ None
+  | CaseRS e0 v0 e1 e2 σ :
      to_val e0 = Some v0 →
-     head_step (Case (InjR e0) x1 e1 x2 e2) σ (subst' e2 x2 v0) σ None
+     head_step (Case (InjR e0) e1 e2) σ (App e2 e0) σ None
   | ForkS e σ:
      head_step (Fork e) σ (Lit LitUnit) σ (Some e)
   | AllocS e v σ l :
diff --git a/heap_lang/lifting.v b/heap_lang/lifting.v
index f531ed535..da7962dee 100644
--- a/heap_lang/lifting.v
+++ b/heap_lang/lifting.v
@@ -147,20 +147,20 @@ Proof.
     ?right_id -?wp_value //; intros; inv_step; eauto.
 Qed.
 
-Lemma wp_case_inl E e0 v0 x1 e1 x2 e2 Φ :
+Lemma wp_case_inl E e0 v0 e1 e2 Φ :
   to_val e0 = Some v0 →
-  ▷ || subst' e1 x1 v0 @ E {{ Φ }} ⊑ || Case (InjL e0) x1 e1 x2 e2 @ E {{ Φ }}.
+  ▷ || App e1 e0 @ E {{ Φ }} ⊑ || Case (InjL e0) e1 e2 @ E {{ Φ }}.
 Proof.
-  intros. rewrite -(wp_lift_pure_det_step (Case _ _ _ _ _)
-    (subst' e1 x1 v0) None) ?right_id //; intros; inv_step; eauto.
+  intros. rewrite -(wp_lift_pure_det_step (Case _ _ _)
+    (App e1 e0) None) ?right_id //; intros; inv_step; eauto.
 Qed.
 
-Lemma wp_case_inr E e0 v0 x1 e1 x2 e2 Φ :
+Lemma wp_case_inr E e0 v0 e1 e2 Φ :
   to_val e0 = Some v0 →
-  ▷ || subst' e2 x2 v0 @ E {{ Φ }} ⊑ || Case (InjR e0) x1 e1 x2 e2 @ E {{ Φ }}.
+  ▷ || App e2 e0 @ E {{ Φ }} ⊑ || Case (InjR e0) e1 e2 @ E {{ Φ }}.
 Proof.
-  intros. rewrite -(wp_lift_pure_det_step (Case _ _ _ _ _)
-    (subst' e2 x2 v0) None) ?right_id //; intros; inv_step; eauto.
+  intros. rewrite -(wp_lift_pure_det_step (Case _ _ _)
+    (App e2 e0) None) ?right_id //; intros; inv_step; eauto.
 Qed.
 
 End lifting.
diff --git a/heap_lang/notation.v b/heap_lang/notation.v
index 655cef7c3..0b4ea4752 100644
--- a/heap_lang/notation.v
+++ b/heap_lang/notation.v
@@ -28,7 +28,7 @@ Notation "<>" := BAnom : binder_scope.
    pretty printing. *)
 Notation "( e1 , e2 , .. , en )" := (Pair .. (Pair e1 e2) .. en) : lang_scope.
 Notation "'match:' e0 'with' 'InjL' x1 => e1 | 'InjR' x2 => e2 'end'" :=
-  (Case e0 x1 e1 x2 e2)
+  (Match e0 x1 e1 x2 e2)
   (e0, x1, e1, x2, e2 at level 200) : lang_scope.
 Notation "()" := LitUnit : lang_scope.
 Notation "# l" := (Lit l%Z%L) (at level 8, format "# l").
diff --git a/heap_lang/substitution.v b/heap_lang/substitution.v
index ffb431cde..6c98a0ab1 100644
--- a/heap_lang/substitution.v
+++ b/heap_lang/substitution.v
@@ -66,11 +66,6 @@ Instance subst_rec f y e x v er :
   SubstIf (BNamed x ≠ f ∧ BNamed x ≠ y) e x v er →
   Subst (Rec f y e) x v (Rec f y er).
 Proof. intros [??]; red; f_equal/=; case_decide; auto. Qed.
-Instance subst_case e0 x1 e1 x2 e2 x v e0r e1r e2r :
-  Subst e0 x v e0r →
-  SubstIf (BNamed x ≠ x1) e1 x v e1r → SubstIf (BNamed x ≠ x2) e2 x v e2r →
-  Subst (Case e0 x1 e1 x2 e2) x v (Case e0r x1 e1r x2 e2r).
-Proof. intros ? [??] [??]; red; f_equal/=; repeat case_decide; auto. Qed.
 
 Instance subst_app e1 e2 x v e1r e2r :
   Subst e1 x v e1r → Subst e2 x v e2r → Subst (App e1 e2) x v (App e1r e2r).
@@ -97,6 +92,10 @@ Instance subst_injL e x v er : Subst e x v er → Subst (InjL e) x v (InjL er).
 Proof. by intros; red; f_equal/=. Qed.
 Instance subst_injR e x v er : Subst e x v er → Subst (InjR e) x v (InjR er).
 Proof. by intros; red; f_equal/=. Qed.
+Instance subst_case e0 e1 e2 x v e0r e1r e2r :
+  Subst e0 x v e0r → Subst e1 x v e1r → Subst e2 x v e2r →
+  Subst (Case e0 e1 e2) x v (Case e0r e1r e2r).
+Proof. by intros; red; f_equal/=. Qed.
 Instance subst_fork e x v er : Subst e x v er → Subst (Fork e) x v (Fork er).
 Proof. by intros; red; f_equal/=. Qed.
 Instance subst_alloc e x v er : Subst e x v er → Subst (Alloc e) x v (Alloc er).
@@ -134,9 +133,7 @@ Fixpoint is_closed (X : stringset) (e : expr) : bool :=
   | Snd e => is_closed X e
   | InjL e => is_closed X e
   | InjR e => is_closed X e
-  | Case e0 x1 e1 x2 e2 =>
-     is_closed X e0 &&
-     is_closed (of_binder x1 ∪ X) e1 && is_closed (of_binder x2 ∪ X) e2
+  | Case e0 e1 e2 => is_closed X e0 && is_closed X e1 && is_closed X e2
   | Fork e => is_closed X e
   | Loc l => true
   | Alloc e => is_closed X e
-- 
GitLab