schirmer@13688: header {* Definite Assignment *} schirmer@13688: haftmann@16417: theory DefiniteAssignment imports WellType begin schirmer@13688: schirmer@13688: text {* Definite Assignment Analysis (cf. 16) schirmer@13688: schirmer@13688: The definite assignment analysis approximates the sets of local schirmer@13688: variables that will be assigned at a certain point of evaluation, and ensures schirmer@13688: that we will only read variables which previously were assigned. schirmer@13688: It should conform to the following idea: schirmer@13688: If the evaluation of a term completes normally (no abruption (exception, schirmer@13688: break, continue, return) appeared) , the set of local variables calculated schirmer@13688: by the analysis is a subset of the schirmer@13688: variables that were actually assigned during evaluation. schirmer@13688: schirmer@13688: To get more precise information about the sets of assigned variables the schirmer@13688: analysis includes the following optimisations: schirmer@13688: \begin{itemize} schirmer@13688: \item Inside of a while loop we also take care of the variables assigned schirmer@13688: before break statements, since the break causes the while loop to schirmer@13688: continue normally. schirmer@13688: \item For conditional statements we take care of constant conditions to schirmer@13688: statically determine the path of evaluation. schirmer@13688: \item Inside a distinct path of a conditional statements we know to which schirmer@13688: boolean value the condition has evaluated to, and so can retrieve more schirmer@13688: information about the variables assigned during evaluation of the schirmer@13688: boolean condition. schirmer@13688: \end{itemize} schirmer@13688: schirmer@13688: Since in our model of Java the return values of methods are stored in a local schirmer@13688: variable we also ensure that every path of (normal) evaluation will assign the schirmer@13688: result variable, or in the sense of real Java every path ends up in and schirmer@13688: return instruction. schirmer@13688: schirmer@13688: Not covered yet: schirmer@13688: \begin{itemize} schirmer@13688: \item analysis of definite unassigned schirmer@13688: \item special treatment of final fields schirmer@13688: \end{itemize} schirmer@13688: *} schirmer@13688: schirmer@13688: section {* Correct nesting of jump statements *} schirmer@13688: schirmer@13688: text {* For definite assignment it becomes crucial, that jumps (break, schirmer@13688: continue, return) are nested correctly i.e. a continue jump is nested in a schirmer@13688: matching while statement, a break jump is nested in a proper label statement, schirmer@13688: a class initialiser does not terminate abruptly with a return. With this we schirmer@13688: can for example ensure that evaluation of an expression will never end up schirmer@13688: with a jump, since no breaks, continues or returns are allowed in an schirmer@13688: expression. *} schirmer@13688: schirmer@13688: consts jumpNestingOkS :: "jump set \ stmt \ bool" schirmer@13688: primrec schirmer@13688: "jumpNestingOkS jmps (Skip) = True" schirmer@13688: "jumpNestingOkS jmps (Expr e) = True" schirmer@13688: "jumpNestingOkS jmps (j\ s) = jumpNestingOkS ({j} \ jmps) s" schirmer@13688: "jumpNestingOkS jmps (c1;;c2) = (jumpNestingOkS jmps c1 \ schirmer@13688: jumpNestingOkS jmps c2)" schirmer@13688: "jumpNestingOkS jmps (If(e) c1 Else c2) = (jumpNestingOkS jmps c1 \ schirmer@13688: jumpNestingOkS jmps c2)" schirmer@13688: "jumpNestingOkS jmps (l\ While(e) c) = jumpNestingOkS ({Cont l} \ jmps) c" schirmer@13688: --{* The label of the while loop only handles continue jumps. Breaks are only schirmer@13688: handled by @{term Lab} *} schirmer@13688: "jumpNestingOkS jmps (Jmp j) = (j \ jmps)" schirmer@13688: "jumpNestingOkS jmps (Throw e) = True" schirmer@13688: "jumpNestingOkS jmps (Try c1 Catch(C vn) c2) = (jumpNestingOkS jmps c1 \ schirmer@13688: jumpNestingOkS jmps c2)" schirmer@13688: "jumpNestingOkS jmps (c1 Finally c2) = (jumpNestingOkS jmps c1 \ schirmer@13688: jumpNestingOkS jmps c2)" schirmer@13688: "jumpNestingOkS jmps (Init C) = True" schirmer@13688: --{* wellformedness of the program must enshure that for all initializers schirmer@13688: jumpNestingOkS {} holds *} schirmer@13688: --{* Dummy analysis for intermediate smallstep term @{term FinA} *} schirmer@13688: "jumpNestingOkS jmps (FinA a c) = False" schirmer@13688: schirmer@13688: schirmer@13688: constdefs jumpNestingOk :: "jump set \ term \ bool" schirmer@13688: "jumpNestingOk jmps t \ (case t of schirmer@13688: In1 se \ (case se of schirmer@13688: Inl e \ True schirmer@13688: | Inr s \ jumpNestingOkS jmps s) schirmer@13688: | In2 v \ True schirmer@13688: | In3 es \ True)" schirmer@13688: schirmer@13688: lemma jumpNestingOk_expr_simp [simp]: "jumpNestingOk jmps (In1l e) = True" schirmer@13688: by (simp add: jumpNestingOk_def) schirmer@13688: schirmer@13688: lemma jumpNestingOk_expr_simp1 [simp]: "jumpNestingOk jmps \e::expr\ = True" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: lemma jumpNestingOk_stmt_simp [simp]: schirmer@13688: "jumpNestingOk jmps (In1r s) = jumpNestingOkS jmps s" schirmer@13688: by (simp add: jumpNestingOk_def) schirmer@13688: schirmer@13688: lemma jumpNestingOk_stmt_simp1 [simp]: schirmer@13688: "jumpNestingOk jmps \s::stmt\ = jumpNestingOkS jmps s" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: lemma jumpNestingOk_var_simp [simp]: "jumpNestingOk jmps (In2 v) = True" schirmer@13688: by (simp add: jumpNestingOk_def) schirmer@13688: schirmer@13688: lemma jumpNestingOk_var_simp1 [simp]: "jumpNestingOk jmps \v::var\ = True" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: lemma jumpNestingOk_expr_list_simp [simp]: "jumpNestingOk jmps (In3 es) = True" schirmer@13688: by (simp add: jumpNestingOk_def) schirmer@13688: schirmer@13688: lemma jumpNestingOk_expr_list_simp1 [simp]: schirmer@13688: "jumpNestingOk jmps \es::expr list\ = True" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: schirmer@13688: schirmer@13688: section {* Calculation of assigned variables for boolean expressions*} schirmer@13688: schirmer@13688: schirmer@13688: subsection {* Very restricted calculation fallback calculation *} schirmer@13688: schirmer@13688: consts the_LVar_name:: "var \ lname" schirmer@13688: primrec schirmer@13688: "the_LVar_name (LVar n) = n" schirmer@13688: schirmer@13688: consts assignsE :: "expr \ lname set" schirmer@13688: assignsV :: "var \ lname set" schirmer@13688: assignsEs:: "expr list \ lname set" schirmer@13688: text {* *} schirmer@13688: primrec schirmer@13688: "assignsE (NewC c) = {}" schirmer@13688: "assignsE (NewA t e) = assignsE e" schirmer@13688: "assignsE (Cast t e) = assignsE e" schirmer@13688: "assignsE (e InstOf r) = assignsE e" schirmer@13688: "assignsE (Lit val) = {}" schirmer@13688: "assignsE (UnOp unop e) = assignsE e" schirmer@13688: "assignsE (BinOp binop e1 e2) = (if binop=CondAnd \ binop=CondOr schirmer@13688: then (assignsE e1) schirmer@13688: else (assignsE e1) \ (assignsE e2))" schirmer@13688: "assignsE (Super) = {}" schirmer@13688: "assignsE (Acc v) = assignsV v" schirmer@13688: "assignsE (v:=e) = (assignsV v) \ (assignsE e) \ schirmer@13688: (if \ n. v=(LVar n) then {the_LVar_name v} schirmer@13688: else {})" schirmer@13688: "assignsE (b? e1 : e2) = (assignsE b) \ ((assignsE e1) \ (assignsE e2))" schirmer@13688: "assignsE ({accC,statT,mode}objRef\mn({pTs}args)) schirmer@13688: = (assignsE objRef) \ (assignsEs args)" schirmer@13688: -- {* Only dummy analysis for intermediate expressions schirmer@13688: @{term Methd}, @{term Body}, @{term InsInitE} and @{term Callee} *} schirmer@13688: "assignsE (Methd C sig) = {}" schirmer@13688: "assignsE (Body C s) = {}" schirmer@13688: "assignsE (InsInitE s e) = {}" schirmer@13688: "assignsE (Callee l e) = {}" schirmer@13688: schirmer@13688: "assignsV (LVar n) = {}" schirmer@13688: "assignsV ({accC,statDeclC,stat}objRef..fn) = assignsE objRef" schirmer@13688: "assignsV (e1.[e2]) = assignsE e1 \ assignsE e2" schirmer@13688: schirmer@13688: "assignsEs [] = {}" schirmer@13688: "assignsEs (e#es) = assignsE e \ assignsEs es" schirmer@13688: schirmer@13688: constdefs assigns:: "term \ lname set" schirmer@13688: "assigns t \ (case t of schirmer@13688: In1 se \ (case se of schirmer@13688: Inl e \ assignsE e schirmer@13688: | Inr s \ {}) schirmer@13688: | In2 v \ assignsV v schirmer@13688: | In3 es \ assignsEs es)" schirmer@13688: schirmer@13688: lemma assigns_expr_simp [simp]: "assigns (In1l e) = assignsE e" schirmer@13688: by (simp add: assigns_def) schirmer@13688: schirmer@13688: lemma assigns_expr_simp1 [simp]: "assigns (\e\) = assignsE e" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: lemma assigns_stmt_simp [simp]: "assigns (In1r s) = {}" schirmer@13688: by (simp add: assigns_def) schirmer@13688: schirmer@13688: lemma assigns_stmt_simp1 [simp]: "assigns (\s::stmt\) = {}" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: lemma assigns_var_simp [simp]: "assigns (In2 v) = assignsV v" schirmer@13688: by (simp add: assigns_def) schirmer@13688: schirmer@13688: lemma assigns_var_simp1 [simp]: "assigns (\v\) = assignsV v" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: lemma assigns_expr_list_simp [simp]: "assigns (In3 es) = assignsEs es" schirmer@13688: by (simp add: assigns_def) schirmer@13688: schirmer@13688: lemma assigns_expr_list_simp1 [simp]: "assigns (\es\) = assignsEs es" schirmer@13688: by (simp add: inj_term_simps) schirmer@13688: schirmer@13688: subsection "Analysis of constant expressions" schirmer@13688: schirmer@13688: consts constVal :: "expr \ val option" schirmer@13688: primrec schirmer@13688: "constVal (NewC c) = None" schirmer@13688: "constVal (NewA t e) = None" schirmer@13688: "constVal (Cast t e) = None" schirmer@13688: "constVal (Inst e r) = None" schirmer@13688: "constVal (Lit val) = Some val" schirmer@13688: "constVal (UnOp unop e) = (case (constVal e) of schirmer@13688: None \ None schirmer@13688: | Some v \ Some (eval_unop unop v))" schirmer@13688: "constVal (BinOp binop e1 e2) = (case (constVal e1) of schirmer@13688: None \ None schirmer@13688: | Some v1 \ (case (constVal e2) of schirmer@13688: None \ None schirmer@13688: | Some v2 \ Some (eval_binop schirmer@13688: binop v1 v2)))" schirmer@13688: "constVal (Super) = None" schirmer@13688: "constVal (Acc v) = None" schirmer@13688: "constVal (Ass v e) = None" schirmer@13688: "constVal (Cond b e1 e2) = (case (constVal b) of schirmer@13688: None \ None schirmer@13688: | Some bv\ (case the_Bool bv of schirmer@13688: True \ (case (constVal e2) of schirmer@13688: None \ None schirmer@13688: | Some v \ constVal e1) schirmer@13688: | False\ (case (constVal e1) of schirmer@13688: None \ None schirmer@13688: | Some v \ constVal e2)))" schirmer@13688: --{* Note that @{text "constVal (Cond b e1 e2)"} is stricter as it could be. schirmer@13688: It requires that all tree expressions are constant even if we can decide schirmer@13688: which branch to choose, provided the constant value of @{term b} *} schirmer@13688: "constVal (Call accC statT mode objRef mn pTs args) = None" schirmer@13688: "constVal (Methd C sig) = None" schirmer@13688: "constVal (Body C s) = None" schirmer@13688: "constVal (InsInitE s e) = None" schirmer@13688: "constVal (Callee l e) = None" schirmer@13688: schirmer@13688: lemma constVal_Some_induct [consumes 1, case_names Lit UnOp BinOp CondL CondR]: schirmer@13688: assumes const: "constVal e = Some v" and schirmer@13688: hyp_Lit: "\ v. P (Lit v)" and schirmer@13688: hyp_UnOp: "\ unop e'. P e' \ P (UnOp unop e')" and schirmer@13688: hyp_BinOp: "\ binop e1 e2. \P e1; P e2\ \ P (BinOp binop e1 e2)" and schirmer@13688: hyp_CondL: "\ b bv e1 e2. \constVal b = Some bv; the_Bool bv; P b; P e1\ schirmer@13688: \ P (b? e1 : e2)" and schirmer@13688: hyp_CondR: "\ b bv e1 e2. \constVal b = Some bv; \the_Bool bv; P b; P e2\ schirmer@13688: \ P (b? e1 : e2)" schirmer@13688: shows "P e" schirmer@13688: proof - schirmer@13688: have "True" and "\ v. constVal e = Some v \ P e" and "True" and "True" schirmer@13688: proof (induct "x::var" and e and "s::stmt" and "es::expr list") schirmer@13688: case Lit schirmer@13688: show ?case by (rule hyp_Lit) schirmer@13688: next schirmer@13688: case UnOp schirmer@13688: thus ?case schirmer@13688: by (auto intro: hyp_UnOp) schirmer@13688: next schirmer@13688: case BinOp schirmer@13688: thus ?case schirmer@13688: by (auto intro: hyp_BinOp) schirmer@13688: next schirmer@13688: case (Cond b e1 e2) schirmer@13688: then obtain v where v: "constVal (b ? e1 : e2) = Some v" schirmer@13688: by blast schirmer@13688: then obtain bv where bv: "constVal b = Some bv" schirmer@13688: by simp schirmer@13688: show ?case schirmer@13688: proof (cases "the_Bool bv") schirmer@13688: case True schirmer@13688: with Cond show ?thesis using v bv schirmer@13688: by (auto intro: hyp_CondL) schirmer@13688: next schirmer@13688: case False schirmer@13688: with Cond show ?thesis using v bv schirmer@13688: by (auto intro: hyp_CondR) schirmer@13688: qed schirmer@13688: qed (simp_all) schirmer@13688: with const schirmer@13688: show ?thesis schirmer@13688: by blast schirmer@13688: qed schirmer@13688: schirmer@13688: lemma assignsE_const_simp: "constVal e = Some v \ assignsE e = {}" schirmer@13688: by (induct rule: constVal_Some_induct) simp_all schirmer@13688: schirmer@13688: schirmer@13688: subsection {* Main analysis for boolean expressions *} schirmer@13688: schirmer@13688: text {* Assigned local variables after evaluating the expression if it evaluates schirmer@13688: to a specific boolean value. If the expression cannot evaluate to a schirmer@13688: @{term Boolean} value UNIV is returned. If we expect true/false the opposite schirmer@13688: constant false/true will also lead to UNIV. *} schirmer@13688: consts assigns_if:: "bool \ expr \ lname set" schirmer@13688: primrec schirmer@13688: "assigns_if b (NewC c) = UNIV" --{*can never evaluate to Boolean*} schirmer@13688: "assigns_if b (NewA t e) = UNIV" --{*can never evaluate to Boolean*} schirmer@13688: "assigns_if b (Cast t e) = assigns_if b e" schirmer@13688: "assigns_if b (Inst e r) = assignsE e" --{*Inst has type Boolean but schirmer@13688: e is a reference type*} schirmer@13688: "assigns_if b (Lit val) = (if val=Bool b then {} else UNIV)" schirmer@13688: "assigns_if b (UnOp unop e) = (case constVal (UnOp unop e) of schirmer@13688: None \ (if unop = UNot schirmer@13688: then assigns_if (\b) e schirmer@13688: else UNIV) schirmer@13688: | Some v \ (if v=Bool b schirmer@13688: then {} schirmer@13688: else UNIV))" schirmer@13688: "assigns_if b (BinOp binop e1 e2) schirmer@13688: = (case constVal (BinOp binop e1 e2) of schirmer@13688: None \ (if binop=CondAnd then schirmer@13688: (case b of schirmer@13688: True \ assigns_if True e1 \ assigns_if True e2 schirmer@13688: | False \ assigns_if False e1 \ schirmer@13688: (assigns_if True e1 \ assigns_if False e2)) schirmer@13688: else schirmer@13688: (if binop=CondOr then schirmer@13688: (case b of schirmer@13688: True \ assigns_if True e1 \ schirmer@13688: (assigns_if False e1 \ assigns_if True e2) schirmer@13688: | False \ assigns_if False e1 \ assigns_if False e2) schirmer@13688: else assignsE e1 \ assignsE e2)) schirmer@13688: | Some v \ (if v=Bool b then {} else UNIV))" schirmer@13688: schirmer@13688: "assigns_if b (Super) = UNIV" --{*can never evaluate to Boolean*} schirmer@13688: "assigns_if b (Acc v) = (assignsV v)" schirmer@13688: "assigns_if b (v := e) = (assignsE (Ass v e))" schirmer@13688: "assigns_if b (c? e1 : e2) = (assignsE c) \ schirmer@13688: (case (constVal c) of schirmer@13688: None \ (assigns_if b e1) \ schirmer@13688: (assigns_if b e2) schirmer@13688: | Some bv \ (case the_Bool bv of schirmer@13688: True \ assigns_if b e1 schirmer@13688: | False \ assigns_if b e2))" schirmer@13688: "assigns_if b ({accC,statT,mode}objRef\mn({pTs}args)) schirmer@13688: = assignsE ({accC,statT,mode}objRef\mn({pTs}args)) " schirmer@13688: -- {* Only dummy analysis for intermediate expressions schirmer@13688: @{term Methd}, @{term Body}, @{term InsInitE} and @{term Callee} *} schirmer@13688: "assigns_if b (Methd C sig) = {}" schirmer@13688: "assigns_if b (Body C s) = {}" schirmer@13688: "assigns_if b (InsInitE s e) = {}" schirmer@13688: "assigns_if b (Callee l e) = {}" schirmer@13688: schirmer@13688: lemma assigns_if_const_b_simp: schirmer@13688: assumes boolConst: "constVal e = Some (Bool b)" (is "?Const b e") schirmer@13688: shows "assigns_if b e = {}" (is "?Ass b e") schirmer@13688: proof - schirmer@13688: have "True" and "\ b. ?Const b e \ ?Ass b e" and "True" and "True" wenzelm@18459: proof (induct _ and e and _ and _ rule: var_expr_stmt.inducts) schirmer@13688: case Lit schirmer@13688: thus ?case by simp schirmer@13688: next schirmer@13688: case UnOp schirmer@13688: thus ?case by simp schirmer@13688: next schirmer@13688: case (BinOp binop) schirmer@13688: thus ?case schirmer@13688: by (cases binop) (simp_all) schirmer@13688: next schirmer@13688: case (Cond c e1 e2 b) wenzelm@23350: note hyp_c = `\ b. ?Const b c \ ?Ass b c` wenzelm@23350: note hyp_e1 = `\ b. ?Const b e1 \ ?Ass b e1` wenzelm@23350: note hyp_e2 = `\ b. ?Const b e2 \ ?Ass b e2` wenzelm@23350: note const = `constVal (c ? e1 : e2) = Some (Bool b)` schirmer@13688: then obtain bv where bv: "constVal c = Some bv" schirmer@13688: by simp schirmer@13688: hence emptyC: "assignsE c = {}" by (rule assignsE_const_simp) schirmer@13688: show ?case schirmer@13688: proof (cases "the_Bool bv") schirmer@13688: case True schirmer@13688: with const bv schirmer@13688: have "?Const b e1" by simp schirmer@13688: hence "?Ass b e1" by (rule hyp_e1) schirmer@13688: with emptyC bv True schirmer@13688: show ?thesis schirmer@13688: by simp schirmer@13688: next schirmer@13688: case False schirmer@13688: with const bv schirmer@13688: have "?Const b e2" by simp schirmer@13688: hence "?Ass b e2" by (rule hyp_e2) schirmer@13688: with emptyC bv False schirmer@13688: show ?thesis schirmer@13688: by simp schirmer@13688: qed schirmer@13688: qed (simp_all) schirmer@13688: with boolConst schirmer@13688: show ?thesis schirmer@13688: by blast schirmer@13688: qed schirmer@13688: schirmer@13688: lemma assigns_if_const_not_b_simp: schirmer@13688: assumes boolConst: "constVal e = Some (Bool b)" (is "?Const b e") wenzelm@18459: shows "assigns_if (\b) e = UNIV" (is "?Ass b e") schirmer@13688: proof - schirmer@13688: have True and "\ b. ?Const b e \ ?Ass b e" and True and True wenzelm@18459: proof (induct _ and e and _ and _ rule: var_expr_stmt.inducts) schirmer@13688: case Lit schirmer@13688: thus ?case by simp schirmer@13688: next schirmer@13688: case UnOp schirmer@13688: thus ?case by simp schirmer@13688: next schirmer@13688: case (BinOp binop) schirmer@13688: thus ?case schirmer@13688: by (cases binop) (simp_all) schirmer@13688: next schirmer@13688: case (Cond c e1 e2 b) wenzelm@23350: note hyp_c = `\ b. ?Const b c \ ?Ass b c` wenzelm@23350: note hyp_e1 = `\ b. ?Const b e1 \ ?Ass b e1` wenzelm@23350: note hyp_e2 = `\ b. ?Const b e2 \ ?Ass b e2` wenzelm@23350: note const = `constVal (c ? e1 : e2) = Some (Bool b)` schirmer@13688: then obtain bv where bv: "constVal c = Some bv" schirmer@13688: by simp schirmer@13688: show ?case schirmer@13688: proof (cases "the_Bool bv") schirmer@13688: case True schirmer@13688: with const bv schirmer@13688: have "?Const b e1" by simp schirmer@13688: hence "?Ass b e1" by (rule hyp_e1) schirmer@13688: with bv True schirmer@13688: show ?thesis schirmer@13688: by simp schirmer@13688: next schirmer@13688: case False schirmer@13688: with const bv schirmer@13688: have "?Const b e2" by simp schirmer@13688: hence "?Ass b e2" by (rule hyp_e2) schirmer@13688: with bv False schirmer@13688: show ?thesis schirmer@13688: by simp schirmer@13688: qed schirmer@13688: qed (simp_all) schirmer@13688: with boolConst schirmer@13688: show ?thesis schirmer@13688: by blast schirmer@13688: qed schirmer@13688: schirmer@13688: subsection {* Lifting set operations to range of tables (map to a set) *} schirmer@13688: schirmer@13688: constdefs schirmer@13688: union_ts:: "('a,'b) tables \ ('a,'b) tables \ ('a,'b) tables" schirmer@13688: ("_ \\ _" [67,67] 65) schirmer@13688: "A \\ B \ \ k. A k \ B k" schirmer@13688: schirmer@13688: constdefs schirmer@13688: intersect_ts:: "('a,'b) tables \ ('a,'b) tables \ ('a,'b) tables" schirmer@13688: ("_ \\ _" [72,72] 71) schirmer@13688: "A \\ B \ \ k. A k \ B k" schirmer@13688: schirmer@13688: constdefs schirmer@13688: all_union_ts:: "('a,'b) tables \ 'b set \ ('a,'b) tables" schirmer@13688: (infixl "\\\<^sub>\" 40) schirmer@13688: "A \\\<^sub>\ B \ \ k. A k \ B" schirmer@13688: schirmer@13688: subsubsection {* Binary union of tables *} schirmer@13688: schirmer@13688: lemma union_ts_iff [simp]: "(c \ (A \\ B) k) = (c \ A k \ c \ B k)" schirmer@13688: by (unfold union_ts_def) blast schirmer@13688: schirmer@13688: lemma union_tsI1 [elim?]: "c \ A k \ c \ (A \\ B) k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma union_tsI2 [elim?]: "c \ B k \ c \ (A \\ B) k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma union_tsCI [intro!]: "(c \ B k \ c \ A k) \ c \ (A \\ B) k" schirmer@13688: by auto schirmer@13688: schirmer@13688: lemma union_tsE [elim!]: schirmer@13688: "\c \ (A \\ B) k; (c \ A k \ P); (c \ B k \ P)\ \ P" schirmer@13688: by (unfold union_ts_def) blast schirmer@13688: schirmer@13688: subsubsection {* Binary intersection of tables *} schirmer@13688: schirmer@13688: lemma intersect_ts_iff [simp]: "c \ (A \\ B) k = (c \ A k \ c \ B k)" schirmer@13688: by (unfold intersect_ts_def) blast schirmer@13688: schirmer@13688: lemma intersect_tsI [intro!]: "\c \ A k; c \ B k\ \ c \ (A \\ B) k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma intersect_tsD1: "c \ (A \\ B) k \ c \ A k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma intersect_tsD2: "c \ (A \\ B) k \ c \ B k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma intersect_tsE [elim!]: schirmer@13688: "\c \ (A \\ B) k; \c \ A k; c \ B k\ \ P\ \ P" schirmer@13688: by simp schirmer@13688: schirmer@13688: schirmer@13688: subsubsection {* All-Union of tables and set *} schirmer@13688: schirmer@13688: lemma all_union_ts_iff [simp]: "(c \ (A \\\<^sub>\ B) k) = (c \ A k \ c \ B)" schirmer@13688: by (unfold all_union_ts_def) blast schirmer@13688: schirmer@13688: lemma all_union_tsI1 [elim?]: "c \ A k \ c \ (A \\\<^sub>\ B) k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma all_union_tsI2 [elim?]: "c \ B \ c \ (A \\\<^sub>\ B) k" schirmer@13688: by simp schirmer@13688: schirmer@13688: lemma all_union_tsCI [intro!]: "(c \ B \ c \ A k) \ c \ (A \\\<^sub>\ B) k" schirmer@13688: by auto schirmer@13688: schirmer@13688: lemma all_union_tsE [elim!]: schirmer@13688: "\c \ (A \\\<^sub>\ B) k; (c \ A k \ P); (c \ B \ P)\ \ P" schirmer@13688: by (unfold all_union_ts_def) blast schirmer@13688: schirmer@13688: schirmer@13688: section "The rules of definite assignment" schirmer@13688: schirmer@13688: schirmer@13688: types breakass = "(label, lname) tables" schirmer@13688: --{* Mapping from a break label, to the set of variables that will be assigned schirmer@13688: if the evaluation terminates with this break *} schirmer@13688: schirmer@13688: record assigned = schirmer@13688: nrm :: "lname set" --{* Definetly assigned variables schirmer@13688: for normal completion*} schirmer@13688: brk :: "breakass" --{* Definetly assigned variables for schirmer@14030: abrupt completion with a break *} schirmer@13688: schirmer@13688: constdefs rmlab :: "'a \ ('a,'b) tables \ ('a,'b) tables" schirmer@13688: "rmlab k A \ \ x. if x=k then UNIV else A x" schirmer@13688: schirmer@13688: (* schirmer@13688: constdefs setbrk :: "breakass \ assigned \ breakass set" schirmer@13688: "setbrk b A \ {b} \ {a| a. a\ brk A \ lab a \ lab b}" schirmer@13688: *) schirmer@13688: schirmer@13688: constdefs range_inter_ts :: "('a,'b) tables \ 'b set" ("\\_" 80) schirmer@13688: "\\A \ {x |x. \ k. x \ A k}" schirmer@13688: berghofe@21765: text {* berghofe@21765: In @{text "E\ B \t\ A"}, berghofe@21765: @{text B} denotes the ''assigned'' variables before evaluating term @{text t}, berghofe@21765: whereas @{text A} denotes the ''assigned'' variables after evaluating term @{text t}. berghofe@21765: The environment @{term E} is only needed for the conditional @{text "_ ? _ : _"}. berghofe@21765: The definite assignment rules refer to the typing rules here to berghofe@21765: distinguish boolean and other expressions. berghofe@21765: *} schirmer@13688: berghofe@23747: inductive berghofe@21765: da :: "env \ lname set \ term \ assigned \ bool" ("_\ _ \_\ _" [65,65,65,65] 71) berghofe@21765: where berghofe@21765: Skip: "Env\ B \\Skip\\ \nrm=B,brk=\ l. UNIV\" schirmer@13688: berghofe@21765: | Expr: "Env\ B \\e\\ A berghofe@21765: \ berghofe@21765: Env\ B \\Expr e\\ A" berghofe@21765: | Lab: "\Env\ B \\c\\ C; nrm A = nrm C \ (brk C) l; brk A = rmlab l (brk C)\ berghofe@21765: \ berghofe@21765: Env\ B \\Break l\ c\\ A" schirmer@13688: berghofe@21765: | Comp: "\Env\ B \\c1\\ C1; Env\ nrm C1 \\c2\\ C2; berghofe@21765: nrm A = nrm C2; brk A = (brk C1) \\ (brk C2)\ berghofe@21765: \ berghofe@21765: Env\ B \\c1;; c2\\ A" berghofe@21765: berghofe@21765: | If: "\Env\ B \\e\\ E; berghofe@21765: Env\ (B \ assigns_if True e) \\c1\\ C1; berghofe@21765: Env\ (B \ assigns_if False e) \\c2\\ C2; berghofe@21765: nrm A = nrm C1 \ nrm C2; berghofe@21765: brk A = brk C1 \\ brk C2 \ berghofe@21765: \ berghofe@21765: Env\ B \\If(e) c1 Else c2\\ A" schirmer@13688: schirmer@13688: --{* Note that @{term E} is not further used, because we take the specialized schirmer@13688: sets that also consider if the expression evaluates to true or false. schirmer@13688: Inside of @{term e} there is no {\tt break} or {\tt finally}, so the break schirmer@13688: map of @{term E} will be the trivial one. So berghofe@21765: @{term "Env\B \\e\\ E"} is just used to ensure the definite assignment in schirmer@13688: expression @{term e}. schirmer@13688: Notice the implicit analysis of a constant boolean expression @{term e} schirmer@13688: in this rule. For example, if @{term e} is constantly @{term True} then schirmer@13688: @{term "assigns_if False e = UNIV"} and therefor @{term "nrm C2=UNIV"}. schirmer@13688: So finally @{term "nrm A = nrm C1"}. For the break maps this trick schirmer@13688: workd too, because the trival break map will map all labels to schirmer@13688: @{term UNIV}. In the example, if no break occurs in @{term c2} the break schirmer@13688: maps will trivially map to @{term UNIV} and if a break occurs it will map schirmer@13688: to @{term UNIV} too, because @{term "assigns_if False e = UNIV"}. So schirmer@13688: in the intersection of the break maps the path @{term c2} will have no schirmer@13688: contribution. schirmer@13688: *} schirmer@13688: berghofe@21765: | Loop: "\Env\ B \\e\\ E; berghofe@21765: Env\ (B \ assigns_if True e) \\c\\ C; berghofe@21765: nrm A = nrm C \ (B \ assigns_if False e); berghofe@21765: brk A = brk C\ berghofe@21765: \ berghofe@21765: Env\ B \\l\ While(e) c\\ A" schirmer@13688: --{* The @{text Loop} rule resembles some of the ideas of the @{text If} rule. schirmer@13688: For the @{term "nrm A"} the set @{term "B \ assigns_if False e"} schirmer@13688: will be @{term UNIV} if the condition is constantly true. To normally exit schirmer@13688: the while loop, we must consider the body @{term c} to be completed schirmer@13688: normally (@{term "nrm C"}) or with a break. But in this model, schirmer@13688: the label @{term l} of the loop schirmer@13688: only handles continue labels, not break labels. The break label will be schirmer@13688: handled by an enclosing @{term Lab} statement. So we don't have to schirmer@13688: handle the breaks specially. schirmer@13688: *} schirmer@13688: berghofe@21765: | Jmp: "\jump=Ret \ Result \ B; berghofe@21765: nrm A = UNIV; berghofe@21765: brk A = (case jump of berghofe@21765: Break l \ \ k. if k=l then B else UNIV berghofe@21765: | Cont l \ \ k. UNIV berghofe@21765: | Ret \ \ k. UNIV)\ berghofe@21765: \ berghofe@21765: Env\ B \\Jmp jump\\ A" schirmer@13688: --{* In case of a break to label @{term l} the corresponding break set is all schirmer@13688: variables assigned before the break. The assigned variables for normal schirmer@13688: completion of the @{term Jmp} is @{term UNIV}, because the statement will schirmer@13688: never complete normally. For continue and return the break map is the schirmer@13688: trivial one. In case of a return we enshure that the result value is schirmer@13688: assigned. schirmer@13688: *} schirmer@13688: berghofe@21765: | Throw: "\Env\ B \\e\\ E; nrm A = UNIV; brk A = (\ l. UNIV)\ berghofe@21765: \ Env\ B \\Throw e\\ A" schirmer@13688: berghofe@21765: | Try: "\Env\ B \\c1\\ C1; berghofe@21765: Env\lcl := lcl Env(VName vn\Class C)\\ (B \ {VName vn}) \\c2\\ C2; berghofe@21765: nrm A = nrm C1 \ nrm C2; berghofe@21765: brk A = brk C1 \\ brk C2\ berghofe@21765: \ Env\ B \\Try c1 Catch(C vn) c2\\ A" schirmer@13688: berghofe@21765: | Fin: "\Env\ B \\c1\\ C1; berghofe@21765: Env\ B \\c2\\ C2; berghofe@21765: nrm A = nrm C1 \ nrm C2; berghofe@21765: brk A = ((brk C1) \\\<^sub>\ (nrm C2)) \\ (brk C2)\ berghofe@21765: \ berghofe@21765: Env\ B \\c1 Finally c2\\ A" schirmer@13688: --{* The set of assigned variables before execution @{term c2} are the same schirmer@13688: as before execution @{term c1}, because @{term c1} could throw an exception schirmer@13688: and so we can't guarantee that any variable will be assigned in @{term c1}. schirmer@13688: The @{text Finally} statement completes schirmer@13688: normally if both @{term c1} and @{term c2} complete normally. If @{term c1} schirmer@14030: completes abruptly with a break, then @{term c2} also will be executed schirmer@13688: and may terminate normally or with a break. The overall break map then is schirmer@13688: the intersection of the maps of both paths. If @{term c2} terminates schirmer@13688: normally we have to extend all break sets in @{term "brk C1"} with schirmer@13688: @{term "nrm C2"} (@{text "\\\<^sub>\"}). If @{term c2} exits with a break this schirmer@13688: break will appear in the overall result state. We don't know if schirmer@13688: @{term c1} completed normally or abruptly (maybe with an exception not only schirmer@13688: a break) so @{term c1} has no contribution to the break map following this schirmer@13688: path. schirmer@13688: *} schirmer@13688: schirmer@13688: --{* Evaluation of expressions and the break sets of definite assignment: schirmer@13688: Thinking of a Java expression we assume that we can never have schirmer@13688: a break statement inside of a expression. So for all expressions the schirmer@13688: break sets could be set to the trivial one: @{term "\ l. UNIV"}. schirmer@13688: But we can't schirmer@13688: trivially proof, that evaluating an expression will never result in a schirmer@13688: break, allthough Java expressions allready syntactically don't allow schirmer@13688: nested stetements in them. The reason are the nested class initialzation schirmer@13688: statements which are inserted by the evaluation rules. So to proof the schirmer@13688: absence of a break we need to ensure, that the initialization statements schirmer@13688: will never end up in a break. In a wellfromed initialization statement, schirmer@13688: of course, were breaks are nested correctly inside of @{term Lab} schirmer@13688: or @{term Loop} statements evaluation of the whole initialization schirmer@13688: statement will never result in a break, because this break will be schirmer@13688: handled inside of the statement. But for simplicity we haven't added schirmer@13688: the analysis of the correct nesting of breaks in the typing judgments schirmer@13688: right now. So we have decided to adjust the rules of definite assignment schirmer@13688: to fit to these circumstances. If an initialization is involved during schirmer@13688: evaluation of the expression (evaluation rules @{text FVar}, @{text NewC} schirmer@13688: and @{text NewA} schirmer@13688: *} schirmer@13688: berghofe@21765: | Init: "Env\ B \\Init C\\ \nrm=B,brk=\ l. UNIV\" schirmer@13688: --{* Wellformedness of a program will ensure, that every static initialiser schirmer@13688: is definetly assigned and the jumps are nested correctly. The case here schirmer@13688: for @{term Init} is just for convenience, to get a proper precondition schirmer@13688: for the induction hypothesis in various proofs, so that we don't have to schirmer@13688: expand the initialisation on every point where it is triggerred by the schirmer@13688: evaluation rules. schirmer@13688: *} berghofe@21765: | NewC: "Env\ B \\NewC C\\ \nrm=B,brk=\ l. UNIV\" berghofe@21765: berghofe@21765: | NewA: "Env\ B \\e\\ A berghofe@21765: \ berghofe@21765: Env\ B \\New T[e]\\ A" schirmer@13688: berghofe@21765: | Cast: "Env\ B \\e\\ A berghofe@21765: \ berghofe@21765: Env\ B \\Cast T e\\ A" schirmer@13688: berghofe@21765: | Inst: "Env\ B \\e\\ A berghofe@21765: \ berghofe@21765: Env\ B \\e InstOf T\\ A" schirmer@13688: berghofe@21765: | Lit: "Env\ B \\Lit v\\ \nrm=B,brk=\ l. UNIV\" schirmer@13688: berghofe@21765: | UnOp: "Env\ B \\e\\ A berghofe@21765: \ berghofe@21765: Env\ B \\UnOp unop e\\ A" schirmer@13688: berghofe@21765: | CondAnd: "\Env\ B \\e1\\ E1; Env\ (B \ assigns_if True e1) \\e2\\ E2; berghofe@21765: nrm A = B \ (assigns_if True (BinOp CondAnd e1 e2) \ berghofe@21765: assigns_if False (BinOp CondAnd e1 e2)); berghofe@21765: brk A = (\ l. UNIV) \ berghofe@21765: \ berghofe@21765: Env\ B \\BinOp CondAnd e1 e2\\ A" schirmer@13688: berghofe@21765: | CondOr: "\Env\ B \\e1\\ E1; Env\ (B \ assigns_if False e1) \\e2\\ E2; berghofe@21765: nrm A = B \ (assigns_if True (BinOp CondOr e1 e2) \ berghofe@21765: assigns_if False (BinOp CondOr e1 e2)); schirmer@13688: brk A = (\ l. UNIV) \ berghofe@21765: \ berghofe@21765: Env\ B \\BinOp CondOr e1 e2\\ A" schirmer@13688: berghofe@21765: | BinOp: "\Env\ B \\e1\\ E1; Env\ nrm E1 \\e2\\ A; berghofe@21765: binop \ CondAnd; binop \ CondOr\ berghofe@21765: \ berghofe@21765: Env\ B \\BinOp binop e1 e2\\ A" schirmer@13688: berghofe@21765: | Super: "This \ B berghofe@21765: \ berghofe@21765: Env\ B \\Super\\ \nrm=B,brk=\ l. UNIV\" schirmer@13688: berghofe@21765: | AccLVar: "\vn \ B; berghofe@21765: nrm A = B; brk A = (\ k. UNIV)\ berghofe@21765: \ berghofe@21765: Env\ B \\Acc (LVar vn)\\ A" schirmer@13688: --{* To properly access a local variable we have to test the definite schirmer@13688: assignment here. The variable must occur in the set @{term B} schirmer@13688: *} schirmer@13688: berghofe@21765: | Acc: "\\ vn. v \ LVar vn; berghofe@21765: Env\ B \\v\\ A\ berghofe@21765: \ berghofe@21765: Env\ B \\Acc v\\ A" schirmer@13688: berghofe@21765: | AssLVar: "\Env\ B \\e\\ E; nrm A = nrm E \ {vn}; brk A = brk E\ berghofe@21765: \ berghofe@21765: Env\ B \\(LVar vn) := e\\ A" schirmer@13688: berghofe@21765: | Ass: "\\ vn. v \ LVar vn; Env\ B \\v\\ V; Env\ nrm V \\e\\ A\ berghofe@21765: \ berghofe@21765: Env\ B \\v := e\\ A" schirmer@13688: berghofe@21765: | CondBool: "\Env\(c ? e1 : e2)\-(PrimT Boolean); berghofe@21765: Env\ B \\c\\ C; berghofe@21765: Env\ (B \ assigns_if True c) \\e1\\ E1; berghofe@21765: Env\ (B \ assigns_if False c) \\e2\\ E2; berghofe@21765: nrm A = B \ (assigns_if True (c ? e1 : e2) \ berghofe@21765: assigns_if False (c ? e1 : e2)); berghofe@21765: brk A = (\ l. UNIV)\ berghofe@21765: \ berghofe@21765: Env\ B \\c ? e1 : e2\\ A" schirmer@13688: berghofe@21765: | Cond: "\\ Env\(c ? e1 : e2)\-(PrimT Boolean); berghofe@21765: Env\ B \\c\\ C; berghofe@21765: Env\ (B \ assigns_if True c) \\e1\\ E1; berghofe@21765: Env\ (B \ assigns_if False c) \\e2\\ E2; berghofe@21765: nrm A = nrm E1 \ nrm E2; brk A = (\ l. UNIV)\ berghofe@21765: \ berghofe@21765: Env\ B \\c ? e1 : e2\\ A" schirmer@13688: berghofe@21765: | Call: "\Env\ B \\e\\ E; Env\ nrm E \\args\\ A\ berghofe@21765: \ berghofe@21765: Env\ B \\{accC,statT,mode}e\mn({pTs}args)\\ A" schirmer@13688: schirmer@13688: -- {* The interplay of @{term Call}, @{term Methd} and @{term Body}: schirmer@13688: Why rules for @{term Methd} and @{term Body} at all? Note that a schirmer@13688: Java source program will not include bare @{term Methd} or @{term Body} schirmer@13688: terms. These terms are just introduced during evaluation. So definite schirmer@13688: assignment of @{term Call} does not consider @{term Methd} or schirmer@13688: @{term Body} at all. So for definite assignment alone we could omit the schirmer@13688: rules for @{term Methd} and @{term Body}. schirmer@13688: But since evaluation of the method invocation is schirmer@13688: split up into three rules we must ensure that we have enough information schirmer@13688: about the call even in the @{term Body} term to make sure that we can schirmer@13688: proof type safety. Also we must be able transport this information schirmer@13688: from @{term Call} to @{term Methd} and then further to @{term Body} schirmer@13688: during evaluation to establish the definite assignment of @{term Methd} schirmer@13688: during evaluation of @{term Call}, and of @{term Body} during evaluation schirmer@13688: of @{term Methd}. This is necessary since definite assignment will be schirmer@13688: a precondition for each induction hypothesis coming out of the evaluation schirmer@13688: rules, and therefor we have to establish the definite assignment of the schirmer@13688: sub-evaluation during the type-safety proof. Note that well-typedness is schirmer@13688: also a precondition for type-safety and so we can omit some assertion schirmer@13688: that are already ensured by well-typedness. schirmer@13688: *} berghofe@21765: | Methd: "\methd (prg Env) D sig = Some m; berghofe@21765: Env\ B \\Body (declclass m) (stmt (mbody (mthd m)))\\ A berghofe@21765: \ berghofe@21765: \ berghofe@21765: Env\ B \\Methd D sig\\ A" berghofe@21765: berghofe@21765: | Body: "\Env\ B \\c\\ C; jumpNestingOkS {Ret} c; Result \ nrm C; berghofe@21765: nrm A = B; brk A = (\ l. UNIV)\ schirmer@13688: \ berghofe@21765: Env\ B \\Body D c\\ A" schirmer@13688: -- {* Note that @{term A} is not correlated to @{term C}. If the body schirmer@13688: statement returns abruptly with return, evaluation of @{term Body} schirmer@13688: will absorb this return and complete normally. So we cannot trivially schirmer@13688: get the assigned variables of the body statement since it has not schirmer@13688: completed normally or with a break. schirmer@13688: If the body completes normally we guarantee that the result variable schirmer@13688: is set with this rule. But if the body completes abruptly with a return schirmer@13688: we can't guarantee that the result variable is set here, since schirmer@13688: definite assignment only talks about normal completion and breaks. So schirmer@13688: for a return the @{term Jump} rule ensures that the result variable is schirmer@13688: set and then this information must be carried over to the @{term Body} schirmer@13688: rule by the conformance predicate of the state. schirmer@13688: *} berghofe@21765: | LVar: "Env\ B \\LVar vn\\ \nrm=B, brk=\ l. UNIV\" schirmer@13688: berghofe@21765: | FVar: "Env\ B \\e\\ A schirmer@13688: \ berghofe@21765: Env\ B \\{accC,statDeclC,stat}e..fn\\ A" schirmer@13688: berghofe@21765: | AVar: "\Env\ B \\e1\\ E1; Env\ nrm E1 \\e2\\ A\ berghofe@21765: \ berghofe@21765: Env\ B \\e1.[e2]\\ A" schirmer@13688: berghofe@21765: | Nil: "Env\ B \\[]::expr list\\ \nrm=B, brk=\ l. UNIV\" berghofe@21765: berghofe@21765: | Cons: "\Env\ B \\e::expr\\ E; Env\ nrm E \\es\\ A\ berghofe@21765: \ berghofe@21765: Env\ B \\e#es\\ A" schirmer@13688: schirmer@13688: schirmer@13688: declare inj_term_sym_simps [simp] schirmer@13688: declare assigns_if.simps [simp del] schirmer@13688: declare split_paired_All [simp del] split_paired_Ex [simp del] schirmer@13688: ML_setup {* wenzelm@17876: change_simpset (fn ss => ss delloop "split_all_tac"); schirmer@13688: *} berghofe@23747: inductive_cases da_elim_cases [cases set]: schirmer@13688: "Env\ B \\Skip\\ A" schirmer@13688: "Env\ B \In1r Skip\ A" schirmer@13688: "Env\ B \\Expr e\\ A" schirmer@13688: "Env\ B \In1r (Expr e)\ A" schirmer@13688: "Env\ B \\l\ c\\ A" schirmer@13688: "Env\ B \In1r (l\ c)\ A" schirmer@13688: "Env\ B \\c1;; c2\\ A" schirmer@13688: "Env\ B \In1r (c1;; c2)\ A" schirmer@13688: "Env\ B \\If(e) c1 Else c2\\ A" schirmer@13688: "Env\ B \In1r (If(e) c1 Else c2)\ A" schirmer@13688: "Env\ B \\l\ While(e) c\\ A" schirmer@13688: "Env\ B \In1r (l\ While(e) c)\ A" schirmer@13688: "Env\ B \\Jmp jump\\ A" schirmer@13688: "Env\ B \In1r (Jmp jump)\ A" schirmer@13688: "Env\ B \\Throw e\\ A" schirmer@13688: "Env\ B \In1r (Throw e)\ A" schirmer@13688: "Env\ B \\Try c1 Catch(C vn) c2\\ A" schirmer@13688: "Env\ B \In1r (Try c1 Catch(C vn) c2)\ A" schirmer@13688: "Env\ B \\c1 Finally c2\\ A" schirmer@13688: "Env\ B \In1r (c1 Finally c2)\ A" schirmer@13688: "Env\ B \\Init C\\ A" schirmer@13688: "Env\ B \In1r (Init C)\ A" schirmer@13688: "Env\ B \\NewC C\\ A" schirmer@13688: "Env\ B \In1l (NewC C)\ A" schirmer@13688: "Env\ B \\New T[e]\\ A" schirmer@13688: "Env\ B \In1l (New T[e])\ A" schirmer@13688: "Env\ B \\Cast T e\\ A" schirmer@13688: "Env\ B \In1l (Cast T e)\ A" schirmer@13688: "Env\ B \\e InstOf T\\ A" schirmer@13688: "Env\ B \In1l (e InstOf T)\ A" schirmer@13688: "Env\ B \\Lit v\\ A" schirmer@13688: "Env\ B \In1l (Lit v)\ A" schirmer@13688: "Env\ B \\UnOp unop e\\ A" schirmer@13688: "Env\ B \In1l (UnOp unop e)\ A" schirmer@13688: "Env\ B \\BinOp binop e1 e2\\ A" schirmer@13688: "Env\ B \In1l (BinOp binop e1 e2)\ A" schirmer@13688: "Env\ B \\Super\\ A" schirmer@13688: "Env\ B \In1l (Super)\ A" schirmer@13688: "Env\ B \\Acc v\\ A" schirmer@13688: "Env\ B \In1l (Acc v)\ A" schirmer@13688: "Env\ B \\v := e\\ A" schirmer@13688: "Env\ B \In1l (v := e)\ A" schirmer@13688: "Env\ B \\c ? e1 : e2\\ A" schirmer@13688: "Env\ B \In1l (c ? e1 : e2)\ A" schirmer@13688: "Env\ B \\{accC,statT,mode}e\mn({pTs}args)\\ A" schirmer@13688: "Env\ B \In1l ({accC,statT,mode}e\mn({pTs}args))\ A" schirmer@13688: "Env\ B \\Methd C sig\\ A" schirmer@13688: "Env\ B \In1l (Methd C sig)\ A" schirmer@13688: "Env\ B \\Body D c\\ A" schirmer@13688: "Env\ B \In1l (Body D c)\ A" schirmer@13688: "Env\ B \\LVar vn\\ A" schirmer@13688: "Env\ B \In2 (LVar vn)\ A" schirmer@13688: "Env\ B \\{accC,statDeclC,stat}e..fn\\ A" schirmer@13688: "Env\ B \In2 ({accC,statDeclC,stat}e..fn)\ A" schirmer@13688: "Env\ B \\e1.[e2]\\ A" schirmer@13688: "Env\ B \In2 (e1.[e2])\ A" schirmer@13688: "Env\ B \\[]::expr list\\ A" schirmer@13688: "Env\ B \In3 ([]::expr list)\ A" schirmer@13688: "Env\ B \\e#es\\ A" schirmer@13688: "Env\ B \In3 (e#es)\ A" schirmer@13688: declare inj_term_sym_simps [simp del] schirmer@13688: declare assigns_if.simps [simp] schirmer@13688: declare split_paired_All [simp] split_paired_Ex [simp] schirmer@13688: ML_setup {* wenzelm@17876: change_simpset (fn ss => ss addloop ("split_all_tac", split_all_tac)); schirmer@13688: *} schirmer@13688: (* To be able to eliminate both the versions with the overloaded brackets: schirmer@13688: (B \\Skip\\ A) and with the explicit constructor (B \In1r Skip\ A), schirmer@13688: every rule appears in both versions schirmer@13688: *) schirmer@13688: schirmer@13688: lemma da_Skip: "A = \nrm=B,brk=\ l. UNIV\ \ Env\ B \\Skip\\ A" schirmer@13688: by (auto intro: da.Skip) schirmer@13688: schirmer@13688: lemma da_NewC: "A = \nrm=B,brk=\ l. UNIV\ \ Env\ B \\NewC C\\ A" schirmer@13688: by (auto intro: da.NewC) schirmer@13688: schirmer@13688: lemma da_Lit: "A = \nrm=B,brk=\ l. UNIV\ \ Env\ B \\Lit v\\ A" schirmer@13688: by (auto intro: da.Lit) schirmer@13688: schirmer@13688: lemma da_Super: "\This \ B;A = \nrm=B,brk=\ l. UNIV\\ \ Env\ B \\Super\\ A" schirmer@13688: by (auto intro: da.Super) schirmer@13688: schirmer@13688: lemma da_Init: "A = \nrm=B,brk=\ l. UNIV\ \ Env\ B \\Init C\\ A" schirmer@13688: by (auto intro: da.Init) schirmer@13688: schirmer@13688: schirmer@13688: (* schirmer@13688: For boolean expressions: schirmer@13688: schirmer@13688: The following holds: "assignsE e \ assigns_if True e \ assigns_if False e" schirmer@13688: but not vice versa: schirmer@13688: "assigns_if True e \ assigns_if False e \ assignsE e" schirmer@13688: schirmer@13688: Example: schirmer@13688: e = ((x < 5) || (y = true)) && (y = true) schirmer@13688: schirmer@13688: = ( a || b ) && c schirmer@13688: schirmer@13688: assigns_if True a = {} schirmer@13688: assigns_if False a = {} schirmer@13688: schirmer@13688: assigns_if True b = {y} schirmer@13688: assigns_if False b = {y} schirmer@13688: schirmer@13688: assigns_if True c = {y} schirmer@13688: assigns_if False c = {y} schirmer@13688: schirmer@13688: assigns_if True (a || b) = assigns_if True a \ schirmer@13688: (assigns_if False a \ assigns_if True b) schirmer@13688: = {} \ ({} \ {y}) = {} schirmer@13688: assigns_if False (a || b) = assigns_if False a \ assigns_if False b schirmer@13688: = {} \ {y} = {y} schirmer@13688: schirmer@13688: schirmer@13688: schirmer@13688: assigns_ifE True e = assigns_if True (a || b) \ assigns_if True c schirmer@13688: = {} \ {y} = {y} schirmer@13688: assigns_ifE False e = assigns_if False (a || b) \ schirmer@13688: (assigns_if True (a || b) \ assigns_if False c) schirmer@13688: = {y} \ ({} \ {y}) = {y} schirmer@13688: schirmer@13688: assignsE e = {} schirmer@13688: *) schirmer@13688: schirmer@13688: lemma assignsE_subseteq_assigns_ifs: schirmer@13688: assumes boolEx: "E\e\-PrimT Boolean" (is "?Boolean e") schirmer@13688: shows "assignsE e \ assigns_if True e \ assigns_if False e" (is "?Incl e") schirmer@13688: proof - schirmer@13688: have True and "?Boolean e \ ?Incl e" and True and True wenzelm@18459: proof (induct _ and e and _ and _ rule: var_expr_stmt.inducts) schirmer@13688: case (Cast T e) schirmer@13688: have "E\e\- (PrimT Boolean)" schirmer@13688: proof - wenzelm@23350: from `E\(Cast T e)\- (PrimT Boolean)` wenzelm@23350: obtain Te where "E\e\-Te" schirmer@13688: "prg E\Te\? PrimT Boolean" schirmer@13688: by cases simp schirmer@13688: thus ?thesis schirmer@13688: by - (drule cast_Boolean2,simp) schirmer@13688: qed schirmer@13688: with Cast.hyps schirmer@13688: show ?case schirmer@13688: by simp schirmer@13688: next schirmer@13688: case (Lit val) schirmer@13688: thus ?case schirmer@13688: by - (erule wt_elim_cases, cases "val", auto simp add: empty_dt_def) schirmer@13688: next schirmer@13688: case (UnOp unop e) schirmer@13688: thus ?case schirmer@13688: by - (erule wt_elim_cases,cases unop, schirmer@13688: (fastsimp simp add: assignsE_const_simp)+) schirmer@13688: next schirmer@13688: case (BinOp binop e1 e2) schirmer@13688: from BinOp.prems obtain e1T e2T schirmer@13688: where "E\e1\-e1T" and "E\e2\-e2T" and "wt_binop (prg E) binop e1T e2T" schirmer@13688: and "(binop_type binop) = Boolean" schirmer@13688: by (elim wt_elim_cases) simp schirmer@13688: with BinOp.hyps schirmer@13688: show ?case schirmer@13688: by - (cases binop, auto simp add: assignsE_const_simp) schirmer@13688: next schirmer@13688: case (Cond c e1 e2) wenzelm@23350: note hyp_c = `?Boolean c \ ?Incl c` wenzelm@23350: note hyp_e1 = `?Boolean e1 \ ?Incl e1` wenzelm@23350: note hyp_e2 = `?Boolean e2 \ ?Incl e2` wenzelm@23350: note wt = `E\(c ? e1 : e2)\-PrimT Boolean` schirmer@13688: then obtain schirmer@13688: boolean_c: "E\c\-PrimT Boolean" and schirmer@13688: boolean_e1: "E\e1\-PrimT Boolean" and schirmer@13688: boolean_e2: "E\e2\-PrimT Boolean" schirmer@13688: by (elim wt_elim_cases) (auto dest: widen_Boolean2) schirmer@13688: show ?case schirmer@13688: proof (cases "constVal c") schirmer@13688: case None schirmer@13688: with boolean_e1 boolean_e2 schirmer@13688: show ?thesis schirmer@13688: using hyp_e1 hyp_e2 schirmer@13688: by (auto) schirmer@13688: next schirmer@13688: case (Some bv) schirmer@13688: show ?thesis schirmer@13688: proof (cases "the_Bool bv") schirmer@13688: case True schirmer@13688: with Some show ?thesis using hyp_e1 boolean_e1 by auto schirmer@13688: next schirmer@13688: case False schirmer@13688: with Some show ?thesis using hyp_e2 boolean_e2 by auto schirmer@13688: qed schirmer@13688: qed schirmer@13688: qed simp_all schirmer@13688: with boolEx schirmer@13688: show ?thesis schirmer@13688: by blast schirmer@13688: qed schirmer@13688: schirmer@13688: schirmer@13688: (* Trick: schirmer@13688: If you have a rule with the abstract term injections: schirmer@13688: e.g: da.Skip "B \\Skip\\ A" schirmer@13688: and the current goal state as an concrete injection: schirmer@13688: e.g: "B \In1r Skip\ A" schirmer@13688: you can convert the rule by: da.Skip [simplified] schirmer@13688: if inj_term_simps is in the simpset schirmer@13688: schirmer@13688: *) schirmer@13688: schirmer@13688: lemma rmlab_same_label [simp]: "(rmlab l A) l = UNIV" schirmer@13688: by (simp add: rmlab_def) schirmer@13688: schirmer@13688: lemma rmlab_same_label1 [simp]: "l=l' \ (rmlab l A) l' = UNIV" schirmer@13688: by (simp add: rmlab_def) schirmer@13688: schirmer@13688: lemma rmlab_other_label [simp]: "l\l'\ (rmlab l A) l' = A l'" schirmer@13688: by (auto simp add: rmlab_def) schirmer@13688: schirmer@13688: lemma range_inter_ts_subseteq [intro]: "\ k. A k \ B k \ \\A \ \\B" schirmer@13688: by (auto simp add: range_inter_ts_def) schirmer@13688: schirmer@13688: lemma range_inter_ts_subseteq': schirmer@13688: "\\ k. A k \ B k; x \ \\A\ \ x \ \\B" schirmer@13688: by (auto simp add: range_inter_ts_def) schirmer@13688: schirmer@13688: lemma da_monotone: wenzelm@23350: assumes da: "Env\ B \t\ A" and wenzelm@23350: "B \ B'" and wenzelm@23350: da': "Env\ B' \t\ A'" schirmer@13688: shows "(nrm A \ nrm A') \ (\ l. (brk A l \ brk A' l))" schirmer@13688: proof - schirmer@13688: from da schirmer@13688: show "\ B' A'. \Env\ B' \t\ A'; B \ B'\ schirmer@13688: \ (nrm A \ nrm A') \ (\ l. (brk A l \ brk A' l))" schirmer@13688: (is "PROP ?Hyp Env B t A") schirmer@13688: proof (induct) schirmer@13688: case Skip schirmer@13688: from Skip.prems Skip.hyps schirmer@13688: show ?case by cases simp schirmer@13688: next schirmer@13688: case Expr schirmer@13688: from Expr.prems Expr.hyps schirmer@13688: show ?case by cases simp schirmer@13688: next berghofe@21765: case (Lab Env B c C A l B' A') wenzelm@23350: note A = `nrm A = nrm C \ brk C l` `brk A = rmlab l (brk C)` wenzelm@23350: note `PROP ?Hyp Env B \c\ C` schirmer@13688: moreover wenzelm@23350: note `B \ B'` schirmer@13688: moreover schirmer@13688: obtain C' schirmer@13688: where "Env\ B' \\c\\ C'" schirmer@13688: and A': "nrm A' = nrm C' \ brk C' l" "brk A' = rmlab l (brk C')" schirmer@13688: using Lab.prems schirmer@13688: by - (erule da_elim_cases,simp) schirmer@13688: ultimately schirmer@13688: have "nrm C \ nrm C'" and hyp_brk: "(\l. brk C l \ brk C' l)" by auto schirmer@13688: then schirmer@13688: have "nrm C \ brk C l \ nrm C' \ brk C' l" by auto schirmer@13688: moreover schirmer@13688: { schirmer@13688: fix l' schirmer@13688: from hyp_brk schirmer@13688: have "rmlab l (brk C) l' \ rmlab l (brk C') l'" schirmer@13688: by (cases "l=l'") simp_all schirmer@13688: } schirmer@13688: moreover note A A' schirmer@13688: ultimately show ?case schirmer@13688: by simp schirmer@13688: next berghofe@21765: case (Comp Env B c1 C1 c2 C2 A B' A') wenzelm@23350: note A = `nrm A = nrm C2` `brk A = brk C1 \\ brk C2` wenzelm@23350: from `Env\ B' \\c1;; c2\\ A'` wenzelm@23350: obtain C1' C2' schirmer@13688: where da_c1: "Env\ B' \\c1\\ C1'" and schirmer@13688: da_c2: "Env\ nrm C1' \\c2\\ C2'" and schirmer@13688: A': "nrm A' = nrm C2'" "brk A' = brk C1' \\ brk C2'" schirmer@13688: by (rule da_elim_cases) auto wenzelm@23350: note `PROP ?Hyp Env B \c1\ C1` wenzelm@23350: moreover note `B \ B'` schirmer@13688: moreover note da_c1 schirmer@13688: ultimately have C1': "nrm C1 \ nrm C1'" "(\l. brk C1 l \ brk C1' l)" wenzelm@23350: by auto wenzelm@23350: note `PROP ?Hyp Env (nrm C1) \c2\ C2` schirmer@13688: with da_c2 C1' schirmer@13688: have C2': "nrm C2 \ nrm C2'" "(\l. brk C2 l \ brk C2' l)" wenzelm@23350: by auto schirmer@13688: with A A' C1' schirmer@13688: show ?case schirmer@13688: by auto schirmer@13688: next berghofe@21765: case (If Env B e E c1 C1 c2 C2 A B' A') wenzelm@23350: note A = `nrm A = nrm C1 \ nrm C2` `brk A = brk C1 \\ brk C2` wenzelm@23350: from `Env\ B' \\If(e) c1 Else c2\\ A'` wenzelm@23350: obtain C1' C2' schirmer@13688: where da_c1: "Env\ B' \ assigns_if True e \\c1\\ C1'" and schirmer@13688: da_c2: "Env\ B' \ assigns_if False e \\c2\\ C2'" and schirmer@13688: A': "nrm A' = nrm C1' \ nrm C2'" "brk A' = brk C1' \\ brk C2'" schirmer@13688: by (rule da_elim_cases) auto wenzelm@23350: note `PROP ?Hyp Env (B \ assigns_if True e) \c1\ C1` wenzelm@23350: moreover note B' = `B \ B'` schirmer@13688: moreover note da_c1 schirmer@13688: ultimately obtain C1': "nrm C1 \ nrm C1'" "(\l. brk C1 l \ brk C1' l)" schirmer@13688: by blast wenzelm@23350: note `PROP ?Hyp Env (B \ assigns_if False e) \c2\ C2` schirmer@13688: with da_c2 B' schirmer@13688: obtain C2': "nrm C2 \ nrm C2'" "(\l. brk C2 l \ brk C2' l)" schirmer@13688: by blast schirmer@13688: with A A' C1' schirmer@13688: show ?case schirmer@13688: by auto schirmer@13688: next berghofe@21765: case (Loop Env B e E c C A l B' A') wenzelm@23350: note A = `nrm A = nrm C \ (B \ assigns_if False e)` `brk A = brk C` wenzelm@23350: from `Env\ B' \\l\ While(e) c\\ A'` wenzelm@23350: obtain C' schirmer@13688: where schirmer@13688: da_c': "Env\ B' \ assigns_if True e \\c\\ C'" and schirmer@13688: A': "nrm A' = nrm C' \ (B' \ assigns_if False e)" schirmer@13688: "brk A' = brk C'" schirmer@13688: by (rule da_elim_cases) auto wenzelm@23350: note `PROP ?Hyp Env (B \ assigns_if True e) \c\ C` wenzelm@23350: moreover note B' = `B \ B'` schirmer@13688: moreover note da_c' schirmer@13688: ultimately obtain C': "nrm C \ nrm C'" "(\l. brk C l \ brk C' l)" schirmer@13688: by blast schirmer@13688: with A A' B' schirmer@13688: have "nrm A \ nrm A'" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: { fix l' schirmer@13688: have "brk A l' \ brk A' l'" schirmer@13688: proof (cases "constVal e") schirmer@13688: case None schirmer@13688: with A A' C' schirmer@13688: show ?thesis schirmer@13688: by (cases "l=l'") auto schirmer@13688: next schirmer@13688: case (Some bv) schirmer@13688: with A A' C' schirmer@13688: show ?thesis schirmer@13688: by (cases "the_Bool bv", cases "l=l'") auto schirmer@13688: qed schirmer@13688: } schirmer@13688: ultimately show ?case schirmer@13688: by auto schirmer@13688: next berghofe@21765: case (Jmp jump B A Env B' A') schirmer@13688: thus ?case by (elim da_elim_cases) (auto split: jump.splits) schirmer@13688: next schirmer@13688: case Throw thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next berghofe@21765: case (Try Env B c1 C1 vn C c2 C2 A B' A') wenzelm@23350: note A = `nrm A = nrm C1 \ nrm C2` `brk A = brk C1 \\ brk C2` wenzelm@23350: from `Env\ B' \\Try c1 Catch(C vn) c2\\ A'` wenzelm@23350: obtain C1' C2' schirmer@13688: where da_c1': "Env\ B' \\c1\\ C1'" and schirmer@13688: da_c2': "Env\lcl := lcl Env(VName vn\Class C)\\ B' \ {VName vn} schirmer@13688: \\c2\\ C2'" and schirmer@13688: A': "nrm A' = nrm C1' \ nrm C2'" schirmer@13688: "brk A' = brk C1' \\ brk C2'" schirmer@13688: by (rule da_elim_cases) auto wenzelm@23350: note `PROP ?Hyp Env B \c1\ C1` wenzelm@23350: moreover note B' = `B \ B'` schirmer@13688: moreover note da_c1' schirmer@13688: ultimately obtain C1': "nrm C1 \ nrm C1'" "(\l. brk C1 l \ brk C1' l)" schirmer@13688: by blast wenzelm@23350: note `PROP ?Hyp (Env\lcl := lcl Env(VName vn\Class C)\) wenzelm@23350: (B \ {VName vn}) \c2\ C2` schirmer@13688: with B' da_c2' schirmer@13688: obtain "nrm C2 \ nrm C2'" "(\l. brk C2 l \ brk C2' l)" schirmer@13688: by blast schirmer@13688: with C1' A A' schirmer@13688: show ?case schirmer@13688: by auto schirmer@13688: next berghofe@21765: case (Fin Env B c1 C1 c2 C2 A B' A') wenzelm@23350: note A = `nrm A = nrm C1 \ nrm C2` wenzelm@23350: `brk A = (brk C1 \\\<^sub>\ nrm C2) \\ (brk C2)` wenzelm@23350: from `Env\ B' \\c1 Finally c2\\ A'` wenzelm@23350: obtain C1' C2' schirmer@13688: where da_c1': "Env\ B' \\c1\\ C1'" and schirmer@13688: da_c2': "Env\ B' \\c2\\ C2'" and schirmer@13688: A': "nrm A' = nrm C1' \ nrm C2'" schirmer@13688: "brk A' = (brk C1' \\\<^sub>\ nrm C2') \\ (brk C2')" schirmer@13688: by (rule da_elim_cases) auto wenzelm@23350: note `PROP ?Hyp Env B \c1\ C1` wenzelm@23350: moreover note B' = `B \ B'` schirmer@13688: moreover note da_c1' schirmer@13688: ultimately obtain C1': "nrm C1 \ nrm C1'" "(\l. brk C1 l \ brk C1' l)" schirmer@13688: by blast wenzelm@23350: note hyp_c2 = `PROP ?Hyp Env B \c2\ C2` schirmer@13688: from da_c2' B' schirmer@13688: obtain "nrm C2 \ nrm C2'" "(\l. brk C2 l \ brk C2' l)" schirmer@13688: by - (drule hyp_c2,auto) schirmer@13688: with A A' C1' schirmer@13688: show ?case schirmer@13688: by auto schirmer@13688: next schirmer@13688: case Init thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case NewC thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case NewA thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Cast thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Inst thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Lit thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case UnOp thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next berghofe@21765: case (CondAnd Env B e1 E1 e2 E2 A B' A') wenzelm@23350: note A = `nrm A = B \ schirmer@13688: assigns_if True (BinOp CondAnd e1 e2) \ wenzelm@23350: assigns_if False (BinOp CondAnd e1 e2)` wenzelm@23350: `brk A = (\l. UNIV)` wenzelm@23350: from `Env\ B' \\BinOp CondAnd e1 e2\\ A'` wenzelm@23350: obtain A': "nrm A' = B' \ schirmer@13688: assigns_if True (BinOp CondAnd e1 e2) \ schirmer@13688: assigns_if False (BinOp CondAnd e1 e2)" schirmer@13688: "brk A' = (\l. UNIV)" schirmer@13688: by (rule da_elim_cases) auto wenzelm@23350: note B' = `B \ B'` schirmer@13688: with A A' show ?case schirmer@13688: by auto schirmer@13688: next schirmer@13688: case CondOr thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case BinOp thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Super thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case AccLVar thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Acc thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case AssLVar thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Ass thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next berghofe@21765: case (CondBool Env c e1 e2 B C E1 E2 A B' A') wenzelm@23350: note A = `nrm A = B \ schirmer@13688: assigns_if True (c ? e1 : e2) \ wenzelm@23350: assigns_if False (c ? e1 : e2)` wenzelm@23350: `brk A = (\l. UNIV)` wenzelm@23350: note `Env\ (c ? e1 : e2)\- (PrimT Boolean)` schirmer@13688: moreover wenzelm@23350: note `Env\ B' \\c ? e1 : e2\\ A'` schirmer@13688: ultimately schirmer@13688: obtain A': "nrm A' = B' \ schirmer@13688: assigns_if True (c ? e1 : e2) \ schirmer@13688: assigns_if False (c ? e1 : e2)" schirmer@13688: "brk A' = (\l. UNIV)" schirmer@13688: by - (erule da_elim_cases,auto simp add: inj_term_simps) schirmer@13688: (* inj_term_simps needed to handle wt (defined without \\) *) wenzelm@23350: note B' = `B \ B'` schirmer@13688: with A A' show ?case schirmer@13688: by auto schirmer@13688: next berghofe@21765: case (Cond Env c e1 e2 B C E1 E2 A B' A') wenzelm@23350: note A = `nrm A = nrm E1 \ nrm E2` `brk A = (\l. UNIV)` wenzelm@23350: note not_bool = `\ Env\ (c ? e1 : e2)\- (PrimT Boolean)` wenzelm@23350: from `Env\ B' \\c ? e1 : e2\\ A'` wenzelm@23350: obtain E1' E2' schirmer@13688: where da_e1': "Env\ B' \ assigns_if True c \\e1\\ E1'" and schirmer@13688: da_e2': "Env\ B' \ assigns_if False c \\e2\\ E2'" and schirmer@13688: A': "nrm A' = nrm E1' \ nrm E2'" schirmer@13688: "brk A' = (\l. UNIV)" schirmer@13688: using not_bool schirmer@13688: by - (erule da_elim_cases, auto simp add: inj_term_simps) schirmer@13688: (* inj_term_simps needed to handle wt (defined without \\) *) wenzelm@23350: note `PROP ?Hyp Env (B \ assigns_if True c) \e1\ E1` wenzelm@23350: moreover note B' = `B \ B'` schirmer@13688: moreover note da_e1' schirmer@13688: ultimately obtain E1': "nrm E1 \ nrm E1'" "(\l. brk E1 l \ brk E1' l)" wenzelm@23350: by blast wenzelm@23350: note `PROP ?Hyp Env (B \ assigns_if False c) \e2\ E2` schirmer@13688: with B' da_e2' schirmer@13688: obtain "nrm E2 \ nrm E2'" "(\l. brk E2 l \ brk E2' l)" schirmer@13688: by blast schirmer@13688: with E1' A A' schirmer@13688: show ?case schirmer@13688: by auto schirmer@13688: next schirmer@13688: case Call schirmer@13688: from Call.prems and Call.hyps schirmer@13688: show ?case by cases auto schirmer@13688: next schirmer@13688: case Methd thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Body thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case LVar thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case FVar thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case AVar thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Nil thus ?case by - (erule da_elim_cases, auto) schirmer@13688: next schirmer@13688: case Cons thus ?case by - (erule da_elim_cases, auto) schirmer@13688: qed wenzelm@23350: qed (rule da', rule `B \ B'`) schirmer@13688: schirmer@13688: lemma da_weaken: wenzelm@23350: assumes da: "Env\ B \t\ A" and "B \ B'" wenzelm@23350: shows "\ A'. Env \ B' \t\ A'" schirmer@13688: proof - wenzelm@15801: note assigned.select_convs [Pure.intro] schirmer@13688: from da schirmer@13688: show "\ B'. B \ B' \ \ A'. Env\ B' \t\ A'" (is "PROP ?Hyp Env B t") schirmer@13688: proof (induct) nipkow@17589: case Skip thus ?case by (iprover intro: da.Skip) schirmer@13688: next nipkow@17589: case Expr thus ?case by (iprover intro: da.Expr) schirmer@13688: next berghofe@21765: case (Lab Env B c C A l B') wenzelm@23350: note `PROP ?Hyp Env B \c\` schirmer@13688: moreover wenzelm@23350: note B' = `B \ B'` schirmer@13688: ultimately obtain C' where "Env\ B' \\c\\ C'" nipkow@17589: by iprover schirmer@13688: then obtain A' where "Env\ B' \\Break l\ c\\ A'" nipkow@17589: by (iprover intro: da.Lab) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Comp Env B c1 C1 c2 C2 A B') wenzelm@23350: note da_c1 = `Env\ B \\c1\\ C1` wenzelm@23350: note `PROP ?Hyp Env B \c1\` schirmer@13688: moreover wenzelm@23350: note B' = `B \ B'` schirmer@13688: ultimately obtain C1' where da_c1': "Env\ B' \\c1\\ C1'" nipkow@17589: by iprover schirmer@13688: with da_c1 B' schirmer@13688: have schirmer@13688: "nrm C1 \ nrm C1'" schirmer@13688: by (rule da_monotone [elim_format]) simp schirmer@13688: moreover wenzelm@23350: note `PROP ?Hyp Env (nrm C1) \c2\` schirmer@13688: ultimately obtain C2' where "Env\ nrm C1' \\c2\\ C2'" nipkow@17589: by iprover schirmer@13688: with da_c1' obtain A' where "Env\ B' \\c1;; c2\\ A'" nipkow@17589: by (iprover intro: da.Comp) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (If Env B e E c1 C1 c2 C2 A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E' where "Env\ B' \\e\\ E'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e\" by (rule If.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain C1' where "Env\ (B' \ assigns_if True e) \\c1\\ C1'" schirmer@13688: proof - schirmer@13688: from B' schirmer@13688: have "(B \ assigns_if True e) \ (B' \ assigns_if True e)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if True e) \c1\" by (rule If.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain C2' where "Env\ (B' \ assigns_if False e) \\c2\\ C2'" schirmer@13688: proof - schirmer@13688: from B' have "(B \ assigns_if False e) \ (B' \ assigns_if False e)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if False e) \c2\" by (rule If.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\If(e) c1 Else c2\\ A'" nipkow@17589: by (iprover intro: da.If) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Loop Env B e E c C A l B') wenzelm@23350: note B' = `B \ B'` wenzelm@23350: obtain E' where "Env\ B' \\e\\ E'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e\" by (rule Loop.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain C' where "Env\ (B' \ assigns_if True e) \\c\\ C'" schirmer@13688: proof - schirmer@13688: from B' schirmer@13688: have "(B \ assigns_if True e) \ (B' \ assigns_if True e)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if True e) \c\" by (rule Loop.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\l\ While(e) c\\ A'" nipkow@17589: by (iprover intro: da.Loop ) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Jmp jump B A Env B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: with Jmp.hyps have "jump = Ret \ Result \ B' " schirmer@13688: by auto schirmer@13688: moreover schirmer@13688: obtain A'::assigned schirmer@13688: where "nrm A' = UNIV" schirmer@13688: "brk A' = (case jump of schirmer@13688: Break l \ \k. if k = l then B' else UNIV schirmer@13688: | Cont l \ \k. UNIV schirmer@13688: | Ret \ \k. UNIV)" schirmer@13688: nipkow@17589: by iprover schirmer@13688: ultimately have "Env\ B' \\Jmp jump\\ A'" schirmer@13688: by (rule da.Jmp) schirmer@13688: thus ?case .. schirmer@13688: next nipkow@17589: case Throw thus ?case by (iprover intro: da.Throw ) schirmer@13688: next berghofe@21765: case (Try Env B c1 C1 vn C c2 C2 A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain C1' where "Env\ B' \\c1\\ C1'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \c1\" by (rule Try.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain C2' where schirmer@13688: "Env\lcl := lcl Env(VName vn\Class C)\\ B' \ {VName vn} \\c2\\ C2'" schirmer@13688: proof - schirmer@13688: from B' have "B \ {VName vn} \ B' \ {VName vn}" by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp (Env\lcl := lcl Env(VName vn\Class C)\) schirmer@13688: (B \ {VName vn}) \c2\" schirmer@13688: by (rule Try.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\Try c1 Catch(C vn) c2\\ A'" nipkow@17589: by (iprover intro: da.Try ) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Fin Env B c1 C1 c2 C2 A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain C1' where C1': "Env\ B' \\c1\\ C1'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \c1\" by (rule Fin.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain C2' where "Env\ B' \\c2\\ C2'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \c2\" by (rule Fin.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\c1 Finally c2\\ A'" nipkow@17589: by (iprover intro: da.Fin ) schirmer@13688: thus ?case .. schirmer@13688: next nipkow@17589: case Init thus ?case by (iprover intro: da.Init) schirmer@13688: next nipkow@17589: case NewC thus ?case by (iprover intro: da.NewC) schirmer@13688: next nipkow@17589: case NewA thus ?case by (iprover intro: da.NewA) schirmer@13688: next nipkow@17589: case Cast thus ?case by (iprover intro: da.Cast) schirmer@13688: next nipkow@17589: case Inst thus ?case by (iprover intro: da.Inst) schirmer@13688: next nipkow@17589: case Lit thus ?case by (iprover intro: da.Lit) schirmer@13688: next nipkow@17589: case UnOp thus ?case by (iprover intro: da.UnOp) schirmer@13688: next berghofe@21765: case (CondAnd Env B e1 E1 e2 E2 A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E1' where "Env\ B' \\e1\\ E1'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e1\" by (rule CondAnd.hyps) wenzelm@23350: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain E2' where "Env\ B' \ assigns_if True e1 \\e2\\ E2'" schirmer@13688: proof - schirmer@13688: from B' have "B \ assigns_if True e1 \ B' \ assigns_if True e1" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if True e1) \e2\" by (rule CondAnd.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\BinOp CondAnd e1 e2\\ A'" nipkow@17589: by (iprover intro: da.CondAnd) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (CondOr Env B e1 E1 e2 E2 A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E1' where "Env\ B' \\e1\\ E1'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e1\" by (rule CondOr.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain E2' where "Env\ B' \ assigns_if False e1 \\e2\\ E2'" schirmer@13688: proof - schirmer@13688: from B' have "B \ assigns_if False e1 \ B' \ assigns_if False e1" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if False e1) \e2\" by (rule CondOr.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\BinOp CondOr e1 e2\\ A'" nipkow@17589: by (iprover intro: da.CondOr) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (BinOp Env B e1 E1 e2 A binop B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E1' where E1': "Env\ B' \\e1\\ E1'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e1\" by (rule BinOp.hyps) wenzelm@23350: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain A' where "Env\ nrm E1' \\e2\\ A'" schirmer@13688: proof - schirmer@13688: have "Env\ B \\e1\\ E1" by (rule BinOp.hyps) schirmer@13688: from this B' E1' schirmer@13688: have "nrm E1 \ nrm E1'" schirmer@13688: by (rule da_monotone [THEN conjE]) schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (nrm E1) \e2\" by (rule BinOp.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: have "Env\ B' \\BinOp binop e1 e2\\ A'" nipkow@17589: using BinOp.hyps by (iprover intro: da.BinOp) schirmer@13688: thus ?case .. schirmer@13688: next schirmer@13688: case (Super B Env B') wenzelm@23350: note B' = `B \ B'` wenzelm@23350: with Super.hyps have "This \ B'" schirmer@13688: by auto nipkow@17589: thus ?case by (iprover intro: da.Super) schirmer@13688: next berghofe@21765: case (AccLVar vn B A Env B') wenzelm@23350: note `vn \ B` schirmer@13688: moreover wenzelm@23350: note `B \ B'` schirmer@13688: ultimately have "vn \ B'" by auto nipkow@17589: thus ?case by (iprover intro: da.AccLVar) schirmer@13688: next nipkow@17589: case Acc thus ?case by (iprover intro: da.Acc) schirmer@13688: next berghofe@21765: case (AssLVar Env B e E A vn B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: then obtain E' where "Env\ B' \\e\\ E'" nipkow@17589: by (rule AssLVar.hyps [elim_format]) iprover schirmer@13688: then obtain A' where schirmer@13688: "Env\ B' \\LVar vn:=e\\ A'" nipkow@17589: by (iprover intro: da.AssLVar) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Ass v Env B V e A B') wenzelm@23350: note B' = `B \ B'` wenzelm@23350: note `\vn. v \ LVar vn` schirmer@13688: moreover schirmer@13688: obtain V' where V': "Env\ B' \\v\\ V'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \v\" by (rule Ass.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain A' where "Env\ nrm V' \\e\\ A'" schirmer@13688: proof - schirmer@13688: have "Env\ B \\v\\ V" by (rule Ass.hyps) schirmer@13688: from this B' V' schirmer@13688: have "nrm V \ nrm V'" schirmer@13688: by (rule da_monotone [THEN conjE]) schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (nrm V) \e\" by (rule Ass.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: have "Env\ B' \\v := e\\ A'" nipkow@17589: by (iprover intro: da.Ass) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (CondBool Env c e1 e2 B C E1 E2 A B') wenzelm@23350: note B' = `B \ B'` wenzelm@23350: note `Env\(c ? e1 : e2)\-(PrimT Boolean)` schirmer@13688: moreover obtain C' where C': "Env\ B' \\c\\ C'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \c\" by (rule CondBool.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain E1' where "Env\ B' \ assigns_if True c \\e1\\ E1'" schirmer@13688: proof - schirmer@13688: from B' schirmer@13688: have "(B \ assigns_if True c) \ (B' \ assigns_if True c)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if True c) \e1\" by (rule CondBool.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain E2' where "Env\ B' \ assigns_if False c \\e2\\ E2'" schirmer@13688: proof - schirmer@13688: from B' schirmer@13688: have "(B \ assigns_if False c) \ (B' \ assigns_if False c)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if False c) \e2\" by(rule CondBool.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\c ? e1 : e2\\ A'" nipkow@17589: by (iprover intro: da.CondBool) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Cond Env c e1 e2 B C E1 E2 A B') wenzelm@23350: note B' = `B \ B'` wenzelm@23350: note `\ Env\(c ? e1 : e2)\-(PrimT Boolean)` schirmer@13688: moreover obtain C' where C': "Env\ B' \\c\\ C'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \c\" by (rule Cond.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain E1' where "Env\ B' \ assigns_if True c \\e1\\ E1'" schirmer@13688: proof - schirmer@13688: from B' schirmer@13688: have "(B \ assigns_if True c) \ (B' \ assigns_if True c)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if True c) \e1\" by (rule Cond.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain E2' where "Env\ B' \ assigns_if False c \\e2\\ E2'" schirmer@13688: proof - schirmer@13688: from B' schirmer@13688: have "(B \ assigns_if False c) \ (B' \ assigns_if False c)" schirmer@13688: by blast schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (B \ assigns_if False c) \e2\" by (rule Cond.hyps) schirmer@13688: ultimately nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: obtain A' where "Env\ B' \\c ? e1 : e2\\ A'" nipkow@17589: by (iprover intro: da.Cond) schirmer@13688: thus ?case .. schirmer@13688: next berghofe@21765: case (Call Env B e E args A accC statT mode mn pTs B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E' where E': "Env\ B' \\e\\ E'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e\" by (rule Call.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain A' where "Env\ nrm E' \\args\\ A'" schirmer@13688: proof - schirmer@13688: have "Env\ B \\e\\ E" by (rule Call.hyps) schirmer@13688: from this B' E' schirmer@13688: have "nrm E \ nrm E'" schirmer@13688: by (rule da_monotone [THEN conjE]) schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (nrm E) \args\" by (rule Call.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: have "Env\ B' \\{accC,statT,mode}e\mn( {pTs}args)\\ A'" nipkow@17589: by (iprover intro: da.Call) schirmer@13688: thus ?case .. schirmer@13688: next nipkow@17589: case Methd thus ?case by (iprover intro: da.Methd) schirmer@13688: next berghofe@21765: case (Body Env B c C A D B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain C' where C': "Env\ B' \\c\\ C'" and nrm_C': "nrm C \ nrm C'" schirmer@13688: proof - schirmer@13688: have "Env\ B \\c\\ C" by (rule Body.hyps) schirmer@13688: moreover note B' schirmer@13688: moreover schirmer@13688: from B' obtain C' where da_c: "Env\ B' \\c\\ C'" schirmer@13688: by (rule Body.hyps [elim_format]) blast schirmer@13688: ultimately schirmer@13688: have "nrm C \ nrm C'" schirmer@13688: by (rule da_monotone [THEN conjE]) nipkow@17589: with da_c that show ?thesis by iprover schirmer@13688: qed schirmer@13688: moreover wenzelm@23350: note `Result \ nrm C` schirmer@13688: with nrm_C' have "Result \ nrm C'" schirmer@13688: by blast wenzelm@23350: moreover note `jumpNestingOkS {Ret} c` schirmer@13688: ultimately obtain A' where schirmer@13688: "Env\ B' \\Body D c\\ A'" nipkow@17589: by (iprover intro: da.Body) schirmer@13688: thus ?case .. schirmer@13688: next nipkow@17589: case LVar thus ?case by (iprover intro: da.LVar) schirmer@13688: next nipkow@17589: case FVar thus ?case by (iprover intro: da.FVar) schirmer@13688: next berghofe@21765: case (AVar Env B e1 E1 e2 A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E1' where E1': "Env\ B' \\e1\\ E1'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e1\" by (rule AVar.hyps) wenzelm@23350: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain A' where "Env\ nrm E1' \\e2\\ A'" schirmer@13688: proof - schirmer@13688: have "Env\ B \\e1\\ E1" by (rule AVar.hyps) schirmer@13688: from this B' E1' schirmer@13688: have "nrm E1 \ nrm E1'" schirmer@13688: by (rule da_monotone [THEN conjE]) schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (nrm E1) \e2\" by (rule AVar.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: have "Env\ B' \\e1.[e2]\\ A'" nipkow@17589: by (iprover intro: da.AVar) schirmer@13688: thus ?case .. schirmer@13688: next nipkow@17589: case Nil thus ?case by (iprover intro: da.Nil) schirmer@13688: next berghofe@21765: case (Cons Env B e E es A B') wenzelm@23350: note B' = `B \ B'` schirmer@13688: obtain E' where E': "Env\ B' \\e\\ E'" schirmer@13688: proof - schirmer@13688: have "PROP ?Hyp Env B \e\" by (rule Cons.hyps) schirmer@13688: with B' nipkow@17589: show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: moreover schirmer@13688: obtain A' where "Env\ nrm E' \\es\\ A'" schirmer@13688: proof - schirmer@13688: have "Env\ B \\e\\ E" by (rule Cons.hyps) schirmer@13688: from this B' E' schirmer@13688: have "nrm E \ nrm E'" schirmer@13688: by (rule da_monotone [THEN conjE]) schirmer@13688: moreover schirmer@13688: have "PROP ?Hyp Env (nrm E) \es\" by (rule Cons.hyps) nipkow@17589: ultimately show ?thesis using that by iprover schirmer@13688: qed schirmer@13688: ultimately schirmer@13688: have "Env\ B' \\e # es\\ A'" nipkow@17589: by (iprover intro: da.Cons) schirmer@13688: thus ?case .. schirmer@13688: qed wenzelm@23350: qed (rule `B \ B'`) schirmer@13688: schirmer@13688: (* Remarks about the proof style: schirmer@13688: schirmer@13688: "by (rule .hyps)" vs "." schirmer@13688: -------------------------- schirmer@13688: schirmer@13688: with .hyps you state more precise were the rule comes from schirmer@13688: schirmer@13688: . takes all assumptions into account, but looks more "light" schirmer@13688: and is more resistent for cut and paste proof in different schirmer@13688: cases. schirmer@13688: schirmer@13688: "intro: da.intros" vs "da." schirmer@13688: --------------------------------- schirmer@13688: The first ist more convinient for cut and paste between cases, schirmer@13688: the second is more informativ for the reader schirmer@13688: *) schirmer@13688: schirmer@13688: corollary da_weakenE [consumes 2]: schirmer@13688: assumes da: "Env\ B \t\ A" and schirmer@13688: B': "B \ B'" and schirmer@13688: ex_mono: "\ A'. \Env\ B' \t\ A'; nrm A \ nrm A'; schirmer@13688: \ l. brk A l \ brk A' l\ \ P" schirmer@13688: shows "P" schirmer@13688: proof - schirmer@13688: from da B' schirmer@13688: obtain A' where A': "Env\ B' \t\ A'" nipkow@17589: by (rule da_weaken [elim_format]) iprover schirmer@13688: with da B' schirmer@13688: have "nrm A \ nrm A' \ (\ l. brk A l \ brk A' l)" schirmer@13688: by (rule da_monotone) schirmer@13688: with A' ex_mono schirmer@13688: show ?thesis nipkow@17589: by iprover schirmer@13688: qed schirmer@13688: nipkow@17589: end