Theory TypeInf

(*  Title:      HOL/MicroJava/Comp/TypeInf.thy
    Author:     Martin Strecker
*)

(* Exact position in theory hierarchy still to be determined *)
theory TypeInf
imports "../J/WellType"
begin



(**********************************************************************)


(*** Inversion of typing rules -- to be moved into WellType.thy
     Also modify the wtpd_expr_… proofs in CorrComp.thy ***)

lemma NewC_invers:
  assumes "ENewC C::T"
  shows "T = Class C  is_class (prg E) C"
  using assms by cases auto

lemma Cast_invers:
  assumes "ECast D e::T"
  shows "C. T = Class D  Ee::C  is_class (prg E) D  prg EC≼? Class D"
  using assms by cases auto

lemma Lit_invers:
  assumes "ELit x::T"
  shows "typeof (λv. None) x = Some T"
  using assms by cases auto

lemma LAcc_invers:
  assumes "ELAcc v::T"
  shows "localT E v = Some T  is_type (prg E) T"
  using assms by cases auto

lemma BinOp_invers:
  assumes "EBinOp bop e1 e2::T'"
  shows "T. Ee1::T  Ee2::T 
            (if bop = Eq then T' = PrimT Boolean
                        else T' = T  T = PrimT Integer)"
  using assms by cases auto

lemma LAss_invers:
  assumes  "Ev::=e::T'"
  shows "T. v ~= This  ELAcc v::T  Ee::T'  prg ET'T"
  using assms by cases auto

lemma FAcc_invers:
  assumes "E{fd}a..fn::fT"
  shows "C. Ea::Class C  field (prg E,C) fn = Some (fd, fT)"
  using assms by cases auto

lemma FAss_invers:
  assumes "E{fd}a..fn:=v::T'"
  shows "T. E{fd}a..fn::T  Ev ::T'  prg ET'T"
  using assms by cases auto

lemma Call_invers:
  assumes "E{C}a..mn({pTs'}ps)::rT"
  shows "pTs md.
    Ea::Class C  Eps[::]pTs  max_spec (prg E) C (mn, pTs) = {((md,rT),pTs')}"
  using assms by cases auto


lemma Nil_invers:
  assumes "E[] [::] Ts"
  shows "Ts = []"
  using assms by cases auto

lemma Cons_invers:
  assumes "Ee#es[::]Ts"
  shows "T Ts'. Ts = T#Ts'  E e::T  E es[::]Ts'"
  using assms by cases auto


lemma Expr_invers:
  assumes "EExpr e"
  shows " T. Ee::T"
  using assms by cases auto

lemma Comp_invers:
  assumes "Es1;; s2"
  shows "Es1  Es2"
  using assms by cases auto

lemma Cond_invers:
  assumes "EIf(e) s1 Else s2"
  shows "Ee::PrimT Boolean  Es1  Es2"
  using assms by cases auto

lemma Loop_invers:
  assumes "EWhile(e) s"
  shows "Ee::PrimT Boolean  Es"
  using assms by cases auto


(**********************************************************************)


declare split_paired_All [simp del]
declare split_paired_Ex [simp del]

method ty_case_simp = ((erule ty_exprs.cases ty_expr.cases; simp)+)[]
method strip_case_simp = (intro strip, ty_case_simp)

(* Uniqueness of types property *)

lemma uniqueness_of_types: "
  ( (E::'a prog × (vname  ty option)) T1 T2. 
  Ee :: T1  Ee :: T2  T1 = T2) 
  ( (E::'a prog × (vname  ty option)) Ts1 Ts2. 
  Ees [::] Ts1  Ees [::] Ts2  Ts1 = Ts2)"
  apply (rule compat_expr_expr_list.induct)
            (* NewC *)
            apply strip_case_simp

           (* Cast *)
           apply strip_case_simp

          (* Lit *)
          apply strip_case_simp

         (* BinOp *)
         apply (intro strip)
         apply (rename_tac binop x2 x3 E T1 T2, case_tac binop)
          (* Eq *)
          apply ty_case_simp
         (* Add *)
         apply ty_case_simp

        (* LAcc *)
        apply (strip_case_simp)

       (* LAss *)
       apply (strip_case_simp)

      (* FAcc *)
      apply (intro strip)
      apply (drule FAcc_invers)+
      apply fastforce

     (* FAss *)
     apply (intro strip)
     apply (drule FAss_invers)+
     apply (elim conjE exE)
     apply (drule FAcc_invers)+
     apply fastforce

    (* Call *)
    apply (intro strip)
    apply (drule Call_invers)+
    apply fastforce

   (* expression lists *)
   apply (strip_case_simp)

  apply (strip_case_simp)
  done


lemma uniqueness_of_types_expr [rule_format (no_asm)]: "
  (E T1 T2. Ee :: T1  Ee :: T2  T1 = T2)"
  by (rule uniqueness_of_types [THEN conjunct1])

lemma uniqueness_of_types_exprs [rule_format (no_asm)]: "
  (E Ts1 Ts2. Ees [::] Ts1  Ees [::] Ts2  Ts1 = Ts2)"
  by (rule uniqueness_of_types [THEN conjunct2])


definition inferred_tp :: "[java_mb env, expr]  ty" where
  "inferred_tp E e == (SOME T. Ee :: T)"

definition inferred_tps :: "[java_mb env, expr list]  ty list" where
  "inferred_tps E es == (SOME Ts. Ees [::] Ts)"

(* get inferred type(s) for well-typed term *)
lemma inferred_tp_wt: "Ee :: T  (inferred_tp E e) = T"
  by (auto simp: inferred_tp_def intro: uniqueness_of_types_expr)

lemma inferred_tps_wt: "Ees [::] Ts  (inferred_tps E es) = Ts"
  by (auto simp: inferred_tps_def intro: uniqueness_of_types_exprs)

end