Theory ResourcedAdequacy

theory ResourcedAdequacy
imports ResourcedDenotational Launchbury "AList-Utils" CorrectnessResourced
begin

lemma demand_not_0: "demand (π’©βŸ¦eβŸ§β‡˜Οβ‡™) β‰  βŠ₯"
proof
  assume "demand (π’©βŸ¦eβŸ§β‡˜Οβ‡™) = βŠ₯"
  with demand_suffices'[where n = 0, simplified, OF this]
  have "(π’©βŸ¦eβŸ§β‡˜Οβ‡™)β‹…βŠ₯ β‰  βŠ₯" by simp
  thus False by simp
qed

text β€Ή
The semantics of an expression, given only @{term r} resources, will only use values from the
environment with less resources.
β€Ί

lemma restr_can_restrict_env: "(π’©βŸ¦ e βŸ§β‡˜Οβ‡™)|β‡˜Cβ‹…r⇙ = (π’©βŸ¦ e βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)|β‡˜Cβ‹…r⇙"
proof(induction e arbitrary: ρ r rule: exp_induct)
  case (Var x)
  show ?case
  proof (rule C_restr_C_cong)
    fix r'
    assume "r' βŠ‘ r"
    have "(π’©βŸ¦ Var x βŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r') = ρ xβ‹…r'" by simp
    also have "… = ((ρ x)|β‡˜r⇙)β‹…r'" using β€Ήr' βŠ‘ rβ€Ί by simp
    also have "… =  (π’©βŸ¦ Var x βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r')" by simp
    finally show "(π’©βŸ¦ Var x βŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r') = (π’©βŸ¦ Var x βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r')".
  qed simp
next
  case (Lam x e)
  show ?case
  proof(rule C_restr_C_cong)
    fix r'
    assume "r' βŠ‘ r"
    hence "r' βŠ‘ Cβ‹…r" by (metis below_C below_trans)
    {
      fix v
      have "ρ(x := v)|βˆ˜β‡˜r⇙ = (ρ|βˆ˜β‡˜r⇙)(x := v)|βˆ˜β‡˜r⇙"
        by simp
      hence "(π’©βŸ¦ e βŸ§β‡˜Ο(x := v)⇙)|β‡˜r'⇙ = (π’©βŸ¦ e βŸ§β‡˜(ρ|βˆ˜β‡˜r⇙)(x := v)⇙)|β‡˜r'⇙"
        by  (subst (1 2) C_restr_eq_lower[OF Lam β€Ήr' βŠ‘ Cβ‹…rβ€Ί ]) simp
    }
    thus "(π’©βŸ¦ Lam [x]. e βŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r') = (π’©βŸ¦ Lam [x]. e βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r')"
      by simp
  qed simp
next
  case (App e x)
  show ?case
  proof (rule C_restr_C_cong)
    fix r'
    assume "r' βŠ‘ r"
    hence "r' βŠ‘ Cβ‹…r" by (metis below_C below_trans)
    hence "(π’©βŸ¦ e βŸ§β‡˜Οβ‡™)β‹…r' = (π’©βŸ¦ e βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…r'"
        by (rule C_restr_eqD[OF App])
    thus "(π’©βŸ¦ App e x βŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r') = (π’©βŸ¦ App e x βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r')"
      using β€Ήr' βŠ‘ rβ€Ί by simp
  qed simp
next
  case (Bool b)
  show ?case by simp
next
  case (IfThenElse scrut e1 e2)
  show ?case
  proof (rule C_restr_C_cong)
    fix r'
    assume "r' βŠ‘ r"
    hence "r' βŠ‘ Cβ‹…r" by (metis below_C below_trans)

    have "(π’©βŸ¦ scrut βŸ§β‡˜Οβ‡™)β‹…r' = (π’©βŸ¦ scrut βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…r'"
      using β€Ήr' βŠ‘ Cβ‹…rβ€Ί by (rule C_restr_eqD[OF IfThenElse(1)])
    moreover
    have "(π’©βŸ¦ e1 βŸ§β‡˜Οβ‡™)β‹…r' = (π’©βŸ¦ e1 βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…r'"
      using β€Ήr' βŠ‘ Cβ‹…rβ€Ί by (rule C_restr_eqD[OF IfThenElse(2)])
    moreover
    have "(π’©βŸ¦ e2 βŸ§β‡˜Οβ‡™)β‹…r' = (π’©βŸ¦ e2 βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…r'"
      using β€Ήr' βŠ‘ Cβ‹…rβ€Ί by (rule C_restr_eqD[OF IfThenElse(3)])
    ultimately
    show "(π’©βŸ¦ (scrut ? e1 : e2) βŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r') = (π’©βŸ¦ (scrut ? e1 : e2) βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r')"
      using β€Ήr' βŠ‘ rβ€Ί by simp
  qed simp
next
  case (Let Ξ“ e)

  txt β€ΉThe lemma, lifted to heapsβ€Ί
  have restr_can_restrict_env_heap : "β‹€ r. (𝒩⦃Γ⦄ρ)|βˆ˜β‡˜r⇙ = (𝒩⦃Γ⦄ρ|βˆ˜β‡˜r⇙)|βˆ˜β‡˜r⇙"
  proof(rule has_ESem.parallel_HSem_ind)
    fix ρ1 ρ2 :: CEnv and r :: C
    assume "ρ1|βˆ˜β‡˜r⇙ = ρ2|βˆ˜β‡˜r⇙"

    show " (ρ ++β‡˜domA Γ⇙ π’©βŸ¦ Ξ“ βŸ§β‡˜Ο1⇙)|βˆ˜β‡˜r⇙ = (ρ|βˆ˜β‡˜r⇙ ++β‡˜domA Γ⇙ π’©βŸ¦ Ξ“ βŸ§β‡˜Ο2⇙)|βˆ˜β‡˜r⇙"
    proof(rule env_C_restr_cong)
      fix x and r'
      assume "r' βŠ‘ r"
      hence "r' βŠ‘ Cβ‹…r" by (metis below_C below_trans)

      show "(ρ ++β‡˜domA Γ⇙ π’©βŸ¦ Ξ“ βŸ§β‡˜Ο1⇙) xβ‹…r' = (ρ|βˆ˜β‡˜r⇙ ++β‡˜domA Γ⇙ π’©βŸ¦ Ξ“ βŸ§β‡˜Ο2⇙) xβ‹…r'"
      proof(cases "x ∈ domA Ξ“")
        case True
        have "(π’©βŸ¦ the (map_of Ξ“ x) βŸ§β‡˜Ο1⇙)β‹…r' = (π’©βŸ¦ the (map_of Ξ“ x) βŸ§β‡˜Ο1|βˆ˜β‡˜r⇙⇙)β‹…r'"
         by (rule C_restr_eqD[OF Let(1)[OF True] β€Ήr' βŠ‘ Cβ‹…rβ€Ί])
        also have "… = (π’©βŸ¦ the (map_of Ξ“ x) βŸ§β‡˜Ο2|βˆ˜β‡˜r⇙⇙)β‹…r'"
          unfolding ‹ρ1|βˆ˜β‡˜r⇙ = ρ2|βˆ˜β‡˜r⇙›..
        also have "…   = (π’©βŸ¦ the (map_of Ξ“ x) βŸ§β‡˜Ο2⇙)β‹…r'"
          by (rule C_restr_eqD[OF Let(1)[OF True] β€Ήr' βŠ‘ Cβ‹…rβ€Ί, symmetric])
        finally
        show ?thesis using True by (simp add: lookupEvalHeap)
      next
        case False
        with β€Ήr' βŠ‘ rβ€Ί
        show ?thesis by simp
      qed
    qed
  qed simp_all

  show ?case
  proof (rule C_restr_C_cong)
    fix r'
    assume "r' βŠ‘ r"
    hence "r' βŠ‘ Cβ‹…r" by (metis below_C below_trans)

    have "(𝒩⦃Γ⦄ρ)|βˆ˜β‡˜r⇙ = (𝒩⦃Γ⦄(ρ|βˆ˜β‡˜r⇙))|βˆ˜β‡˜r⇙"
      by (rule restr_can_restrict_env_heap)
    hence "(π’©βŸ¦ e βŸ§β‡˜π’©β¦ƒΞ“β¦„Οβ‡™)β‹…r' = (π’©βŸ¦ e βŸ§β‡˜π’©β¦ƒΞ“β¦„Ο|βˆ˜β‡˜r⇙⇙)β‹…r'"
      by (subst (1 2) C_restr_eqD[OF Let(2) β€Ήr' βŠ‘ Cβ‹…rβ€Ί]) simp

    thus "(π’©βŸ¦ Let Ξ“ e βŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r') = (π’©βŸ¦ Let Ξ“ e βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r')"
      using β€Ήr' βŠ‘ rβ€Ί by simp
  qed simp
qed

lemma can_restrict_env:
  "(π’©βŸ¦eβŸ§β‡˜Οβ‡™)β‹…(Cβ‹…r) = (π’©βŸ¦ e βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r)"
  by (rule C_restr_eqD[OF restr_can_restrict_env below_refl])

text β€Ή
When an expression @{term e} terminates, then we can remove such an expression from the heap and it
still terminates. This is the crucial trick to handle black-holing in the resourced semantics.
β€Ί

lemma add_BH:
  assumes "map_of Ξ“ x = Some e"
  assumes  "(π’©βŸ¦eβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r' β‰  βŠ₯"
  shows "(π’©βŸ¦eβŸ§β‡˜π’©β¦ƒdelete x Γ⦄⇙)β‹…r' β‰  βŠ₯"
proof-
  obtain r where r: "Cβ‹…r = demand (π’©βŸ¦eβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)"
    using demand_not_0 by (cases "demand (π’©βŸ¦ e βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)") auto

  from  assms(2)
  have "Cβ‹…r βŠ‘ r'" unfolding r not_bot_demand by simp

  from assms(1)
  have [simp]: "the (map_of Ξ“ x) = e" by (metis option.sel)

  from assms(1)
  have [simp]: "x ∈ domA Ξ“" by (metis domIff dom_map_of_conv_domA not_Some_eq)

  define ub where "ub = 𝒩⦃Γ⦄" ― β€ΉAn upper bound for the inductionβ€Ί

  have heaps: "(𝒩⦃Γ⦄)|βˆ˜β‡˜r⇙ βŠ‘ 𝒩⦃delete x Γ⦄" and "𝒩⦃Γ⦄ βŠ‘ ub"
  proof (induction rule: HSem_bot_ind) 
    fix ρ
    assume "ρ|βˆ˜β‡˜r⇙ βŠ‘ 𝒩⦃delete x Γ⦄"
    assume "ρ βŠ‘ ub"

    show "(π’©βŸ¦ Ξ“ βŸ§β‡˜Οβ‡™)|βˆ˜β‡˜r⇙ βŠ‘ 𝒩⦃delete x Γ⦄"
    proof (rule fun_belowI)
      fix y
      show "((π’©βŸ¦ Ξ“ βŸ§β‡˜Οβ‡™)|βˆ˜β‡˜r⇙) y βŠ‘ (𝒩⦃delete x Γ⦄) y"
      proof (cases "y = x")
        case True
        have "((π’©βŸ¦ Ξ“ βŸ§β‡˜Οβ‡™)|βˆ˜β‡˜r⇙) x = (π’©βŸ¦ e βŸ§β‡˜Οβ‡™)|β‡˜r⇙"
          by (simp add: lookupEvalHeap)
        also have "… βŠ‘ (π’©βŸ¦ e βŸ§β‡˜ub⇙)|β‡˜r⇙"
          using ‹ρ βŠ‘ ubβ€Ί by (intro monofun_cfun_arg)
        also have "… = (π’©βŸ¦ e βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)|β‡˜r⇙"
          unfolding ub_def..
        also have "… = βŠ₯"
          using r by (rule  C_restr_bot_demand[OF eq_imp_below])
        also have "… = (𝒩⦃delete x Γ⦄) x"
          by (simp add: lookup_HSem_other)
        finally
        show ?thesis unfolding True.
      next
        case False
        show ?thesis
        proof (cases "y ∈ domA Ξ“")
          case True
          have "(π’©βŸ¦ the (map_of Ξ“ y) βŸ§β‡˜Οβ‡™)|β‡˜r⇙ = (π’©βŸ¦ the (map_of Ξ“ y) βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙)|β‡˜r⇙"
            by (rule C_restr_eq_lower[OF restr_can_restrict_env below_C])
          also have "… βŠ‘ π’©βŸ¦ the (map_of Ξ“ y) βŸ§β‡˜Ο|βˆ˜β‡˜r⇙⇙"
            by (rule C_restr_below)
          also note ‹ρ|βˆ˜β‡˜r⇙ βŠ‘ 𝒩⦃delete x Γ⦄›
          finally
          show ?thesis
            using β€Ήy ∈ domA Ξ“β€Ί β€Ήy β‰  xβ€Ί
            by (simp add: lookupEvalHeap lookup_HSem_heap)
        next
          case False
          thus ?thesis by simp
        qed
      qed
    qed

    from ‹ρ βŠ‘ ubβ€Ί
    have "(π’©βŸ¦ Ξ“ βŸ§β‡˜Οβ‡™) βŠ‘ (π’©βŸ¦ Ξ“ βŸ§β‡˜ub⇙)" 
      by (rule cont2monofunE[rotated]) simp
    also have "… = ub"
      unfolding ub_def HSem_bot_eq[symmetric]..
    finally     
    show "(π’©βŸ¦ Ξ“ βŸ§β‡˜Οβ‡™) βŠ‘ ub".
  qed simp_all

  from assms(2)
  have "(π’©βŸ¦eβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…(Cβ‹…r) β‰  βŠ₯"
    unfolding r
    by (rule demand_suffices[OF infinite_resources_suffice])
  also
  have "(π’©βŸ¦eβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…(Cβ‹…r) = (π’©βŸ¦eβŸ§β‡˜(𝒩⦃Γ⦄)|βˆ˜β‡˜r⇙⇙)β‹…(Cβ‹…r)"
    by (rule can_restrict_env)
  also
  have "… βŠ‘ (π’©βŸ¦eβŸ§β‡˜π’©β¦ƒdelete x Γ⦄⇙)β‹…(Cβ‹…r)"
    by (intro monofun_cfun_arg monofun_cfun_fun heaps )
  also
  have "… βŠ‘ (π’©βŸ¦eβŸ§β‡˜π’©β¦ƒdelete x Γ⦄⇙)β‹…r'"
    using β€ΉCβ‹…r βŠ‘ r'β€Ί by (rule monofun_cfun_arg)
  finally
  show ?thesis by this (intro cont2cont)+
qed

text β€Ή
The semantics is continuous, so we can apply induction here:
β€Ί

lemma resourced_adequacy:
  assumes "(π’©βŸ¦eβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r β‰  βŠ₯"
  shows "βˆƒ Ξ” v. Ξ“ : e β‡“β‡˜S⇙ Ξ” : v"
using assms
proof(induction r arbitrary: Ξ“ e S rule: C.induct[case_names adm bot step])
  case adm show ?case by simp
next
  case bot
  hence False by auto
  thus ?case..
next
  case (step r)
  show ?case
  proof(cases e rule:exp_strong_exhaust(1)[where c = "(Ξ“,S)", case_names Var App Let Lam Bool IfThenElse])
  case (Var x)
    let ?e = "the (map_of Ξ“ x)"
    from step.prems[unfolded Var]
    have "x ∈ domA Ξ“" 
      by (auto intro: ccontr simp add: lookup_HSem_other)
    hence "map_of Ξ“ x = Some ?e" by (rule domA_map_of_Some_the)
    moreover
    from step.prems[unfolded Var] β€Ήmap_of Ξ“ x = Some ?eβ€Ί β€Ήx ∈ domA Ξ“β€Ί
    have "(π’©βŸ¦?eβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r β‰  βŠ₯" by (auto simp add: lookup_HSem_heap  simp del: app_strict)
    hence "(π’©βŸ¦?eβŸ§β‡˜π’©β¦ƒdelete x Γ⦄⇙)β‹…r β‰  βŠ₯" by (rule add_BH[OF β€Ήmap_of Ξ“ x = Some ?eβ€Ί])
    from step.IH[OF this]
    obtain Ξ” v where "delete x Ξ“ : ?e β‡“β‡˜x # S⇙ Ξ” : v" by blast
    ultimately
    have "Ξ“ : (Var x) β‡“β‡˜S⇙ (x,v) #  Ξ” : v" by (rule Variable)
    thus ?thesis using Var by auto
  next
  case (App e' x)
    have "finite (set S βˆͺ fv (Ξ“, e'))" by simp
    from finite_list[OF this]
    obtain S' where S': "set S' = set S βˆͺ fv (Ξ“, e')"..

    from step.prems[unfolded App]
    have prem: "((π’©βŸ¦ e' βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r ↓CFn (𝒩⦃Γ⦄) x|β‡˜r⇙)β‹…r β‰  βŠ₯" by (auto simp del: app_strict)
    hence "(π’©βŸ¦e'βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r β‰  βŠ₯" by auto
    from step.IH[OF this]
    obtain Ξ” v where lhs': "Ξ“ : e' β‡“β‡˜S'⇙ Ξ” : v" by blast 

    have "fv (Ξ“, e') βŠ† set S'" using S' by auto
    from correctness_empty_env[OF lhs' this]
    have correct1: "π’©βŸ¦e'βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™ βŠ‘ π’©βŸ¦vβŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™" and "𝒩⦃Γ⦄ βŠ‘ 𝒩⦃Δ⦄" by auto

    from prem
    have "((π’©βŸ¦ v βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r ↓CFn (𝒩⦃Γ⦄) x|β‡˜r⇙)β‹…r β‰  βŠ₯"
      by (rule not_bot_below_trans)(intro correct1 monofun_cfun_fun  monofun_cfun_arg)
    with result_evaluated[OF lhs']
    have "isLam v" by (cases r, auto, cases v rule: isVal.cases, auto)
    then obtain y e'' where n': "v = (Lam [y]. e'')" by (rule isLam_obtain_fresh)
    with lhs'
    have lhs: "Ξ“ : e' β‡“β‡˜S'⇙ Ξ” : Lam [y]. e''" by simp

    have "((π’©βŸ¦ v βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r ↓CFn (𝒩⦃Γ⦄) x|β‡˜r⇙)β‹…r β‰  βŠ₯" by fact
    also have "(𝒩⦃Γ⦄) x|β‡˜r⇙ βŠ‘ (𝒩⦃Γ⦄) x" by (rule C_restr_below)
    also note β€Ήv = _β€Ί
    also note β€Ή(𝒩⦃Γ⦄) βŠ‘ (𝒩⦃Δ⦄)β€Ί
    also have "(π’©βŸ¦ Lam [y]. e'' βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r βŠ‘ CFnβ‹…(Ξ› v. π’©βŸ¦e''βŸ§β‡˜(𝒩⦃Δ⦄)(y := v)⇙)"
      by (rule CELam_no_restr)
    also have "(… ↓CFn (𝒩⦃Δ⦄) x)β‹…r = (π’©βŸ¦e''βŸ§β‡˜(𝒩⦃Δ⦄)(y := ((𝒩⦃Δ⦄) x))⇙)β‹…r" by simp
    also have "… = (π’©βŸ¦e''[y::=x]βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r"
      unfolding ESem_subst..
    finally
    have "… β‰  βŠ₯" by this (intro cont2cont cont_fun)+
    then
    obtain Θ v' where rhs: "Ξ” : e''[y::=x] β‡“β‡˜S'⇙ Θ : v'" using step.IH by blast

    have "Ξ“ : App e' x β‡“β‡˜S'⇙ Θ : v'"
      by (rule reds_ApplicationI[OF lhs rhs])
    hence "Ξ“ : App e' x β‡“β‡˜S⇙ Θ : v'"
      apply (rule reds_smaller_L) using S' by auto
    thus ?thesis using App by auto
  next
  case (Lam v e')
    have "Ξ“ : Lam [v]. e' β‡“β‡˜S⇙ Ξ“ : Lam [v]. e'" ..
    thus ?thesis using Lam by blast
  next
  case (Bool b)
    have "Ξ“ : Bool b β‡“β‡˜S⇙ Ξ“ : Bool b" by rule
    thus ?thesis using Bool by blast
  next
  case (IfThenElse scrut e1 e2)

    from step.prems[unfolded IfThenElse]
    have prem: "CB_projectβ‹…((π’©βŸ¦ scrut βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r)β‹…((π’©βŸ¦ e1 βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r)β‹…((π’©βŸ¦ e2 βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r) β‰  βŠ₯" by (auto simp del: app_strict)
    then obtain b where
      is_CB: "(π’©βŸ¦ scrut βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r = CBβ‹…(Discr b)"
      and not_bot2: "((π’©βŸ¦ (if b then e1 else e2) βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r) β‰  βŠ₯"
    unfolding CB_project_not_bot by (auto split: if_splits)

    have "finite (set S βˆͺ fv (Ξ“, scrut))" by simp
    from finite_list[OF this]
    obtain S' where S': "set S' = set S βˆͺ fv (Ξ“, scrut)"..


    from is_CB have "(π’©βŸ¦ scrut βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r β‰  βŠ₯" by simp
    from step.IH[OF this]
    obtain Ξ” v where lhs': "Ξ“ : scrut β‡“β‡˜S'⇙ Ξ” : v" by blast
    then have "isVal v" by (rule result_evaluated)

    have "fv (Ξ“, scrut) βŠ† set S'" using S' by simp
    from correctness_empty_env[OF lhs' this]
    have correct1: "π’©βŸ¦scrutβŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™ βŠ‘ π’©βŸ¦vβŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™" and correct2: "𝒩⦃Γ⦄ βŠ‘ 𝒩⦃Δ⦄" by auto

    from correct1
    have "(π’©βŸ¦ scrut βŸ§β‡˜π’©β¦ƒΞ“β¦„β‡™)β‹…r βŠ‘ (π’©βŸ¦ v βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r" by (rule monofun_cfun_fun)
    with is_CB
    have "(π’©βŸ¦ v βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r = CBβ‹…(Discr b)" by simp
    with β€ΉisVal vβ€Ί
    have "v = Bool b" by (cases v rule: isVal.cases) (case_tac r, auto)+

    from not_bot2 ‹𝒩⦃Γ⦄ βŠ‘ 𝒩⦃Δ⦄›
    have "(π’©βŸ¦ (if b then e1 else e2) βŸ§β‡˜π’©β¦ƒΞ”β¦„β‡™)β‹…r β‰  βŠ₯"
      by (rule not_bot_below_trans[OF _ monofun_cfun_fun[OF monofun_cfun_arg]])
    from step.IH[OF this]
    obtain Θ v' where rhs: "Ξ” : (if b then e1 else e2) β‡“β‡˜S'⇙ Θ : v'" by blast

    from lhs'[unfolded β€Ήv = _β€Ί] rhs
    have "Ξ“ : (scrut ? e1 : e2) β‡“β‡˜S'⇙ Θ : v'" by rule
    hence "Ξ“ : (scrut ? e1 : e2) β‡“β‡˜S⇙ Θ : v'"
      apply (rule reds_smaller_L) using S' by auto
    thus ?thesis unfolding IfThenElse by blast
  next
  case (Let Ξ” e')
    from step.prems[unfolded Let(2)]
    have prem: "(π’©βŸ¦e'βŸ§β‡˜π’©β¦ƒΞ”β¦„π’©β¦ƒΞ“β¦„β‡™)β‹…r β‰  βŠ₯" 
      by (simp  del: app_strict)
    also
      have "atom ` domA Ξ” β™―* Ξ“" using Let(1) by (simp add: fresh_star_Pair)
      hence "𝒩⦃Δ⦄𝒩⦃Γ⦄ = 𝒩⦃Δ @ Γ⦄" by (rule HSem_merge)
    finally 
    have "(π’©βŸ¦e'βŸ§β‡˜π’©β¦ƒΞ” @ Γ⦄⇙)β‹…r β‰  βŠ₯".
    then
    obtain Θ v where "Ξ” @ Ξ“ : e' β‡“β‡˜S⇙ Θ : v" using step.IH by blast
    hence "Ξ“ : Let Ξ” e' β‡“β‡˜S⇙ Θ : v"
      by (rule reds.Let[OF Let(1)])
    thus ?thesis using Let by auto
  qed
qed

end