wenzelm@12857: (* Title: HOL/Bali/WellType.thy schirmer@12854: ID: $Id$ schirmer@12854: Author: David von Oheimb schirmer@12854: *) schirmer@12854: header {* Well-typedness of Java programs *} schirmer@12854: haftmann@16417: theory WellType imports DeclConcepts begin schirmer@12854: schirmer@12854: text {* schirmer@12854: improvements over Java Specification 1.0: schirmer@12854: \begin{itemize} schirmer@12854: \item methods of Object can be called upon references of interface or array type schirmer@12854: \end{itemize} schirmer@12854: simplifications: schirmer@12854: \begin{itemize} schirmer@12854: \item the type rules include all static checks on statements and expressions, schirmer@12854: e.g. definedness of names (of parameters, locals, fields, methods) schirmer@12854: \end{itemize} schirmer@12854: design issues: schirmer@12854: \begin{itemize} schirmer@12854: \item unified type judgment for statements, variables, expressions, schirmer@12854: expression lists schirmer@12854: \item statements are typed like expressions with dummy type Void schirmer@12854: \item the typing rules take an extra argument that is capable of determining schirmer@12854: the dynamic type of objects. Therefore, they can be used for both schirmer@12854: checking static types and determining runtime types in transition semantics. schirmer@12854: \end{itemize} schirmer@12854: *} schirmer@12854: schirmer@12854: types lenv schirmer@13688: = "(lname, ty) table" --{* local variables, including This and Result*} schirmer@12854: schirmer@12854: record env = schirmer@13688: prg:: "prog" --{* program *} schirmer@13688: cls:: "qtname" --{* current package and class name *} schirmer@13688: lcl:: "lenv" --{* local environment *} schirmer@12854: schirmer@12854: translations schirmer@12854: "lenv" <= (type) "(lname, ty) table" schirmer@12854: "lenv" <= (type) "lname \ ty option" schirmer@12854: "env" <= (type) "\prg::prog,cls::qtname,lcl::lenv\" schirmer@12854: "env" <= (type) "\prg::prog,cls::qtname,lcl::lenv,\::'a\" schirmer@12854: schirmer@12854: schirmer@12854: schirmer@12854: syntax schirmer@13688: pkg :: "env \ pname" --{* select the current package from an environment *} schirmer@13688: translations schirmer@12854: "pkg e" == "pid (cls e)" schirmer@12854: schirmer@12854: section "Static overloading: maximally specific methods " schirmer@12854: schirmer@12854: types schirmer@12854: emhead = "ref_ty \ mhead" schirmer@12854: schirmer@13688: --{* Some mnemotic selectors for emhead *} schirmer@12854: constdefs schirmer@12854: "declrefT" :: "emhead \ ref_ty" schirmer@12854: "declrefT \ fst" schirmer@12854: schirmer@12854: "mhd" :: "emhead \ mhead" schirmer@12854: "mhd \ snd" schirmer@12854: schirmer@12854: lemma declrefT_simp[simp]:"declrefT (r,m) = r" schirmer@12854: by (simp add: declrefT_def) schirmer@12854: schirmer@12854: lemma mhd_simp[simp]:"mhd (r,m) = m" schirmer@12854: by (simp add: mhd_def) schirmer@12854: schirmer@12854: lemma static_mhd_simp[simp]: "static (mhd m) = is_static m" schirmer@12854: by (cases m) (simp add: member_is_static_simp mhd_def) schirmer@12854: schirmer@12854: lemma mhd_resTy_simp [simp]: "resTy (mhd m) = resTy m" schirmer@12854: by (cases m) simp schirmer@12854: schirmer@12854: lemma mhd_is_static_simp [simp]: "is_static (mhd m) = is_static m" schirmer@12854: by (cases m) simp schirmer@12854: schirmer@12854: lemma mhd_accmodi_simp [simp]: "accmodi (mhd m) = accmodi m" schirmer@12854: by (cases m) simp schirmer@12854: schirmer@12854: consts schirmer@12854: cmheads :: "prog \ qtname \ qtname \ sig \ emhead set" schirmer@12854: Objectmheads :: "prog \ qtname \ sig \ emhead set" schirmer@12854: accObjectmheads:: "prog \ qtname \ ref_ty \ sig \ emhead set" schirmer@12854: mheads :: "prog \ qtname \ ref_ty \ sig \ emhead set" schirmer@12854: defs schirmer@12854: cmheads_def: schirmer@12854: "cmheads G S C schirmer@12854: \ \sig. (\(Cls,mthd). (ClassT Cls,(mhead mthd))) ` o2s (accmethd G S C sig)" schirmer@12854: Objectmheads_def: schirmer@12854: "Objectmheads G S schirmer@12854: \ \sig. (\(Cls,mthd). (ClassT Cls,(mhead mthd))) schirmer@12854: ` o2s (filter_tab (\sig m. accmodi m \ Private) (accmethd G S Object) sig)" schirmer@12854: accObjectmheads_def: schirmer@12854: "accObjectmheads G S T schirmer@12854: \ if G\RefT T accessible_in (pid S) schirmer@12854: then Objectmheads G S schirmer@12854: else \sig. {}" schirmer@12854: primrec schirmer@12854: "mheads G S NullT = (\sig. {})" schirmer@12854: "mheads G S (IfaceT I) = (\sig. (\(I,h).(IfaceT I,h)) schirmer@12854: ` accimethds G (pid S) I sig \ schirmer@12854: accObjectmheads G S (IfaceT I) sig)" schirmer@12854: "mheads G S (ClassT C) = cmheads G S C" schirmer@12854: "mheads G S (ArrayT T) = accObjectmheads G S (ArrayT T)" schirmer@12854: schirmer@12854: constdefs schirmer@13688: --{* applicable methods, cf. 15.11.2.1 *} schirmer@12854: appl_methds :: "prog \ qtname \ ref_ty \ sig \ (emhead \ ty list)\ set" schirmer@12854: "appl_methds G S rt \ \ sig. schirmer@12854: {(mh,pTs') |mh pTs'. mh \ mheads G S rt \name=name sig,parTs=pTs'\ \ schirmer@12854: G\(parTs sig)[\]pTs'}" schirmer@12854: schirmer@13688: --{* more specific methods, cf. 15.11.2.2 *} schirmer@12854: more_spec :: "prog \ emhead \ ty list \ emhead \ ty list \ bool" schirmer@12854: "more_spec G \ \(mh,pTs). \(mh',pTs'). G\pTs[\]pTs'" schirmer@12854: (*more_spec G \\((d,h),pTs). \((d',h'),pTs'). G\RefT d\RefT d'\G\pTs[\]pTs'*) schirmer@12854: schirmer@13688: --{* maximally specific methods, cf. 15.11.2.2 *} schirmer@12854: max_spec :: "prog \ qtname \ ref_ty \ sig \ (emhead \ ty list)\ set" schirmer@12854: schirmer@12854: "max_spec G S rt sig \{m. m \appl_methds G S rt sig \ schirmer@12854: (\m'\appl_methds G S rt sig. more_spec G m' m \ m'=m)}" schirmer@12854: schirmer@12854: schirmer@12854: lemma max_spec2appl_meths: schirmer@12854: "x \ max_spec G S T sig \ x \ appl_methds G S T sig" schirmer@12854: by (auto simp: max_spec_def) schirmer@12854: schirmer@12854: lemma appl_methsD: "(mh,pTs')\appl_methds G S T \name=mn,parTs=pTs\ \ schirmer@12854: mh \ mheads G S T \name=mn,parTs=pTs'\ \ G\pTs[\]pTs'" schirmer@12854: by (auto simp: appl_methds_def) schirmer@12854: schirmer@12854: lemma max_spec2mheads: schirmer@12854: "max_spec G S rt \name=mn,parTs=pTs\ = insert (mh, pTs') A schirmer@12854: \ mh \ mheads G S rt \name=mn,parTs=pTs'\ \ G\pTs[\]pTs'" schirmer@12854: apply (auto dest: equalityD2 subsetD max_spec2appl_meths appl_methsD) schirmer@12854: done schirmer@12854: schirmer@12854: schirmer@12854: constdefs schirmer@12854: empty_dt :: "dyn_ty" schirmer@12854: "empty_dt \ \a. None" schirmer@12854: schirmer@12854: invmode :: "('a::type)member_scheme \ expr \ inv_mode" schirmer@12925: "invmode m e \ if is_static m schirmer@12925: then Static schirmer@12925: else if e=Super then SuperM else IntVir" schirmer@12854: schirmer@12854: lemma invmode_nonstatic [simp]: schirmer@12854: "invmode \access=a,static=False,\=x\ (Acc (LVar e)) = IntVir" schirmer@12854: apply (unfold invmode_def) schirmer@12925: apply (simp (no_asm) add: member_is_static_simp) schirmer@12925: done schirmer@12925: schirmer@12925: schirmer@12925: lemma invmode_Static_eq [simp]: "(invmode m e = Static) = is_static m" schirmer@12925: apply (unfold invmode_def) schirmer@12854: apply (simp (no_asm)) schirmer@12854: done schirmer@12854: schirmer@12854: schirmer@12925: lemma invmode_IntVir_eq: "(invmode m e = IntVir) = (\(is_static m) \ e\Super)" schirmer@12854: apply (unfold invmode_def) schirmer@12854: apply (simp (no_asm)) schirmer@12854: done schirmer@12854: schirmer@12854: lemma Null_staticD: schirmer@12925: "a'=Null \ (is_static m) \ invmode m e = IntVir \ a' \ Null" schirmer@12854: apply (clarsimp simp add: invmode_IntVir_eq) schirmer@12854: done schirmer@12854: schirmer@13688: section "Typing for unary operations" schirmer@13688: schirmer@13337: consts unop_type :: "unop \ prim_ty" schirmer@13337: primrec schirmer@13337: "unop_type UPlus = Integer" schirmer@13337: "unop_type UMinus = Integer" schirmer@13337: "unop_type UBitNot = Integer" schirmer@13337: "unop_type UNot = Boolean" schirmer@12854: schirmer@13337: consts wt_unop :: "unop \ ty \ bool" schirmer@13337: primrec schirmer@13337: "wt_unop UPlus t = (t = PrimT Integer)" schirmer@13337: "wt_unop UMinus t = (t = PrimT Integer)" schirmer@13337: "wt_unop UBitNot t = (t = PrimT Integer)" schirmer@13337: "wt_unop UNot t = (t = PrimT Boolean)" schirmer@13337: schirmer@13688: section "Typing for binary operations" schirmer@13688: schirmer@13337: consts binop_type :: "binop \ prim_ty" schirmer@13337: primrec schirmer@13337: "binop_type Mul = Integer" schirmer@13337: "binop_type Div = Integer" schirmer@13337: "binop_type Mod = Integer" schirmer@13337: "binop_type Plus = Integer" schirmer@13337: "binop_type Minus = Integer" schirmer@13337: "binop_type LShift = Integer" schirmer@13337: "binop_type RShift = Integer" schirmer@13337: "binop_type RShiftU = Integer" schirmer@13337: "binop_type Less = Boolean" schirmer@13337: "binop_type Le = Boolean" schirmer@13337: "binop_type Greater = Boolean" schirmer@13337: "binop_type Ge = Boolean" schirmer@13337: "binop_type Eq = Boolean" schirmer@13337: "binop_type Neq = Boolean" schirmer@13337: "binop_type BitAnd = Integer" schirmer@13337: "binop_type And = Boolean" schirmer@13337: "binop_type BitXor = Integer" schirmer@13337: "binop_type Xor = Boolean" schirmer@13337: "binop_type BitOr = Integer" schirmer@13337: "binop_type Or = Boolean" schirmer@13384: "binop_type CondAnd = Boolean" schirmer@13384: "binop_type CondOr = Boolean" schirmer@13337: schirmer@13337: consts wt_binop :: "prog \ binop \ ty \ ty \ bool" schirmer@13337: primrec schirmer@13337: "wt_binop G Mul t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Div t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Mod t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Plus t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Minus t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G LShift t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G RShift t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G RShiftU t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Less t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Le t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Greater t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Ge t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Eq t1 t2 = (G\t1\t2 \ G\t2\t1)" schirmer@13337: "wt_binop G Neq t1 t2 = (G\t1\t2 \ G\t2\t1)" schirmer@13337: "wt_binop G BitAnd t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G And t1 t2 = ((t1 = PrimT Boolean) \ (t2 = PrimT Boolean))" schirmer@13337: "wt_binop G BitXor t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Xor t1 t2 = ((t1 = PrimT Boolean) \ (t2 = PrimT Boolean))" schirmer@13337: "wt_binop G BitOr t1 t2 = ((t1 = PrimT Integer) \ (t2 = PrimT Integer))" schirmer@13337: "wt_binop G Or t1 t2 = ((t1 = PrimT Boolean) \ (t2 = PrimT Boolean))" schirmer@13384: "wt_binop G CondAnd t1 t2 = ((t1 = PrimT Boolean) \ (t2 = PrimT Boolean))" schirmer@13384: "wt_binop G CondOr t1 t2 = ((t1 = PrimT Boolean) \ (t2 = PrimT Boolean))" schirmer@13337: schirmer@13688: section "Typing for terms" schirmer@13384: schirmer@12854: types tys = "ty + ty list" schirmer@12854: translations schirmer@12854: "tys" <= (type) "ty + ty list" schirmer@12854: berghofe@21765: berghofe@21765: inductive2 berghofe@21765: wt :: "env \ dyn_ty \ [term,tys] \ bool" ("_,_\_\_" [51,51,51,51] 50) berghofe@21765: and wt_stmt :: "env \ dyn_ty \ stmt \ bool" ("_,_\_\\" [51,51,51 ] 50) berghofe@21765: and ty_expr :: "env \ dyn_ty \ [expr ,ty ] \ bool" ("_,_\_\-_" [51,51,51,51] 50) berghofe@21765: and ty_var :: "env \ dyn_ty \ [var ,ty ] \ bool" ("_,_\_\=_" [51,51,51,51] 50) berghofe@21765: and ty_exprs :: "env \ dyn_ty \ [expr list, ty list] \ bool" berghofe@21765: ("_,_\_\\_" [51,51,51,51] 50) berghofe@21765: where berghofe@21765: berghofe@21765: "E,dt\s\\ \ E,dt\In1r s\Inl (PrimT Void)" berghofe@21765: | "E,dt\e\-T \ E,dt\In1l e\Inl T" berghofe@21765: | "E,dt\e\=T \ E,dt\In2 e\Inl T" berghofe@21765: | "E,dt\e\\T \ E,dt\In3 e\Inr T" berghofe@21765: berghofe@21765: --{* well-typed statements *} berghofe@21765: berghofe@21765: | Skip: "E,dt\Skip\\" berghofe@21765: berghofe@21765: | Expr: "\E,dt\e\-T\ \ berghofe@21765: E,dt\Expr e\\" berghofe@21765: --{* cf. 14.6 *} berghofe@21765: | Lab: "E,dt\c\\ \ berghofe@21765: E,dt\l\ c\\" berghofe@21765: berghofe@21765: | Comp: "\E,dt\c1\\; berghofe@21765: E,dt\c2\\\ \ berghofe@21765: E,dt\c1;; c2\\" berghofe@21765: berghofe@21765: --{* cf. 14.8 *} berghofe@21765: | If: "\E,dt\e\-PrimT Boolean; berghofe@21765: E,dt\c1\\; berghofe@21765: E,dt\c2\\\ \ berghofe@21765: E,dt\If(e) c1 Else c2\\" berghofe@21765: berghofe@21765: --{* cf. 14.10 *} berghofe@21765: | Loop: "\E,dt\e\-PrimT Boolean; berghofe@21765: E,dt\c\\\ \ berghofe@21765: E,dt\l\ While(e) c\\" berghofe@21765: --{* cf. 14.13, 14.15, 14.16 *} berghofe@21765: | Jmp: "E,dt\Jmp jump\\" schirmer@12854: berghofe@21765: --{* cf. 14.16 *} berghofe@21765: | Throw: "\E,dt\e\-Class tn; berghofe@21765: prg E\tn\\<^sub>C SXcpt Throwable\ \ berghofe@21765: E,dt\Throw e\\" berghofe@21765: --{* cf. 14.18 *} berghofe@21765: | Try: "\E,dt\c1\\; prg E\tn\\<^sub>C SXcpt Throwable; berghofe@21765: lcl E (VName vn)=None; E \lcl := lcl E(VName vn\Class tn)\,dt\c2\\\ berghofe@21765: \ berghofe@21765: E,dt\Try c1 Catch(tn vn) c2\\" berghofe@21765: berghofe@21765: --{* cf. 14.18 *} berghofe@21765: | Fin: "\E,dt\c1\\; E,dt\c2\\\ \ berghofe@21765: E,dt\c1 Finally c2\\" berghofe@21765: berghofe@21765: | Init: "\is_class (prg E) C\ \ berghofe@21765: E,dt\Init C\\" berghofe@21765: --{* @{term Init} is created on the fly during evaluation (see Eval.thy). berghofe@21765: The class isn't necessarily accessible from the points @{term Init} berghofe@21765: is called. Therefor we only demand @{term is_class} and not berghofe@21765: @{term is_acc_class} here. berghofe@21765: *} berghofe@21765: berghofe@21765: --{* well-typed expressions *} berghofe@21765: berghofe@21765: --{* cf. 15.8 *} berghofe@21765: | NewC: "\is_acc_class (prg E) (pkg E) C\ \ berghofe@21765: E,dt\NewC C\-Class C" berghofe@21765: --{* cf. 15.9 *} berghofe@21765: | NewA: "\is_acc_type (prg E) (pkg E) T; berghofe@21765: E,dt\i\-PrimT Integer\ \ berghofe@21765: E,dt\New T[i]\-T.[]" berghofe@21765: berghofe@21765: --{* cf. 15.15 *} berghofe@21765: | Cast: "\E,dt\e\-T; is_acc_type (prg E) (pkg E) T'; berghofe@21765: prg E\T\? T'\ \ berghofe@21765: E,dt\Cast T' e\-T'" berghofe@21765: berghofe@21765: --{* cf. 15.19.2 *} berghofe@21765: | Inst: "\E,dt\e\-RefT T; is_acc_type (prg E) (pkg E) (RefT T'); berghofe@21765: prg E\RefT T\? RefT T'\ \ berghofe@21765: E,dt\e InstOf T'\-PrimT Boolean" berghofe@21765: berghofe@21765: --{* cf. 15.7.1 *} berghofe@21765: | Lit: "\typeof dt x = Some T\ \ berghofe@21765: E,dt\Lit x\-T" schirmer@12854: berghofe@21765: | UnOp: "\E,dt\e\-Te; wt_unop unop Te; T=PrimT (unop_type unop)\ berghofe@21765: \ berghofe@21765: E,dt\UnOp unop e\-T" berghofe@21765: berghofe@21765: | BinOp: "\E,dt\e1\-T1; E,dt\e2\-T2; wt_binop (prg E) binop T1 T2; berghofe@21765: T=PrimT (binop_type binop)\ berghofe@21765: \ berghofe@21765: E,dt\BinOp binop e1 e2\-T" berghofe@21765: berghofe@21765: --{* cf. 15.10.2, 15.11.1 *} berghofe@21765: | Super: "\lcl E This = Some (Class C); C \ Object; berghofe@21765: class (prg E) C = Some c\ \ berghofe@21765: E,dt\Super\-Class (super c)" berghofe@21765: berghofe@21765: --{* cf. 15.13.1, 15.10.1, 15.12 *} berghofe@21765: | Acc: "\E,dt\va\=T\ \ berghofe@21765: E,dt\Acc va\-T" berghofe@21765: berghofe@21765: --{* cf. 15.25, 15.25.1 *} berghofe@21765: | Ass: "\E,dt\va\=T; va \ LVar This; berghofe@21765: E,dt\v \-T'; berghofe@21765: prg E\T'\T\ \ berghofe@21765: E,dt\va:=v\-T'" berghofe@21765: berghofe@21765: --{* cf. 15.24 *} berghofe@21765: | Cond: "\E,dt\e0\-PrimT Boolean; berghofe@21765: E,dt\e1\-T1; E,dt\e2\-T2; berghofe@21765: prg E\T1\T2 \ T = T2 \ prg E\T2\T1 \ T = T1\ \ berghofe@21765: E,dt\e0 ? e1 : e2\-T" berghofe@21765: berghofe@21765: --{* cf. 15.11.1, 15.11.2, 15.11.3 *} berghofe@21765: | Call: "\E,dt\e\-RefT statT; berghofe@21765: E,dt\ps\\pTs; berghofe@21765: max_spec (prg E) (cls E) statT \name=mn,parTs=pTs\ berghofe@21765: = {((statDeclT,m),pTs')} berghofe@21765: \ \ berghofe@21765: E,dt\{cls E,statT,invmode m e}e\mn({pTs'}ps)\-(resTy m)" schirmer@12854: berghofe@21765: | Methd: "\is_class (prg E) C; berghofe@21765: methd (prg E) C sig = Some m; berghofe@21765: E,dt\Body (declclass m) (stmt (mbody (mthd m)))\-T\ \ berghofe@21765: E,dt\Methd C sig\-T" berghofe@21765: --{* The class @{term C} is the dynamic class of the method call berghofe@21765: (cf. Eval.thy). berghofe@21765: It hasn't got to be directly accessible from the current package berghofe@21765: @{term "(pkg E)"}. berghofe@21765: Only the static class must be accessible (enshured indirectly by berghofe@21765: @{term Call}). berghofe@21765: Note that l is just a dummy value. It is only used in the smallstep berghofe@21765: semantics. To proof typesafety directly for the smallstep semantics berghofe@21765: we would have to assume conformance of l here! berghofe@21765: *} berghofe@21765: berghofe@21765: | Body: "\is_class (prg E) D; berghofe@21765: E,dt\blk\\; berghofe@21765: (lcl E) Result = Some T; berghofe@21765: is_type (prg E) T\ \ berghofe@21765: E,dt\Body D blk\-T" berghofe@21765: --{* The class @{term D} implementing the method must not directly be berghofe@21765: accessible from the current package @{term "(pkg E)"}, but can also berghofe@21765: be indirectly accessible due to inheritance (enshured in @{term Call}) berghofe@21765: The result type hasn't got to be accessible in Java! (If it is not berghofe@21765: accessible you can only assign it to Object). berghofe@21765: For dummy value l see rule @{term Methd}. berghofe@21765: *} berghofe@21765: berghofe@21765: --{* well-typed variables *} berghofe@21765: berghofe@21765: --{* cf. 15.13.1 *} berghofe@21765: | LVar: "\lcl E vn = Some T; is_acc_type (prg E) (pkg E) T\ \ berghofe@21765: E,dt\LVar vn\=T" berghofe@21765: --{* cf. 15.10.1 *} berghofe@21765: | FVar: "\E,dt\e\-Class C; berghofe@21765: accfield (prg E) (cls E) C fn = Some (statDeclC,f)\ \ berghofe@21765: E,dt\{cls E,statDeclC,is_static f}e..fn\=(type f)" berghofe@21765: --{* cf. 15.12 *} berghofe@21765: | AVar: "\E,dt\e\-T.[]; berghofe@21765: E,dt\i\-PrimT Integer\ \ berghofe@21765: E,dt\e.[i]\=T" berghofe@21765: berghofe@21765: berghofe@21765: --{* well-typed expression lists *} berghofe@21765: berghofe@21765: --{* cf. 15.11.??? *} berghofe@21765: | Nil: "E,dt\[]\\[]" berghofe@21765: berghofe@21765: --{* cf. 15.11.??? *} berghofe@21765: | Cons: "\E,dt\e \-T; berghofe@21765: E,dt\es\\Ts\ \ berghofe@21765: E,dt\e#es\\T#Ts" berghofe@21765: schirmer@12854: schirmer@12854: syntax (* for purely static typing *) schirmer@12854: wt_ :: "env \ [term,tys] \ bool" ("_|-_::_" [51,51,51] 50) schirmer@12854: wt_stmt_ :: "env \ stmt \ bool" ("_|-_:<>" [51,51 ] 50) schirmer@12854: ty_expr_ :: "env \ [expr ,ty ] \ bool" ("_|-_:-_" [51,51,51] 50) schirmer@12854: ty_var_ :: "env \ [var ,ty ] \ bool" ("_|-_:=_" [51,51,51] 50) schirmer@12854: ty_exprs_:: "env \ [expr list, schirmer@12854: \ ty list] \ bool" ("_|-_:#_" [51,51,51] 50) schirmer@12854: schirmer@12854: syntax (xsymbols) schirmer@12854: wt_ :: "env \ [term,tys] \ bool" ("_\_\_" [51,51,51] 50) schirmer@12854: wt_stmt_ :: "env \ stmt \ bool" ("_\_\\" [51,51 ] 50) schirmer@12854: ty_expr_ :: "env \ [expr ,ty ] \ bool" ("_\_\-_" [51,51,51] 50) schirmer@12854: ty_var_ :: "env \ [var ,ty ] \ bool" ("_\_\=_" [51,51,51] 50) schirmer@12854: ty_exprs_ :: "env \ [expr list, schirmer@12854: \ ty list] \ bool" ("_\_\\_" [51,51,51] 50) schirmer@12854: schirmer@12854: translations schirmer@12854: "E\t\ T" == "E,empty_dt\t\ T" schirmer@13688: "E\s\\" == "E\In1r s\Inl (PrimT Void)" schirmer@13688: "E\e\-T" == "E\In1l e\Inl T" schirmer@13688: "E\e\=T" == "E\In2 e\Inl T" schirmer@13688: "E\e\\T" == "E\In3 e\Inr T" schirmer@12854: schirmer@13337: schirmer@12854: declare not_None_eq [simp del] schirmer@12854: declare split_if [split del] split_if_asm [split del] schirmer@12854: declare split_paired_All [simp del] split_paired_Ex [simp del] schirmer@12854: ML_setup {* wenzelm@17876: change_simpset (fn ss => ss delloop "split_all_tac") schirmer@12854: *} schirmer@13688: berghofe@21765: inductive_cases2 wt_elim_cases [cases set]: schirmer@12854: "E,dt\In2 (LVar vn) \T" schirmer@12925: "E,dt\In2 ({accC,statDeclC,s}e..fn)\T" schirmer@12854: "E,dt\In2 (e.[i]) \T" schirmer@12854: "E,dt\In1l (NewC C) \T" schirmer@12854: "E,dt\In1l (New T'[i]) \T" schirmer@12854: "E,dt\In1l (Cast T' e) \T" schirmer@12854: "E,dt\In1l (e InstOf T') \T" schirmer@12854: "E,dt\In1l (Lit x) \T" schirmer@13337: "E,dt\In1l (UnOp unop e) \T" schirmer@13337: "E,dt\In1l (BinOp binop e1 e2) \T" schirmer@12854: "E,dt\In1l (Super) \T" schirmer@12854: "E,dt\In1l (Acc va) \T" schirmer@12854: "E,dt\In1l (Ass va v) \T" schirmer@12854: "E,dt\In1l (e0 ? e1 : e2) \T" schirmer@12925: "E,dt\In1l ({accC,statT,mode}e\mn({pT'}p))\T" schirmer@12854: "E,dt\In1l (Methd C sig) \T" schirmer@12854: "E,dt\In1l (Body D blk) \T" schirmer@12854: "E,dt\In3 ([]) \Ts" schirmer@12854: "E,dt\In3 (e#es) \Ts" schirmer@12854: "E,dt\In1r Skip \x" schirmer@12854: "E,dt\In1r (Expr e) \x" schirmer@12854: "E,dt\In1r (c1;; c2) \x" schirmer@12854: "E,dt\In1r (l\ c) \x" schirmer@12854: "E,dt\In1r (If(e) c1 Else c2) \x" schirmer@12854: "E,dt\In1r (l\ While(e) c) \x" schirmer@13688: "E,dt\In1r (Jmp jump) \x" schirmer@12854: "E,dt\In1r (Throw e) \x" schirmer@12854: "E,dt\In1r (Try c1 Catch(tn vn) c2)\x" schirmer@12854: "E,dt\In1r (c1 Finally c2) \x" schirmer@12854: "E,dt\In1r (Init C) \x" schirmer@12854: declare not_None_eq [simp] schirmer@12854: declare split_if [split] split_if_asm [split] schirmer@12854: declare split_paired_All [simp] split_paired_Ex [simp] schirmer@12854: ML_setup {* wenzelm@17876: change_simpset (fn ss => ss addloop ("split_all_tac", split_all_tac)); schirmer@12854: *} schirmer@12854: schirmer@12854: lemma is_acc_class_is_accessible: schirmer@12854: "is_acc_class G P C \ G\(Class C) accessible_in P" schirmer@12854: by (auto simp add: is_acc_class_def) schirmer@12854: schirmer@12854: lemma is_acc_iface_is_iface: "is_acc_iface G P I \ is_iface G I" schirmer@12854: by (auto simp add: is_acc_iface_def) schirmer@12854: wenzelm@13524: lemma is_acc_iface_Iface_is_accessible: schirmer@12854: "is_acc_iface G P I \ G\(Iface I) accessible_in P" schirmer@12854: by (auto simp add: is_acc_iface_def) schirmer@12854: schirmer@12854: lemma is_acc_type_is_type: "is_acc_type G P T \ is_type G T" schirmer@12854: by (auto simp add: is_acc_type_def) schirmer@12854: wenzelm@13524: lemma is_acc_iface_is_accessible: wenzelm@13524: "is_acc_type G P T \ G\T accessible_in P" schirmer@12854: by (auto simp add: is_acc_type_def) schirmer@12854: schirmer@12854: lemma wt_Methd_is_methd: schirmer@12854: "E\In1l (Methd C sig)\T \ is_methd (prg E) C sig" schirmer@12854: apply (erule_tac wt_elim_cases) schirmer@12854: apply clarsimp schirmer@12854: apply (erule is_methdI, assumption) schirmer@12854: done schirmer@12854: schirmer@13688: schirmer@13688: text {* Special versions of some typing rules, better suited to pattern schirmer@13688: match the conclusion (no selectors in the conclusion) schirmer@13688: *} schirmer@12854: schirmer@12854: lemma wt_Call: schirmer@12854: "\E,dt\e\-RefT statT; E,dt\ps\\pTs; schirmer@12854: max_spec (prg E) (cls E) statT \name=mn,parTs=pTs\ schirmer@12925: = {((statDeclC,m),pTs')};rT=(resTy m);accC=cls E; schirmer@12925: mode = invmode m e\ \ E,dt\{accC,statT,mode}e\mn({pTs'}ps)\-rT" schirmer@12854: by (auto elim: wt.Call) schirmer@12854: schirmer@12854: schirmer@12854: lemma invocationTypeExpr_noClassD: schirmer@12854: "\ E\e\-RefT statT\ schirmer@12854: \ (\ statC. statT \ ClassT statC) \ invmode m e \ SuperM" schirmer@12854: proof - schirmer@12854: assume wt: "E\e\-RefT statT" schirmer@12854: show ?thesis schirmer@12854: proof (cases "e=Super") schirmer@12854: case True schirmer@12854: with wt obtain "C" where "statT = ClassT C" by (blast elim: wt_elim_cases) schirmer@12854: then show ?thesis by blast schirmer@12854: next schirmer@12854: case False then show ?thesis schirmer@12854: by (auto simp add: invmode_def split: split_if_asm) schirmer@12854: qed schirmer@12854: qed schirmer@12854: schirmer@12854: lemma wt_Super: schirmer@12854: "\lcl E This = Some (Class C); C \ Object; class (prg E) C = Some c; D=super c\ schirmer@12854: \ E,dt\Super\-Class D" schirmer@12854: by (auto elim: wt.Super) schirmer@12854: schirmer@12925: lemma wt_FVar: schirmer@12925: "\E,dt\e\-Class C; accfield (prg E) (cls E) C fn = Some (statDeclC,f); schirmer@12925: sf=is_static f; fT=(type f); accC=cls E\ schirmer@12925: \ E,dt\{accC,statDeclC,sf}e..fn\=fT" schirmer@12925: by (auto dest: wt.FVar) schirmer@12854: schirmer@12854: schirmer@12854: lemma wt_init [iff]: "E,dt\Init C\\ = is_class (prg E) C" schirmer@12854: by (auto elim: wt_elim_cases intro: "wt.Init") schirmer@12854: schirmer@12854: declare wt.Skip [iff] schirmer@12854: schirmer@12854: lemma wt_StatRef: schirmer@12854: "is_acc_type (prg E) (pkg E) (RefT rt) \ E\StatRef rt\-RefT rt" schirmer@12854: apply (rule wt.Cast) schirmer@12854: apply (rule wt.Lit) schirmer@12854: apply (simp (no_asm)) schirmer@12854: apply (simp (no_asm_simp)) schirmer@12854: apply (rule cast.widen) schirmer@12854: apply (simp (no_asm)) schirmer@12854: done schirmer@12854: schirmer@12854: lemma wt_Inj_elim: schirmer@12854: "\E. E,dt\t\U \ case t of schirmer@12854: In1 ec \ (case ec of schirmer@12854: Inl e \ \T. U=Inl T schirmer@12854: | Inr s \ U=Inl (PrimT Void)) schirmer@12854: | In2 e \ (\T. U=Inl T) schirmer@12854: | In3 e \ (\T. U=Inr T)" schirmer@12854: apply (erule wt.induct) schirmer@12854: apply auto schirmer@12854: done schirmer@12854: schirmer@13688: --{* In the special syntax to distinguish the typing judgements for expressions, schirmer@13688: statements, variables and expression lists the kind of term corresponds schirmer@13688: to the kind of type in the end e.g. An statement (injection @{term In3} schirmer@13688: into terms, always has type void (injection @{term Inl} into the generalised schirmer@13688: types. The following simplification procedures establish these kinds of schirmer@13688: correlation. schirmer@13688: *} schirmer@13688: berghofe@21765: lemma wt_expr_eq: "E,dt\In1l t\U = (\T. U=Inl T \ E,dt\t\-T)" berghofe@21765: by (auto, frule wt_Inj_elim, auto) berghofe@21765: berghofe@21765: lemma wt_var_eq: "E,dt\In2 t\U = (\T. U=Inl T \ E,dt\t\=T)" berghofe@21765: by (auto, frule wt_Inj_elim, auto) berghofe@21765: berghofe@21765: lemma wt_exprs_eq: "E,dt\In3 t\U = (\Ts. U=Inr Ts \ E,dt\t\\Ts)" berghofe@21765: by (auto, frule wt_Inj_elim, auto) berghofe@21765: berghofe@21765: lemma wt_stmt_eq: "E,dt\In1r t\U = (U=Inl(PrimT Void)\E,dt\t\\)" berghofe@21765: by (auto, frule wt_Inj_elim, auto, frule wt_Inj_elim, auto) berghofe@21765: schirmer@12854: ML {* berghofe@21765: fun wt_fun name lhs = schirmer@12854: let schirmer@12854: fun is_Inj (Const (inj,_) $ _) = true schirmer@12854: | is_Inj _ = false berghofe@21765: fun pred (_ $ _ $ _ $ _ $ x) = is_Inj x schirmer@12854: in wenzelm@13462: cond_simproc name lhs pred (thm name) schirmer@12854: end schirmer@12854: berghofe@21765: val wt_expr_proc = wt_fun "wt_expr_eq" "E,dt\In1l t\U"; berghofe@21765: val wt_var_proc = wt_fun "wt_var_eq" "E,dt\In2 t\U"; berghofe@21765: val wt_exprs_proc = wt_fun "wt_exprs_eq" "E,dt\In3 t\U"; berghofe@21765: val wt_stmt_proc = wt_fun "wt_stmt_eq" "E,dt\In1r t\U"; schirmer@12854: *} schirmer@12854: schirmer@12854: ML {* schirmer@12854: Addsimprocs [wt_expr_proc,wt_var_proc,wt_exprs_proc,wt_stmt_proc] schirmer@12854: *} schirmer@12854: schirmer@13688: lemma wt_elim_BinOp: schirmer@13688: "\E,dt\In1l (BinOp binop e1 e2)\T; schirmer@13688: \T1 T2 T3. schirmer@13688: \E,dt\e1\-T1; E,dt\e2\-T2; wt_binop (prg E) binop T1 T2; schirmer@13688: E,dt\(if b then In1l e2 else In1r Skip)\T3; schirmer@13688: T = Inl (PrimT (binop_type binop))\ schirmer@13688: \ P\ schirmer@13688: \ P" schirmer@13688: apply (erule wt_elim_cases) schirmer@13688: apply (cases b) schirmer@13688: apply auto schirmer@13688: done schirmer@13688: schirmer@12854: lemma Inj_eq_lemma [simp]: schirmer@12854: "(\T. (\T'. T = Inj T' \ P T') \ Q T) = (\T'. P T' \ Q (Inj T'))" schirmer@12854: by auto schirmer@12854: schirmer@12854: (* unused *) schirmer@12854: lemma single_valued_tys_lemma [rule_format (no_asm)]: schirmer@12854: "\S T. G\S\T \ G\T\S \ S = T \ E,dt\t\T \ schirmer@12854: G = prg E \ (\T'. E,dt\t\T' \ T = T')" schirmer@12854: apply (cases "E", erule wt.induct) schirmer@12854: apply (safe del: disjE) schirmer@12854: apply (simp_all (no_asm_use) split del: split_if_asm) schirmer@12854: apply (safe del: disjE) schirmer@12854: (* 17 subgoals *) schirmer@13337: apply (tactic {* ALLGOALS (fn i => if i = 11 then EVERY'[thin_tac "?E,dt\e0\-PrimT Boolean", thin_tac "?E,dt\e1\-?T1", thin_tac "?E,dt\e2\-?T2"] i else thin_tac "All ?P" i) *}) schirmer@12854: (*apply (safe del: disjE elim!: wt_elim_cases)*) schirmer@12854: apply (tactic {*ALLGOALS (eresolve_tac (thms "wt_elim_cases"))*}) schirmer@12854: apply (simp_all (no_asm_use) split del: split_if_asm) schirmer@13337: apply (erule_tac [12] V = "All ?P" in thin_rl) (* Call *) schirmer@12854: apply ((blast del: equalityCE dest: sym [THEN trans])+) schirmer@12854: done schirmer@12854: schirmer@12854: (* unused *) schirmer@12854: lemma single_valued_tys: schirmer@12854: "ws_prog (prg E) \ single_valued {(t,T). E,dt\t\T}" schirmer@12854: apply (unfold single_valued_def) schirmer@12854: apply clarsimp schirmer@12854: apply (rule single_valued_tys_lemma) schirmer@12854: apply (auto intro!: widen_antisym) schirmer@12854: done schirmer@12854: schirmer@12854: lemma typeof_empty_is_type [rule_format (no_asm)]: schirmer@12854: "typeof (\a. None) v = Some T \ is_type G T" schirmer@12854: apply (rule val.induct) schirmer@12854: apply auto schirmer@12854: done schirmer@12854: schirmer@12854: (* unused *) schirmer@12854: lemma typeof_is_type [rule_format (no_asm)]: schirmer@12854: "(\a. v \ Addr a) \ (\T. typeof dt v = Some T \ is_type G T)" schirmer@12854: apply (rule val.induct) schirmer@12854: prefer 5 schirmer@12854: apply fast schirmer@12854: apply (simp_all (no_asm)) schirmer@12854: done schirmer@12854: schirmer@12854: end