diff -r de505273c971 -r 00d4a435777f src/HOL/Bali/TypeRel.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Bali/TypeRel.thy Mon Jan 28 17:00:19 2002 +0100 @@ -0,0 +1,667 @@ +(* Title: isabelle/Bali/TypeRel.thy + ID: $Id$ + Author: David von Oheimb + Copyright 1997 Technische Universitaet Muenchen +*) +header {* The relations between Java types *} + +theory TypeRel = Decl: + +text {* +simplifications: +\begin{itemize} +\item subinterface, subclass and widening relation includes identity +\end{itemize} +improvements over Java Specification 1.0: +\begin{itemize} +\item narrowing reference conversion also in cases where the return types of a + pair of methods common to both types are in widening (rather identity) + relation +\item one could add similar constraints also for other cases +\end{itemize} +design issues: +\begin{itemize} +\item the type relations do not require @{text is_type} for their arguments +\item the subint1 and subcls1 relations imply @{text is_iface}/@{text is_class} + for their first arguments, which is required for their finiteness +\end{itemize} +*} + +consts + +(*subint1, in Decl.thy*)  (* direct subinterface *) +(*subint , by translation*)   (* subinterface (+ identity) *) +(*subcls1, in Decl.thy*)  (* direct subclass *) +(*subcls , by translation*)   (* subclass *) +(*subclseq, by translation*)  (* subclass + identity *) + implmt1 :: "prog \ (qtname \ qtname) set" (* direct implementation *) + implmt :: "prog \ (qtname \ qtname) set" (* implementation *) + widen :: "prog \ (ty \ ty ) set" (* widening *) + narrow :: "prog \ (ty \ ty ) set" (* narrowing *) + cast :: "prog \ (ty \ ty ) set"  (* casting *) + +syntax + + "@subint1" :: "prog => [qtname, qtname] => bool" ("_|-_<:I1_" [71,71,71] 70) + "@subint" :: "prog => [qtname, qtname] => bool" ("_|-_<=:I _"[71,71,71] 70) + (* Defined in Decl.thy: + "@subcls1" :: "prog => [qtname, qtname] => bool" ("_|-_<:C1_" [71,71,71] 70) + "@subclseq":: "prog => [qtname, qtname] => bool" ("_|-_<=:C _"[71,71,71] 70) + "@subcls" :: "prog => [qtname, qtname] => bool" ("_|-_<:C _"[71,71,71] 70) + *) + "@implmt1" :: "prog => [qtname, qtname] => bool" ("_|-_~>1_" [71,71,71] 70) + "@implmt" :: "prog => [qtname, qtname] => bool" ("_|-_~>_" [71,71,71] 70) + "@widen" :: "prog => [ty , ty ] => bool" ("_|-_<=:_" [71,71,71] 70) + "@narrow" :: "prog => [ty , ty ] => bool" ("_|-_:>_" [71,71,71] 70) + "@cast" :: "prog => [ty , ty ] => bool" ("_|-_<=:? _"[71,71,71] 70) + +syntax (symbols) + + "@subint1" :: "prog \ [qtname, qtname] \ bool" ("_\_\I1_" [71,71,71] 70) + "@subint" :: "prog \ [qtname, qtname] \ bool" ("_\_\I _" [71,71,71] 70) + (* Defined in Decl.thy: +\ "@subcls1" :: "prog \ [qtname, qtname] \ bool" ("_\_\\<^sub>C\<^sub>1_" [71,71,71] 70) + "@subclseq":: "prog \ [qtname, qtname] \ bool" ("_\_\\<^sub>C _" [71,71,71] 70) + "@subcls" :: "prog \ [qtname, qtname] \ bool" ("_\_\\<^sub>C _" [71,71,71] 70) + *) + "@implmt1" :: "prog \ [qtname, qtname] \ bool" ("_\_\1_" [71,71,71] 70) + "@implmt" :: "prog \ [qtname, qtname] \ bool" ("_\_\_" [71,71,71] 70) + "@widen" :: "prog \ [ty , ty ] \ bool" ("_\_\_" [71,71,71] 70) + "@narrow" :: "prog \ [ty , ty ] \ bool" ("_\_\_" [71,71,71] 70) + "@cast" :: "prog \ [ty , ty ] \ bool" ("_\_\? _" [71,71,71] 70) + +translations + + "G\I \I1 J" == "(I,J) \ subint1 G" + "G\I \I J" == "(I,J) \(subint1 G)^*" (* cf. 9.1.3 *) + (* Defined in Decl.thy: + "G\C \\<^sub>C\<^sub>1 D" == "(C,D) \ subcls1 G" + "G\C \\<^sub>C D" == "(C,D) \(subcls1 G)^*" + *) + "G\C \1 I" == "(C,I) \ implmt1 G" + "G\C \ I" == "(C,I) \ implmt G" + "G\S \ T" == "(S,T) \ widen G" + "G\S \ T" == "(S,T) \ narrow G" + "G\S \? T" == "(S,T) \ cast G" + + +section "subclass and subinterface relations" + + (* direct subinterface in Decl.thy, cf. 9.1.3 *) + (* direct subclass in Decl.thy, cf. 8.1.3 *) + +lemmas subcls_direct = subcls1I [THEN r_into_rtrancl, standard] + +lemma subcls_direct1: + "\class G C = Some c; C \ Object;D=super c\ \ G\C\\<^sub>C D" +apply (auto dest: subcls_direct) +done + +lemma subcls1I1: + "\class G C = Some c; C \ Object;D=super c\ \ G\C\\<^sub>C\<^sub>1 D" +apply (auto dest: subcls1I) +done + +lemma subcls_direct2: + "\class G C = Some c; C \ Object;D=super c\ \ G\C\\<^sub>C D" +apply (auto dest: subcls1I1) +done + +lemma subclseq_trans: "\G\A \\<^sub>C B; G\B \\<^sub>C C\ \ G\A \\<^sub>C C" +by (blast intro: rtrancl_trans) + +lemma subcls_trans: "\G\A \\<^sub>C B; G\B \\<^sub>C C\ \ G\A \\<^sub>C C" +by (blast intro: trancl_trans) + +lemma SXcpt_subcls_Throwable_lemma: +"\class G (SXcpt xn) = Some xc; + super xc = (if xn = Throwable then Object else SXcpt Throwable)\ +\ G\SXcpt xn\\<^sub>C SXcpt Throwable" +apply (case_tac "xn = Throwable") +apply simp_all +apply (drule subcls_direct) +apply (auto dest: sym) +done + +lemma subcls_ObjectI: "\is_class G C; ws_prog G\ \ G\C\\<^sub>C Object" +apply (erule ws_subcls1_induct) +apply clarsimp +apply (case_tac "C = Object") +apply (fast intro: r_into_rtrancl [THEN rtrancl_trans])+ +done + +lemma subclseq_ObjectD [dest!]: "G\Object\\<^sub>C C \ C = Object" +apply (erule rtrancl_induct) +apply (auto dest: subcls1D) +done + +lemma subcls_ObjectD [dest!]: "G\Object\\<^sub>C C \ False" +apply (erule trancl_induct) +apply (auto dest: subcls1D) +done + +lemma subcls_ObjectI1 [intro!]: + "\C \ Object;is_class G C;ws_prog G\ \ G\C \\<^sub>C Object" +apply (drule (1) subcls_ObjectI) +apply (auto intro: rtrancl_into_trancl3) +done + +lemma subcls_is_class: "(C,D) \ (subcls1 G)^+ \ is_class G C" +apply (erule trancl_trans_induct) +apply (auto dest!: subcls1D) +done + +lemma subcls_is_class2 [rule_format (no_asm)]: + "G\C\\<^sub>C D \ is_class G D \ is_class G C" +apply (erule rtrancl_induct) +apply (drule_tac [2] subcls1D) +apply auto +done + +lemma single_inheritance: +"\G\A \\<^sub>C\<^sub>1 B; G\A \\<^sub>C\<^sub>1 C\ \ B = C" +by (auto simp add: subcls1_def) + +lemma subcls_compareable: +"\G\A \\<^sub>C X; G\A \\<^sub>C Y + \ \ G\X \\<^sub>C Y \ G\Y \\<^sub>C X" +by (rule triangle_lemma) (auto intro: single_inheritance) + +lemma subcls1_irrefl: "\G\C \\<^sub>C\<^sub>1 D; ws_prog G \ + \ C \ D" +proof + assume ws: "ws_prog G" and + subcls1: "G\C \\<^sub>C\<^sub>1 D" and + eq_C_D: "C=D" + from subcls1 obtain c + where + neq_C_Object: "C\Object" and + clsC: "class G C = Some c" and + super_c: "super c = D" + by (auto simp add: subcls1_def) + with super_c subcls1 eq_C_D + have subcls_super_c_C: "G\super c \\<^sub>C C" + by auto + from ws clsC neq_C_Object + have "\ G\super c \\<^sub>C C" + by (auto dest: ws_prog_cdeclD) + from this subcls_super_c_C + show "False" + by (rule notE) +qed + +lemma no_subcls_Object: "G\C \\<^sub>C D \ C \ Object" +by (erule converse_trancl_induct) (auto dest: subcls1D) + +lemma subcls_acyclic: "\G\C \\<^sub>C D; ws_prog G\ \ \ G\D \\<^sub>C C" +proof - + assume ws: "ws_prog G" + assume subcls_C_D: "G\C \\<^sub>C D" + then show ?thesis + proof (induct rule: converse_trancl_induct) + fix C + assume subcls1_C_D: "G\C \\<^sub>C\<^sub>1 D" + then obtain c where + "C\Object" and + "class G C = Some c" and + "super c = D" + by (auto simp add: subcls1_def) + with ws + show "\ G\D \\<^sub>C C" + by (auto dest: ws_prog_cdeclD) + next + fix C Z + assume subcls1_C_Z: "G\C \\<^sub>C\<^sub>1 Z" and + subcls_Z_D: "G\Z \\<^sub>C D" and + nsubcls_D_Z: "\ G\D \\<^sub>C Z" + show "\ G\D \\<^sub>C C" + proof + assume subcls_D_C: "G\D \\<^sub>C C" + show "False" + proof - + from subcls_D_C subcls1_C_Z + have "G\D \\<^sub>C Z" + by (auto dest: r_into_trancl trancl_trans) + with nsubcls_D_Z + show ?thesis + by (rule notE) + qed + qed + qed +qed + +lemma subclseq_cases [consumes 1, case_names Eq Subcls]: + "\G\C \\<^sub>C D; C = D \ P; G\C \\<^sub>C D \ P\ \ P" +by (blast intro: rtrancl_cases) + +lemma subclseq_acyclic: + "\G\C \\<^sub>C D; G\D \\<^sub>C C; ws_prog G\ \ C=D" +by (auto elim: subclseq_cases dest: subcls_acyclic) + +lemma subcls_irrefl: "\G\C \\<^sub>C D; ws_prog G\ + \ C \ D" +proof - + assume ws: "ws_prog G" + assume subcls: "G\C \\<^sub>C D" + then show ?thesis + proof (induct rule: converse_trancl_induct) + fix C + assume "G\C \\<^sub>C\<^sub>1 D" + with ws + show "C\D" + by (blast dest: subcls1_irrefl) + next + fix C Z + assume subcls1_C_Z: "G\C \\<^sub>C\<^sub>1 Z" and + subcls_Z_D: "G\Z \\<^sub>C D" and + neq_Z_D: "Z \ D" + show "C\D" + proof + assume eq_C_D: "C=D" + show "False" + proof - + from subcls1_C_Z eq_C_D + have "G\D \\<^sub>C Z" + by (auto) + also + from subcls_Z_D ws + have "\ G\D \\<^sub>C Z" + by (rule subcls_acyclic) + ultimately + show ?thesis + by - (rule notE) + qed + qed + qed +qed + +lemma invert_subclseq: +"\G\C \\<^sub>C D; ws_prog G\ + \ \ G\D \\<^sub>C C" +proof - + assume ws: "ws_prog G" and + subclseq_C_D: "G\C \\<^sub>C D" + show ?thesis + proof (cases "D=C") + case True + with ws + show ?thesis + by (auto dest: subcls_irrefl) + next + case False + with subclseq_C_D + have "G\C \\<^sub>C D" + by (blast intro: rtrancl_into_trancl3) + with ws + show ?thesis + by (blast dest: subcls_acyclic) + qed +qed + +lemma invert_subcls: +"\G\C \\<^sub>C D; ws_prog G\ + \ \ G\D \\<^sub>C C" +proof - + assume ws: "ws_prog G" and + subcls_C_D: "G\C \\<^sub>C D" + then + have nsubcls_D_C: "\ G\D \\<^sub>C C" + by (blast dest: subcls_acyclic) + show ?thesis + proof + assume "G\D \\<^sub>C C" + then show "False" + proof (cases rule: subclseq_cases) + case Eq + with ws subcls_C_D + show ?thesis + by (auto dest: subcls_irrefl) + next + case Subcls + with nsubcls_D_C + show ?thesis + by blast + qed + qed +qed + +lemma subcls_superD: + "\G\C \\<^sub>C D; class G C = Some c\ \ G\(super c) \\<^sub>C D" +proof - + assume clsC: "class G C = Some c" + assume subcls_C_C: "G\C \\<^sub>C D" + then obtain S where + "G\C \\<^sub>C\<^sub>1 S" and + subclseq_S_D: "G\S \\<^sub>C D" + by (blast dest: tranclD) + with clsC + have "S=super c" + by (auto dest: subcls1D) + with subclseq_S_D show ?thesis by simp +qed + + +lemma subclseq_superD: + "\G\C \\<^sub>C D; C\D;class G C = Some c\ \ G\(super c) \\<^sub>C D" +proof - + assume neq_C_D: "C\D" + assume clsC: "class G C = Some c" + assume subclseq_C_D: "G\C \\<^sub>C D" + then show ?thesis + proof (cases rule: subclseq_cases) + case Eq with neq_C_D show ?thesis by contradiction + next + case Subcls + with clsC show ?thesis by (blast dest: subcls_superD) + qed +qed + +section "implementation relation" + +defs + (* direct implementation, cf. 8.1.3 *) +implmt1_def:"implmt1 G\{(C,I). C\Object \ (\c\class G C: I\set (superIfs c))}" + +lemma implmt1D: "G\C\1I \ C\Object \ (\c\class G C: I\set (superIfs c))" +apply (unfold implmt1_def) +apply auto +done + + +inductive "implmt G" intros (* cf. 8.1.4 *) + + direct: "G\C\1J \\ \ G\C\J" + subint: "\G\C\1I; G\I\I J\ \ G\C\J" + subcls1: "\G\C\\<^sub>C\<^sub>1D; G\D\J \ \ G\C\J" + +lemma implmtD: "G\C\J \ (\I. G\C\1I \ G\I\I J) \ (\D. G\C\\<^sub>C\<^sub>1D \ G\D\J)" +apply (erule implmt.induct) +apply fast+ +done + +lemma implmt_ObjectE [elim!]: "G\Object\I \ R" +by (auto dest!: implmtD implmt1D subcls1D) + +lemma subcls_implmt [rule_format (no_asm)]: "G\A\\<^sub>C B \ G\B\K \ G\A\K" +apply (erule rtrancl_induct) +apply (auto intro: implmt.subcls1) +done + +lemma implmt_subint2: "\ G\A\J; G\J\I K\ \ G\A\K" +apply (erule make_imp, erule implmt.induct) +apply (auto dest: implmt.subint rtrancl_trans implmt.subcls1) +done + +lemma implmt_is_class: "G\C\I \ is_class G C" +apply (erule implmt.induct) +apply (blast dest: implmt1D subcls1D)+ +done + + +section "widening relation" + +inductive "widen G" intros(*widening, viz. method invocation conversion, cf. 5.3 + i.e. kind of syntactic subtyping *) + refl: "G\T\T"(*identity conversion, cf. 5.1.1 *) + subint: "G\I\I J \ G\Iface I\ Iface J"(*wid.ref.conv.,cf. 5.1.4 *) + int_obj: "G\Iface I\ Class Object" + subcls: "G\C\\<^sub>C D \ G\Class C\ Class D" + implmt: "G\C\I \ G\Class C\ Iface I" + null: "G\NT\ RefT R" + arr_obj: "G\T.[]\ Class Object" + array: "G\RefT S\RefT T \ G\RefT S.[]\ RefT T.[]" + +declare widen.refl [intro!] +declare widen.intros [simp] + +(* too strong in general: +lemma widen_PrimT: "G\PrimT x\T \ T = PrimT x" +*) +lemma widen_PrimT: "G\PrimT x\T \ (\y. T = PrimT y)" +apply (ind_cases "G\S\T") +by auto + +(* too strong in general: +lemma widen_PrimT2: "G\S\PrimT x \ S = PrimT x" +*) +lemma widen_PrimT2: "G\S\PrimT x \ \y. S = PrimT y" +apply (ind_cases "G\S\T") +by auto + +lemma widen_RefT: "G\RefT R\T \ \t. T=RefT t" +apply (ind_cases "G\S\T") +by auto + +lemma widen_RefT2: "G\S\RefT R \ \t. S=RefT t" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Iface: "G\Iface I\T \ T=Class Object \ (\J. T=Iface J)" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Iface2: "G\S\ Iface J \ S = NT \ (\I. S = Iface I) \ (\D. S = Class D)" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Iface_Iface: "G\Iface I\ Iface J \ G\I\I J" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Iface_Iface_eq [simp]: "G\Iface I\ Iface J = G\I\I J" +apply (rule iffI) +apply (erule widen_Iface_Iface) +apply (erule widen.subint) +done + +lemma widen_Class: "G\Class C\T \ (\D. T=Class D) \ (\I. T=Iface I)" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Class2: "G\S\ Class C \ C = Object \ S = NT \ (\D. S = Class D)" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Class_Class: "G\Class C\ Class cm \ G\C\\<^sub>C cm" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Class_Class_eq [simp]: "G\Class C\ Class cm = G\C\\<^sub>C cm" +apply (rule iffI) +apply (erule widen_Class_Class) +apply (erule widen.subcls) +done + +lemma widen_Class_Iface: "G\Class C\ Iface I \ G\C\I" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Class_Iface_eq [simp]: "G\Class C\ Iface I = G\C\I" +apply (rule iffI) +apply (erule widen_Class_Iface) +apply (erule widen.implmt) +done + +lemma widen_Array: "G\S.[]\T \ T=Class Object \ (\T'. T=T'.[] \ G\S\T')" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Array2: "G\S\T.[] \ S = NT \ (\S'. S=S'.[] \ G\S'\T)" +apply (ind_cases "G\S\T") +by auto + + +lemma widen_ArrayPrimT: "G\PrimT t.[]\T \ T=Class Object \ T=PrimT t.[]" +apply (ind_cases "G\S\T") +by auto + +lemma widen_ArrayRefT: + "G\RefT t.[]\T \ T=Class Object \ (\s. T=RefT s.[] \ G\RefT t\RefT s)" +apply (ind_cases "G\S\T") +by auto + +lemma widen_ArrayRefT_ArrayRefT_eq [simp]: + "G\RefT T.[]\RefT T'.[] = G\RefT T\RefT T'" +apply (rule iffI) +apply (drule widen_ArrayRefT) +apply simp +apply (erule widen.array) +done + +lemma widen_Array_Array: "G\T.[]\T'.[] \ G\T\T'" +apply (drule widen_Array) +apply auto +done + +lemma widen_Array_Class: "G\S.[] \ Class C \ C=Object" +by (auto dest: widen_Array) + +(* +qed_typerel "widen_NT2" "G\S\NT \ S = NT" + [prove_widen_lemma "G\S\T \ T = NT \ S = NT"] +*) +lemma widen_NT2: "G\S\NT \ S = NT" +apply (ind_cases "G\S\T") +by auto + +lemma widen_Object:"\isrtype G T;ws_prog G\ \ G\RefT T \ Class Object" +apply (case_tac T) +apply (auto) +apply (subgoal_tac "G\pid_field_type\\<^sub>C Object") +apply (auto intro: subcls_ObjectI) +done + +lemma widen_trans_lemma [rule_format (no_asm)]: + "\G\S\U; \C. is_class G C \ G\C\\<^sub>C Object\ \ \T. G\U\T \ G\S\T" +apply (erule widen.induct) +apply safe +prefer 5 apply (drule widen_RefT) apply clarsimp +apply (frule_tac [1] widen_Iface) +apply (frule_tac [2] widen_Class) +apply (frule_tac [3] widen_Class) +apply (frule_tac [4] widen_Iface) +apply (frule_tac [5] widen_Class) +apply (frule_tac [6] widen_Array) +apply safe +apply (rule widen.int_obj) +prefer 6 apply (drule implmt_is_class) apply simp +apply (tactic "ALLGOALS (etac thin_rl)") +prefer 6 apply simp +apply (rule_tac [9] widen.arr_obj) +apply (rotate_tac [9] -1) +apply (frule_tac [9] widen_RefT) +apply (auto elim!: rtrancl_trans subcls_implmt implmt_subint2) +done + +lemma ws_widen_trans: "\G\S\U; G\U\T; ws_prog G\ \ G\S\T" +by (auto intro: widen_trans_lemma subcls_ObjectI) + +lemma widen_antisym_lemma [rule_format (no_asm)]: "\G\S\T; + \I J. G\I\I J \ G\J\I I \ I = J; + \C D. G\C\\<^sub>C D \ G\D\\<^sub>C C \ C = D; + \I . G\Object\I \ False\ \ G\T\S \ S = T" +apply (erule widen.induct) +apply (auto dest: widen_Iface widen_NT2 widen_Class) +done + +lemmas subint_antisym = + subint1_acyclic [THEN acyclic_impl_antisym_rtrancl, standard] +lemmas subcls_antisym = + subcls1_acyclic [THEN acyclic_impl_antisym_rtrancl, standard] + +lemma widen_antisym: "\G\S\T; G\T\S; ws_prog G\ \ S=T" +by (fast elim: widen_antisym_lemma subint_antisym [THEN antisymD] + subcls_antisym [THEN antisymD]) + +lemma widen_ObjectD [dest!]: "G\Class Object\T \ T=Class Object" +apply (frule widen_Class) +apply (fast dest: widen_Class_Class widen_Class_Iface) +done + +constdefs + widens :: "prog \ [ty list, ty list] \ bool" ("_\_[\]_" [71,71,71] 70) + "G\Ts[\]Ts' \ list_all2 (\T T'. G\T\T') Ts Ts'" + +lemma widens_Nil [simp]: "G\[][\][]" +apply (unfold widens_def) +apply auto +done + +lemma widens_Cons [simp]: "G\(S#Ss)[\](T#Ts) = (G\S\T \ G\Ss[\]Ts)" +apply (unfold widens_def) +apply auto +done + + +section "narrowing relation" + +(* all properties of narrowing and casting conversions we actually need *) +(* these can easily be proven from the definitions below *) +(* +rules + cast_RefT2 "G\S\? RefT R \ \t. S=RefT t" + cast_PrimT2 "G\S\? PrimT pt \ \t. S=PrimT t \ G\PrimT t\PrimT pt" +*) + +(* more detailed than necessary for type-safety, see above rules. *) +inductive "narrow G" intros (* narrowing reference conversion, cf. 5.1.5 *) + + subcls: "G\C\\<^sub>C D \ G\ Class D\Class C" + implmt: "\G\C\I \ G\ Class C\Iface I" + obj_arr: "G\Class Object\T.[]" + int_cls: "G\ Iface I\Class C" + subint: "imethds G I hidings imethds G J entails + (\(md, mh ) (md',mh').\G\mrt mh\mrt mh') \ + \G\I\I J \\\\ G\ Iface I\Iface J" + array: "G\RefT S\RefT T \\ G\ RefT S.[]\RefT T.[]" + +(*unused*) +lemma narrow_RefT: "G\RefT R\T \ \t. T=RefT t" +apply (ind_cases "G\S\T") +by auto + +lemma narrow_RefT2: "G\S\RefT R \ \t. S=RefT t" +apply (ind_cases "G\S\T") +by auto + +(*unused*) +lemma narrow_PrimT: "G\PrimT pt\T \ \t. T=PrimT t" +apply (ind_cases "G\S\T") +by auto + +lemma narrow_PrimT2: "G\S\PrimT pt \ + \t. S=PrimT t \ G\PrimT t\PrimT pt" +apply (ind_cases "G\S\T") +by auto + + +section "casting relation" + +inductive "cast G" intros (* casting conversion, cf. 5.5 *) + + widen: "G\S\T \ G\S\? T" + narrow: "G\S\T \ G\S\? T" + +(* +lemma ??unknown??: "\G\S\T; G\S\T\ \ R" + deferred *) + +(*unused*) +lemma cast_RefT: "G\RefT R\? T \ \t. T=RefT t" +apply (ind_cases "G\S\? T") +by (auto dest: widen_RefT narrow_RefT) + +lemma cast_RefT2: "G\S\? RefT R \ \t. S=RefT t" +apply (ind_cases "G\S\? T") +by (auto dest: widen_RefT2 narrow_RefT2) + +(*unused*) +lemma cast_PrimT: "G\PrimT pt\? T \ \t. T=PrimT t" +apply (ind_cases "G\S\? T") +by (auto dest: widen_PrimT narrow_PrimT) + +lemma cast_PrimT2: "G\S\? PrimT pt \ \t. S=PrimT t \ G\PrimT t\PrimT pt" +apply (ind_cases "G\S\? T") +by (auto dest: widen_PrimT2 narrow_PrimT2) + +end