Module analysis

Require syntax.
Require Lattice.
Require SumLattice.
Require func.
Require StackLattice.
Require AbVal.
Require FiniteSet.

Definition AbRef := [P:Program] (FiniteSet (max_log_ClassName P)).
Definition LatAbRef : (P:Program)(Lattice (AbRef P)) :=
 [P:Program] (LatticeFiniteSet (max_log_ClassName P)).

Definition AbVal := [P:Program](lift (AbRef P)+AbNum).
Definition LatAbVal : (P:Program)(Lattice (AbVal P)) :=
 [P:Program](sum_Lattice ? ? (LatAbRef P) LatAbNum).

Definition AbStack := [P:Program](stack (AbVal P)).
Definition LatAbStack : (P:Program)(Lattice (AbStack P)) :=
 [P:Program](StackLattice ? (LatAbVal P)).

Definition AbLocalVar := [P:Program](funcTree (AbVal P) (max_log_Var P)).
Definition LatAbLocalVar : (P:Program)(Lattice (AbLocalVar P)) :=
 [P:Program](funcTree_Lattice (AbVal P) (LatAbVal P) (max_log_Var P)).

Definition AbFuncPcStack := [P:Program](funcTree (AbStack P) (max_log_pc P)).
Definition LatAbFuncPcStack : (P:Program)(Lattice (AbFuncPcStack P)) :=
 [P:Program](funcTree_Lattice (AbStack P) (LatAbStack P) (max_log_pc P)).
Definition AbFuncStack := [P:Program](funcTree (AbFuncPcStack P) (max_log_MethodName P)).
Definition LatAbFuncStack : (P:Program)(Lattice (AbFuncStack P)) :=
 [P:Program](funcTree_Lattice (AbFuncPcStack P) (LatAbFuncPcStack P) (max_log_MethodName P)).

Definition AbFuncPcLocalVar := [P:Program](funcTree (AbLocalVar P) (max_log_pc P)).
Definition LatAbFuncPcLocalVar : (P:Program)(Lattice (AbFuncPcLocalVar P)) :=
 [P:Program](funcTree_Lattice (AbLocalVar P) (LatAbLocalVar P) (max_log_pc P)).
Definition AbFuncLocalVar := [P:Program](funcTree (AbFuncPcLocalVar P) (max_log_MethodName P)).
Definition LatAbFuncLocalVar : (P:Program)(Lattice (AbFuncLocalVar P)) :=
 [P:Program](funcTree_Lattice (AbFuncPcLocalVar P) (LatAbFuncPcLocalVar P) (max_log_MethodName P)).

Definition AbFrame := [P:Program] (AbFuncLocalVar P)*(AbFuncStack P).
Definition LatAbFrame : (P:Program)(Lattice (AbFrame P)) :=
 [P:Program](prod_Lattice ? ? (LatAbFuncLocalVar P) (LatAbFuncStack P) ).

Definition AbObject := [P:Program](funcTree (AbVal P) (max_log_Field P)).
Definition LatAbObject : (P:Program)(Lattice (AbObject P)) :=
 [P:Program](funcTree_Lattice (AbVal P) (LatAbVal P) (max_log_Field P)).
 
Definition AbHeap := [P:Program](funcTree (AbObject P) (max_log_ClassName P)).
Definition LatAbHeap : (P:Program)(Lattice (AbHeap P)) :=
 [P:Program](funcTree_Lattice (AbObject P) (LatAbObject P) (max_log_ClassName P)).

Definition AbState := [P:Program] (AbHeap P)*(AbFrame P).
Definition LatAbState : (P:Program)(Lattice (AbState P)) :=
 [P:Program](prod_Lattice ? ? (LatAbHeap P) (LatAbFrame P)).

Definition AbOperator : (P:Program) Operator -> (AbVal P) -> (AbVal P) -> (AbVal P) :=
[P,op]
 Cases op of
  | OpMult => (lift_right_binop ? ? AbMult)
  | OpPlus =>(lift_right_binop ? ? AbPlus)
  | OpComp =>(lift_right_binop ? ? AbComp)
  | OpMinus => (lift_right_binop ? ? AbMinus)
 end.

Definition AbBinop : (P:Program) Operator -> (AbStack P) -> (AbStack P) :=
[P,op,S]
 let X=(AbTop (LatAbVal P) S) in
 let Y=(AbTop (LatAbVal P) (AbPop S)) in
  (AbPush (AbOperator P op X Y) (AbPop (AbPop S))).

Fixpoint AbPop_n [P:Program;S:(AbStack P);n:nat] : (AbStack P) :=
 Cases n of
    O => S
  | (S p) => (AbPop (AbPop_n P S p))
 end.

Fixpoint AbTop_n [P:Program;S:(AbStack P);n:nat] : (list (AbVal P)) :=
 Cases n of
     O => (nil ?)
  | (S p) => (cons (AbTop (LatAbVal P) S) (AbTop_n P (AbPop S) p))
 end.

Fixpoint subst_n_rec [P:Program;p:Var;L:(AbLocalVar P);l:(list (AbVal P))] : (AbLocalVar P) :=
 Cases l of
  | nil => L
  | (cons v q) => (subst (LatAbVal P) (subst_n_rec P (add_un p) L q) p v)
 end.

Definition subst_n : (P:Program)(list (AbVal P))->(AbLocalVar P) :=
 [P,l](subst_n_rec P xH (bottom (LatAbLocalVar P)) l).

Definition betaTypeOfField : (P:Program)typeOfField->(AbVal P) :=
 [P,t]Cases t of
 | fieldNum => (some_sum ? (inr ? ? (const (0))))
 | fieldRef => (bottom (LatAbVal P))
 end.
    
Fixpoint AbDef_rec [P:Program;l:(list Field)] : (AbObject P) :=
 Cases l of
    nil => (bottom (LatAbObject P))
 | (cons fi q) => (subst (LatAbVal P) (AbDef_rec P q) (nameField fi) (betaTypeOfField P (typeField fi)))
 end.

Definition AbDef : (P:Program)ClassName->(AbObject P) :=
 [P,cl]Cases (searchClass P cl) of
         | None => (bottom (LatAbObject P))
         | (Some c) => (AbDef_rec P (instanceFields c))
    end.

Record Address : Set := add {
  mAdd:MethodName;
  pcAdd:progCount
}.

Definition applyS : (P:Program)(AbFuncStack P)->Address->(AbStack P) :=
 [P,S,add]
 (apply (LatAbStack P)
        (apply (LatAbFuncPcStack P) S (mAdd add))
        (pcAdd add)).
Coercion applyS : AbFuncStack >-> FUNCLASS.

Definition applyL : (P:Program)(AbFuncLocalVar P)->Address->(AbLocalVar P) :=
 [P,L,add]
 (apply (LatAbLocalVar P)
        (apply (LatAbFuncPcLocalVar P) L (mAdd add))
        (pcAdd add)).
Coercion applyL : AbFuncLocalVar >-> FUNCLASS.

Inductive Constraint [P:Program] : Set :=
 | c2S : Address -> (AbStack P) -> (Constraint P)
 | c2H : (AbHeap P) -> (Constraint P)
 | S2S : Address -> Address -> ((AbStack P) -> (AbStack P)) -> (Constraint P)
 | L2L : Address -> Address -> ((AbLocalVar P) -> (AbLocalVar P)) -> (Constraint P)
 | SL2S : Address -> Address -> ((AbStack P) -> (AbLocalVar P) -> (AbStack P)) -> (Constraint P)
 | SL2L : Address -> Address -> ((AbStack P) -> (AbLocalVar P) -> (AbLocalVar P)) -> (Constraint P)
 | HS2S : Address -> Address -> ((AbHeap P) -> (AbStack P) -> (AbStack P)) -> (Constraint P)
 | S2H : Address -> ((AbStack P)->(AbHeap P)) -> (Constraint P)
 | S2allS : Address -> ((AbStack P) ->(AbFuncStack P)) -> (Constraint P)
 | S2allL : Address -> ((AbStack P) -> (AbFuncLocalVar P)) -> (Constraint P)
 | allS2S : Address -> ((AbFuncStack P) -> (AbStack P)) -> (Constraint P).

Definition validAd : (P:Program)Address->Prop :=
 [P,ad]
 (inf_log (mAdd ad) (max_log_MethodName P)) /\
 (inf_log (pcAdd ad) (max_log_pc P)).

Definition validConstraint : (P:Program)(Constraint P)->Prop :=
 [P,c]Cases c of
   | (c2S add_out S0) => (validAd P add_out)
   | (c2H H0) => True
   | (S2S add_in add_out F) => (validAd P add_out)
   | (L2L add_in add_out F) => (validAd P add_out)
   | (SL2S add_in add_out F) => (validAd P add_out)
   | (SL2L add_in add_out F) => (validAd P add_out)
   | (HS2S add_in add_out F) => (validAd P add_out)
   | (S2H add_in F) => True
   | (S2allS add_in F) => True
   | (S2allL add_in F) => True
   | (allS2S add_out F) => (validAd P add_out)
 end.

Inductive verifyContraint [P:Program] : (AbState P) -> (Constraint P) -> Prop :=
 | verify_c2S : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                 ad_out:Address;S0:(AbStack P))
                (order (LatAbStack P) S0 (S ad_out)) ->
                   (verifyContraint P (H,(L,S)) (c2S P ad_out S0))
 | verify_c2H : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                 H0:(AbHeap P))
                (order (LatAbHeap P) H0 H) ->
                   (verifyContraint P (H,(L,S)) (c2H P H0))
 | verify_S2S : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                 ad_in,ad_out:Address;F:((AbStack P)->(AbStack P)))
                (order (LatAbStack P) (F (S ad_in)) (S ad_out)) ->
                   (verifyContraint P (H,(L,S)) (S2S P ad_in ad_out F))
 | verify_L2L : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                 ad_in,ad_out:Address;F:((AbLocalVar P)->(AbLocalVar P)))
                (order (LatAbLocalVar P) (F (L ad_in)) (L ad_out)) ->
                   (verifyContraint P (H,(L,S)) (L2L P ad_in ad_out F))
 | verify_SL2S : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                  ad_in,ad_out:Address;F:((AbStack P)->(AbLocalVar P)->(AbStack P)))
                (order (LatAbStack P) (F (S ad_in) (L ad_in)) (S ad_out)) ->
                   (verifyContraint P (H,(L,S)) (SL2S P ad_in ad_out F))
 | verify_SL2L : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                 ad_in,ad_out:Address;F:((AbStack P)->(AbLocalVar P)->(AbLocalVar P)))
                (order (LatAbLocalVar P) (F (S ad_in) (L ad_in)) (L ad_out)) ->
                   (verifyContraint P (H,(L,S)) (SL2L P ad_in ad_out F))
 | verify_HS2S : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                  ad_in,ad_out:Address;F:((AbHeap P)->(AbStack P)->(AbStack P)))
                (order (LatAbStack P) (F H (S ad_in)) (S ad_out)) ->
                   (verifyContraint P (H,(L,S)) (HS2S P ad_in ad_out F))
 | verify_S2H : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                 ad_in:Address;F:((AbStack P)->(AbHeap P)))
                (order (LatAbHeap P) (F (S ad_in)) H) ->
                   (verifyContraint P (H,(L,S)) (S2H P ad_in F))
 | verify_S2allS : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                    ad_in:Address;F:((AbStack P)->(AbFuncStack P)))
                   (order (LatAbFuncStack P) (F (S ad_in)) S) ->
                  (verifyContraint P (H,(L,S)) (S2allS P ad_in F))
 | verify_S2allL : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                    ad_in:Address;F:((AbStack P)->(AbFuncLocalVar P)))
                   (order (LatAbFuncLocalVar P) (F (S ad_in)) L) ->
                  (verifyContraint P (H,(L,S)) (S2allL P ad_in F))
 | verify_allS2S : (H:(AbHeap P);L:(AbFuncLocalVar P);S:(AbFuncStack P);
                    ad_out:Address;F:((AbFuncStack P)->(AbStack P)))
                  (order (LatAbStack P) (F S) (S ad_out)) ->
                  (verifyContraint P (H,(L,S)) (allS2S P ad_out F)).

Definition Flow : (P:Program) MethodName -> progCount -> Instruction -> (list (Constraint P)) :=
[P,m,pc,I]
Cases I of
 | nop =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)]S)
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | (push c) =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)](AbPush (some_sum ? (inr ? ? (betaNum c))) S))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | pop =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)](AbPop S))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | (numop op) =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)](AbBinop P op S))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | (load i) =>
    (cons (SL2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P);L:(AbLocalVar P)](AbPush (apply (LatAbVal P) L i) S))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | (store i) =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)](AbPop S))
    (cons (SL2L P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P);L:(AbLocalVar P)](subst (LatAbVal P) L i (AbTop (LatAbVal P) S)))
    (nil (Constraint P))))
 | (If pc') =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)]
           (lift_right_unop (LatAbStack P)
                            (AbIf_NZ (LatAbStack P) (AbPop S))
                            (AbTop (LatAbVal P) S)))
    (cons (SL2L P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P);L:(AbLocalVar P)]
           (lift_right_unop (LatAbLocalVar P)
                            (AbIf_NZ (LatAbLocalVar P) L)
                            (AbTop (LatAbVal P) S)))
    (cons (S2S P (add m pc) (add m pc')
           [S:(AbStack P)]
           (lift_right_unop (LatAbStack P)
                            (AbIf_Z (LatAbStack P) (AbPop S))
                            (AbTop (LatAbVal P) S)))
    (cons (SL2L P (add m pc) (add m pc')
           [S:(AbStack P);L:(AbLocalVar P)]
           (lift_right_unop (LatAbLocalVar P)
                            (AbIf_Z (LatAbLocalVar P) L)
                            (AbTop (LatAbVal P) S)))
    (nil (Constraint P))))))
 | (putfield f) =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)](AbPop (AbPop S)))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (cons (S2H P (add m pc)
           [S:(AbStack P)]
           let F=[cl:ClassName]
                 (subst (LatAbVal P) (bottom (LatAbObject P))
                      f (AbTop (LatAbVal P) S)) in
           (lift_left_unop (LatAbHeap P)
             (FiniteSet.map (LatAbObject P) F)
             (AbTop (LatAbVal P) (AbPop S))))
    (nil (Constraint P)))))
 | (new cl) =>
    (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)](AbPush (some_sum ? (inl ? ? (singleton cl))) S))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (cons (c2H P (subst (LatAbObject P)
                        (bottom (LatAbHeap P))
                        cl (AbDef P cl)))
    (nil (Constraint P)))))
 | (getfield f) =>
    (cons (HS2S P (add m pc) (add m (nextAddress P m pc))
           [H:(AbHeap P);S:(AbStack P)]
           (AbPush (lift_left_unop (LatAbVal P)
                     (join_on_set (LatAbVal P)
                                  [cl](apply (LatAbVal P) (apply (LatAbObject P) H cl) f))
                   (AbTop (LatAbVal P) S))
                   (AbPop S)))
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | (invokevirtual mID) =>
    (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
    (cons (S2allL P (add m pc)
               [s:(AbStack P)]
               (lift_left_unop (LatAbFuncLocalVar P)
                     (join_on_set (LatAbFuncLocalVar P)
                      [cl]Cases (methodLookup P mID cl) of
                            | None => (bottom (LatAbFuncLocalVar P))
                            | (Some M') => let n=(nbArguments M') in
                             (subst (LatAbFuncPcLocalVar P)
                               (bottom (LatAbFuncLocalVar P))
                               (nameMethod M')
                               (subst (LatAbLocalVar P)
                                      (bottom (LatAbFuncPcLocalVar P))
                                      xH
                                      (subst_n P (cons (some_sum ? (inl ? ? (singleton cl))) (AbTop_n P (AbPop s) n)))))
                          end)
                 (AbTop (LatAbVal P) s)))
    (cons (S2allS P (add m pc)
                  [s:(AbStack P)]
                  (lift_left_unop (LatAbFuncStack P)
                     (join_on_set (LatAbFuncStack P)
                      [cl]Cases (methodLookup P mID cl) of
                            | None => (bottom (LatAbFuncStack P))
                            | (Some M') =>
                             (subst (LatAbFuncPcStack P)
                               (bottom (LatAbFuncStack P))
                               (nameMethod M')
                               (subst (LatAbStack P)
                                      (bottom (LatAbFuncPcStack P))
                                      xH
                                      (some ? (nil ?))))
                          end)
                 (AbTop (LatAbVal P) s)))
    (cons (allS2S P (add m (nextAddress P m pc))
               [SS:(AbFuncStack P)]
               (lift_left_unop (LatAbStack P)
                     (join_on_set (LatAbStack P)
                      [cl]Cases (methodLookup P mID cl) of
                            | None => (bottom (LatAbStack P))
                            | (Some M') => let n=(nbArguments M') in
                               (AbPush (AbTop (LatAbVal P) (SS (add (nameMethod M') (END M'))))
                                       (AbPop_n P (SS (add m pc)) (S n)))
                          end)
                 (AbTop (LatAbVal P) (SS (add m pc)))))
    (nil (Constraint P))))))
 | return =>
     (Cases (searchMethod P m) of
        | None => (nil (Constraint P))
        | (Some M) => (cons (S2S P (add m pc) (add m (END M))
                               [S:(AbStack P)]S)
                          (nil (Constraint P)))
      end)
 | dup => (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)] (AbPush (AbTop (LatAbVal P) S) S))
          (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
                           (nil (Constraint P))))
 | (goto pc') =>
    (cons (S2S P (add m pc) (add m pc')
           [S:(AbStack P)]S)
    (cons (L2L P (add m pc) (add m pc')
           [L:(AbLocalVar P)]L)
    (nil (Constraint P))))
 | swap => (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)]
                let AbTop1 = (AbTop (LatAbVal P) S) in
                  let AbPop1 = (AbPop S) in
                    let AbTop2 = (AbTop (LatAbVal P) AbPop1) in
                      (AbPush AbTop2 (AbPush AbTop1 (AbPop AbPop1) )))
          (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
                           (nil (Constraint P))))
| dup2 => (cons (S2S P (add m pc) (add m (nextAddress P m pc))
           [S:(AbStack P)]
                let AbTop1 = (AbTop (LatAbVal P) S) in
                  let AbPop1 = (AbPop S) in
                    let AbTop2 = (AbTop (LatAbVal P) AbPop1) in
                      (AbPush AbTop1 (AbPush AbTop2 S )))
          (cons (L2L P (add m pc) (add m (nextAddress P m pc))
           [L:(AbLocalVar P)]L)
                           (nil (Constraint P))))
end.
 

Definition init_flow : (P:Program) (Constraint P) :=
[P:Program]
(c2S P (add (main P) xH) (some ? (nil ?))).

Lemma valid_init_flow : (P:Program)(validConstraint P (init_flow P)).
Unfold init_flow validConstraint.
Intros; Split; Simpl.
Unfold max_log_MethodName.
Elim (hypothesis_on_main P); Intros.
Elim H; Intros.
Rewrite <- H1.
Apply in_inf_log; Auto.
Constructor.
Qed.

Definition verifyFlow : (P:Program)MethodName->progCount->Instruction->(AbState P)->Prop :=
 [P,m,pc,I,St](c:(Constraint P)) (In c (Flow P m pc I)) -> (verifyContraint P St c).

Definition verifyAllFlow : (P:Program)(AbState P)->Prop :=
 [P,AbS]
 (verifyContraint P AbS (init_flow P)) /\
 (m:MethodName;pc:progCount;I:Instruction)
 (instructionAt P m pc)=(Some I) ->
   (verifyFlow P m pc I AbS).

Lemma verifyAllFlow_hyp1 : (P:Program;AbS:(AbState P))
 (verifyAllFlow P AbS) ->
 (m:MethodName;pc:progCount;I:Instruction)
   (instructionAt P m pc)=(Some I) ->
   (verifyFlow P m pc I AbS).
Unfold verifyAllFlow; Intuition.
Qed.

Lemma validFlow : (P:Program;m:MethodName;pc:progCount;I:Instruction;c:(Constraint P))
 (instructionAt P m pc)=(Some I) ->
 (In c (Flow P m pc I)) ->
 (validConstraint P c).
Intros P m pc I c H.
NewDestruct I; Simpl;
 Intros H'; (Elim H'; Fail) Orelse (Decompose [or] H');
Try (Match Context With
  [id:?=c|-?]->Rewrite <- id; Clear id
| [id:False|-?]->Elim id);
Try (Split;
[Apply (instructionAt_some_inf_log_MethodName ? ? ? ? H)
|Simpl; Apply (valid_nextAddress ? ? ? ? H)]).
Split.
Apply (instructionAt_some_inf_log_MethodName ? ? ? ? H).
Clear H'.
Simpl; Elim (instructionAt_some ? ? ? ? H); Intuition.
Apply inf_log_trans with (anti_convert (length (instructions x))).
Replace (anti_convert (length (instructions x))) with (END x); [Intros|Unfold END;Auto].
Unfold max_log_pc; Apply in_inf_log; Auto.
Apply (valid_if_hypothesis P x); Auto.
Split.
Apply (instructionAt_some_inf_log_MethodName ? ? ? ? H).
Clear H'.
Simpl; Elim (instructionAt_some ? ? ? ? H); Intuition.
Apply inf_log_trans with (anti_convert (length (instructions x))).
Replace (anti_convert (length (instructions x))) with (END x); [Intros|Unfold END;Auto].
Unfold max_log_pc; Apply in_inf_log; Auto.
Apply (valid_if_hypothesis P x); Auto.
Clear H'; Unfold validConstraint; Auto.
Clear H'; Unfold validConstraint; Auto.
Clear H'; Unfold validConstraint; Auto.
Clear H'; Unfold validConstraint; Auto.
Generalize H'; Clear H'.
CaseEq '(searchMethod P m); Intros.
Elim H' ; Clear H'; Intros.
Rewrite <- H1.
Split.
Simpl.
Apply (instructionAt_some_inf_log_MethodName ? ? ? ? H).
Simpl.
Unfold max_log_pc.
Apply in_inf_log.
Elim (searchMethod_some ? ? ? H0); Intros; Auto.
Elim H1.
Elim H'.
Unfold validConstraint ; Auto.
Unfold validAd ; Simpl ; Auto.
Split.
EApply instructionAt_some_inf_log_MethodName ; EAuto.
EApply valid_goto_instructionAt ; EAuto.
Unfold validConstraint ; Auto.
Unfold validAd ; Simpl ; Auto.
Split.
EApply instructionAt_some_inf_log_MethodName ; EAuto.
EApply valid_goto_instructionAt ; EAuto.
Qed.

Inductive constraint_monotone [P:Program] : (Constraint P) -> Prop :=
 | monotone_c2S : (ad_out:Address;S0:(AbStack P))
                   (constraint_monotone P (c2S P ad_out S0))
 | monotone_c2H : (H0:(AbHeap P))
                   (constraint_monotone P (c2H P H0))
 | monotone_S2S : (ad_in,ad_out:Address;F:((AbStack P)->(AbStack P)))
                  ((S1,S2:(AbStack P))
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbStack P) (F S1) (F S2))) ->
                   (constraint_monotone P (S2S P ad_in ad_out F))
 | monotone_L2L : (ad_in,ad_out:Address;F:((AbLocalVar P)->(AbLocalVar P)))
                  ((L1,L2:(AbLocalVar P))
                    (order (LatAbLocalVar P) L1 L2) ->
                    (order (LatAbLocalVar P) (F L1) (F L2))) ->
                   (constraint_monotone P (L2L P ad_in ad_out F))
 | monotone_SL2S : (ad_in,ad_out:Address;F:((AbStack P)->(AbLocalVar P)->(AbStack P)))
                  ((L1,L2:(AbLocalVar P);S1,S2:(AbStack P))
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbLocalVar P) L1 L2) ->
                    (order (LatAbStack P) (F S1 L1) (F S2 L2))) ->
                   (constraint_monotone P (SL2S P ad_in ad_out F))
 | monotone_SL2L : (ad_in,ad_out:Address;F:((AbStack P)->(AbLocalVar P)->(AbLocalVar P)))
                  ((L1,L2:(AbLocalVar P);S1,S2:(AbStack P))
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbLocalVar P) L1 L2) ->
                    (order (LatAbLocalVar P) (F S1 L1) (F S2 L2))) ->
                   (constraint_monotone P (SL2L P ad_in ad_out F))
 | monotone_HS2S : (ad_in,ad_out:Address;F:((AbHeap P)->(AbStack P)->(AbStack P)))
                  ((H1,H2:(AbHeap P);S1,S2:(AbStack P))
                    (order (LatAbHeap P) H1 H2) ->
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbStack P) (F H1 S1) (F H2 S2))) ->
                   (constraint_monotone P (HS2S P ad_in ad_out F))
 | monotone_S2H : (ad_in:Address;F:((AbStack P)->(AbHeap P)))
                  ((S1,S2:(AbStack P))
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbHeap P) (F S1) (F S2))) ->
                   (constraint_monotone P (S2H P ad_in F))
 | monotone_S2allS : (ad_in:Address;F:((AbStack P)->(AbFuncStack P)))
                  ((S1,S2:(AbStack P))
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbFuncStack P) (F S1) (F S2))) ->
                  (constraint_monotone P (S2allS P ad_in F))
 | monotone_S2allL : (ad_in:Address;F:((AbStack P)->(AbFuncLocalVar P)))
                  ((S1,S2:(AbStack P))
                    (order (LatAbStack P) S1 S2) ->
                    (order (LatAbFuncLocalVar P) (F S1) (F S2))) ->
                  (constraint_monotone P (S2allL P ad_in F))
 | monotone_allS2S : (ad_out:Address;F:((AbFuncStack P)->(AbStack P)))
                  ((S1,S2:(AbFuncStack P))
                    (order (LatAbFuncStack P) S1 S2) ->
                    (order (LatAbStack P) (F S1) (F S2))) ->
                  (constraint_monotone P (allS2S P ad_out F)).

Lemma AbBinop_monotone : (P:Program;op:Operator;s1,s2:(AbStack P))
 (order (LatAbStack P) s1 s2) ->
 (order (LatAbStack P) (AbBinop P op s1) (AbBinop P op s2)).
Intros P op s1 s2 H; Unfold AbBinop.
Apply (AbPush_monotone (LatAbVal P)).
Unfold AbOperator.
Case op ; Apply (lift_right_binop_keep_monotone ? ? (LatAbRef P) LatAbNum).
Intros.
Apply AbMult_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbPop_monotone; Auto.

Apply AbPlus_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbPop_monotone; Auto.

Apply AbComp_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbPop_monotone; Auto.

Apply AbMinus_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbPop_monotone; Auto.

Apply AbPop_monotone; Auto.
Apply AbPop_monotone; Auto.
Qed.

Lemma subst_n_rec_monotone : (P:Program;L:(AbLocalVar P);l1,l2:(list (AbVal P));p:Var)
 (order (LatAbStack P) (some ? l1) (some ? l2)) ->
 (order (LatAbLocalVar P) (subst_n_rec P p L l1) (subst_n_rec P p L l2)).
NewInduction l1; Intros.
Inversion_clear H.
Auto.
Inversion_clear H.
Unfold subst_n_rec.
Apply (subst_monotone ? (LatAbVal P) (max_log_Var P)); Auto.
Qed.

Lemma subst_n_monotone : (P:Program;l1,l2:(list (AbVal P)))
 (order (LatAbStack P) (some ? l1) (some ? l2)) ->
 (order (LatAbLocalVar P) (subst_n P l1) (subst_n P l2)).
Unfold subst_n; Intros; Apply subst_n_rec_monotone; Auto.
Qed.

Lemma AbPop_n_monotone : (P:Program;n:nat;S1,S2:(AbStack P))
 (order (LatAbStack P) S1 S2) ->
 (order (LatAbStack P) (AbPop_n P S1 n) (AbPop_n P S2 n)).
NewInduction n; Simpl; Intros.
Auto.
Apply AbPop_monotone; Auto.
Qed.

Lemma AbTop_n_monotone : (P:Program;n:nat;S1,S2:(AbStack P))
 (order (LatAbStack P) S1 S2) ->
 (order (LatAbStack P) (some ? (AbTop_n P S1 n)) (some ? (AbTop_n P S2 n))).
NewInduction n; Intros.
Cbv Beta Iota Delta [AbTop_n]; Auto.
Unfold AbTop_n.
Constructor.
Apply AbTop_monotone; Auto.
Generalize (IHn (AbPop S1) (AbPop S2)); Unfold AbTop_n; Intros.
Apply H0.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Qed.

Lemma monotone_Flow : (P:Program;m:MethodName;pc:progCount;I:Instruction;c:(Constraint P))
 (instructionAt P m pc)=(Some I) ->
 (In c (Flow P m pc I)) ->
 (constraint_monotone P c).
Intros P m pc I c H.
NewDestruct I; Simpl;
 Intros H'; (Elim H'; Fail) Orelse (Decompose [or] H');
Try (Match Context With
  [id:?=c|-?]->Rewrite <- id; Clear id
| [id:False|-?]->Elim id);
Try Constructor; Intros; Auto.
Apply (AbPush_monotone (LatAbVal P)); Auto.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Apply AbBinop_monotone; Auto.
Apply (AbPush_monotone (LatAbVal P)); Auto.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Apply (subst_monotone ? (LatAbVal P) (max_log_Var P)); Auto.
Apply AbTop_monotone; Auto.
Apply lift_right_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply AbIf_NZ_monotone; Auto.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Apply AbTop_monotone; Auto.
Apply lift_right_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply AbIf_NZ_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply lift_right_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply AbIf_Z_monotone; Auto.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Apply AbTop_monotone; Auto.
Apply lift_right_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply AbIf_Z_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply (AbPush_monotone (LatAbVal P)); Auto.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Apply (AbPop_monotone (LatAbVal P)); Auto.
Apply lift_left_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply (map_monotone (max_log_ClassName P) ? (LatAbObject P)); Intros; Auto.
Apply (subst_monotone ? (LatAbVal P) (max_log_Field P)); Auto.
Apply AbTop_monotone; Auto.
Apply AbTop_monotone; Auto.
Apply AbPop_monotone; Auto.
Apply (AbPush_monotone (LatAbVal P)); Auto.
Apply lift_left_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply join_on_set_monotone.
Intros; Apply apply_monotone.
Apply apply_monotone.
Auto.
Auto.
Apply AbTop_monotone; Auto.
Apply AbPop_monotone; Auto.
Apply lift_left_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros.
Apply join_on_set_monotone.
Intros p; CaseEq '(methodLookup P m0 p); Intros.
Apply (subst_monotone ? (LatAbFuncPcLocalVar P) (max_log_MethodName P)); Auto.
Apply (subst_monotone ? (LatAbLocalVar P) (max_log_pc P)); Auto.
Apply subst_n_monotone.
Constructor.
Constructor; Auto.
Apply (AbTop_n_monotone P (nbArguments m1) (AbPop S1) (AbPop S2)).
Apply (AbPop_monotone (LatAbVal P)); Auto.
Auto.
Auto.
Apply AbTop_monotone; Auto.
Apply lift_left_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros; Auto.
Apply join_on_set_monotone.
Intros p ; CaseEq '(methodLookup P m0 p); Intros.
Auto.
Auto.
Auto.
Apply AbTop_monotone; Auto.
Apply lift_left_unop_keep_monotone with (LatAbRef P) LatAbNum; Intros; Auto.
Apply join_on_set_monotone.
Intros p ; CaseEq '(methodLookup P m0 p); Intros.
Apply (AbPush_monotone (LatAbVal P)); Auto.
Apply AbTop_monotone; Auto.
Unfold applyS.
Apply apply_monotone.
Apply apply_monotone; Auto.
Apply AbPop_monotone.
Apply (AbPop_n_monotone P).
Unfold applyS.
Apply apply_monotone.
Apply apply_monotone; Auto.
Auto.
Auto.
Apply AbTop_monotone; Auto.
Unfold applyS.
Apply apply_monotone.
Apply apply_monotone; Auto.
Generalize H'; Clear H'.
CaseEq '(searchMethod P m); Intros.
Elim H'; Clear H'; Intros.
Rewrite <- H1; Constructor.
Intros; Auto.
Elim H1.
Elim H'.
Simpl.
Apply AbPush_monotone ; Auto.
Apply AbTop_monotone ; Auto.
Simpl.
Apply AbPush_monotone ; Auto.
Apply AbTop_monotone ; Auto.
Apply AbPop_monotone ; Auto.
Simpl.
Apply AbPush_monotone ; Auto.
Apply AbTop_monotone ; Auto.
Apply AbPop_monotone ; Auto.
Apply AbPop_monotone ; Auto.
Simpl.
Apply AbPush_monotone ; Auto.
Apply AbTop_monotone ; Auto.
Simpl.
Apply AbPush_monotone ; Auto.
Apply AbTop_monotone ; Auto.
Apply AbPop_monotone ; Auto.
Qed.


Index
This page has been generated by coqdoc