Theory Sorts

section "Sorts"

(* 
  Some stuff on sorts. Mostly from Sort.ML I think.
*)

theory Sorts
imports Term
begin

definition [simp]: "empty_osig = ({}, Map.empty)"

definition "sort_les cs s1 s2 = (sort_leq cs s1 s2 ∧ ¬ sort_leq cs s2 s1)"
definition "sort_eqv cs s1 s2 = (sort_leq cs s1 s2 ∧ sort_leq cs s2 s1)"

lemmas class_defs = class_leq_def class_les_def class_ex_def
lemmas sort_defs = sort_leq_def sort_les_def sort_eqv_def sort_ex_def

lemma sort_ex_class_ex: "sort_ex cs S ≡ ∀c ∈ S. class_ex cs c"
  by (auto simp add: sort_ex_def class_ex_def subset_eq)

(* Did not want to write the wf_subclass cs assumption each time + allowed type class instances inside
  Now probably more trouble than help
*)
locale wf_subclass_loc =
  fixes cs :: "class rel"
  assumes wf[simp]: "wf_subclass cs"
begin 

lemma class_les_irrefl: "¬ class_les cs c c"
  using wf by (simp add: class_les_def)
lemma class_les_trans: "class_les cs x y ⟹ class_les cs y z ⟹ class_les cs x z"
  using wf by (auto simp add: class_les_def class_leq_def trans_def)

lemma class_leq_refl[iff]: "class_ex cs c ⟹ class_leq cs c c" 
  using wf by (simp add: class_leq_def class_ex_def refl_on_def) 
lemma class_leq_trans: "class_leq cs x y ⟹ class_leq cs y z ⟹ class_leq cs x z"
  using wf by (auto simp add: class_leq_def elim: transE)
lemma class_leq_antisym: "class_leq cs c1 c2 ⟹ class_leq cs c2 c1 ⟹ c1=c2" 
  using wf by (auto intro: antisymD simp: trans_def class_leq_def)

(* classes form a ~ partial order with class_les/class_leq a for a well-formed a*)
lemma sort_leq_refl[iff]: "sort_ex cs s ⟹ sort_leq cs s s" 
  using class_leq_refl by (auto simp add: sort_ex_class_ex sort_leq_def)
lemma sort_leq_trans: "sort_leq cs x y ⟹ sort_leq cs y z ⟹ sort_leq cs x z"
  by (meson class_leq_trans sort_leq_def)
lemma sort_leq_ex: "sort_leq cs s1 s2 ⟹ sort_ex cs s2"
  by (auto simp add: sort_ex_def class_leq_def sort_leq_def intro: FieldI2)
(* ... *)

lemma sort_leq_minimize: 
  "sort_leq cs s1 s2 ⟹ ∃s1'. (∀c1 ∈ s1' . ∃c2 ∈ s2. class_leq cs c1 c2) ∧ sort_leq cs s1' s2"
  by (meson class_leq_refl sort_ex_class_ex sort_leq_ex sort_leq_refl)

lemma "sort_ex cs s2 ⟹ s1 ⊆ s2 ⟹ sort_ex cs s1"
  by (meson sort_ex_def subset_trans)

lemma superset_imp_sort_leq: "sort_ex cs s2 ⟹ s1 ⊇ s2 ⟹ sort_leq cs s1 s2"
  by (auto simp add: sort_ex_class_ex sort_leq_def sort_ex_def)
lemma full_sort_top: "sort_ex cs s ⟹ sort_leq cs s full_sort" 
  by (simp add: sort_leq_def)

(* Is this even useful? *)
lemma sort_les_trans: "sort_les cs x y ⟹ sort_les cs y z ⟹ sort_les cs x z"
  using sort_les_def sort_leq_trans by blast
                                                               
lemma sort_eqvI: "sort_leq cs s1 s2 ⟹ sort_leq cs s2 s1 ⟹ sort_eqv cs s1 s2" 
  by (simp add: sort_eqv_def)
lemma sort_eqv_refl: "sort_ex cs s ⟹ sort_eqv cs s s" 
  using sort_leq_refl by (auto simp add: sort_eqv_def)
lemma sort_eqv_trans: "sort_eqv cs x y ⟹ sort_eqv cs y z ⟹ sort_eqv cs x z"
  using sort_eqv_def sort_leq_trans by blast
lemma sort_eqv_sym: "sort_eqv cs x y ⟹ sort_eqv cs y x"
  by (auto simp add: sort_eqv_def)
(* sort_eqv a is ~ equivalence relation.. *)

lemma normalize_sort_empty[simp]: "normalize_sort cs full_sort = full_sort"
  by (simp add: normalize_sort_def)
lemma normalize_sort_normalize_sort[simp]: 
  "normalize_sort cs (normalize_sort cs s) = normalize_sort cs s" 
  by (auto simp add: normalize_sort_def)

lemma sort_ex_norm_sort: "sort_ex cs s ⟹ sort_ex cs (normalize_sort cs s)"
  by (simp add: normalize_sort_def sort_ex_class_ex)

lemma normalized_sort_subset: "normalize_sort cs s ⊆ s"
  by (auto simp add: normalize_sort_def)

lemma normalize_sort_removed_elem_irrelevant':
  assumes "sort_ex cs (insert c s)"
  assumes "c ∉ (normalize_sort cs (insert c s))"
  shows "normalize_sort cs (insert c s) = normalize_sort cs s"
proof-
  have "class_ex cs c" using assms(1) by (auto simp add: sort_ex_class_ex)
  from this assms(2) obtain c' where "class_les cs c' c" "c' ∈ s"
    using class_les_irrefl by (auto simp add: normalize_sort_def)
  thus ?thesis 
    using ‹class_ex cs c› class_les_irrefl class_les_trans by (simp add: normalize_sort_def) blast
qed

corollary normalize_sort_removed_elem_irrelevant:
  assumes "sort_ex cs (insert c s)"
  assumes "c ∉ (normalize_sort cs (insert c s))"
  shows "normalize_sort cs (insert c s) = normalize_sort cs s"
  using assms normalize_sort_removed_elem_irrelevant' 
  by (simp add: normalize_sort_def)

lemma normalize_sort_nempt_is_nempty:
  assumes finite: "finite s"
  assumes nempty: "s ≠ full_sort"
  assumes "sort_ex cs s"
  shows "normalize_sort cs s ≠ full_sort"
using assms proof (induction s rule: finite_induct)
  case empty
  then show ?case by simp
next
  case (insert c s)
  note ICons = this
  then show ?case
  proof(cases s)
    case emptyI
    hence "normalize_sort cs (insert c s) = {c}"
      using insert class_les_irrefl by (auto simp add: normalize_sort_def sort_ex_class_ex)
    then show ?thesis by simp
  next
    case (insertI c' s')
    hence "normalize_sort cs s ≠ full_sort" 
      using ICons by (auto simp add: normalize_sort_def sort_ex_class_ex)
    then show ?thesis
    proof (cases "c ∈ (normalize_sort cs s)")
      case True
      hence "insert c s = s" 
        using normalized_sort_subset by fastforce
      then show ?thesis 
        using ICons by (auto simp add: normalize_sort_def sort_ex_class_ex class_les_def)
    next
      case False
      then show ?thesis 
        using normalize_sort_removed_elem_irrelevant
        using insert.prems(2) ICons(3) ‹normalize_sort cs s ≠ full_sort› by auto
    qed
  qed
qed

lemma choose_smaller_in_sort:
  assumes elem: "c ∈ s" and nelem: "c ∉ (normalize_sort cs s)" and "sort_ex cs s"
  obtains c' where "c' ∈ s" and "class_les cs c' c"
  using assms by (auto simp add: normalize_sort_def sort_ex_class_ex)

lemma normalize_ex_bound':
  assumes finite: "finite s" and elem: "c ∈ s" and nelem: "c ∉ (normalize_sort cs s)" 
    and "sort_ex cs s"
  shows "∃c' ∈ (normalize_sort cs s) . class_les cs c' c"
using assms proof (induction s arbitrary: c)
  case empty
  then show ?case by simp
next
  case (insert ic s)
  then show ?case
  proof(cases "ic=c")
    case True
    then show ?thesis
      by (smt (z3) choose_smaller_in_sort class_les_irrefl class_les_trans insert.IH insert.prems(2) 
          insert.prems(3) insert_iff insert_subset normalize_sort_removed_elem_irrelevant' sort_ex_def)
  next
    case False
    hence "c ∈ s" using insert.prems by simp
    then show ?thesis
    proof(cases "ic ∈ (normalize_sort cs (insert ic s))")
      case True
      then show ?thesis
      proof(cases "class_les cs ic c")
        case True
        then show ?thesis
          using insert ‹c ∈ s› normalize_sort_removed_elem_irrelevant' sort_ex_def
          by (metis insert_subset)
      next
        case False
        
        obtain c'' where c'': "c'' ∈ (normalize_sort cs s)" "class_les cs c'' c"
          using insert ‹c ∈ s› normalize_sort_removed_elem_irrelevant' sort_ex_def
          by (metis False choose_smaller_in_sort class_les_trans insert_iff insert_subset)
        moreover have "(c'', c) ∈ cs" "(c, c'') ∉ cs"
          using c'' by (simp_all add: class_leq_def class_les_def)
        moreover hence "¬ class_les cs ic c''"
          by (meson False class_leq_def class_les_def class_les_trans)

        ultimately show ?thesis 
          by (auto simp add: normalize_sort_def sort_ex_class_ex class_ex_def class_leq_def class_les_def)
      qed
    next
      case False
      then show ?thesis
        by (metis (full_types) insert.IH insert.prems(2) insert.prems(3) ‹c ∈ s› 
            normalize_sort_removed_elem_irrelevant sort_ex_def insert_subset)
    qed
  qed
qed

corollary normalize_ex_bound:
  assumes finite: "finite s" and elem: "c ∈ s" and nelem: "c ∉ (normalize_sort cs s)" 
    and "sort_ex cs s"
  obtains c' where "c' ∈ (normalize_sort cs s)" and "class_les cs c' c"
  using assms normalize_ex_bound' by auto

lemma "sort_ex cs s ⟹ sort_leq cs s (normalize_sort cs s)" 
  by (auto simp add: normalize_sort_def sort_leq_def sort_ex_class_ex)
lemma sort_eqv_normalize_sort:
  assumes "finite s"
  assumes "sort_ex cs s" 
  shows "sort_eqv cs s (normalize_sort cs s)"
proof (intro sort_eqvI)
  show "sort_leq cs s (normalize_sort cs s)" 
    using assms(2) by (auto simp add:  normalize_sort_def sort_leq_def sort_ex_class_ex)
next
  show "sort_leq cs (normalize_sort cs s) s"
  proof (unfold sort_leq_def; intro ballI)
    fix c2 assume "c2 ∈ s"
    show "∃c1 ∈ normalize_sort cs s. class_leq cs c1 c2"
    proof (cases "c2 ∈ normalize_sort cs s")
      case True
      then show ?thesis using ‹c2 ∈ s› assms sort_ex_class_ex by fast
    next
      case False
      from this obtain c' where "c' ∈ normalize_sort cs s" and "class_les cs c' c2" 
        using ‹c2 ∈ s› normalize_ex_bound assms by metis
      then show ?thesis using class_les_def by metis
    qed 
  qed
qed

lemma normalize_sort_eq_imp_sort_eqv: "sort_ex cs s1 ⟹ sort_ex cs s2 ⟹ finite s1 ⟹ finite s2
  ⟹ normalize_sort cs s1 = normalize_sort cs s2
  ⟹ sort_eqv cs s1 s2"
  by (metis sort_eqv_sym sort_eqv_trans wf_subclass_loc.sort_eqv_normalize_sort wf_subclass_loc_axioms)

lemma "class_leq cs c1 c2 ⟷ class_les cs c1 c2 ∨ (c1=c2 ∧ class_ex cs c1)"
  by (meson FieldI1 class_ex_def class_leq_antisym class_leq_def class_leq_refl class_les_def)

lemma sort_eqv_imp_normalize_sort_eq:
  assumes "sort_ex cs s1" "sort_ex cs s2" "sort_eqv cs s1 s2"
  shows "normalize_sort cs s1 = normalize_sort cs s2"
proof (rule ccontr)
  have "sort_leq cs s1 s2" "sort_leq cs s2 s1"
    using assms(3) by (auto simp add: sort_eqv_def)

  assume "normalize_sort cs s1 ≠ normalize_sort cs s2"
  hence "¬ normalize_sort cs s1 ⊆ normalize_sort cs s2 ∨ 
    ¬ normalize_sort cs s2 ⊆ normalize_sort cs s1"
    by simp
  from this consider "¬ normalize_sort cs s1 ⊆ normalize_sort cs s2"
    | "normalize_sort cs s1 ⊆ normalize_sort cs s2" 
      "¬ normalize_sort cs s2 ⊆ normalize_sort cs s1"
    by blast
  thus False
  proof cases
    case 1
    from this obtain c where c: "c ∈ normalize_sort cs s1" "c ∉ normalize_sort cs s2"
      by blast
    from this obtain c' where c': "c' ∈ normalize_sort cs s2" "class_les cs c' c"
      by (smt (z3) ‹sort_leq cs s1 s2› ‹sort_leq cs s2 s1› class_les_def mem_Collect_eq normalize_sort_def 
          sort_leq_def wf_subclass_loc.class_leq_antisym wf_subclass_loc.class_leq_trans wf_subclass_loc_axioms)
    then show ?thesis
    proof(cases "c' ∈ normalize_sort cs s1")
      case True
      hence "c ∉ normalize_sort cs s1"
        using c c' by (auto simp add: normalize_sort_def)
      then show ?thesis using c(1) by simp
    next
      case False
      from False c' obtain c'' where c'': "c'' ∈ normalize_sort cs s1" "class_les cs c'' c'"
      by (smt (z3) ‹sort_leq cs s1 s2› ‹sort_leq cs s2 s1› class_les_def mem_Collect_eq normalize_sort_def 
          sort_leq_def wf_subclass_loc.class_leq_antisym wf_subclass_loc.class_leq_trans wf_subclass_loc_axioms)
      hence "class_les cs c'' c"
        using c'(2) class_les_trans by blast
      hence "c ∉ normalize_sort cs s1"
        using c c'' by (auto simp add: normalize_sort_def)
      then show ?thesis using c(1) by simp
    qed
  next
    (* Should work analogous, let's see *)
    case 2
    from this obtain c where c: "c ∈ normalize_sort cs s2" "c ∉ normalize_sort cs s1"
      by blast
    from this obtain c' where c': "c' ∈ normalize_sort cs s1" "class_les cs c' c"
      by (smt (z3) ‹sort_leq cs s1 s2› ‹sort_leq cs s2 s1› class_les_def mem_Collect_eq normalize_sort_def 
          sort_leq_def wf_subclass_loc.class_leq_antisym wf_subclass_loc.class_leq_trans wf_subclass_loc_axioms)
    then show ?thesis
    proof(cases "c' ∈ normalize_sort cs s2")
      case True
      hence "c ∉ normalize_sort cs s2"
        using c c' by (auto simp add: normalize_sort_def)
      then show ?thesis using c(1) by simp
    next
      case False
      from False c' obtain c'' where c'':"c''∈ normalize_sort cs s2" "class_les cs c'' c'"
      by (smt (z3) ‹sort_leq cs s1 s2› ‹sort_leq cs s2 s1› class_les_def mem_Collect_eq normalize_sort_def 
          sort_leq_def wf_subclass_loc.class_leq_antisym wf_subclass_loc.class_leq_trans wf_subclass_loc_axioms)
      hence "class_les cs c'' c"
        using c'(2) class_les_trans by blast
      hence "c ∉ normalize_sort cs s2"
        using c c'' by (auto simp add: normalize_sort_def)
      then show ?thesis using c(1) by simp
    qed
  qed
qed

corollary sort_eqv_iff_normalize_sort_eq:
  assumes "finite s1" "finite s2"
  assumes "sort_ex cs s1" "sort_ex cs s2"
  shows "sort_eqv cs s1 s2 ⟷ normalize_sort cs s1 = normalize_sort cs s2"
using assms normalize_sort_eq_imp_sort_eqv sort_eqv_imp_normalize_sort_eq by blast

end

lemma tcsigs_sorts_defined: "wf_osig oss ⟹ 
  (∀ars ∈ ran (tcsigs oss) . ∀ss ∈ ran ars . ∀s ∈ set ss. sort_ex (subclass oss) s)"
  by (cases oss) (simp add: wf_sort_def all_normalized_and_ex_tcsigs_def)

lemma osig_subclass_loc: "wf_osig oss ⟹ wf_subclass_loc (subclass oss)"
  using wf_subclass_loc.intro by (cases oss) simp

lemma wf_osig_imp_wf_subclass_loc: "wf_osig oss ⟹ wf_subclass_loc (subclass oss)"
  by (cases oss) (simp add: wf_subclass_loc_def)

lemma has_sort_Tv_imp_sort_leq: "has_sort oss (Tv idn S) S' ⟹ sort_leq (subclass oss) S S'"
  by (auto simp add: has_sort.simps)

end