Theory execute_WellType

(*  Title:      Jinja/J/execute_WellType.thy
    Author:     Christoph Petzinger
    Copyright   2004 Technische Universitaet Muenchen
*)

section ‹Code Generation For WellType›

theory execute_WellType
imports
  WellType Examples
begin

(* Replace WT_WTs.WTCond with new intros WT_WTs.WTCond1 and WT_WTs.WTCond2 *)

lemma WTCond1:
  "⟦P,E ⊢ e :: Boolean;  P,E ⊢ e1::T1;  P,E ⊢ e2::T2; P ⊢ T1 ≤ T2;
    P ⊢ T2 ≤ T1 ⟶ T2 = T1 ⟧ ⟹ P,E ⊢ if (e) e1 else e2 :: T2"
by (fastforce)

lemma WTCond2:
  "⟦P,E ⊢ e :: Boolean;  P,E ⊢ e1::T1;  P,E ⊢ e2::T2; P ⊢ T2 ≤ T1;
    P ⊢ T1 ≤ T2 ⟶ T1 = T2 ⟧ ⟹ P,E ⊢ if (e) e1 else e2 :: T1"
by (fastforce)

lemmas [code_pred_intro] =
  WT_WTs.WTNew
  WT_WTs.WTCast
  WT_WTs.WTVal
  WT_WTs.WTVar
  WT_WTs.WTBinOpEq
  WT_WTs.WTBinOpAdd
  WT_WTs.WTLAss
  WT_WTs.WTFAcc
  WT_WTs.WTFAss
  WT_WTs.WTCall
  WT_WTs.WTBlock
  WT_WTs.WTSeq

declare
  WTCond1 [code_pred_intro WTCond1]
  WTCond2 [code_pred_intro WTCond2]

lemmas [code_pred_intro] =
  WT_WTs.WTWhile
  WT_WTs.WTThrow
  WT_WTs.WTTry
  WT_WTs.WTNil
  WT_WTs.WTCons

code_pred
  (modes: i ⇒ i ⇒ i ⇒ i ⇒ bool as type_check, i ⇒ i ⇒ i ⇒ o ⇒ bool as infer_type)
  WT
proof -
  case WT
  from WT.prems show thesis
  proof(cases (no_simp))
    case (WTCond E e e1 T1 e2 T2 T)
    from ‹x ⊢ T1 ≤ T2 ∨ x ⊢ T2 ≤ T1› show thesis
    proof
      assume "x ⊢ T1 ≤ T2"
      with ‹x ⊢ T1 ≤ T2 ⟶ T = T2› have "T = T2" ..
      from ‹xa = E› ‹xb = if (e) e1 else e2› ‹xc = T› ‹x,E ⊢ e :: Boolean› 
        ‹x,E ⊢ e1 :: T1› ‹x,E ⊢ e2 :: T2› ‹x ⊢ T1 ≤ T2› ‹x ⊢ T2 ≤ T1 ⟶ T = T1›
      show ?thesis unfolding ‹T = T2› by(rule WT.WTCond1[OF refl])
    next
      assume "x ⊢ T2 ≤ T1"
      with ‹x ⊢ T2 ≤ T1 ⟶ T = T1› have "T = T1" ..
      from ‹xa = E› ‹xb = if (e) e1 else e2› ‹xc = T› ‹x,E ⊢ e :: Boolean› 
        ‹x,E ⊢ e1 :: T1› ‹x,E ⊢ e2 :: T2› ‹x ⊢ T2 ≤ T1› ‹x ⊢ T1 ≤ T2 ⟶ T = T2›
      show ?thesis unfolding ‹T = T1› by(rule WT.WTCond2[OF refl])
    qed
  qed(assumption|erule (2) WT.that[OF refl])+
next
  case WTs
  from WTs.prems show thesis
    by(cases (no_simp))(assumption|erule (2) WTs.that[OF refl])+
qed

notation infer_type (‹_,_ ⊢ _ :: '_› [51,51,51]100)

definition test1 where "test1 = [],Map.empty ⊢ testExpr1 :: _"
definition test2 where "test2 = [], Map.empty  ⊢ testExpr2 :: _"
definition test3 where "test3 = [], Map.empty(''V'' ↦ Integer)  ⊢ testExpr3 :: _"
definition test4 where "test4 = [], Map.empty(''V'' ↦ Integer)  ⊢ testExpr4 :: _"
definition test5 where "test5 = [classObject, (''C'',(''Object'',[(''F'',Integer)],[]))], Map.empty  ⊢ testExpr5 :: _"
definition test6 where "test6 = [classObject, classI], Map.empty  ⊢ testExpr6 :: _"

ML_val ‹
  val SOME(@{code Integer}, _) = Predicate.yield @{code test1};
  val SOME(@{code Integer}, _) = Predicate.yield @{code test2};
  val SOME(@{code Integer}, _) = Predicate.yield @{code test3};
  val SOME(@{code Void}, _) = Predicate.yield @{code test4};
  val SOME(@{code Void}, _) = Predicate.yield @{code test5};
  val SOME(@{code Integer}, _) = Predicate.yield @{code test6};
›

definition testmb_isNull where "testmb_isNull = [classObject, classA], Map.empty([this] [↦] [Class ''A'']) ⊢ mb_isNull :: _"
definition testmb_add where "testmb_add = [classObject, classA], Map.empty([this,''i''] [↦] [Class ''A'',Integer]) ⊢ mb_add :: _"
definition testmb_mult_cond where "testmb_mult_cond = [classObject, classA], Map.empty([this,''j''] [↦] [Class ''A'',Integer]) ⊢ mb_mult_cond :: _"
definition testmb_mult_block where "testmb_mult_block = [classObject, classA], Map.empty([this,''i'',''j'',''temp''] [↦] [Class ''A'',Integer,Integer,Integer]) ⊢ mb_mult_block :: _"
definition testmb_mult where "testmb_mult = [classObject, classA], Map.empty([this,''i'',''j''] [↦] [Class ''A'',Integer,Integer]) ⊢ mb_mult :: _"

ML_val ‹
  val SOME(@{code Boolean}, _) = Predicate.yield @{code testmb_isNull};
  val SOME(@{code Integer}, _) = Predicate.yield @{code testmb_add};
  val SOME(@{code Boolean}, _) = Predicate.yield @{code testmb_mult_cond};
  val SOME(@{code Void}, _) = Predicate.yield @{code testmb_mult_block};
  val SOME(@{code Integer}, _) = Predicate.yield @{code testmb_mult};
›

definition test where "test = [classObject, classA], Map.empty ⊢ testExpr_ClassA :: _"

ML_val ‹
  val SOME(@{code Integer}, _) = Predicate.yield @{code test};
›

end