| |
cstatics.abs
notation syntax rels ;
import syntax wf statics1 ;
reserve TE for :tyenv;
reserve VE for :varenv;
reserve G for :tyenv × varenv;
reserve C for :id;
reserve id for :id;
// bug detected: input/output analysis told me of a mistyped
// variable
//
// Expressions can type to void (== NONE) because a method
// call may not return a value, and a method call can be
// part of an expression.
lfp cexp_hastype
Id PLOOKUP(VE)(x) = SOME(vt)
// -----------------------------------------------
(TE,VE) |- IdA(x) cvar_hastype vt
Access (TE,VE) |- arr cexp_hastype SOME(VT(st,dim)) &
0 < dim &
(TE,VE) |- e cexp_hastype SOME(VT(PrimT(intT),0))
// ----------------------------------------------------
(TE,VE) |- AccessA(arr,e) cvar_hastype VT(st,dim-1)
Var (TE,VE) |- v cvar_hastype vt
// ---------------------------------------
(TE,VE) |- VarA(v) cexp_hastype SOME(vt)
Void
// --------------------------------
(TE,VE) |- VoidA cexp_hastype NONE
Prim p prim_hastype pt
// ----------------------------------------
(TE,VE) |- PrimA(p) cexp_hastype SOME(VT(PrimT(pt),0))
NewArray 0 < LEN(dims)+ext &
TE |- st wf_simptype &
(!j. j < LEN(dims) --> (TE,VE) |- EL(j)(dims) cexp_hastype SOME(VT(PrimT(intT),0)))
// ---------------------------------------------------------------------
(TE,VE) |- NewArrayA(st,dims,ext) cexp_hastype SOME(VT(st,LEN(dims)+ext))
FieldA
(TE,VE) |- obj cexp_hastype SOME(VT(Class(C),0)) &
((C',f),vt) :: FDecs(TE,C)
// ----------------------------------------------------
(TE,VE) |- FieldA(obj,C',f) cvar_hastype vt
NewClassA
TE |- C wf_class &
(!fld vt. (fld,vt) :: FDecs(TE,C) --> TE |- vt wf_vartype) &
flds = PGRAPH {fspec | FDecs(TE,C)(fspec)}
// -----------------------------------------------------------------
(TE,VE) |- NewClassA(C,flds) cexp_hastype SOME(VT(Class(C),0))
CallA
LEN(args) = nargs &
LEN(AT) = nargs &
(TE,VE) |- e cexp_hastype SOME(vt) &
MSigs(TE,vt)(m,MT(AT,rt))
// ----------------------------------------------------
(TE,VE) |- CallA(e,AT,m,args) cexp_hastype rt
// Execution: The CCall and ICall rules are tricky, because the third
// line incrmentally creates an array Vts, i.e. we have < new
// pattern variables. We need explicit support for variable
// sized collections of pattern variables, indexed by numbers. This
// is like building in primitives for arrays in programming languages.
//
// We make LEN(pvar) = exp a declaration of an array of pattern
// variables, and EL(exp)(pvar) an acceptable declaration of
// a pattern variable.
//
// Nb. whether an array access is an instance of a pattern variable
// or an expression is statically undecidable: extra information
// needs to be provided by the user.
//
// Could broaden this to pattern vars indexed by any finite set??

// cstmt_hastype
//
// env |- stmt cstmt_hastype <varType option>
//
// options used for void types, which are not regular types.

// bug detected: redesigned cstmt_hastype so it doesn't actually
// return a type. Detected because of difficulty of evaluating
// the constructions used.
//
// BUG: For the moment I am forcing Expr() constructs to type to :void.
lfp cstmt_hastype
Assign (TE,VE) |- v cvar_hastype vt &
(TE,VE) |- e cexp_hastype SOME(vt') &
TE |- vt' varty_widens_to vt
// -----------------------------------------------
(TE,VE) |- AssignA(v,e) cstmt_hastype
If (TE,VE) |- stmt1 cstmt_hastype &
(TE,VE) |- stmt2 cstmt_hastype &
(TE,VE) |- e cexp_hastype SOME(VT(PrimT(boolT),0))
// ------------------------------------------------------------------
(TE,VE) |- IfA(e,stmt1,stmt2) cstmt_hastype
Block !j. j < LEN(stmts) --> (TE,VE) |- EL(j)(stmts) cstmt_hastype
// ------------------------------------------------------------------
(TE,VE) |- BlockA(stmts) cstmt_hastype
Expr (TE,VE) |- e cexp_hastype NONE
// ----------------------------------------
(TE,VE) |- ExprA(e) cstmt_hastype
// bug detected: case when no return statement was specifed was
// screwy
lfp cbody_hastype
body
(TE,VE) |- stmt cstmt_hastype &
(TE,VE) |- exp cexp_hastype vt
// ---------------------------------------------------------------
(TE,VE) |- (stmt,exp) cbody_hastype vt

// cmethod_hastype
//
//
// The complex FOLDL expression iterates through the bound variables,
// replacing each by a fresh variable, and adding the new variable
// to the environment.

lfp cmethod_hastype
mbody
ELS(Xord) = PDOM(Xtys) &
ORDERING(Xord) = T &
(TE,(Xtys <+ (this, VT(Class(C),0)))) |- body cbody_hastype rt' &
TE |- rt' expty_widens_to rt
// -------------------------------------------------------------------
(C,TE) |- ((Xord,Xtys),body) cmethod_hastype MT(MAP(PAPPLY(Xtys))(Xord),rt)
// BUG: we don't check that everything in class has a decl. We do
// check it the other way around.
//
// bug found by execution: this was getting assigned the wrong type.
def cclass_hastype
(C,TE) |- (Csupo,mbodies) cclass_hastype (Csupo',Is,fields,methods) <=>
(Csupo = Csupo') &
Cdec(TE,C) = SOME(CLASS(Csupo,Is,fields,methods)) &
(!m mt. (m,mt) :: methods -->
(?mbody. (m,mbody) :: ELS(mbodies) &
(C,TE) |- mbody cmethod_hastype mt) ) &
(!m mbody. (m,mbody) :: ELS(mbodies) -->
(?mt. (m,mt) :: methods &
(C,TE) |- mbody cmethod_hastype mt) )
def cprog_hastype
TE |- (cprog:cprog) cprog_hastype <=>
(!C ctyp. C :: PDOM(FST(TE)) & Cdec(TE,C) = SOME(CLASS(ctyp)) -->
(?cclass. (C,cclass) :: ELS(cprog) &
(C,TE) |- cclass cclass_hastype ctyp) ) &
(!C cclass. (C,cclass) :: ELS(cprog) -->
(?ctyp. Cdec(TE,C) = SOME(CLASS(ctyp)) &
(C,TE) |- cclass cclass_hastype ctyp) )
|