diff -r de505273c971 -r 00d4a435777f src/HOL/Bali/DeclConcepts.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Bali/DeclConcepts.thy Mon Jan 28 17:00:19 2002 +0100 @@ -0,0 +1,2540 @@ +header {* Advanced concepts on Java declarations like overriding, inheritance, +dynamic method lookup*} + +theory DeclConcepts = TypeRel: + +section "access control (cf. 6.6), overriding and hiding (cf. 8.4.6.1)" + +constdefs +is_public :: "prog \ qtname \ bool" +"is_public G qn \ (case class G qn of + None \ (case iface G qn of + None \ False + | Some iface \ access iface = Public) + | Some class \ access class = Public)" + +subsection "accessibility of types (cf. 6.6.1)" +text {* +Primitive types are always accessible, interfaces and classes are accessible +in their package or if they are defined public, an array type is accessible if +its element type is accessible *} + +consts accessible_in :: "prog \ ty \ pname \ bool" + ("_ \ _ accessible'_in _" [61,61,61] 60) + rt_accessible_in:: "prog \ ref_ty \ pname \ bool" + ("_ \ _ accessible'_in' _" [61,61,61] 60) +primrec +"G\(PrimT p) accessible_in pack = True" +accessible_in_RefT_simp: +"G\(RefT r) accessible_in pack = G\r accessible_in' pack" + +"G\(NullT) accessible_in' pack = True" +"G\(IfaceT I) accessible_in' pack = ((pid I = pack) \ is_public G I)" +"G\(ClassT C) accessible_in' pack = ((pid C = pack) \ is_public G C)" +"G\(ArrayT ty) accessible_in' pack = G\ty accessible_in pack" + +declare accessible_in_RefT_simp [simp del] + +constdefs + is_acc_class :: "prog \ pname \ qtname \ bool" + "is_acc_class G P C \ is_class G C \ G\(Class C) accessible_in P" + is_acc_iface :: "prog \ pname \ qtname \ bool" + "is_acc_iface G P I \ is_iface G I \ G\(Iface I) accessible_in P" + is_acc_type :: "prog \ pname \ ty \ bool" + "is_acc_type G P T \ is_type G T \ G\T accessible_in P" + is_acc_reftype :: "prog \ pname \ ref_ty \ bool" + "is_acc_reftype G P T \ isrtype G T \ G\T accessible_in' P" + +lemma is_acc_classD: + "is_acc_class G P C \ is_class G C \ G\(Class C) accessible_in P" +by (simp add: is_acc_class_def) + +lemma is_acc_class_is_class: "is_acc_class G P C \ is_class G C" +by (auto simp add: is_acc_class_def) + +lemma is_acc_ifaceD: + "is_acc_iface G P I \ is_iface G I \ G\(Iface I) accessible_in P" +by (simp add: is_acc_iface_def) + +lemma is_acc_typeD: + "is_acc_type G P T \ is_type G T \ G\T accessible_in P" +by (simp add: is_acc_type_def) + +lemma is_acc_reftypeD: +"is_acc_reftype G P T \ isrtype G T \ G\T accessible_in' P" +by (simp add: is_acc_reftype_def) + +subsection "accessibility of members" +text {* +The accessibility of members is more involved as the accessibility of types. +We have to distinguish several cases to model the different effects of +accessibility during inheritance, overriding and ordinary member access +*} + +subsubsection {* Various technical conversion and selection functions *} + +text {* overloaded selector @{text accmodi} to select the access modifier +out of various HOL types *} + +axclass has_accmodi < "type" +consts accmodi:: "'a::has_accmodi \ acc_modi" + +instance acc_modi::has_accmodi +by (intro_classes) + +defs (overloaded) +acc_modi_accmodi_def: "accmodi (a::acc_modi) \ a" + +lemma acc_modi_accmodi_simp[simp]: "accmodi (a::acc_modi) = a" +by (simp add: acc_modi_accmodi_def) + +instance access_field_type:: ("type","type") has_accmodi +by (intro_classes) + +defs (overloaded) +decl_acc_modi_def: "accmodi (d::('a:: type) decl_scheme) \ access d" + + +lemma decl_acc_modi_simp[simp]: "accmodi (d::('a::type) decl_scheme) = access d" +by (simp add: decl_acc_modi_def) + +instance * :: ("type",has_accmodi) has_accmodi +by (intro_classes) + +defs (overloaded) +pair_acc_modi_def: "accmodi p \ (accmodi (snd p))" + +lemma pair_acc_modi_simp[simp]: "accmodi (x,a) = (accmodi a)" +by (simp add: pair_acc_modi_def) + +instance memberdecl :: has_accmodi +by (intro_classes) + +defs (overloaded) +memberdecl_acc_modi_def: "accmodi m \ (case m of + fdecl f \ accmodi f + | mdecl m \ accmodi m)" + +lemma memberdecl_fdecl_acc_modi_simp[simp]: + "accmodi (fdecl m) = accmodi m" +by (simp add: memberdecl_acc_modi_def) + +lemma memberdecl_mdecl_acc_modi_simp[simp]: + "accmodi (mdecl m) = accmodi m" +by (simp add: memberdecl_acc_modi_def) + +text {* overloaded selector @{text declclass} to select the declaring class +out of various HOL types *} + +axclass has_declclass < "type" +consts declclass:: "'a::has_declclass \ qtname" + +instance pid_field_type::("type","type") has_declclass +by (intro_classes) + +defs (overloaded) +qtname_declclass_def: "declclass (q::qtname) \ q" + +lemma qtname_declclass_simp[simp]: "declclass (q::qtname) = q" +by (simp add: qtname_declclass_def) + +instance * :: ("has_declclass","type") has_declclass +by (intro_classes) + +defs (overloaded) +pair_declclass_def: "declclass p \ declclass (fst p)" + +lemma pair_declclass_simp[simp]: "declclass (c,x) = declclass c" +by (simp add: pair_declclass_def) + +text {* overloaded selector @{text is_static} to select the static modifier +out of various HOL types *} + + +axclass has_static < "type" +consts is_static :: "'a::has_static \ bool" + +(* +consts is_static :: "'a \ bool" +*) + +instance access_field_type :: ("type","has_static") has_static +by (intro_classes) + +defs (overloaded) +decl_is_static_def: + "is_static (m::('a::has_static) decl_scheme) \ is_static (Decl.decl.more m)" + +instance static_field_type :: ("type","type") has_static +by (intro_classes) + +defs (overloaded) +static_field_type_is_static_def: + "is_static (m::(bool,'b::type) static_field_type) \ static_val m" + +lemma member_is_static_simp: "is_static (m::'a member_scheme) = static m" +apply (cases m) +apply (simp add: static_field_type_is_static_def + decl_is_static_def Decl.member.dest_convs) +done + +instance * :: ("type","has_static") has_static +by (intro_classes) + +defs (overloaded) +pair_is_static_def: "is_static p \ is_static (snd p)" + +lemma pair_is_static_simp [simp]: "is_static (x,s) = is_static s" +by (simp add: pair_is_static_def) + +lemma pair_is_static_simp1: "is_static p = is_static (snd p)" +by (simp add: pair_is_static_def) + +instance memberdecl:: has_static +by (intro_classes) + +defs (overloaded) +memberdecl_is_static_def: + "is_static m \ (case m of + fdecl f \ is_static f + | mdecl m \ is_static m)" + +lemma memberdecl_is_static_fdecl_simp[simp]: + "is_static (fdecl f) = is_static f" +by (simp add: memberdecl_is_static_def) + +lemma memberdecl_is_static_mdecl_simp[simp]: + "is_static (mdecl m) = is_static m" +by (simp add: memberdecl_is_static_def) + +lemma mhead_static_simp [simp]: "is_static (mhead m) = is_static m" +by (cases m) (simp add: mhead_def member_is_static_simp) + +constdefs (* some mnemotic selectors for (qtname \ ('a::more) decl_scheme) + * the first component is a class or interface name + * the second component is a method, field or method head *) +(* "declclass":: "(qtname \ ('a::more) decl_scheme) \ qtname"*) +(* "declclass \ fst" *) (* get the class component *) + + "decliface":: "(qtname \ ('a::type) decl_scheme) \ qtname" + "decliface \ fst" (* get the interface component *) + +(* + "member":: "(qtname \ ('a::type) decl_scheme) \ ('a::type) decl_scheme" +*) + "mbr":: "(qtname \ memberdecl) \ memberdecl" + "mbr \ snd" (* get the memberdecl component *) + + "mthd":: "('b \ 'a) \ 'a" + (* also used for mdecl,mhead *) + "mthd \ snd" (* get the method component *) + + "fld":: "('b \ ('a::type) decl_scheme) \ ('a::type) decl_scheme" + (* also used for ((vname \ qtname)\ field) *) + "fld \ snd" (* get the field component *) + +(* "accmodi" :: "('b \ ('a::type) decl_scheme) \ acc_modi"*) + (* also used for mdecl *) +(* "accmodi \ access \ snd"*) (* get the access modifier *) +(* + "is_static" ::"('b \ ('a::type) member_scheme) \ bool" *) + (* also defined for emhead cf. WellType *) + (*"is_static \ static \ snd"*) (* get the static modifier *) + +constdefs (* some mnemotic selectors for (vname \ qtname) *) + fname:: "(vname \ 'a) \ vname" (* also used for fdecl *) + "fname \ fst" + + declclassf:: "(vname \ qtname) \ qtname" + "declclassf \ snd" + +(* +lemma declclass_simp[simp]: "declclass (C,m) = C" +by (simp add: declclass_def) +*) + +lemma decliface_simp[simp]: "decliface (I,m) = I" +by (simp add: decliface_def) + +lemma mbr_simp[simp]: "mbr (C,m) = m" +by (simp add: mbr_def) + +lemma access_mbr_simp [simp]: "(accmodi (mbr m)) = accmodi m" +by (cases m) (simp add: mbr_def) + +lemma mthd_simp[simp]: "mthd (C,m) = m" +by (simp add: mthd_def) + +lemma fld_simp[simp]: "fld (C,f) = f" +by (simp add: fld_def) + +lemma accmodi_simp[simp]: "accmodi (C,m) = access m" +by (simp ) + +lemma access_mthd_simp [simp]: "(access (mthd m)) = accmodi m" +by (cases m) (simp add: mthd_def) + +lemma access_fld_simp [simp]: "(access (fld f)) = accmodi f" +by (cases f) (simp add: fld_def) + +(* +lemma is_static_simp[simp]: "is_static (C,m) = static m" +by (simp add: is_static_def) +*) + +lemma static_mthd_simp[simp]: "static (mthd m) = is_static m" +by (cases m) (simp add: mthd_def member_is_static_simp) + +lemma mthd_is_static_simp [simp]: "is_static (mthd m) = is_static m" +by (cases m) simp + +lemma static_fld_simp[simp]: "static (fld f) = is_static f" +by (cases f) (simp add: fld_def member_is_static_simp) + +lemma ext_field_simp [simp]: "(declclass f,fld f) = f" +by (cases f) (simp add: fld_def) + +lemma ext_method_simp [simp]: "(declclass m,mthd m) = m" +by (cases m) (simp add: mthd_def) + +lemma ext_mbr_simp [simp]: "(declclass m,mbr m) = m" +by (cases m) (simp add: mbr_def) + +lemma fname_simp[simp]:"fname (n,c) = n" +by (simp add: fname_def) + +lemma declclassf_simp[simp]:"declclassf (n,c) = c" +by (simp add: declclassf_def) + +constdefs (* some mnemotic selectors for (vname \ qtname) *) + "fldname" :: "(vname \ qtname) \ vname" + "fldname \ fst" + + "fldclass" :: "(vname \ qtname) \ qtname" + "fldclass \ snd" + +lemma fldname_simp[simp]: "fldname (n,c) = n" +by (simp add: fldname_def) + +lemma fldclass_simp[simp]: "fldclass (n,c) = c" +by (simp add: fldclass_def) + +lemma ext_fieldname_simp[simp]: "(fldname f,fldclass f) = f" +by (simp add: fldname_def fldclass_def) + +text {* Convert a qualified method declaration (qualified with its declaring +class) to a qualified member declaration: @{text methdMembr} *} + +constdefs +methdMembr :: "(qtname \ mdecl) \ (qtname \ memberdecl)" + "methdMembr m \ (fst m,mdecl (snd m))" + +lemma methdMembr_simp[simp]: "methdMembr (c,m) = (c,mdecl m)" +by (simp add: methdMembr_def) + +lemma accmodi_methdMembr_simp[simp]: "accmodi (methdMembr m) = accmodi m" +by (cases m) (simp add: methdMembr_def) + +lemma is_static_methdMembr_simp[simp]: "is_static (methdMembr m) = is_static m" +by (cases m) (simp add: methdMembr_def) + +lemma declclass_methdMembr_simp[simp]: "declclass (methdMembr m) = declclass m" +by (cases m) (simp add: methdMembr_def) + +text {* Convert a qualified method (qualified with its declaring +class) to a qualified member declaration: @{text method} *} + +constdefs +method :: "sig \ (qtname \ methd) \ (qtname \ memberdecl)" +"method sig m \ (declclass m, mdecl (sig, mthd m))" + +lemma method_simp[simp]: "method sig (C,m) = (C,mdecl (sig,m))" +by (simp add: method_def) + +lemma accmodi_method_simp[simp]: "accmodi (method sig m) = accmodi m" +by (simp add: method_def) + +lemma declclass_method_simp[simp]: "declclass (method sig m) = declclass m" +by (simp add: method_def) + +lemma is_static_method_simp[simp]: "is_static (method sig m) = is_static m" +by (cases m) (simp add: method_def) + +lemma mbr_method_simp[simp]: "mbr (method sig m) = mdecl (sig,mthd m)" +by (simp add: mbr_def method_def) + +lemma memberid_method_simp[simp]: "memberid (method sig m) = mid sig" + by (simp add: method_def) + +constdefs +fieldm :: "vname \ (qtname \ field) \ (qtname \ memberdecl)" +"fieldm n f \ (declclass f, fdecl (n, fld f))" + +lemma fieldm_simp[simp]: "fieldm n (C,f) = (C,fdecl (n,f))" +by (simp add: fieldm_def) + +lemma accmodi_fieldm_simp[simp]: "accmodi (fieldm n f) = accmodi f" +by (simp add: fieldm_def) + +lemma declclass_fieldm_simp[simp]: "declclass (fieldm n f) = declclass f" +by (simp add: fieldm_def) + +lemma is_static_fieldm_simp[simp]: "is_static (fieldm n f) = is_static f" +by (cases f) (simp add: fieldm_def) + +lemma mbr_fieldm_simp[simp]: "mbr (fieldm n f) = fdecl (n,fld f)" +by (simp add: mbr_def fieldm_def) + +lemma memberid_fieldm_simp[simp]: "memberid (fieldm n f) = fid n" +by (simp add: fieldm_def) + +text {* Select the signature out of a qualified method declaration: + @{text msig} *} + +constdefs msig:: "(qtname \ mdecl) \ sig" +"msig m \ fst (snd m)" + +lemma msig_simp[simp]: "msig (c,(s,m)) = s" +by (simp add: msig_def) + +text {* Convert a qualified method (qualified with its declaring +class) to a qualified method declaration: @{text qmdecl} *} + +constdefs qmdecl :: "sig \ (qtname \ methd) \ (qtname \ mdecl)" +"qmdecl sig m \ (declclass m, (sig,mthd m))" + +lemma qmdecl_simp[simp]: "qmdecl sig (C,m) = (C,(sig,m))" +by (simp add: qmdecl_def) + +lemma declclass_qmdecl_simp[simp]: "declclass (qmdecl sig m) = declclass m" +by (simp add: qmdecl_def) + +lemma accmodi_qmdecl_simp[simp]: "accmodi (qmdecl sig m) = accmodi m" +by (simp add: qmdecl_def) + +lemma is_static_qmdecl_simp[simp]: "is_static (qmdecl sig m) = is_static m" +by (cases m) (simp add: qmdecl_def) + +lemma msig_qmdecl_simp[simp]: "msig (qmdecl sig m) = sig" +by (simp add: qmdecl_def) + +lemma mdecl_qmdecl_simp[simp]: + "mdecl (mthd (qmdecl sig new)) = mdecl (sig, mthd new)" +by (simp add: qmdecl_def) + +lemma methdMembr_qmdecl_simp [simp]: + "methdMembr (qmdecl sig old) = method sig old" +by (simp add: methdMembr_def qmdecl_def method_def) + +text {* overloaded selector @{text resTy} to select the result type +out of various HOL types *} + +axclass has_resTy < "type" +consts resTy:: "'a::has_resTy \ ty" + +instance access_field_type :: ("type","has_resTy") has_resTy +by (intro_classes) + +defs (overloaded) +decl_resTy_def: + "resTy (m::('a::has_resTy) decl_scheme) \ resTy (Decl.decl.more m)" + +instance static_field_type :: ("type","has_resTy") has_resTy +by (intro_classes) + +defs (overloaded) +static_field_type_resTy_def: + "resTy (m::(bool,'b::has_resTy) static_field_type) + \ resTy (static_more m)" + +instance pars_field_type :: ("type","has_resTy") has_resTy +by (intro_classes) + +defs (overloaded) +pars_field_type_resTy_def: + "resTy (m::(vname list,'b::has_resTy) pars_field_type) + \ resTy (pars_more m)" + +instance resT_field_type :: ("type","type") has_resTy +by (intro_classes) + +defs (overloaded) +resT_field_type_resTy_def: + "resTy (m::(ty,'b::type) resT_field_type) + \ resT_val m" + +lemma mhead_resTy_simp: "resTy (m::'a mhead_scheme) = resT m" +apply (cases m) +apply (simp add: decl_resTy_def static_field_type_resTy_def + pars_field_type_resTy_def resT_field_type_resTy_def + member.dest_convs mhead.dest_convs) +done + +lemma resTy_mhead [simp]:"resTy (mhead m) = resTy m" +by (simp add: mhead_def mhead_resTy_simp) + +instance * :: ("type","has_resTy") has_resTy +by (intro_classes) + +defs (overloaded) +pair_resTy_def: "resTy p \ resTy (snd p)" + +lemma pair_resTy_simp[simp]: "resTy (x,m) = resTy m" +by (simp add: pair_resTy_def) + +lemma qmdecl_resTy_simp [simp]: "resTy (qmdecl sig m) = resTy m" +by (cases m) (simp) + +lemma resTy_mthd [simp]:"resTy (mthd m) = resTy m" +by (cases m) (simp add: mthd_def ) + +subsubsection "inheritable-in" +text {* +@{text "G\m inheritable_in P"}: m can be inherited by +classes in package P if: +\begin{itemize} +\item the declaration class of m is accessible in P and +\item the member m is declared with protected or public access or if it is + declared with default (package) access, the package of the declaration + class of m is also P. If the member m is declared with private access + it is not accessible for inheritance at all. +\end{itemize} +*} +constdefs +inheritable_in:: + "prog \ (qtname \ memberdecl) \ pname \ bool" + ("_ \ _ inheritable'_in _" [61,61,61] 60) +"G\membr inheritable_in pack + \ (case (accmodi membr) of + Private \ False + | Package \ (pid (declclass membr)) = pack + | Protected \ True + | Public \ True)" + +syntax +Method_inheritable_in:: + "prog \ (qtname \ mdecl) \ pname \ bool" + ("_ \Method _ inheritable'_in _ " [61,61,61] 60) + +translations +"G\Method m inheritable_in p" == "G\methdMembr m inheritable_in p" + +syntax +Methd_inheritable_in:: + "prog \ sig \ (qtname \ methd) \ pname \ bool" + ("_ \Methd _ _ inheritable'_in _ " [61,61,61,61] 60) + +translations +"G\Methd s m inheritable_in p" == "G\(method s m) inheritable_in p" + +subsubsection "declared-in/undeclared-in" + +constdefs cdeclaredmethd:: "prog \ qtname \ (sig,methd) table" +"cdeclaredmethd G C + \ (case class G C of + None \ \ sig. None + | Some c \ table_of (methods c) + )" + +constdefs +cdeclaredfield:: "prog \ qtname \ (vname,field) table" +"cdeclaredfield G C + \ (case class G C of + None \ \ sig. None + | Some c \ table_of (cfields c) + )" + + +constdefs +declared_in:: "prog \ memberdecl \ qtname \ bool" + ("_\ _ declared'_in _" [61,61,61] 60) +"G\m declared_in C \ (case m of + fdecl (fn,f ) \ cdeclaredfield G C fn = Some f + | mdecl (sig,m) \ cdeclaredmethd G C sig = Some m)" + +syntax +method_declared_in:: "prog \ (qtname \ mdecl) \ qtname \ bool" + ("_\Method _ declared'_in _" [61,61,61] 60) +translations +"G\Method m declared_in C" == "G\mdecl (mthd m) declared_in C" + +syntax +methd_declared_in:: "prog \ sig \(qtname \ methd) \ qtname \ bool" + ("_\Methd _ _ declared'_in _" [61,61,61,61] 60) +translations +"G\Methd s m declared_in C" == "G\mdecl (s,mthd m) declared_in C" + +lemma declared_in_classD: + "G\m declared_in C \ is_class G C" +by (cases m) + (auto simp add: declared_in_def cdeclaredmethd_def cdeclaredfield_def) + +constdefs +undeclared_in:: "prog \ memberid \ qtname \ bool" + ("_\ _ undeclared'_in _" [61,61,61] 60) + +"G\m undeclared_in C \ (case m of + fid fn \ cdeclaredfield G C fn = None + | mid sig \ cdeclaredmethd G C sig = None)" + +lemma method_declared_inI: + "\class G C = Some c; table_of (methods c) sig = Some m\ + \ G\mdecl (sig,m) declared_in C" +by (auto simp add: declared_in_def cdeclaredmethd_def) + + +subsubsection "members" + +consts +members:: "prog \ (qtname \ (qtname \ memberdecl)) set" +(* Can't just take a function: prog \ qtname \ memberdecl set because + the class qtname changes to the superclass in the inductive definition + below +*) + +syntax +member_of:: "prog \ (qtname \ memberdecl) \ qtname \ bool" + ("_ \ _ member'_of _" [61,61,61] 60) + +translations + "G\m member_of C" \ "(C,m) \ members G" + +inductive "members G" intros + +Immediate: "\G\mbr m declared_in C;declclass m = C\ \ G\m member_of C" +Inherited: "\G\m inheritable_in (pid C); G\memberid m undeclared_in C; + G\C \\<^sub>C\<^sub>1 S; G\(Class S) accessible_in (pid C);G\m member_of S + \ \ G\m member_of C" +text {* Note that in the case of an inherited member only the members of the +direct superclass are concerned. If a member of a superclass of the direct +superclass isn't inherited in the direct superclass (not member of the +direct superclass) than it can't be a member of the class. E.g. If a +member of a class A is defined with package access it isn't member of a +subclass S if S isn't in the same package as A. Any further subclasses +of S will not inherit the member, regardless if they are in the same +package as A or not.*} + +syntax +method_member_of:: "prog \ (qtname \ mdecl) \ qtname \ bool" + ("_ \Method _ member'_of _" [61,61,61] 60) + +translations + "G\Method m member_of C" \ "G\(methdMembr m) member_of C" + +syntax +methd_member_of:: "prog \ sig \ (qtname \ methd) \ qtname \ bool" + ("_ \Methd _ _ member'_of _" [61,61,61,61] 60) + +translations + "G\Methd s m member_of C" \ "G\(method s m) member_of C" + +syntax +fieldm_member_of:: "prog \ vname \ (qtname \ field) \ qtname \ bool" + ("_ \Field _ _ member'_of _" [61,61,61] 60) + +translations + "G\Field n f member_of C" \ "G\fieldm n f member_of C" + +constdefs +inherits:: "prog \ qtname \ (qtname \ memberdecl) \ bool" + ("_ \ _ inherits _" [61,61,61] 60) +"G\C inherits m + \ G\m inheritable_in (pid C) \ G\memberid m undeclared_in C \ + (\ S. G\C \\<^sub>C\<^sub>1 S \ G\(Class S) accessible_in (pid C) \ G\m member_of S)" + +lemma inherits_member: "G\C inherits m \ G\m member_of C" +by (auto simp add: inherits_def intro: members.Inherited) + + +constdefs member_in::"prog \ (qtname \ memberdecl) \ qtname \ bool" + ("_ \ _ member'_in _" [61,61,61] 60) +"G\m member_in C \ \ provC. G\ C \\<^sub>C provC \ G \ m member_of provC" +text {* A member is in a class if it is member of the class or a superclass. +If a member is in a class we can select this member. This additional notion +is necessary since not all members are inherited to subclasses. So such +members are not member-of the subclass but member-in the subclass.*} + +syntax +method_member_in:: "prog \ (qtname \ mdecl) \ qtname \ bool" + ("_ \Method _ member'_in _" [61,61,61] 60) + +translations + "G\Method m member_in C" \ "G\(methdMembr m) member_in C" + +syntax +methd_member_in:: "prog \ sig \ (qtname \ methd) \ qtname \ bool" + ("_ \Methd _ _ member'_in _" [61,61,61,61] 60) + +translations + "G\Methd s m member_in C" \ "G\(method s m) member_in C" + +consts stat_overridesR:: + "prog \ ((qtname \ mdecl) \ (qtname \ mdecl)) set" + +lemma member_inD: "G\m member_in C + \ \ provC. G\ C \\<^sub>C provC \ G \ m member_of provC" +by (auto simp add: member_in_def) + +lemma member_inI: "\G \ m member_of provC;G\ C \\<^sub>C provC\ \ G\m member_in C" +by (auto simp add: member_in_def) + +lemma member_of_to_member_in: "G \ m member_of C \ G \m member_in C" +by (auto intro: member_inI) + + +subsubsection "overriding" + +text {* Unfortunately the static notion of overriding (used during the +typecheck of the compiler) and the dynamic notion of overriding (used during +execution in the JVM) are not exactly the same. +*} + +text {* Static overriding (used during the typecheck of the compiler) *} +syntax +stat_overrides:: "prog \ (qtname \ mdecl) \ (qtname \ mdecl) \ bool" + ("_ \ _ overrides\<^sub>S _" [61,61,61] 60) +translations + "G\new overrides\<^sub>S old" == "(new,old) \ stat_overridesR G " + +inductive "stat_overridesR G" intros + +Direct: "\\ is_static new; msig new = msig old; + G\(declclass new) \\<^sub>C (declclass old); + G\Method new declared_in (declclass new); + G\Method old declared_in (declclass old); + G\Method old inheritable_in pid (declclass new); + G\(declclass new) \\<^sub>C\<^sub>1 superNew; + G \Method old member_of superNew + \ \ G\new overrides\<^sub>S old" + +Indirect: "\G\new overrides\<^sub>S inter; G\inter overrides\<^sub>S old\ + \ G\new overrides\<^sub>S old" + +text {* Dynamic overriding (used during the typecheck of the compiler) *} +consts overridesR:: + "prog \ ((qtname \ mdecl) \ (qtname \ mdecl)) set" + + +overrides:: "prog \ (qtname \ mdecl) \ (qtname \ mdecl) \ bool" + ("_ \ _ overrides _" [61,61,61] 60) +translations + "G\new overrides old" == "(new,old) \ overridesR G " + +inductive "overridesR G" intros + +Direct: "\\ is_static new; \ is_static old; accmodi new \ Private; + msig new = msig old; + G\(declclass new) \\<^sub>C (declclass old); + G\Method new declared_in (declclass new); + G\Method old declared_in (declclass old); + G\Method old inheritable_in pid (declclass new); + G\resTy new \ resTy old + \ \ G\new overrides old" + +Indirect: "\G\new overrides inter; G\inter overrides old\ + \ G\new overrides old" + +syntax +sig_stat_overrides:: + "prog \ sig \ (qtname \ methd) \ (qtname \ methd) \ bool" + ("_,_\ _ overrides\<^sub>S _" [61,61,61,61] 60) +translations + "G,s\new overrides\<^sub>S old" \ "G\(qmdecl s new) overrides\<^sub>S (qmdecl s old)" + +syntax +sig_overrides:: "prog \ sig \ (qtname \ methd) \ (qtname \ methd) \ bool" + ("_,_\ _ overrides _" [61,61,61,61] 60) +translations + "G,s\new overrides old" \ "G\(qmdecl s new) overrides (qmdecl s old)" + +subsubsection "Hiding" + +constdefs hides:: +"prog \ (qtname \ mdecl) \ (qtname \ mdecl) \ bool" + ("_\ _ hides _" [61,61,61] 60) +"G\new hides old + \ is_static new \ msig new = msig old \ + G\(declclass new) \\<^sub>C (declclass old) \ + G\Method new declared_in (declclass new) \ + G\Method old declared_in (declclass old) \ + G\Method old inheritable_in pid (declclass new)" + +syntax +sig_hides:: "prog \ sig \ (qtname \ mdecl) \ (qtname \ mdecl) \ bool" + ("_,_\ _ hides _" [61,61,61,61] 60) +translations + "G,s\new hides old" \ "G\(qmdecl s new) hides (qmdecl s old)" + +lemma hidesI: +"\is_static new; msig new = msig old; + G\(declclass new) \\<^sub>C (declclass old); + G\Method new declared_in (declclass new); + G\Method old declared_in (declclass old); + G\Method old inheritable_in pid (declclass new) + \ \ G\new hides old" +by (auto simp add: hides_def) + +lemma hidesD: +"\G\new hides old\ \ + declclass new \ Object \ is_static new \ msig new = msig old \ + G\(declclass new) \\<^sub>C (declclass old) \ + G\Method new declared_in (declclass new) \ + G\Method old declared_in (declclass old)" +by (auto simp add: hides_def) + +lemma overrides_commonD: +"\G\new overrides old\ \ + declclass new \ Object \ \ is_static new \ \ is_static old \ + accmodi new \ Private \ + msig new = msig old \ + G\(declclass new) \\<^sub>C (declclass old) \ + G\Method new declared_in (declclass new) \ + G\Method old declared_in (declclass old)" +by (induct set: overridesR) (auto intro: trancl_trans) + +lemma ws_overrides_commonD: +"\G\new overrides old;ws_prog G\ \ + declclass new \ Object \ \ is_static new \ \ is_static old \ + accmodi new \ Private \ G\resTy new \ resTy old \ + msig new = msig old \ + G\(declclass new) \\<^sub>C (declclass old) \ + G\Method new declared_in (declclass new) \ + G\Method old declared_in (declclass old)" +by (induct set: overridesR) (auto intro: trancl_trans ws_widen_trans) + +lemma stat_overrides_commonD: +"\G\new overrides\<^sub>S old\ \ + declclass new \ Object \ \ is_static new \ msig new = msig old \ + G\(declclass new) \\<^sub>C (declclass old) \ + G\Method new declared_in (declclass new) \ + G\Method old declared_in (declclass old)" +by (induct set: stat_overridesR) (auto intro: trancl_trans) + +lemma overrides_eq_sigD: + "\G\new overrides old\ \ msig old=msig new" +by (auto dest: overrides_commonD) + +lemma hides_eq_sigD: + "\G\new hides old\ \ msig old=msig new" +by (auto simp add: hides_def) + +subsubsection "permits access" +constdefs +permits_acc:: + "prog \ (qtname \ memberdecl) \ qtname \ qtname \ bool" + ("_ \ _ in _ permits'_acc'_to _" [61,61,61,61] 60) + +"G\membr in class permits_acc_to accclass + \ (case (accmodi membr) of + Private \ (declclass membr = accclass) + | Package \ (pid (declclass membr) = pid accclass) + | Protected \ (pid (declclass membr) = pid accclass) + \ + (G\accclass \\<^sub>C declclass membr \ G\class \\<^sub>C accclass) + | Public \ True)" +text {* +The subcondition of the @{term "Protected"} case: +@{term "G\accclass \\<^sub>C declclass membr"} could also be relaxed to: +@{term "G\accclass \\<^sub>C declclass membr"} since in case both classes are the +same the other condition @{term "(pid (declclass membr) = pid accclass)"} +holds anyway. +*} + +text {* Like in case of overriding, the static and dynamic accessibility +of members is not uniform. +\begin{itemize} +\item Statically the class/interface of the member must be accessible for the + member to be accessible. During runtime this is not necessary. For + Example, if a class is accessible and we are allowed to access a member + of this class (statically) we expect that we can access this member in + an arbitrary subclass (during runtime). It's not intended to restrict + the access to accessible subclasses during runtime. +\item Statically the member we want to access must be "member of" the class. + Dynamically it must only be "member in" the class. +\end{itemize} +*} + + +consts +accessible_fromR:: + "prog \ qtname \ ((qtname \ memberdecl) \ qtname) set" + +syntax +accessible_from:: + "prog \ (qtname \ memberdecl) \ qtname \ qtname \ bool" + ("_ \ _ of _ accessible'_from _" [61,61,61,61] 60) + +translations +"G\membr of cls accessible_from accclass" + \ "(membr,cls) \ accessible_fromR G accclass" + +syntax +method_accessible_from:: + "prog \ (qtname \ mdecl) \ qtname \ qtname \ bool" + ("_ \Method _ of _ accessible'_from _" [61,61,61,61] 60) + +translations +"G\Method m of cls accessible_from accclass" + \ "G\methdMembr m of cls accessible_from accclass" + +syntax +methd_accessible_from:: + "prog \ sig \ (qtname \ methd) \ qtname \ qtname \ bool" + ("_ \Methd _ _ of _ accessible'_from _" [61,61,61,61,61] 60) + +translations +"G\Methd s m of cls accessible_from accclass" + \ "G\(method s m) of cls accessible_from accclass" + +syntax +field_accessible_from:: + "prog \ vname \ (qtname \ field) \ qtname \ qtname \ bool" + ("_ \Field _ _ of _ accessible'_from _" [61,61,61,61,61] 60) + +translations +"G\Field fn f of C accessible_from accclass" + \ "G\(fieldm fn f) of C accessible_from accclass" + +inductive "accessible_fromR G accclass" intros +immediate: "\G\membr member_of class; + G\(Class class) accessible_in (pid accclass); + G\membr in class permits_acc_to accclass + \ \ G\membr of class accessible_from accclass" + +overriding: "\G\membr member_of class; + G\(Class class) accessible_in (pid accclass); + membr=(C,mdecl new); + G\(C,new) overrides\<^sub>S old; + G\class \\<^sub>C sup; + G\Method old of sup accessible_from accclass + \\ G\membr of class accessible_from accclass" + +consts +dyn_accessible_fromR:: + "prog \ qtname \ ((qtname \ memberdecl) \ qtname) set" + +syntax +dyn_accessible_from:: + "prog \ (qtname \ memberdecl) \ qtname \ qtname \ bool" + ("_ \ _ in _ dyn'_accessible'_from _" [61,61,61,61] 60) + +translations +"G\membr in C dyn_accessible_from accC" + \ "(membr,C) \ dyn_accessible_fromR G accC" + +syntax +method_dyn_accessible_from:: + "prog \ (qtname \ mdecl) \ qtname \ qtname \ bool" + ("_ \Method _ in _ dyn'_accessible'_from _" [61,61,61,61] 60) + +translations +"G\Method m in C dyn_accessible_from accC" + \ "G\methdMembr m in C dyn_accessible_from accC" + +syntax +methd_dyn_accessible_from:: + "prog \ sig \ (qtname \ methd) \ qtname \ qtname \ bool" + ("_ \Methd _ _ in _ dyn'_accessible'_from _" [61,61,61,61,61] 60) + +translations +"G\Methd s m in C dyn_accessible_from accC" + \ "G\(method s m) in C dyn_accessible_from accC" + +syntax +field_dyn_accessible_from:: + "prog \ vname \ (qtname \ field) \ qtname \ qtname \ bool" + ("_ \Field _ _ in _ dyn'_accessible'_from _" [61,61,61,61,61] 60) + +translations +"G\Field fn f in dynC dyn_accessible_from accC" + \ "G\(fieldm fn f) in dynC dyn_accessible_from accC" + +(* #### Testet JVM noch über den Bytecodeverifier hinaus ob der + statische Typ accessible ist bevor es den Zugriff erlaubt + \ Test mit Reflektion\ +*) +inductive "dyn_accessible_fromR G accclass" intros +immediate: "\G\membr member_in class; + G\membr in class permits_acc_to accclass + \ \ G\membr in class dyn_accessible_from accclass" + +overriding: "\G\membr member_in class; + membr=(C,mdecl new); + G\(C,new) overrides old; + G\class \\<^sub>C sup; + G\Method old in sup dyn_accessible_from accclass + \\ G\membr in class dyn_accessible_from accclass" + + +lemma accessible_from_commonD: "G\m of C accessible_from S + \ G\m member_of C \ G\(Class C) accessible_in (pid S)" +by (auto elim: accessible_fromR.induct) + +lemma declared_not_undeclared: + "G\m declared_in C \ \ G\ memberid m undeclared_in C" +by (cases m) (auto simp add: declared_in_def undeclared_in_def) + +lemma not_undeclared_declared: + "\ G\ membr_id undeclared_in C \ (\ m. G\m declared_in C \ + membr_id = memberid m)" +proof - + assume not_undecl:"\ G\ membr_id undeclared_in C" + show ?thesis (is "?P membr_id") + proof (cases membr_id) + case (fid vname) + with not_undecl + obtain fld where + "G\fdecl (vname,fld) declared_in C" + by (auto simp add: undeclared_in_def declared_in_def + cdeclaredfield_def) + with fid show ?thesis + by auto + next + case (mid sig) + with not_undecl + obtain mthd where + "G\mdecl (sig,mthd) declared_in C" + by (auto simp add: undeclared_in_def declared_in_def + cdeclaredmethd_def) + with mid show ?thesis + by auto + qed +qed + +lemma unique_declared_in: + "\G\m declared_in C; G\n declared_in C; memberid m = memberid n\ + \ m = n" +by (auto simp add: declared_in_def cdeclaredmethd_def cdeclaredfield_def + split: memberdecl.splits) + +lemma unique_member_of: + (assumes n: "G\n member_of C" and + m: "G\m member_of C" and + eqid: "memberid n = memberid m" + ) "n=m" +proof - + from n m eqid + show "n=m" + proof (induct) + case (Immediate C n) + assume member_n: "G\ mbr n declared_in C" "declclass n = C" + assume eqid: "memberid n = memberid m" + assume "G \ m member_of C" + then show "n=m" + proof (cases) + case (Immediate _ m') + with eqid + have "m=m'" + "memberid n = memberid m" + "G\ mbr m declared_in C" + "declclass m = C" + by auto + with member_n + show ?thesis + by (cases n, cases m) + (auto simp add: declared_in_def + cdeclaredmethd_def cdeclaredfield_def + split: memberdecl.splits) + next + case (Inherited _ _ m') + then have "G\ memberid m undeclared_in C" + by simp + with eqid member_n + show ?thesis + by (cases n) (auto dest: declared_not_undeclared) + qed + next + case (Inherited C S n) + assume undecl: "G\ memberid n undeclared_in C" + assume super: "G\C\\<^sub>C\<^sub>1S" + assume hyp: "\G \ m member_of S; memberid n = memberid m\ \ n = m" + assume eqid: "memberid n = memberid m" + assume "G \ m member_of C" + then show "n=m" + proof (cases) + case Immediate + then have "G\ mbr m declared_in C" by simp + with eqid undecl + show ?thesis + by (cases m) (auto dest: declared_not_undeclared) + next + case Inherited + with super have "G \ m member_of S" + by (auto dest!: subcls1D) + with eqid hyp + show ?thesis + by blast + qed + qed +qed + +lemma member_of_is_classD: "G\m member_of C \ is_class G C" +proof (induct set: members) + case (Immediate C m) + assume "G\ mbr m declared_in C" + then show "is_class G C" + by (cases "mbr m") + (auto simp add: declared_in_def cdeclaredmethd_def cdeclaredfield_def) +next + case (Inherited C S m) + assume "G\C\\<^sub>C\<^sub>1S" and "is_class G S" + then show "is_class G C" + by - (rule subcls_is_class2,auto) +qed + +lemma member_of_declC: + "G\m member_of C + \ G\mbr m declared_in (declclass m)" +by (induct set: members) auto + +lemma member_of_member_of_declC: + "G\m member_of C + \ G\m member_of (declclass m)" +by (auto dest: member_of_declC intro: members.Immediate) + +lemma member_of_class_relation: + "G\m member_of C \ G\C \\<^sub>C declclass m" +proof (induct set: members) + case (Immediate C m) + then show "G\C \\<^sub>C declclass m" by simp +next + case (Inherited C S m) + then show "G\C \\<^sub>C declclass m" + by (auto dest: r_into_rtrancl intro: rtrancl_trans) +qed + +lemma member_in_class_relation: + "G\m member_in C \ G\C \\<^sub>C declclass m" +by (auto dest: member_inD member_of_class_relation + intro: rtrancl_trans) + +lemma member_of_Package: + "\G\m member_of C; accmodi m = Package\ + \ pid (declclass m) = pid C" +proof - + assume member: "G\m member_of C" + then show " accmodi m = Package \ ?thesis" (is "PROP ?P m C") + proof (induct rule: members.induct) + fix C m + assume C: "declclass m = C" + then show "pid (declclass m) = pid C" + by simp + next + fix C S m + assume inheritable: "G \ m inheritable_in pid C" + assume hyp: "PROP ?P m S" and + package_acc: "accmodi m = Package" + with inheritable package_acc hyp + show "pid (declclass m) = pid C" + by (auto simp add: inheritable_in_def) + qed +qed + +lemma dyn_accessible_from_commonD: "G\m in C dyn_accessible_from S + \ G\m member_in C" +by (auto elim: dyn_accessible_fromR.induct) + +(* ### Gilt nicht für wf_progs!dynmaisches Override, + da die accmodi Bedingung nur für stat override gilt! *) +(* +lemma override_Package: + "\G\new overrides old; + \ new old. G\new overrides old \ accmodi old \ accmodi new; + accmodi old = Package; accmodi new = Package\ + \ pid (declclass old) = pid (declclass new)" +proof - + assume wf: "\ new old. G\new overrides old \ accmodi old \ accmodi new" + assume ovverride: "G\new overrides old" + then show "\accmodi old = Package;accmodi new = Package\ \ ?thesis" + (is "?Pack old \ ?Pack new \ ?EqPid old new") + proof (induct rule: overridesR.induct) + case Direct + fix new old + assume "accmodi old = Package" + "G \ methdMembr old inheritable_in pid (declclass new)" + then show "pid (declclass old) = pid (declclass new)" + by (auto simp add: inheritable_in_def) + next + case (Indirect inter new old) + assume accmodi_old: "accmodi old = Package" and + accmodi_new: "accmodi new = Package" + assume "G \ new overrides inter" + with wf have le_inter_new: "accmodi inter \ accmodi new" + by blast + assume "G \ inter overrides old" + with wf have le_old_inter: "accmodi old \ accmodi inter" + by blast + from accmodi_old accmodi_new le_inter_new le_old_inter + have "accmodi inter = Package" + by(auto simp add: le_acc_def less_acc_def) + with Indirect accmodi_old accmodi_new + show "?EqPid old new" + by auto + qed +qed + +lemma stat_override_Package: + "\G\new overrides\<^sub>S old; + \ new old. G\new overrides\<^sub>S old \ accmodi old \ accmodi new; + accmodi old = Package; accmodi new = Package\ + \ pid (declclass old) = pid (declclass new)" +proof - + assume wf: "\ new old. G\new overrides\<^sub>S old \ accmodi old \ accmodi new" + assume ovverride: "G\new overrides\<^sub>S old" + then show "\accmodi old = Package;accmodi new = Package\ \ ?thesis" + (is "?Pack old \ ?Pack new \ ?EqPid old new") + proof (induct rule: stat_overridesR.induct) + case Direct + fix new old + assume "accmodi old = Package" + "G \ methdMembr old inheritable_in pid (declclass new)" + then show "pid (declclass old) = pid (declclass new)" + by (auto simp add: inheritable_in_def) + next + case (Indirect inter new old) + assume accmodi_old: "accmodi old = Package" and + accmodi_new: "accmodi new = Package" + assume "G \ new overrides\<^sub>S inter" + with wf have le_inter_new: "accmodi inter \ accmodi new" + by blast + assume "G \ inter overrides\<^sub>S old" + with wf have le_old_inter: "accmodi old \ accmodi inter" + by blast + from accmodi_old accmodi_new le_inter_new le_old_inter + have "accmodi inter = Package" + by(auto simp add: le_acc_def less_acc_def) + with Indirect accmodi_old accmodi_new + show "?EqPid old new" + by auto + qed +qed + +*) +lemma no_Private_stat_override: + "\G\new overrides\<^sub>S old\ \ accmodi old \ Private" +by (induct set: stat_overridesR) (auto simp add: inheritable_in_def) + +lemma no_Private_override: "\G\new overrides old\ \ accmodi old \ Private" +by (induct set: overridesR) (auto simp add: inheritable_in_def) + +lemma permits_acc_inheritance: + "\G\m in statC permits_acc_to accC; G\dynC \\<^sub>C statC + \ \ G\m in dynC permits_acc_to accC" +by (cases "accmodi m") + (auto simp add: permits_acc_def + intro: subclseq_trans) + +lemma field_accessible_fromD: + "\G\membr of C accessible_from accC;is_field membr\ + \ G\membr member_of C \ + G\(Class C) accessible_in (pid accC) \ + G\membr in C permits_acc_to accC" +by (cases set: accessible_fromR) + (auto simp add: is_field_def split: memberdecl.splits) + +lemma field_accessible_from_permits_acc_inheritance: +"\G\membr of statC accessible_from accC; is_field membr; G \ dynC \\<^sub>C statC\ +\ G\membr in dynC permits_acc_to accC" +by (auto dest: field_accessible_fromD intro: permits_acc_inheritance) + + +(* +lemma accessible_Package: + "\G \ m of C accessible_from S;accmodi m = Package; + \ new old. G\new overrides\<^sub>S old \ accmodi old \ accmodi new\ + \ pid S = pid C \ pid C = pid (declclass m)" +proof - + assume wf: "\ new old. G\new overrides\<^sub>S old \ accmodi old \ accmodi new" + assume "G \ m of C accessible_from S" + then show "accmodi m = Package \ pid S = pid C \ pid C = pid (declclass m)" + (is "?Pack m \ ?P C m") + proof (induct rule: accessible_fromR.induct) + fix C m + assume "G\m member_of C" + "G \ m in C permits_acc_to S" + "accmodi m = Package" + then show "?P C m" + by (auto dest: member_of_Package simp add: permits_acc_def) + next + fix declC C new newm old Sup + assume member_new: "G \ new member_of C" and + acc_C: "G \ Class C accessible_in pid S" and + new: "new = (declC, mdecl newm)" and + override: "G \ (declC, newm) overrides\<^sub>S old" and + subcls_C_Sup: "G\C \\<^sub>C Sup" and + acc_old: "G \ methdMembr old of Sup accessible_from S" and + hyp: "?Pack (methdMembr old) \ ?P Sup (methdMembr old)" and + accmodi_new: "accmodi new = Package" + from override wf + have accmodi_weaken: "accmodi old \ accmodi newm" + by (cases old,cases newm) auto + from override new + have "accmodi old \ Private" + by (simp add: no_Private_stat_override) + with accmodi_weaken accmodi_new new + have accmodi_old: "accmodi old = Package" + by (cases "accmodi old") (auto simp add: le_acc_def less_acc_def) + with hyp + have P_sup: "?P Sup (methdMembr old)" + by (simp) + from wf override new accmodi_old accmodi_new + have eq_pid_new_old: "pid (declclass new) = pid (declclass old)" + by (auto dest: stat_override_Package) + from member_new accmodi_new + have "pid (declclass new) = pid C" + by (auto dest: member_of_Package) + with eq_pid_new_old P_sup show "?P C new" + by auto + qed +qed +*) +lemma accessible_fieldD: + "\G\membr of C accessible_from accC; is_field membr\ + \ G\membr member_of C \ + G\(Class C) accessible_in (pid accC) \ + G\membr in C permits_acc_to accC" +by (induct rule: accessible_fromR.induct) (auto dest: is_fieldD) + +(* lemmata: + Wegen G\Super accessible_in (pid C) folgt: + G\m declared_in C; G\m member_of D; accmodi m = Package (G\D \\<^sub>C C) + \ pid C = pid D + + C package + m public in C + für alle anderen D: G\m undeclared_in C + m wird in alle subklassen vererbt, auch aus dem Package heraus! + + G\m member_of C \ \ D. G\C \\<^sub>C D \ G\m declared_in D +*) + +(* Begriff (C,m) overrides (D,m) + 3 Fälle: Direkt, + Indirekt über eine Zwischenklasse (ohne weiteres override) + Indirekt über override +*) + +(* +"G\m member_of C \ +constdefs declares_method:: "prog \ sig \ qtname \ methd \ bool" + ("_,_\ _ declares'_method _" [61,61,61,61] 60) +"G,sig\C declares_method m \ cdeclaredmethd G C sig = Some m" + +constdefs is_declared:: "prog \ sig \ (qtname \ methd) \ bool" +"is_declared G sig em \ G,sig\declclass em declares_method mthd em" +*) + +lemma member_of_Private: +"\G\m member_of C; accmodi m = Private\ \ declclass m = C" +by (induct set: members) (auto simp add: inheritable_in_def) + +lemma member_of_subclseq_declC: + "G\m member_of C \ G\C \\<^sub>C declclass m" +by (induct set: members) (auto dest: r_into_rtrancl intro: rtrancl_trans) + +lemma member_of_inheritance: + (assumes m: "G\m member_of D" and + subclseq_D_C: "G\D \\<^sub>C C" and + subclseq_C_m: "G\C \\<^sub>C declclass m" and + ws: "ws_prog G" + ) "G\m member_of C" +proof - + from m subclseq_D_C subclseq_C_m + show ?thesis + proof (induct) + case (Immediate D m) + assume "declclass m = D" and + "G\D\\<^sub>C C" and "G\C\\<^sub>C declclass m" + with ws have "D=C" + by (auto intro: subclseq_acyclic) + with Immediate + show "G\m member_of C" + by (auto intro: members.Immediate) + next + case (Inherited D S m) + assume member_of_D_props: + "G \ m inheritable_in pid D" + "G\ memberid m undeclared_in D" + "G \ Class S accessible_in pid D" + "G \ m member_of S" + assume super: "G\D\\<^sub>C\<^sub>1S" + assume hyp: "\G\S\\<^sub>C C; G\C\\<^sub>C declclass m\ \ G \ m member_of C" + assume subclseq_C_m: "G\C\\<^sub>C declclass m" + assume "G\D\\<^sub>C C" + then show "G\m member_of C" + proof (cases rule: subclseq_cases) + case Eq + assume "D=C" + with super member_of_D_props + show ?thesis + by (auto intro: members.Inherited) + next + case Subcls + assume "G\D\\<^sub>C C" + with super + have "G\S\\<^sub>C C" + by (auto dest: subcls1D subcls_superD) + with subclseq_C_m hyp show ?thesis + by blast + qed + qed +qed + +lemma member_of_subcls: + (assumes old: "G\old member_of C" and + new: "G\new member_of D" and + eqid: "memberid new = memberid old" and + subclseq_D_C: "G\D \\<^sub>C C" and + subcls_new_old: "G\declclass new \\<^sub>C declclass old" and + ws: "ws_prog G" + ) "G\D \\<^sub>C C" +proof - + from old + have subclseq_C_old: "G\C \\<^sub>C declclass old" + by (auto dest: member_of_subclseq_declC) + from new + have subclseq_D_new: "G\D \\<^sub>C declclass new" + by (auto dest: member_of_subclseq_declC) + from subcls_new_old ws + have neq_new_old: "new\old" + by (cases new,cases old) (auto dest: subcls_irrefl) + from subclseq_D_new subclseq_D_C + have "G\(declclass new) \\<^sub>C C \ G\C \\<^sub>C (declclass new)" + by (rule subcls_compareable) + then have "G\(declclass new) \\<^sub>C C" + proof + assume "G\declclass new\\<^sub>C C" then show ?thesis . + next + assume "G\C \\<^sub>C (declclass new)" + with new subclseq_D_C ws + have "G\new member_of C" + by (blast intro: member_of_inheritance) + with eqid old + have "new=old" + by (blast intro: unique_member_of) + with neq_new_old + show ?thesis + by contradiction + qed + then show ?thesis + proof (cases rule: subclseq_cases) + case Eq + assume "declclass new = C" + with new have "G\new member_of C" + by (auto dest: member_of_member_of_declC) + with eqid old + have "new=old" + by (blast intro: unique_member_of) + with neq_new_old + show ?thesis + by contradiction + next + case Subcls + assume "G\declclass new\\<^sub>C C" + with subclseq_D_new + show "G\D\\<^sub>C C" + by (rule rtrancl_trancl_trancl) + qed +qed + +corollary member_of_overrides_subcls: + "\G\Methd sig old member_of C; G\Methd sig new member_of D;G\D \\<^sub>C C; + G,sig\new overrides old; ws_prog G\ + \ G\D \\<^sub>C C" +by (drule overrides_commonD) (auto intro: member_of_subcls) + +corollary member_of_stat_overrides_subcls: + "\G\Methd sig old member_of C; G\Methd sig new member_of D;G\D \\<^sub>C C; + G,sig\new overrides\<^sub>S old; ws_prog G\ + \ G\D \\<^sub>C C" +by (drule stat_overrides_commonD) (auto intro: member_of_subcls) + + + +lemma inherited_field_access: + (assumes stat_acc: "G\membr of statC accessible_from accC" and + is_field: "is_field membr" and + subclseq: "G \ dynC \\<^sub>C statC" + ) "G\membr in dynC dyn_accessible_from accC" +proof - + from stat_acc is_field subclseq + show ?thesis + by (auto dest: accessible_fieldD + intro: dyn_accessible_fromR.immediate + member_inI + permits_acc_inheritance) +qed + +lemma accessible_inheritance: + (assumes stat_acc: "G\m of statC accessible_from accC" and + subclseq: "G\dynC \\<^sub>C statC" and + member_dynC: "G\m member_of dynC" and + dynC_acc: "G\(Class dynC) accessible_in (pid accC)" + ) "G\m of dynC accessible_from accC" +proof - + from stat_acc + have member_statC: "G\m member_of statC" + by (auto dest: accessible_from_commonD) + from stat_acc + show ?thesis + proof (cases) + case immediate + with member_dynC member_statC subclseq dynC_acc + show ?thesis + by (auto intro: accessible_fromR.immediate permits_acc_inheritance) + next + case overriding + with member_dynC subclseq dynC_acc + show ?thesis + by (auto intro: accessible_fromR.overriding rtrancl_trancl_trancl) + qed +qed + +section "fields and methods" + + +types + fspec = "vname \ qtname" + +translations + "fspec" <= (type) "vname \ qtname" + +constdefs +imethds:: "prog \ qtname \ (sig,qtname \ mhead) tables" +"imethds G I + \ iface_rec (G,I) + (\I i ts. (Un_tables ts) \\ + (o2s \ table_of (map (\(s,m). (s,I,m)) (imethods i))))" +text {* methods of an interface, with overriding and inheritance, cf. 9.2 *} + +constdefs +accimethds:: "prog \ pname \ qtname \ (sig,qtname \ mhead) tables" +"accimethds G pack I + \ if G\Iface I accessible_in pack + then imethds G I + else \ k. {}" +text {* only returns imethds if the interface is accessible *} + +constdefs +methd:: "prog \ qtname \ (sig,qtname \ methd) table" + +"methd G C + \ class_rec (G,C) empty + (\C c subcls_mthds. + filter_tab (\sig m. G\C inherits method sig m) + subcls_mthds + ++ + table_of (map (\(s,m). (s,C,m)) (methods c)))" +text {* @{term "methd G C"}: methods of a class C (statically visible from C), + with inheritance and hiding cf. 8.4.6; + Overriding is captured by @{text dynmethd}. + Every new method with the same signature coalesces the + method of a superclass. *} + +constdefs +accmethd:: "prog \ qtname \ qtname \ (sig,qtname \ methd) table" +"accmethd G S C + \ filter_tab (\sig m. G\method sig m of C accessible_from S) + (methd G C)" +text {* @{term "accmethd G S C"}: only those methods of @{term "methd G C"}, + accessible from S *} + +text {* Note the class component in the accessibility filter. The class where + method @{term m} is declared (@{term declC}) isn't necessarily accessible + from the current scope @{term S}. The method can be made accessible + through inheritance, too. + So we must test accessibility of method @{term m} of class @{term C} + (not @{term "declclass m"}) *} + +constdefs +dynmethd:: "prog \ qtname \ qtname \ (sig,qtname \ methd) table" +"dynmethd G statC dynC + \ \ sig. + (if G\dynC \\<^sub>C statC + then (case methd G statC sig of + None \ None + | Some statM + \ (class_rec (G,dynC) empty + (\C c subcls_mthds. + subcls_mthds + ++ + (filter_tab + (\ _ dynM. G,sig\dynM overrides statM \ dynM=statM) + (methd G C) )) + ) sig + ) + else None)" +(* +"dynmethd G statC dynC + \ \ sig. + (if G\dynC \\<^sub>C statC + then (case methd G statC sig of + None \ None + | Some statM + \ (class_rec (G,statC) empty + (\C c subcls_mthds. + subcls_mthds + ++ + (filter_tab + (\ _ dynM. G,sig\dynM overrides statM) + (table_of (map (\(s,m). (s,C,m)) (methods c))))) + ) sig + ) + else None)"*) +text {* @{term "dynmethd G statC dynC"}: dynamic method lookup of a reference + with dynamic class @{term dynC} and static class @{term statC} *} +text {* Note some kind of duality between @{term methd} and @{term dynmethd} + in the @{term class_rec} arguments. Whereas @{term methd} filters the + subclass methods (to get only the inherited ones), @{term dynmethd} + filters the new methods (to get only those methods which actually + override the methods of the static class) *} + +constdefs +dynimethd:: "prog \ qtname \ qtname \ (sig,qtname \ methd) table" +"dynimethd G I dynC + \ \ sig. if imethds G I sig \ {} + then methd G dynC sig + else dynmethd G Object dynC sig" +text {* @{term "dynimethd G I dynC"}: dynamic method lookup of a reference with + dynamic class dynC and static interface type I *} +text {* + When calling an interface method, we must distinguish if the method signature + was defined in the interface or if it must be an Object method in the other + case. If it was an interface method we search the class hierarchy + starting at the dynamic class of the object up to Object to find the + first matching method (@{term methd}). Since all interface methods have + public access the method can't be coalesced due to some odd visibility + effects like in case of dynmethd. The method will be inherited or + overridden in all classes from the first class implementing the interface + down to the actual dynamic class. + *} + +constdefs +dynlookup::"prog \ ref_ty \ qtname \ (sig,qtname \ methd) table" +"dynlookup G statT dynC + \ (case statT of + NullT \ empty + | IfaceT I \ dynimethd G I dynC + | ClassT statC \ dynmethd G statC dynC + | ArrayT ty \ dynmethd G Object dynC)" +text {* @{term "dynlookup G statT dynC"}: dynamic lookup of a method within the + static reference type statT and the dynamic class dynC. + In a wellformd context statT will not be NullT and in case + statT is an array type, dynC=Object *} + +constdefs +fields:: "prog \ qtname \ ((vname \ qtname) \ field) list" +"fields G C + \ class_rec (G,C) [] (\C c ts. map (\(n,t). ((n,C),t)) (cfields c) @ ts)" +text {* @{term "fields G C"} + list of fields of a class, including all the fields of the superclasses + (private, inherited and hidden ones) not only the accessible ones + (an instance of a object allocates all these fields *} + +constdefs +accfield:: "prog \ qtname \ qtname \ (vname, qtname \ field) table" +"accfield G S C + \ let field_tab = table_of((map (\((n,d),f).(n,(d,f)))) (fields G C)) + in filter_tab (\n (declC,f). G\ (declC,fdecl (n,f)) of C accessible_from S) + field_tab" +text {* @{term "accfield G C S"}: fields of a class @{term C} which are + accessible from scope of class + @{term S} with inheritance and hiding, cf. 8.3 *} +text {* note the class component in the accessibility filter (see also + @{term methd}). + The class declaring field @{term f} (@{term declC}) isn't necessarily + accessible from scope @{term S}. The field can be made visible through + inheritance, too. So we must test accessibility of field @{term f} of class + @{term C} (not @{term "declclass f"}) *} + +constdefs + + is_methd :: "prog \ qtname \ sig \ bool" + "is_methd G \ \C sig. is_class G C \ methd G C sig \ None" + +constdefs efname:: "((vname \ qtname) \ field) \ (vname \ qtname)" +"efname \ fst" + +lemma efname_simp[simp]:"efname (n,f) = n" +by (simp add: efname_def) + + +subsection "imethds" + +lemma imethds_rec: "\iface G I = Some i; ws_prog G\ \ + imethds G I = Un_tables ((\J. imethds G J)`set (isuperIfs i)) \\ + (o2s \ table_of (map (\(s,mh). (s,I,mh)) (imethods i)))" +apply (unfold imethds_def) +apply (rule iface_rec [THEN trans]) +apply auto +done + + +(* local lemma *) +lemma imethds_norec: + "\iface G md = Some i; ws_prog G; table_of (imethods i) sig = Some mh\ \ + (md, mh) \ imethds G md sig" +apply (subst imethds_rec) +apply assumption+ +apply (rule iffD2) +apply (rule overrides_t_Some_iff) +apply (rule disjI1) +apply (auto elim: table_of_map_SomeI) +done + +lemma imethds_declI: "\m \ imethds G I sig; ws_prog G; is_iface G I\ \ + (\i. iface G (decliface m) = Some i \ + table_of (imethods i) sig = Some (mthd m)) \ + (I,decliface m) \ (subint1 G)^* \ m \ imethds G (decliface m) sig" +apply (erule make_imp) +apply (rule ws_subint1_induct, assumption, assumption) +apply (subst imethds_rec, erule conjunct1, assumption) +apply (force elim: imethds_norec intro: rtrancl_into_rtrancl2) +done + +lemma imethds_cases [consumes 3, case_names NewMethod InheritedMethod]: + (assumes im: "im \ imethds G I sig" and + ifI: "iface G I = Some i" and + ws: "ws_prog G" and + hyp_new: "table_of (map (\(s, mh). (s, I, mh)) (imethods i)) sig + = Some im \ P" and + hyp_inh: "\ J. \J \ set (isuperIfs i); im \ imethds G J sig\ \ P" + ) "P" +proof - + from ifI ws im hyp_new hyp_inh + show "P" + by (auto simp add: imethds_rec) +qed + +subsection "accimethd" + +lemma accimethds_simp [simp]: +"G\Iface I accessible_in pack \ accimethds G pack I = imethds G I" +by (simp add: accimethds_def) + +lemma accimethdsD: + "im \ accimethds G pack I sig + \ im \ imethds G I sig \ G\Iface I accessible_in pack" +by (auto simp add: accimethds_def) + +lemma accimethdsI: +"\im \ imethds G I sig;G\Iface I accessible_in pack\ + \ im \ accimethds G pack I sig" +by simp + +subsection "methd" + +lemma methd_rec: "\class G C = Some c; ws_prog G\ \ + methd G C + = (if C = Object + then empty + else filter_tab (\sig m. G\C inherits method sig m) + (methd G (super c))) + ++ table_of (map (\(s,m). (s,C,m)) (methods c))" +apply (unfold methd_def) +apply (erule class_rec [THEN trans], assumption) +apply (simp) +done + +(* local lemma *) +lemma methd_norec: + "\class G declC = Some c; ws_prog G;table_of (methods c) sig = Some m\ + \ methd G declC sig = Some (declC, m)" +apply (simp only: methd_rec) +apply (rule disjI1 [THEN override_Some_iff [THEN iffD2]]) +apply (auto elim: table_of_map_SomeI) +done + + +lemma methd_declC: +"\methd G C sig = Some m; ws_prog G;is_class G C\ \ + (\d. class G (declclass m)=Some d \ table_of (methods d) sig=Some (mthd m)) \ + G\C \\<^sub>C (declclass m) \ methd G (declclass m) sig = Some m" +apply (erule make_imp) +apply (rule ws_subcls1_induct, assumption, assumption) +apply (subst methd_rec, assumption) +apply (case_tac "Ca=Object") +apply (force elim: methd_norec ) + +apply simp +apply (case_tac "table_of (map (\(s, m). (s, Ca, m)) (methods c)) sig") +apply (force intro: rtrancl_into_rtrancl2) + +apply (auto intro: methd_norec) +done + +lemma methd_inheritedD: + "\class G C = Some c; ws_prog G;methd G C sig = Some m\ + \ (declclass m \ C \ G \C inherits method sig m)" +by (auto simp add: methd_rec) + +lemma methd_diff_cls: +"\ws_prog G; is_class G C; is_class G D; + methd G C sig = m; methd G D sig = n; m\n +\ \ C\D" +by (auto simp add: methd_rec) + +lemma method_declared_inI: + "\table_of (methods c) sig = Some m; class G C = Some c\ + \ G\mdecl (sig,m) declared_in C" +by (auto simp add: cdeclaredmethd_def declared_in_def) + +lemma methd_declared_in_declclass: + "\methd G C sig = Some m; ws_prog G;is_class G C\ + \ G\Methd sig m declared_in (declclass m)" +by (auto dest: methd_declC method_declared_inI) + +lemma member_methd: + (assumes member_of: "G\Methd sig m member_of C" and + ws: "ws_prog G" + ) "methd G C sig = Some m" +proof - + from member_of + have iscls_C: "is_class G C" + by (rule member_of_is_classD) + from iscls_C ws member_of + show ?thesis (is "?Methd C") + proof (induct rule: ws_class_induct') + case (Object co) + assume "G \Methd sig m member_of Object" + then have "G\Methd sig m declared_in Object \ declclass m = Object" + by (cases set: members) (cases m, auto dest: subcls1D) + with ws Object + show "?Methd Object" + by (cases m) + (auto simp add: declared_in_def cdeclaredmethd_def methd_rec + intro: table_of_mapconst_SomeI) + next + case (Subcls C c) + assume clsC: "class G C = Some c" and + neq_C_Obj: "C \ Object" and + hyp: "G \Methd sig m member_of super c \ ?Methd (super c)" and + member_of: "G \Methd sig m member_of C" + from member_of + show "?Methd C" + proof (cases) + case (Immediate Ca membr) + then have "Ca=C" "membr = method sig m" and + "G\Methd sig m declared_in C" "declclass m = C" + by (cases m,auto) + with clsC + have "table_of (map (\(s, m). (s, C, m)) (methods c)) sig = Some m" + by (cases m) + (auto simp add: declared_in_def cdeclaredmethd_def + intro: table_of_mapconst_SomeI) + with clsC neq_C_Obj ws + show ?thesis + by (simp add: methd_rec) + next + case (Inherited Ca S membr) + with clsC + have eq_Ca_C: "Ca=C" and + undecl: "G\mid sig undeclared_in C" and + super: "G \Methd sig m member_of (super c)" + by (auto dest: subcls1D) + from eq_Ca_C clsC undecl + have "table_of (map (\(s, m). (s, C, m)) (methods c)) sig = None" + by (auto simp add: undeclared_in_def cdeclaredmethd_def + intro: table_of_mapconst_NoneI) + moreover + from Inherited have "G \ C inherits (method sig m)" + by (auto simp add: inherits_def) + moreover + note clsC neq_C_Obj ws super hyp + ultimately + show ?thesis + by (auto simp add: methd_rec intro: filter_tab_SomeI) + qed + qed +qed + +(*unused*) +lemma finite_methd:"ws_prog G \ finite {methd G C sig |sig C. is_class G C}" +apply (rule finite_is_class [THEN finite_SetCompr2]) +apply (intro strip) +apply (erule_tac ws_subcls1_induct, assumption) +apply (subst methd_rec) +apply (assumption) +apply (auto intro!: finite_range_map_of finite_range_filter_tab finite_range_map_of_override) +done + +lemma finite_dom_methd: + "\ws_prog G; is_class G C\ \ finite (dom (methd G C))" +apply (erule_tac ws_subcls1_induct) +apply assumption +apply (subst methd_rec) +apply (assumption) +apply (auto intro!: finite_dom_map_of finite_dom_filter_tab) +done + + +subsection "accmethd" + +lemma accmethd_SomeD: +"accmethd G S C sig = Some m + \ methd G C sig = Some m \ G\method sig m of C accessible_from S" +by (auto simp add: accmethd_def dest: filter_tab_SomeD) + +lemma accmethd_SomeI: +"\methd G C sig = Some m; G\method sig m of C accessible_from S\ + \ accmethd G S C sig = Some m" +by (auto simp add: accmethd_def intro: filter_tab_SomeI) + +lemma accmethd_declC: +"\accmethd G S C sig = Some m; ws_prog G; is_class G C\ \ + (\d. class G (declclass m)=Some d \ + table_of (methods d) sig=Some (mthd m)) \ + G\C \\<^sub>C (declclass m) \ methd G (declclass m) sig = Some m \ + G\method sig m of C accessible_from S" +by (auto dest: accmethd_SomeD methd_declC accmethd_SomeI) + + +lemma finite_dom_accmethd: + "\ws_prog G; is_class G C\ \ finite (dom (accmethd G S C))" +by (auto simp add: accmethd_def intro: finite_dom_filter_tab finite_dom_methd) + + +subsection "dynmethd" + +lemma dynmethd_rec: +"\class G dynC = Some c; ws_prog G\ \ + dynmethd G statC dynC sig + = (if G\dynC \\<^sub>C statC + then (case methd G statC sig of + None \ None + | Some statM + \ (case methd G dynC sig of + None \ dynmethd G statC (super c) sig + | Some dynM \ + (if G,sig\ dynM overrides statM \ dynM = statM + then Some dynM + else (dynmethd G statC (super c) sig) + ))) + else None)" + (is "_ \ _ \ ?Dynmethd_def dynC sig = ?Dynmethd_rec dynC c sig") +proof - + assume clsDynC: "class G dynC = Some c" and + ws: "ws_prog G" + then show "?Dynmethd_def dynC sig = ?Dynmethd_rec dynC c sig" + proof (induct rule: ws_class_induct'') + case (Object co) + show "?Dynmethd_def Object sig = ?Dynmethd_rec Object co sig" + proof (cases "G\Object \\<^sub>C statC") + case False + then show ?thesis by (simp add: dynmethd_def) + next + case True + then have eq_statC_Obj: "statC = Object" .. + show ?thesis + proof (cases "methd G statC sig") + case None then show ?thesis by (simp add: dynmethd_def) + next + case Some + with True Object ws eq_statC_Obj + show ?thesis + by (auto simp add: dynmethd_def class_rec + intro: filter_tab_SomeI) + qed + qed + next + case (Subcls dynC c sc) + show "?Dynmethd_def dynC sig = ?Dynmethd_rec dynC c sig" + proof (cases "G\dynC \\<^sub>C statC") + case False + then show ?thesis by (simp add: dynmethd_def) + next + case True + note subclseq_dynC_statC = True + show ?thesis + proof (cases "methd G statC sig") + case None then show ?thesis by (simp add: dynmethd_def) + next + case (Some statM) + note statM = Some + let "?filter C" = + "filter_tab + (\_ dynM. G,sig \ dynM overrides statM \ dynM = statM) + (methd G C)" + let "?class_rec C" = + "(class_rec (G, C) empty + (\C c subcls_mthds. subcls_mthds ++ (?filter C)))" + from statM Subcls ws subclseq_dynC_statC + have dynmethd_dynC_def: + "?Dynmethd_def dynC sig = + ((?class_rec (super c)) + ++ + (?filter dynC)) sig" + by (simp (no_asm_simp) only: dynmethd_def class_rec) + auto + show ?thesis + proof (cases "dynC = statC") + case True + with subclseq_dynC_statC statM dynmethd_dynC_def + have "?Dynmethd_def dynC sig = Some statM" + by (auto intro: override_find_right filter_tab_SomeI) + with subclseq_dynC_statC True Some + show ?thesis + by auto + next + case False + with subclseq_dynC_statC Subcls + have subclseq_super_statC: "G\(super c) \\<^sub>C statC" + by (blast dest: subclseq_superD) + show ?thesis + proof (cases "methd G dynC sig") + case None + then have "?filter dynC sig = None" + by (rule filter_tab_None) + then have "?Dynmethd_def dynC sig=?class_rec (super c) sig" + by (simp add: dynmethd_dynC_def) + with subclseq_super_statC statM None + have "?Dynmethd_def dynC sig = ?Dynmethd_def (super c) sig" + by (auto simp add: empty_def dynmethd_def) + with None subclseq_dynC_statC statM + show ?thesis + by simp + next + case (Some dynM) + note dynM = Some + let ?Termination = "G \ qmdecl sig dynM overrides qmdecl sig statM \ + dynM = statM" + show ?thesis + proof (cases "?filter dynC sig") + case None + with dynM + have no_termination: "\ ?Termination" + by (simp add: filter_tab_def) + from None + have "?Dynmethd_def dynC sig=?class_rec (super c) sig" + by (simp add: dynmethd_dynC_def) + with subclseq_super_statC statM dynM no_termination + show ?thesis + by (auto simp add: empty_def dynmethd_def) + next + case Some + with dynM + have termination: "?Termination" + by (auto) + with Some dynM + have "?Dynmethd_def dynC sig=Some dynM" + by (auto simp add: dynmethd_dynC_def) + with subclseq_super_statC statM dynM termination + show ?thesis + by (auto simp add: dynmethd_def) + qed + qed + qed + qed + qed + qed +qed + +lemma dynmethd_C_C:"\is_class G C; ws_prog G\ +\ dynmethd G C C sig = methd G C sig" +apply (auto simp add: dynmethd_rec) +done + +lemma dynmethdSomeD: + "\dynmethd G statC dynC sig = Some dynM; is_class G dynC; ws_prog G\ + \ G\dynC \\<^sub>C statC \ (\ statM. methd G statC sig = Some statM)" +apply clarify +apply rotate_tac +by (auto simp add: dynmethd_rec) + +lemma dynmethd_Some_cases [consumes 3, case_names Static Overrides]: + (assumes dynM: "dynmethd G statC dynC sig = Some dynM" and + is_cls_dynC: "is_class G dynC" and + ws: "ws_prog G" and + hyp_static: "methd G statC sig = Some dynM \ P" and + hyp_override: "\ statM. \methd G statC sig = Some statM;dynM\statM; + G,sig\dynM overrides statM\ \ P" + ) "P" +proof - + from is_cls_dynC obtain dc where clsDynC: "class G dynC = Some dc" by blast + from clsDynC ws dynM hyp_static hyp_override + show "P" + proof (induct rule: ws_class_induct) + case (Object co) + with ws have "statC = Object" + by (auto simp add: dynmethd_rec) + with ws Object show ?thesis by (auto simp add: dynmethd_C_C) + next + case (Subcls C c) + with ws show ?thesis + by (auto simp add: dynmethd_rec) + qed +qed + +lemma no_override_in_Object: + (assumes dynM: "dynmethd G statC dynC sig = Some dynM" and + is_cls_dynC: "is_class G dynC" and + ws: "ws_prog G" and + statM: "methd G statC sig = Some statM" and + neq_dynM_statM: "dynM\statM" + ) + "dynC \ Object" +proof - + from is_cls_dynC obtain dc where clsDynC: "class G dynC = Some dc" by blast + from clsDynC ws dynM statM neq_dynM_statM + show ?thesis (is "?P dynC") + proof (induct rule: ws_class_induct) + case (Object co) + with ws have "statC = Object" + by (auto simp add: dynmethd_rec) + with ws Object show "?P Object" by (auto simp add: dynmethd_C_C) + next + case (Subcls dynC c) + with ws show "?P dynC" + by (auto simp add: dynmethd_rec) + qed +qed + + +lemma dynmethd_Some_rec_cases [consumes 3, + case_names Static Override Recursion]: +(assumes dynM: "dynmethd G statC dynC sig = Some dynM" and + clsDynC: "class G dynC = Some c" and + ws: "ws_prog G" and + hyp_static: "methd G statC sig = Some dynM \ P" and + hyp_override: "\ statM. \methd G statC sig = Some statM; + methd G dynC sig = Some dynM; statM\dynM; + G,sig\ dynM overrides statM\ \ P" and + + hyp_recursion: "\dynC\Object; + dynmethd G statC (super c) sig = Some dynM\ \ P" + ) "P" +proof - + from clsDynC have "is_class G dynC" by simp + note no_override_in_Object' = no_override_in_Object [OF dynM this ws] + from ws clsDynC dynM hyp_static hyp_override hyp_recursion + show ?thesis + by (auto simp add: dynmethd_rec dest: no_override_in_Object') +qed + +lemma dynmethd_declC: +"\dynmethd G statC dynC sig = Some m; + is_class G statC;ws_prog G + \ \ + (\d. class G (declclass m)=Some d \ table_of (methods d) sig=Some (mthd m)) \ + G\dynC \\<^sub>C (declclass m) \ methd G (declclass m) sig = Some m" +proof - + assume is_cls_statC: "is_class G statC" + assume ws: "ws_prog G" + assume m: "dynmethd G statC dynC sig = Some m" + from m + have "G\dynC \\<^sub>C statC" by (auto simp add: dynmethd_def) + from this is_cls_statC + have is_cls_dynC: "is_class G dynC" by (rule subcls_is_class2) + from is_cls_dynC ws m + show ?thesis (is "?P dynC") + proof (induct rule: ws_class_induct') + case (Object co) + with ws have "statC=Object" by (auto simp add: dynmethd_rec) + with ws Object + show "?P Object" + by (auto simp add: dynmethd_C_C dest: methd_declC) + next + case (Subcls dynC c) + assume hyp: "dynmethd G statC (super c) sig = Some m \ ?P (super c)" and + clsDynC: "class G dynC = Some c" and + m': "dynmethd G statC dynC sig = Some m" and + neq_dynC_Obj: "dynC \ Object" + from ws this obtain statM where + subclseq_dynC_statC: "G\dynC \\<^sub>C statC" and + statM: "methd G statC sig = Some statM" + by (blast dest: dynmethdSomeD) + from clsDynC neq_dynC_Obj + have subclseq_dynC_super: "G\dynC \\<^sub>C (super c)" + by (auto intro: subcls1I) + from m' clsDynC ws + show "?P dynC" + proof (cases rule: dynmethd_Some_rec_cases) + case Static + with is_cls_statC ws subclseq_dynC_statC + show ?thesis + by (auto intro: rtrancl_trans dest: methd_declC) + next + case Override + with clsDynC ws + show ?thesis + by (auto dest: methd_declC) + next + case Recursion + with hyp subclseq_dynC_super + show ?thesis + by (auto intro: rtrancl_trans) + qed + qed +qed + +lemma methd_Some_dynmethd_Some: + (assumes statM: "methd G statC sig = Some statM" and + subclseq: "G\dynC \\<^sub>C statC" and + is_cls_statC: "is_class G statC" and + ws: "ws_prog G" + ) "\ dynM. dynmethd G statC dynC sig = Some dynM" + (is "?P dynC") +proof - + from subclseq is_cls_statC + have is_cls_dynC: "is_class G dynC" by (rule subcls_is_class2) + then obtain dc where + clsDynC: "class G dynC = Some dc" by blast + from clsDynC ws subclseq + show "?thesis" + proof (induct rule: ws_class_induct) + case (Object co) + with ws have "statC = Object" + by (auto) + with ws Object statM + show "?P Object" + by (auto simp add: dynmethd_C_C) + next + case (Subcls dynC dc) + assume clsDynC': "class G dynC = Some dc" + assume neq_dynC_Obj: "dynC \ Object" + assume hyp: "G\super dc\\<^sub>C statC \ ?P (super dc)" + assume subclseq': "G\dynC\\<^sub>C statC" + then + show "?P dynC" + proof (cases rule: subclseq_cases) + case Eq + with ws statM clsDynC' + show ?thesis + by (auto simp add: dynmethd_rec) + next + case Subcls + assume "G\dynC\\<^sub>C statC" + from this clsDynC' + have "G\super dc\\<^sub>C statC" by (rule subcls_superD) + with hyp ws clsDynC' subclseq' statM + show ?thesis + by (auto simp add: dynmethd_rec) + qed + qed +qed + +lemma dynmethd_cases [consumes 4, case_names Static Overrides]: + (assumes statM: "methd G statC sig = Some statM" and + subclseq: "G\dynC \\<^sub>C statC" and + is_cls_statC: "is_class G statC" and + ws: "ws_prog G" and + hyp_static: "dynmethd G statC dynC sig = Some statM \ P" and + hyp_override: "\ dynM. \dynmethd G statC dynC sig = Some dynM; + dynM\statM; + G,sig\dynM overrides statM\ \ P" + ) "P" +proof - + from subclseq is_cls_statC + have is_cls_dynC: "is_class G dynC" by (rule subcls_is_class2) + then obtain dc where + clsDynC: "class G dynC = Some dc" by blast + from statM subclseq is_cls_statC ws + obtain dynM + where dynM: "dynmethd G statC dynC sig = Some dynM" + by (blast dest: methd_Some_dynmethd_Some) + from dynM is_cls_dynC ws + show ?thesis + proof (cases rule: dynmethd_Some_cases) + case Static + with hyp_static dynM statM show ?thesis by simp + next + case Overrides + with hyp_override dynM statM show ?thesis by simp + qed +qed + +lemma ws_dynmethd: + (assumes statM: "methd G statC sig = Some statM" and + subclseq: "G\dynC \\<^sub>C statC" and + is_cls_statC: "is_class G statC" and + ws: "ws_prog G" + ) + "\ dynM. dynmethd G statC dynC sig = Some dynM \ + is_static dynM = is_static statM \ G\resTy dynM\resTy statM" +proof - + from statM subclseq is_cls_statC ws + show ?thesis + proof (cases rule: dynmethd_cases) + case Static + with statM + show ?thesis + by simp + next + case Overrides + with ws + show ?thesis + by (auto dest: ws_overrides_commonD) + qed +qed + +(* +lemma dom_dynmethd: + "dom (dynmethd G statC dynC) \ dom (methd G statC) \ dom (methd G dynC)" +by (auto simp add: dynmethd_def dom_def) + +lemma finite_dom_dynmethd: + "\ws_prog G; is_class G statC; is_class G dynC\ + \ finite (dom (dynmethd G statC dynC))" +apply (rule_tac B="dom (methd G statC) \ dom (methd G dynC)" in finite_subset) +apply (rule dom_dynmethd) +apply (rule finite_UnI) +apply (drule (2) finite_dom_methd)+ +done +*) +(* +lemma dynmethd_SomeD: +"\ws_prog G; is_class G statC; is_class G dynC; + methd G statC sig = Some sm; dynmethd G statC dynC sig = Some dm; sm \ dm + \ \ G\dynC \\<^sub>C statC \ + (declclass dm \ dynC \ G \ dm accessible_through_inheritance_in dynC)" +by (auto simp add: dynmethd_def + dest: methd_inheritedD methd_diff_cls + intro: rtrancl_into_trancl3) +*) + +subsection "dynlookup" + +lemma dynlookup_cases [consumes 1, case_names NullT IfaceT ClassT ArrayT]: +"\dynlookup G statT dynC sig = x; + \statT = NullT ; empty sig = x \ \ P; + \ I. \statT = IfaceT I ; dynimethd G I dynC sig = x\ \ P; + \ statC.\statT = ClassT statC; dynmethd G statC dynC sig = x\ \ P; + \ ty. \statT = ArrayT ty ; dynmethd G Object dynC sig = x\ \ P + \ \ P" +by (cases statT) (auto simp add: dynlookup_def) + +subsection "fields" + +lemma fields_rec: "\class G C = Some c; ws_prog G\ \ + fields G C = map (\(fn,ft). ((fn,C),ft)) (cfields c) @ + (if C = Object then [] else fields G (super c))" +apply (simp only: fields_def) +apply (erule class_rec [THEN trans]) +apply assumption +apply clarsimp +done + +(* local lemma *) +lemma fields_norec: +"\class G fd = Some c; ws_prog G; table_of (cfields c) fn = Some f\ + \ table_of (fields G fd) (fn,fd) = Some f" +apply (subst fields_rec) +apply assumption+ +apply (subst map_of_override [symmetric]) +apply (rule disjI1 [THEN override_Some_iff [THEN iffD2]]) +apply (auto elim: table_of_map2_SomeI) +done + +(* local lemma *) +lemma table_of_fieldsD: +"table_of (map (\(fn,ft). ((fn,C),ft)) (cfields c)) efn = Some f +\ (declclassf efn) = C \ table_of (cfields c) (fname efn) = Some f" +apply (case_tac "efn") +by auto + +lemma fields_declC: + "\table_of (fields G C) efn = Some f; ws_prog G; is_class G C\ \ + (\d. class G (declclassf efn) = Some d \ + table_of (cfields d) (fname efn)=Some f) \ + G\C \\<^sub>C (declclassf efn) \ table_of (fields G (declclassf efn)) efn = Some f" +apply (erule make_imp) +apply (rule ws_subcls1_induct, assumption, assumption) +apply (subst fields_rec, assumption) +apply clarify +apply (simp only: map_of_override [symmetric] del: map_of_override) +apply (case_tac "table_of (map (split (\fn. Pair (fn, Ca))) (cfields c)) efn") +apply (force intro:rtrancl_into_rtrancl2 simp add: override_def) + +apply (frule_tac fd="Ca" in fields_norec) +apply assumption +apply blast +apply (frule table_of_fieldsD) +apply (frule_tac n="table_of (map (split (\fn. Pair (fn, Ca))) (cfields c))" + and m="table_of (if Ca = Object then [] else fields G (super c))" + in override_find_right) +apply (case_tac "efn") +apply (simp) +done + +lemma fields_emptyI: "\y. \ws_prog G; class G C = Some c;cfields c = []; + C \ Object \ class G (super c) = Some y \ fields G (super c) = []\ \ + fields G C = []" +apply (subst fields_rec) +apply assumption +apply auto +done + +(* easier than with table_of *) +lemma fields_mono_lemma: +"\x \ set (fields G C); G\D \\<^sub>C C; ws_prog G\ + \ x \ set (fields G D)" +apply (erule make_imp) +apply (erule converse_rtrancl_induct) +apply fast +apply (drule subcls1D) +apply clarsimp +apply (subst fields_rec) +apply auto +done + + +lemma ws_unique_fields_lemma: + "\(efn,fd) \ set (fields G (super c)); fc \ set (cfields c); ws_prog G; + fname efn = fname fc; declclassf efn = C; + class G C = Some c; C \ Object; class G (super c) = Some d\ \ R" +apply (frule_tac ws_prog_cdeclD [THEN conjunct2], assumption, assumption) +apply (drule_tac weak_map_of_SomeI) +apply (frule_tac subcls1I [THEN subcls1_irrefl], assumption, assumption) +apply (auto dest: fields_declC [THEN conjunct2 [THEN conjunct1[THEN rtranclD]]]) +done + +lemma ws_unique_fields: "\is_class G C; ws_prog G; + \C c. \class G C = Some c\ \ unique (cfields c) \ \ + unique (fields G C)" +apply (rule ws_subcls1_induct, assumption, assumption) +apply (subst fields_rec, assumption) +apply (auto intro!: unique_map_inj injI + elim!: unique_append ws_unique_fields_lemma fields_norec + ) +done + + +subsection "accfield" + +lemma accfield_fields: + "accfield G S C fn = Some f + \ table_of (fields G C) (fn, declclass f) = Some (fld f)" +apply (simp only: accfield_def Let_def) +apply (rule table_of_remap_SomeD) +apply (auto dest: filter_tab_SomeD) +done + + +lemma accfield_declC_is_class: + "\is_class G C; accfield G S C en = Some (fd, f); ws_prog G\ \ + is_class G fd" +apply (drule accfield_fields) +apply (drule fields_declC [THEN conjunct1], assumption) +apply auto +done + +lemma accfield_accessibleD: + "accfield G S C fn = Some f \ G\Field fn f of C accessible_from S" +by (auto simp add: accfield_def Let_def) + +subsection "is methd" + +lemma is_methdI: +"\class G C = Some y; methd G C sig = Some b\ \ is_methd G C sig" +apply (unfold is_methd_def) +apply auto +done + +lemma is_methdD: +"is_methd G C sig \ class G C \ None \ methd G C sig \ None" +apply (unfold is_methd_def) +apply auto +done + +lemma finite_is_methd: + "ws_prog G \ finite (Collect (split (is_methd G)))" +apply (unfold is_methd_def) +apply (subst SetCompr_Sigma_eq) +apply (rule finite_is_class [THEN finite_SigmaI]) +apply (simp only: mem_Collect_eq) +apply (fold dom_def) +apply (erule finite_dom_methd) +apply assumption +done + +section "calculation of the superclasses of a class" + +constdefs + superclasses:: "prog \ qtname \ qtname set" + "superclasses G C \ class_rec (G,C) {} + (\ C c superclss. (if C=Object + then {} + else insert (super c) superclss))" + +lemma superclasses_rec: "\class G C = Some c; ws_prog G\ \ + superclasses G C + = (if (C=Object) + then {} + else insert (super c) (superclasses G (super c)))" +apply (unfold superclasses_def) +apply (erule class_rec [THEN trans], assumption) +apply (simp) +done + +lemma superclasses_mono: +"\G\C \\<^sub>C D;ws_prog G; class G C = Some c; + \ C c. \class G C = Some c;C\Object\ \ \ sc. class G (super c) = Some sc; + x\superclasses G D +\ \ x\superclasses G C" +proof - + + assume ws: "ws_prog G" and + cls_C: "class G C = Some c" and + wf: "\C c. \class G C = Some c; C \ Object\ + \ \sc. class G (super c) = Some sc" + assume clsrel: "G\C\\<^sub>C D" + thus "\ c. \class G C = Some c; x\superclasses G D\\ + x\superclasses G C" (is "PROP ?P C" + is "\ c. ?CLS C c \ ?SUP D \ ?SUP C") + proof (induct ?P C rule: converse_trancl_induct) + fix C c + assume "G\C\\<^sub>C\<^sub>1D" "class G C = Some c" "x \ superclasses G D" + with wf ws show "?SUP C" + by (auto intro: no_subcls1_Object + simp add: superclasses_rec subcls1_def) + next + fix C S c + assume clsrel': "G\C \\<^sub>C\<^sub>1 S" "G\S \\<^sub>C D" + and hyp : "\ s. \class G S = Some s; x \ superclasses G D\ + \ x \ superclasses G S" + and cls_C': "class G C = Some c" + and x: "x \ superclasses G D" + moreover note wf ws + moreover from calculation + have "?SUP S" + by (force intro: no_subcls1_Object simp add: subcls1_def) + moreover from calculation + have "super c = S" + by (auto intro: no_subcls1_Object simp add: subcls1_def) + ultimately show "?SUP C" + by (auto intro: no_subcls1_Object simp add: superclasses_rec) + qed +qed + +lemma subclsEval: +"\G\C \\<^sub>C D;ws_prog G; class G C = Some c; + \ C c. \class G C = Some c;C\Object\ \ \ sc. class G (super c) = Some sc + \ \ D\superclasses G C" +proof - + note converse_trancl_induct + = converse_trancl_induct [consumes 1,case_names Single Step] + assume + ws: "ws_prog G" and + cls_C: "class G C = Some c" and + wf: "\C c. \class G C = Some c; C \ Object\ + \ \sc. class G (super c) = Some sc" + assume clsrel: "G\C\\<^sub>C D" + thus "\ c. class G C = Some c\ D\superclasses G C" + (is "PROP ?P C" is "\ c. ?CLS C c \ ?SUP C") + proof (induct ?P C rule: converse_trancl_induct) + fix C c + assume "G\C \\<^sub>C\<^sub>1 D" "class G C = Some c" + with ws wf show "?SUP C" + by (auto intro: no_subcls1_Object simp add: superclasses_rec subcls1_def) + next + fix C S c + assume "G\C \\<^sub>C\<^sub>1 S" "G\S\\<^sub>C D" + "\s. class G S = Some s \ D \ superclasses G S" + "class G C = Some c" + with ws wf show "?SUP C" + by - (rule superclasses_mono, + auto dest: no_subcls1_Object simp add: subcls1_def ) + qed +qed + +end \ No newline at end of file