| |
wfenv.abs

// This file defines environments and the well-formedness
// constraints upon them, and other interesting things
// like searching through class hierarchies for nearest
// fields/methods.

notation syntax rels ;
import syntax wf ;
reserve TE for :tyenv;
reserve C for :id;
reserve i for :id;

// Well formed environments
//
// We do not force environments to be finite here.
//
// RANDOM NOTES
//
// old execution problem: Cadd, Vadd etc. are almost constructors, but
// are not 1-1 (though the side conditions in the rules ensure
// they are).
//
// Hence we resort to a concrete model of declarations.
//
// Fix suggested by David von Oheimb: Environment well-formedness does not
// depend on order of introduction at all in Java. Hence scrap use of
// inductive relation and just define as a set/unary relation.
//
// The rules below have been modified from those in the tech report.
// The two return-types-wider clauses demand a minimum behaviour
// from MSigsC and MSigsI: all super-methods must continue
// to be available at the new class/interface.

def wf_tyenv TE wf_tyenv <=>
(?methods. Cdec(TE,Object) = SOME(CLASS(NONE,EMPTY,PEMPTY,methods))) &
(!C. C :: PDOM(FST(TE)) -->
!Csupo Is fields methods. Cdec(TE,C) = SOME(CLASS(Csupo,Is,fields,methods)) -->
(!Csup. Csupo = SOME(Csup) -->
(~(TE |- Csup subclass_of C)) &
(!m at rt1. MSigsC(TE,Csup)(m,MT(at,rt1)) -->
(?rt2. MSigsC(TE,C)(m,MT(at,rt2)) &
TE |- rt2 expty_widens_to rt1) )) &
(Csupo = NONE --> (C = Object) &
(fields = PEMPTY) &
(Is = EMPTY) ) &
(!m mt1. (m,mt1) :: methods -->
!mt2. (m,mt2) :: methods -->
(if (Args(mt1) = Args(mt2)) then (mt1 = mt2) else T) ) &
(!i. i :: Is -->
!m at rt1. MSigsI(TE,i)(m,MT(at,rt1)) -->
(?rt2. MSigsC(TE,C)(m,MT(at,rt2)) &
TE |- rt2 expty_widens_to rt1) ))
&
(!i Is methods.
i :: PDOM(SND(TE)) &
Idec(TE,i) = SOME(INTERFACE(Is,methods)) -->
(!i'. i' :: Is -->
(~(TE |- i' subinterface_of i)) ) &
(!m mt1. (m,mt1) :: methods -->
!mt2. (m,mt2) :: methods -->
(if (Args(mt1) = Args(mt2)) then (mt1 = mt2) else T) ) &
(!i'. i' :: Is -->
!m at rt1. MSigsI(TE,i')(m,MT(at,rt1)) -->
(?rt2. MSigsI(TE,i)(m,MT(at,rt2)) &
TE |- rt2 expty_widens_to rt1) ) &
(Is = EMPTY -->
!m at rt1. (m,MT(at,rt1)) :: methods -->
!rt2. MSigsC(TE,Object)(m,MT(at,rt2)) -->
(TE |- rt1 expty_widens_to rt2) ))

// Reflexivity results for widening relations.

lemma simpty_widens_to-refl [prolog,simp,auto]
TE |- st1 simpty_widens_to st1
thm varty_widens_to-refl [prolog,simp,auto]
TE |- vt1 varty_widens_to vt1
thm expty_widens_to-refl [prolog,simp,auto]
TE |- et1 expty_widens_to et1

// Results about Object
//
// In a wfenv, Object is only a subclass of Object

lemma Object-implements TE wf_tyenv --> ~(TE |- Object implements i);
lemma Object-subclass TE wf_tyenv --> (TE |- Object subclass_of C <=> C = Object);
lemma Object-simpty
TE wf_tyenv --> (TE |- Class(Object) simpty_widens_to st <=> st = Class(Object));

// Transitivity results for widening relations.

lemma simpty_widens_to-trans
TE wf_tyenv &
TE |- vt1 simpty_widens_to vt2 &
TE |- vt2 simpty_widens_to vt3 -->
TE |- vt1 simpty_widens_to vt3
thm varty_widens_to-trans
TE wf_tyenv &
TE |- vt1 varty_widens_to vt2 &
TE |- vt2 varty_widens_to vt3 -->
TE |- vt1 varty_widens_to vt3
thm expty_widens_to-trans
TE wf_tyenv &
TE |- vt1 expty_widens_to vt2 &
TE |- vt2 expty_widens_to vt3 -->
TE |- vt1 expty_widens_to vt3
// subtype lemmas follow, e.g. anything that widens to an array is an
// array of the some simple type that widens to the simple type of the array.
//
// the proofs of these are all by straight forward case analysis using the rules
thm lemma">array-widens-lemma
TE |- expty expty_widens_to SOME(VT(simpty0,dim)) &
0 < dim
--> ?simpty1.
expty = SOME(VT(simpty1,dim)) &
TE |- simpty1 simpty_widens_to simpty0
thm lemma">prim-widens-lemma
TE |- expty expty_widens_to SOME(VT(PrimT(primty),0))
<=> expty = SOME(VT(PrimT(primty),0))
thm lemma">var-prim-widens-lemma
TE |- varty varty_widens_to VT(PrimT(primty),0)
--> varty = VT(PrimT(primty),0)
thm lemma">class-widens-lemma
TE wf_tyenv &
TE |- expty expty_widens_to SOME(VT(Class(C),0)) &
C <> Object
--> ?C'. TE |- C' subclass_of C &
expty = SOME(VT(Class(C'),0));
// a lemma that need not be exported:
lemma FDecs-finds-subclasses
FDecs(TE,C)((Cf,f),vt) --> TE |- C subclass_of Cf;
thm object-fields-unique
TE wf_tyenv & FDecs(TE,C)(fspec) & FDecs(TE,C)(fspec')
--> fspec = fspec';
thm object-fields-form-graph
TE wf_tyenv --> IS_GRAPH {fspec | FDecs(TE,C)(fspec)};
thm FDecs-Object
TE wf_tyenv --> ~(x :: FDecs(TE,Object));
// subclasses inherit (or redeclare) methods from superclasses.
//
// This says that if we did a static search for the method from class C0,
// and got a result, then did the same from C1, then we get a method
// with a return type that is narrower.
lemma class-inherited-class-methods-are-narrower
TE wf_tyenv &
TE |- C1 subclass_of C0 &
MSigsC(TE,C0)(m,MT(AT,rt0))
--> ?rt1. MSigsC(TE,C1)(m,MT(AT,rt1)) & TE |- rt1 expty_widens_to rt0
lemma interface-inherited-interface-methods-are-narrower
TE wf_tyenv &
TE |- i1 subinterface_of i0 &
MSigsI(TE,i0)(m,MT(AT,rt0))
--> ?rt1. MSigsI(TE,i1)(m,MT(AT,rt1)) & TE |- rt1 expty_widens_to rt0
lemma class-inherited-interface-methods-are-narrower
TE wf_tyenv &
TE |- C1 implements i1 &
MSigsI(TE,i0)(m,MT(AT,rt0))
--> ?rt1. MSigsC(TE,C2)(m,MT(AT,rt1)) & TE |- rt1 expty_widens_to rt0
// all interfaces inherit (or redeclare with narrower type) methods from Object.
lemma interface-inherited-Object-methods-are-narrower
TE wf_tyenv &
TE |- i wellfounded_interface &
MSigsC(TE,Object)(m,MT(AT,rt0))
--> ?rt1. MSigsI(TE,i)(m,MT(AT,rt1)) & TE |- rt1 expty_widens_to rt0
// all interfaces inherit (or redeclare with narrower type) methods from Object.
lemma array-inherited-Object-methods-are-identical
MSigsC(TE,Object)(m,MT(AT,rt0))
--> MSigsA(TE)(m,MT(AT,rt0))
// subclasses inherit declared fields. Should be strengthened to be up to widening,
// so array methods can be modelled correctly.
thm inherited-fields-exist
TE wf_tyenv &
TE |- C1 subclass_of C0 &
((C',f),var0_ty) :: FDecs(TE,C0) -->
((C',f),var0_ty) :: FDecs(TE,C1)
// The crucial theorem about visibility of methods under widening, for all reference types.
thm inherited-methods-exist
TE wf_tyenv &
MSigs(TE,vt0)(m,MT(AT,rt0)) &
TE |- vt1 varty_widens_to vt0
--> ?rt1. MSigs(TE,vt1)(m,MT(AT,rt1)) & TE |- rt1 expty_widens_to rt0
|