| |
link2_0.art
notation syntax rels runtime rstatics ;
import syntax wf wfenv statics1 cstatics runtime0 link2_0 ;

// Lemma 3.1. If a class inherits a method declaration with method type
// then it provides a method body that satisfies that method type.
//
// Both the static (MSigsC) search and the runtime (MethBody) search
// begin at the same class (C). We prove in wfenv.art that as we move
// to subclasses the method is still found by the static MDecs search,
// with a possible narrower return type.
//
// This first part says method bodies are always found.

thm inheritance-is-implemented
if TE wf_tyenv TE_wf
TE |- cprog cprog_hastype cprog_types
MSigsC(TE,C)(m,mt) search
then ?Xord body. MethBodyC(m,Args(mt),C,cprog)(Xord,body) g
proceed by rule induction on search with C variable;
case Hit
mt = MT(AT,rt)
Cdec(TE,C) = SOME(CLASS(Csupo,Is,fields,methods)) [rw,auto]
(m,MT(AT,rt)) :: methods m_in_methods;
consider cbody,Csupo',mbodies st
(C,cbody) :: ELS(cprog) cbody_in_prog
cbody = (Csupo',mbodies)
(C,TE) |- cbody cclass_hastype (Csupo,Is,fields,methods) cbody_types
by CPROG_HASTYPE__classes_exist [cprog,TE,C],cprog_types,Cdec,PDOM,IN_ELIM,PFORALL_SPLIT;
consider mbody,Xord,Xtys,body st
Csupo = Csupo'
(m,mbody) :: ELS(mbodies)
mbody = ((Xord,Xtys),body)
(C,TE) |- mbody cmethod_hastype MT(AT,rt) a2
by CCLASS_HASTYPE__methods_exist [TE,methods,fields,Is,Csupo/Csupo',Csupo'/Csupo],
CCLASS_HASTYPE__subclasses_match [TE,methods,fields,Is,Csupo/Csupo',Csupo'/Csupo],
cbody_types,m_in_methods,PEXISTS_SPLIT;
then qed by MethBodyC__Hit,cbody_in_prog, g [Xord,body],Args, rule cases on a2;
case Miss
mt = MT(AT,rt)
Cdec(TE,C) = SOME(CLASS(SOME(Csup),Is,fields,methods)) [rw,auto]
?Xord body. MethBodyC(m,Args(mt),Csup,cprog)(Xord,body) ihyp
MSigsC(TE,Csup)(m,mt)
!AT' rt'. (m,MT(AT',rt')) :: methods --> AT <> AT' alldiff;
consider Xord,body st
MethBodyC(m,AT,Csup,cprog)(Xord,body) recurse by ihyp,Args;
consider cbody,mbodies,Csupo' st
(C,cbody) :: ELS(cprog) cbody_in_prog
cbody = (Csupo',mbodies)
(C,TE) |- cbody cclass_hastype (SOME(Csup),Is,fields,methods) cbody_types
by CPROG_HASTYPE__classes_exist [cprog,TE,C],cprog_types,Cdec,PDOM,IN_ELIM,PFORALL_SPLIT;
have Csupo' = SOME(Csup)
!m mbody. (m,mbody) :: ELS(mbodies) -->
?mt. (m,mt) :: methods &
(C,TE) |- mbody cmethod_hastype mt t1
by CCLASS_HASTYPE__methoddecs_exist,CCLASS_HASTYPE__subclasses_match,cbody_types;
// suffices to show the following condition
sts !Xord Xtys body. (m,((Xord,Xtys),body)) :: ELS(mbodies) --> MAP(PAPPLY(Xtys))(Xord) <> AT
by MethBodyC__Miss [cprog,mbodies,C/C,Csup/Csup],
g [Xord,body],recurse,cbody_in_prog,Args;
then consider Xord',Xtys',body',mbody' st
+ (m,mbody') :: ELS(mbodies) m_in_mbodies
+ mbody' = ((Xord',Xtys'),body')
- MAP(PAPPLY(Xtys'))(Xord') <> AT;
consider mt' st
(m,mt') :: methods m_in_methods
(C,TE) |- mbody' cmethod_hastype mt' t2 by t1 [mbody',m],m_in_mbodies ;
let AT' = MAP(PAPPLY(Xtys'))(Xord') ;
consider rt' st mt' = MT(AT',rt') by rule cases on t2;
then qed by alldiff [AT',rt'],m_in_methods;
end;

// This second part says that if a method body is found for a
// call to an object method, then it is well typed.

thm implemented-object-inheritance-is-welltyped
if TE wf_tyenv TE_wf
TE |- cprog cprog_hastype cprog_types
MSigsC(TE,C)(m,MT(AT,rt2)) search
MethBodyC(m,AT,C,cprog)(Xord,body) fetch
then ?Xtys C''. TE |- C subclass_of C'' &
(C'',TE) |- ((Xord,Xtys),body) cmethod_hastype MT(AT,rt2) g
proceed by rule induction on fetch with C variable;
case Hit
(C,(Csupo,mbodies)) :: ELS(cprog) cclass_in_prog
(m,mbody) :: ELS(mbodies) mbody_in_mbodies
mbody = ((Xord,Xtys),body)
MAP(PAPPLY(Xtys))(Xord) = AT ;
let cclass = (Csupo,mbodies) ;
consider ctyp,Is1,fields1,methods1,Csupo' st
Cdec(TE,C) = SOME(CLASS(ctyp)) [rw,auto]
ctyp = (Csupo',Is1,fields1,methods1)
(C,TE) |- cclass cclass_hastype ctyp cclass_types
by CPROG_HASTYPE__classdecs_exist [cprog,cclass,C,TE],cprog_types,cclass_in_prog;
consider mt st
Csupo = Csupo'
(m,mt) :: methods1 m_in_methods1
(C,TE) |- mbody cmethod_hastype mt mbody_types
by CCLASS_HASTYPE__methoddecs_exist,
CCLASS_HASTYPE__subclasses_match,cclass_types,mbody_in_mbodies;
consider rt st mt = MT(AT,rt) by rule cases on mbody_types;
per cases
case Cdec(TE,C) = SOME(CLASS(Csupo,Is2,fields2,methods2)) [rw,auto]
(m,MT(AT,rt2)) :: methods2 m2;
have ctyp = (Csupo,Is2,fields2,methods2) ;
have mt = MT(AT,rt2) by
WF_TYENV__class_argtypes_unique [TE,mt/mt1,MT(AT,rt2)/mt2,C/C,m/m,methods1,Csupo/Csupo,Is1,fields1],
TE_wf,PDOM,IN_ELIM,Cdec,m2,m_in_methods1,Args;
then qed by mbody_types,g [C,Xtys];
case Cdec(TE,C) = SOME(CLASS(SOME(Csup),Is2,fields2,methods2)) [rw,auto]
MSigsC(TE,Csup)(m,MT(AT,rt2))
!AT' rt'. (m,MT(AT',rt')) :: methods2 --> AT <> AT' no_match;
have ctyp = (SOME(Csup),Is2,fields2,methods2) ;
contradiction by m_in_methods1,no_match [AT,rt];
end by rule cases on search;
case Miss
(C,(SOME(Csup),mbodies)) :: ELS(cprog) cclass_in_prog
!Xord Xtys body. (m,((Xord,Xtys),body)) :: ELS(mbodies) --> MAP(PAPPLY(Xtys))(Xord) <> AT no_match
MSigsC(TE,Csup)(m,MT(AT,rt2)) -->
?Xtys C''. TE |- Csup subclass_of C'' &
(C'',TE) |- ((Xord,Xtys),body) cmethod_hastype MT(AT,rt2) ihyp
MethBodyC(m,AT,Csup,cprog)(Xord,body)
let cclass = (SOME(Csup),mbodies) ;
consider ctyp, Is,fields,methods,Csupo' st
Cdec(TE,C) = SOME(CLASS(ctyp)) [rw,auto]
ctyp = (Csupo',Is,fields,methods) [auto,rw]
(C,TE) |- cclass cclass_hastype ctyp cclass_types
by CPROG_HASTYPE__classdecs_exist [TE,cprog,cclass,C],cprog_types,cclass_in_prog;
have Csupo' = SOME(Csup)
!m mt. (m,mt) :: methods -->
?mbody. (m,mbody) :: ELS(mbodies) &
(C,TE) |- mbody cmethod_hastype mt mbodies_exist
by CCLASS_HASTYPE__methods_exist,CCLASS_HASTYPE__subclasses_match,cclass_types;
per cases
case Cdec(TE,C) = SOME(CLASS(Csupo,Is2,fields2,methods2)) [rw,auto]
(m,MT(AT,rt2)) :: methods2 m2;
have ctyp = (Csupo,Is2,fields2,methods2) ;
consider mbody,Xord2,Xtys2,body2 st
(m,mbody) :: ELS(mbodies) m_in_mbodies
mbody = ((Xord2,Xtys2),body2)
(C,TE) |- mbody cmethod_hastype MT(AT,rt2) mbody_types
by mbodies_exist [m,MT(AT,rt2)],m2;
have AT = MAP(PAPPLY(Xtys2))(Xord2) by rule cases on mbody_types;
then contradiction by no_match,m_in_mbodies,Cdec;
case Cdec(TE,C) = SOME(CLASS(SOME(Csup),Is2,fields2,methods2)) [rw,auto]
MSigsC(TE,Csup)(m,MT(AT,rt2)) m1
!AT' rt'. (m,MT(AT',rt')) :: methods2 --> AT <> AT' no_match;
have ctyp = (SOME(Csup),Is2,fields2,methods2) ;
consider Xtys',C'' st
TE |- Csup subclass_of C''
(C'',TE) |- ((Xord,Xtys'),body) cmethod_hastype MT(AT,rt2) by ihyp,m1;
then qed by g [Xtys',C''], subclass_of__Step;
end by rule cases on search;
end;

// Same thing for calling array methods...

thm implemented-array-inheritance-is-welltyped
if TE wf_tyenv
TE |- cprog cprog_hastype
0 < dim
MSigsA(TE)(m,MT(AT,rt))
MethBodyA(m,AT,VT(st,dim),cprog)(Xord,body)
then ?Xtys C'. TE |- VT(st,dim) varty_widens_to VT(Class(C'),0) &
(C',TE) |- ((Xord,Xtys),body) cmethod_hastype MT(AT,rt)
then qed by MSigsA__elim,MethBodyA,
implemented-object-inheritance-is-welltyped [TE,cprog,AT,Object/C,m/m,Xord,body,rt],
varty_widens_to-trans [TE,VT(Class(Object),0)/vt2,VT(st,dim)/vt1],varty_widens_to__ArrayToObject [TE,st];

// And thus for any sort of heap object...

thm implemented-inheritance-is-welltyped
TE wf_tyenv &
TE |- cprog cprog_hastype &
MSigs(TE,VT(st,dim))(m,MT(AT,rt)) &
MethBody(m,AT,VT(st,dim),cprog)(Xord,body)
--> ?Xtys C'. TE |- VT(st,dim) varty_widens_to VT(Class(C'),0) &
(C',TE) |- ((Xord,Xtys),body) cmethod_hastype MT(AT,rt)
qed by MSigs,MethBody,implemented-array-inheritance-is-welltyped [TE,cprog],
implemented-object-inheritance-is-welltyped [TE,cprog],
structural cases on st,ZERO_CASES [dim]
|