Require
ResultList.
Require
Export
TabTree.
Require
Export
Arith.
Require
Export
PolyList.
Require
Max.
Require
Omega.
Definition
integer := nat.
Definition
Var := positive.
Definition
progCount := positive.
Definition
Var_dec := positive_dec.
Definition
ClassName := positive.
Definition
FieldName := positive.
Definition
Field_dec := positive_dec.
Definition
MethodID := positive.
Definition
MethodName := positive.
Definition
MethodName_dec := positive_dec.
Inductive
Operator : Set :=
| OpMult : Operator
| OpPlus : Operator
| OpComp : Operator
| OpMinus : Operator.
Inductive
Instruction : Set :=
| nop : Instruction
| push : integer -> Instruction
| pop : Instruction
| numop : Operator -> Instruction
| load : Var -> Instruction
| store : Var -> Instruction
| If : progCount -> Instruction
| new : ClassName -> Instruction
| putfield : FieldName -> Instruction
| getfield : FieldName -> Instruction
| invokevirtual : MethodID -> Instruction
| return : Instruction
| dup : Instruction
| goto : progCount -> Instruction
| swap : Instruction
| dup2 : Instruction.
Inductive
typeOfField : Set :=
| fieldNum : typeOfField
| fieldRef : typeOfField.
Record
Field : Set := Field_constr {
nameField : FieldName;
typeField : typeOfField
}.
Record
Method : Set := Method_constr {
nameMethod : MethodName;
instructions : (list Instruction);
nbArguments : nat
}.
Inductive
allNameMethodsDistincts : (list Method)->Prop :=
| allNameMethodsDistincts1 : (allNameMethodsDistincts (nil ?))
| allNameMethodsDistincts2 : (m:Method;l:(list Method))
~(EX m':Method | (In m' l)/\(nameMethod m)=(nameMethod m')) ->
(allNameMethodsDistincts l) ->
(allNameMethodsDistincts (cons m l)).
Record
Class : Set := Class_constr {
nameClass : ClassName;
list_methods_lookup : (list (MethodID*MethodName));
instanceFields : (list Field)
}.
Record
Program : Set := Program_constr {
classes : (list Class);
methods : (list Method);
methodsValid : (allNameMethodsDistincts methods);
main : MethodName;
hypothesis_on_main : (EX M:Method | (In M methods)/\(nameMethod M)=main);
valid_if_hypothesis : (m:Method;pc:progCount)
(In m methods) ->
(In (If pc) (instructions m)) ->
(compare pc (anti_convert (length (instructions m))) EGAL)=INFERIEUR;
valid_goto_hypothesis : (m:Method;pc:progCount)
(In m methods) ->
(In (goto pc) (instructions m)) ->
(compare pc (anti_convert (length (instructions m))) EGAL)=INFERIEUR;
no_return_in_main_hypothesis :
(m:Method)(nameMethod m)=main -> ~(In return (instructions m))
}.
Definition
append_instructions :=
[P:Program](append_list (map instructions (methods P))).
Lemma
append_instructions_correct :
(P:Program;m:Method;i:Instruction)
(In m (methods P)) ->
(In i (instructions m)) -> (In i (append_instructions P)).
Intros; Unfold append_instructions.
Generalize (in_append_list ? (instructions m)); Intros.
Apply H1; Auto.
Apply in_map; Auto.
Qed
.
Definition
max_log_ClassName := [P:Program]
(max_log_list ? nameClass (classes P)).
Definition
max_log_MethodName := [P:Program]
(max_log_list ? nameMethod (methods P)).
Definition
extract_Var :=
[i:Instruction]Cases i of
(load x) => x
| (store x) => x
| _ => xH
end.
Definition
max_log_Var := [P:Program]
(max (max_log_list ? extract_Var (append_instructions P))
(max_log_list ? [m](anti_convert (S (nbArguments m))) (methods P))).
Lemma
valid_nbArguments :
(P:Program;m:Method)
(In m (methods P)) ->
(inf_log (anti_convert (S (nbArguments m))) (max_log_Var P)).
Intros; Unfold max_log_Var.
Apply inf_log_trans' with (max_log_list Method [m0:Method](anti_convert (S (nbArguments m0)))
(methods P)).
Apply in_inf_log with f:=[m0:Method](anti_convert (S (nbArguments m0))); Auto.
Apply le_max_r.
Qed
.
Definition
append_fields :=
[P:Program](map nameField (append_list (map instanceFields (classes P)))).
Lemma
append_fields_correct :
(P:Program;c:Class;f:Field)
(In c (classes P)) ->
(In f (instanceFields c)) -> (In (nameField f) (append_fields P)).
Intros; Unfold append_fields.
Generalize (in_append_list ? (instanceFields c)); Intros.
Apply in_map.
Apply H1; Auto.
Apply in_map; Auto.
Qed
.
Definition
extract_Field :=
[i:Instruction]Cases i of
(putfield x) => x
| (getfield x) => x
| _ => xH
end.
Definition
max_log_Field := [P:Program]
(max (max_log_list ? extract_Field (append_instructions P))
(max_log_list ? [x]x (append_fields P))).
Lemma
valid_instanceField : (P:Program;c:Class;f:Field)
(In c (classes P)) -> (In f (instanceFields c)) ->
(inf_log (nameField f) (max_log_Field P)).
Intros; Unfold max_log_Field.
Apply inf_log_trans' with (max_log_list positive [x:positive]x (append_fields P)).
Apply in_inf_log with f:=[x:FieldName]x.
Apply append_fields_correct with c; Auto.
Apply le_max_r.
Qed
.
Lemma
valid_putfield :
(P:Program;m:Method;f:FieldName)
(In m (methods P)) ->
(In (putfield f) (instructions m)) -> (inf_log f (max_log_Field P)).
Intros.
Replace f with (extract_Field (putfield f)).
Unfold max_log_Field.
Apply inf_log_trans' with (max_log_list Instruction extract_Field (append_instructions P)).
Intros; Apply in_inf_log.
Apply (append_instructions_correct P m); Auto.
Apply le_max_l.
Auto.
Qed
.
Lemma
valid_getfield :
(P:Program;m:Method;f:FieldName)
(In m (methods P)) ->
(In (getfield f) (instructions m)) -> (inf_log f (max_log_Field P)).
Intros.
Replace f with (extract_Field (getfield f)).
Unfold max_log_Field.
Apply inf_log_trans' with (max_log_list Instruction extract_Field (append_instructions P)).
Intros; Apply in_inf_log.
Apply (append_instructions_correct P m); Auto.
Apply le_max_l.
Auto.
Qed
.
Lemma
valid_load :
(P:Program;m:Method;x:Var)
(In m (methods P)) ->
(In (load x) (instructions m)) -> (inf_log x (max_log_Var P)).
Intros.
Replace x with (extract_Var (load x)).
Unfold max_log_Var.
Apply inf_log_trans' with (max_log_list Instruction extract_Var (append_instructions P)).
Intros; Apply in_inf_log.
Apply (append_instructions_correct P m); Auto.
Apply le_max_l.
Auto.
Qed
.
Lemma
valid_store :
(P:Program;m:Method;x:Var)
(In m (methods P)) ->
(In (store x) (instructions m)) -> (inf_log x (max_log_Var P)).
Intros.
Replace x with (extract_Var (store x)).
Unfold max_log_Var.
Apply inf_log_trans' with (max_log_list Instruction extract_Var (append_instructions P)).
Intros; Apply in_inf_log.
Apply (append_instructions_correct P m); Auto.
Apply le_max_l.
Auto.
Qed
.
Definition
END : Method -> progCount :=
[m](anti_convert (length (instructions m))).
Definition
max_log_pc := [P:Program]
(max_log_list ? END (methods P)).
Definition
nth_positive := [l:(list Instruction);pc:positive]
Cases pc of
xH => (nth_error l (0))
| _ => (nth_error l (convert (sub_un pc)))
end.
Tactic
Definition
CaseEq a :=
Generalize (refl_equal ? a); Pattern -1 a; Case a.
Lemma
nth_error_some : (A:Set;l:(list A);n:nat;x:A)
(nth_error l n)=(Some ? x) -> (In x l).
NewInduction l; Destruct n; Simpl; Intros.
Discriminate H.
Discriminate H.
Injection H; Auto.
Right; Apply IHl with n0; Auto.
Qed
.
Lemma
nth_error_some_inf : (A:Set;l:(list A);n:nat;x:A)
(nth_error l n)=(Some ? x) -> (lt n (length l)).
NewInduction l; Destruct n; Simpl; Intros.
Discriminate H.
Discriminate H.
Omega.
Apply lt_n_S.
Apply IHl with x; Auto.
Qed
.
Lemma
nth_positive_some : (I:Instruction;l:(list Instruction);pc:positive)
(nth_positive l pc)=(Some ? I) ->
(In I l).
Unfold nth_positive; Destruct pc; Intros.
Apply nth_error_some with (convert (sub_un (xI p))); Auto.
Apply nth_error_some with (convert (sub_un (xO p))); Auto.
Apply nth_error_some with (0); Auto.
Qed
.
Lemma
nth_positive_some_inf : (I:Instruction;l:(list Instruction);pc:positive)
(nth_positive l pc)=(Some ? I) ->
(compare pc (anti_convert (length l)) EGAL)=INFERIEUR.
Unfold nth_positive; Intros.
Elim (ZL11 pc); Intros.
Subst.
Generalize H; Clear H.
Case l; Simpl; Intros.
Discriminate H.
Apply convert_compare_INFERIEUR.
Unfold convert; Simpl.
Rewrite convert_add_un.
Generalize (bij1 (length l0)); Unfold convert; Intros H'; Rewrite H'.
Simpl.
Omega.
Apply convert_compare_INFERIEUR.
Rewrite bij1.
Replace (convert pc) with (S (convert (sub_un pc))).
Apply lt_n_S.
Generalize H0 H; Clear H0 H; Case pc; Intros.
Apply nth_error_some_inf with I; Auto.
Apply nth_error_some_inf with I; Auto.
Elim H0; Reflexivity.
Replace (S (convert (sub_un pc))) with (convert (add_un (sub_un pc))).
Elim (add_sub_one pc); Intros.
Elim H0; Auto.
Rewrite H1; Auto.
Unfold convert; Simpl.
Rewrite convert_add_un.
Auto.
Qed
.
Fixpoint
searchMethod_rec [m0:MethodName;l:(list Method)] : (option Method):=
Cases l of
nil => (None ?)
| (cons m q) =>
Cases (MethodName_dec m0 (nameMethod m)) of
| (left _) => (Some ? m)
| (right _) => (searchMethod_rec m0 q)
end
end.
Definition
searchMethod := [P:Program;m:MethodName]
(searchMethod_rec m (methods P)).
Definition
instructionAt := [P:Program;m:MethodName;pc:progCount]
Cases (searchMethod P m) of
| None => (None ?)
| (Some meth) => (nth_positive (instructions meth) pc)
end.
Lemma
searchMethod_rec_some : (m:MethodName;l:(list Method);M:Method)
(searchMethod_rec m l)=(Some ? M) ->
(In M l)/\(nameMethod M)=m.
NewInduction l; Simpl; Intros.
Discriminate H.
Generalize H; Clear H.
Case MethodName_dec; Intros.
Injection H; Intros; Subst; Auto.
Elim (IHl ? H); Intros; Auto.
Qed
.
Lemma
searchMethod_rec_some_inv : (m:MethodName;l:(list Method);M:Method)
(allNameMethodsDistincts l) ->
(In M l) -> (nameMethod M)=m ->
(searchMethod_rec m l)=(Some ? M).
NewInduction l; Simpl; Intros.
Elim H0.
Inversion_clear H.
Elim H0; Clear H0; Intros.
Subst.
Case MethodName_dec; Intros; Auto.
Elim n; Auto.
Case MethodName_dec; Intros.
Elim H2; Exists M.
Rewrite <- e; Auto.
Auto.
Qed
.
Lemma
searchMethod_some : (P:Program;m:MethodName;M:Method)
(searchMethod P m)=(Some ? M) ->
(In M (methods P))/\(nameMethod M)=m.
Unfold searchMethod; Intros.
Apply searchMethod_rec_some; Auto.
Qed
.
Lemma
searchMethod_some_inv : (P:Program;M:Method)
(In M (methods P))->
(searchMethod P (nameMethod M))=(Some ? M).
Unfold searchMethod; Intros.
Apply searchMethod_rec_some_inv; Auto.
Apply (methodsValid P).
Qed
.
Lemma
instructionAt_some : (P:Program;m:MethodName;pc:progCount;I:Instruction)
(instructionAt P m pc)=(Some ? I) ->
(EX M:Method | (In M (methods P)) /\ (nameMethod M)=m /\
(In I (instructions M)) /\ (compare pc (END M) EGAL)=INFERIEUR).
Intros P m pc I; Unfold instructionAt.
Generalize (searchMethod_some P m).
Case (searchMethod P m); Intros.
Exists m0.
Elim (H m0); Auto; Intros.
Do 2 Try Split; Auto.
Split.
Apply nth_positive_some with pc; Auto.
Unfold END; Apply nth_positive_some_inf with I; Auto.
Discriminate H0.
Qed
.
Lemma
instructionAt_some_inf_log_pc : (P:Program;m:MethodName;pc:progCount;I:Instruction)
(instructionAt P m pc)=(Some ? I) ->
(inf_log pc (max_log_pc P)).
Intros P m pc I; Unfold instructionAt max_log_pc.
Generalize (searchMethod_some P m).
Case (searchMethod P m); Intros.
Apply inf_log_trans with (END m0).
Apply in_inf_log.
Elim (H m0); Intuition.
Unfold END.
Apply nth_positive_some_inf with I; Auto.
Discriminate H0.
Qed
.
Lemma
instructionAt_some_inf_log_MethodName : (P:Program;m:MethodName;pc:progCount;I:Instruction)
(instructionAt P m pc)=(Some ? I) ->
(inf_log m (max_log_MethodName P)).
Intros P m pc I; Unfold instructionAt max_log_MethodName.
Generalize (searchMethod_some P m).
Case (searchMethod P m); Intros.
Replace m with (nameMethod m0).
Apply in_inf_log.
Elim (H m0); Intuition.
Elim (H m0); Intuition.
Discriminate H0.
Qed
.
Lemma
valid_load_instructionAt :
(P:Program;m:MethodName;pc:progCount;x:Var)
(instructionAt P m pc)=(Some ? (load x)) ->
(inf_log x (max_log_Var P)).
Intros.
Elim (instructionAt_some P m pc (load x)); Intuition.
Apply valid_load with x0; Auto.
Qed
.
Lemma
valid_store_instructionAt :
(P:Program;m:MethodName;pc:progCount;x:Var)
(instructionAt P m pc)=(Some ? (store x)) ->
(inf_log x (max_log_Var P)).
Intros.
Elim (instructionAt_some P m pc (store x)); Intuition.
Apply valid_store with x0; Auto.
Qed
.
Lemma
valid_ClassName : (P:Program;cl:ClassName)
(EX c:Class | (In c (classes P)) /\ cl=(nameClass c)) ->
(inf_log cl (max_log_ClassName P)).
Intros.
Elim H; Intuition.
Rewrite H2; Unfold max_log_ClassName.
Apply in_inf_log; Auto.
Qed
.
Lemma
valid_putfield_instructionAt :
(P:Program;m:MethodName;pc:progCount;f:FieldName)
(instructionAt P m pc)=(Some ? (putfield f)) ->
(inf_log f (max_log_Field P)).
Intros.
Elim (instructionAt_some P m pc (putfield f)); Intuition.
Apply valid_putfield with x; Auto.
Qed
.
Lemma
valid_getfield_instructionAt :
(P:Program;m:MethodName;pc:progCount;f:FieldName)
(instructionAt P m pc)=(Some ? (getfield f)) ->
(inf_log f (max_log_Field P)).
Intros.
Elim (instructionAt_some P m pc (getfield f)); Intuition.
Apply valid_getfield with x; Auto.
Qed
.
Lemma
valid_goto_instructionAt :
(P:Program;m:MethodName;pc,pc':progCount;f:FieldName)
(instructionAt P m pc)=(Some ? (goto pc')) ->
(inf_log pc' (max_log_pc P)).
Intros.
Elim (instructionAt_some P m pc (goto pc')); Intuition.
Generalize (valid_goto_hypothesis P x pc' H1 H2);
Replace (anti_convert (length (instructions x))) with (END x);
[Intros|Unfold END;Auto].
Clear H4.
Unfold max_log_pc.
Generalize (in_inf_log ? END (methods P) x H1) ; Intros.
EApply inf_log_trans ; EAuto.
Qed
.
Definition
nextAddress : Program -> MethodName -> progCount -> progCount :=
[P,m,pc]
Cases (searchMethod P m) of
| None => pc
| (Some meth) =>
Cases (positive_dec pc (END meth)) of
| (left _) => pc
| (right _) => (add_un pc)
end
end.
Lemma
valid_nextAddress : (P:Program;m:MethodName;pc:progCount;I:Instruction)
(instructionAt P m pc)=(Some ? I) ->
(inf_log (nextAddress P m pc) (max_log_pc P)).
Unfold nextAddress instructionAt; Intros P m pc I.
CaseEq '(searchMethod P m); Intros.
Elim (searchMethod_some ? ? ? H); Intros.
Case positive_dec; Intros.
Subst; Unfold max_log_pc.
Apply in_inf_log; Auto.
Generalize (nth_positive_some_inf ? ? ? H0); Intros.
Case (positive_dec (add_un pc) (END m0)); Intros.
Rewrite e; Unfold max_log_pc; Apply in_inf_log; Auto.
Generalize H3; Clear H3;
Replace (anti_convert (length (instructions m0))) with (END m0); [Intros|Unfold END;Auto].
Apply inf_log_trans with (END m0).
Unfold max_log_pc; Apply in_inf_log; Auto.
Apply convert_compare_INFERIEUR.
Generalize (compare_convert_INFERIEUR ? ? H3); Clear H3; Intros.
Replace (convert (add_un pc)) with (S (convert pc)).
Unfold lt in H3.
Cut ~(S (convert pc))=(convert (END m0)).
Inversion_clear H3.
Intros H'; Elim H'; Auto.
Intros.
Auto with zarith.
Red; Intros; Elim n0.
Apply convert_intro.
Rewrite <- H4; Unfold convert.
Rewrite convert_add_un; Auto.
Unfold convert; Rewrite convert_add_un; Auto.
Discriminate H0.
Qed
.
Fixpoint
searchField_rec [l:(list Field)] : FieldName->(option Field) :=
[f]Cases l of
nil => (None ?)
| (cons fi q) => Cases (positive_dec f (nameField fi)) of
(left _) => (Some ? fi)
| (right _) => (searchField_rec q f)
end
end.
Definition
searchField : Class->FieldName->(option Field) :=
[c,f](searchField_rec (instanceFields c) f).
Lemma
searchField_some : (c:Class;f:FieldName;fi:Field)
(searchField c f)=(Some ? fi) ->
(In fi (instanceFields c)) /\ f=(nameField fi).
Unfold searchField.
Intros c f fi; Generalize (instanceFields c).
NewInduction l; Simpl; Intros.
Discriminate H.
Generalize H; Clear H; Case positive_dec; Intros.
Injection H; Intros; Subst; Intuition.
Elim IHl; Intros; Auto.
Qed
.
Fixpoint
searchClass_rec [l:(list Class)] : ClassName->(option Class) :=
[f]Cases l of
nil => (None ?)
| (cons fi q) => Cases (positive_dec f (nameClass fi)) of
(left _) => (Some ? fi)
| (right _) => (searchClass_rec q f)
end
end.
Definition
searchClass : Program->ClassName->(option Class) :=
[P,f](searchClass_rec (classes P) f).
Lemma
searchClass_some : (P:Program;cl:ClassName;c:Class)
(searchClass P cl)=(Some ? c) ->
(In c (classes P)) /\ cl=(nameClass c).
Unfold searchClass.
Intros P cl; Generalize (classes P).
NewInduction l; Simpl; Intros.
Discriminate H.
Generalize H; Clear H; Case positive_dec; Intros.
Injection H; Intros; Subst; Intuition.
Elim (IHl c); Intros; Auto.
Qed
.
Lemma
searchClass_find : (P:Program;cl:ClassName)
(EX c:Class | (In c (classes P)) /\ cl=(nameClass c)) ->
~(searchClass P cl)=(None ?).
Intros.
Elim H; Clear H; Intros c (H1,H2).
Generalize H1; Unfold searchClass.
Generalize (classes P); Clear H1.
NewInduction l; Simpl; Intros.
Elim H1.
Case positive_dec; Intros.
Discriminate.
Elim H1; Intros.
Subst; Elim n; Auto.
Auto.
Qed
.
Fixpoint
searchWithMethodID [l:(list MethodID*MethodName)] : MethodID->(option MethodName) :=
[id0]Cases l of
nil => (None ?)
| (cons (id,m) q) => Cases (positive_dec id0 id) of
(left _) => (Some ? m)
| (right _) => (searchWithMethodID q id0)
end
end.
Definition
methodLookup : Program -> MethodID -> ClassName -> (option Method) :=
[P,id,cl]
Cases (searchClass P cl) of
None => (None ?)
|(Some c) => Cases (searchWithMethodID (list_methods_lookup c) id) of
None => (None ?)
|(Some m) => Cases (searchMethod P m) of
None => (None ?)
|(Some M) => (Some ? M)
end
end
end.
Lemma
No_return_in_main : (P : Program ; m : MethodName ; pc : progCount)
(main P) = m -> ~(instructionAt P m pc)=(Some ? return).
Red; Intros.
Elim (instructionAt_some ? ? ? ? H0).
Intros M (H1,(H2,(H3,H4))).
Elim (no_return_in_main_hypothesis P M).
Rewrite H; Auto.
Auto.
Qed
.