Symbolic expressions
Require Import Extra.
Require Op.
Import Utf8 Coqlib.
Import AST Globalenvs.
Import Integers Values.
Set Implicit Arguments.
Unset Elimination Schemes.
Local Coercion is_true :
bool >->
Sortclass.
Section EVAL.
Context (
find_symbol:
ident →
option block) (
sp:
val).
Definition symbol_address (
s:
ident) (
o:
int) :
val :=
match find_symbol s with
|
Some b =>
Vptr b o
|
None =>
Vundef
end.
Context (
valid_pointer :
block →
Z →
bool).
Definition eval_condition (
cond:
Op.condition) (
args:
list val) :
option bool :=
match cond,
args with
|
Op.Ccomp c,
v1 ::
v2 ::
nil =>
Val.cmp_bool c v1 v2
|
Op.Ccompu c,
v1 ::
v2 ::
nil =>
Val.cmpu_bool valid_pointer c v1 v2
|
Op.Ccompimm c n,
v1 ::
nil =>
Val.cmp_bool c v1 (
Vint n)
|
Op.Ccompuimm c n,
v1 ::
nil =>
Val.cmpu_bool valid_pointer c v1 (
Vint n)
|
Op.Ccompf c,
v1 ::
v2 ::
nil =>
Val.cmpf_bool c v1 v2
|
Op.Cnotcompf c,
v1 ::
v2 ::
nil =>
option_map negb (
Val.cmpf_bool c v1 v2)
|
Op.Ccompfs c,
v1 ::
v2 ::
nil =>
Val.cmpfs_bool c v1 v2
|
Op.Cnotcompfs c,
v1 ::
v2 ::
nil =>
option_map negb (
Val.cmpfs_bool c v1 v2)
|
Op.Cmaskzero n,
v1 ::
nil =>
Val.maskzero_bool v1 n
|
Op.Cmasknotzero n,
v1 ::
nil =>
option_map negb (
Val.maskzero_bool v1 n)
|
_,
_ =>
None
end.
Remark op_eval_condition m :
(∀
b o,
Memory.Mem.valid_pointer m b o =
valid_pointer b o) →
∀
cond args,
eval_condition cond args =
Op.eval_condition cond args m.
Proof.
intros E.
destruct cond; try reflexivity;
intros [ | α args ]; try reflexivity;
destruct args as [ | β args ]; try reflexivity;
try (destruct args as [ | γ args ]; try reflexivity);
destruct α; try reflexivity;
try (destruct β; try reflexivity);
simpl; rewrite ! E; reflexivity.
Qed.
Definition eval_addressing
(
addr:
Op.addressing) (
vl:
list val) :
option val :=
match addr,
vl with
|
Op.Aindexed n,
v1::
nil =>
Some (
Val.add v1 (
Vint n))
|
Op.Aindexed2 n,
v1::
v2::
nil =>
Some (
Val.add (
Val.add v1 v2) (
Vint n))
|
Op.Ascaled sc ofs,
v1::
nil =>
Some (
Val.add (
Val.mul v1 (
Vint sc)) (
Vint ofs))
|
Op.Aindexed2scaled sc ofs,
v1::
v2::
nil =>
Some(
Val.add v1 (
Val.add (
Val.mul v2 (
Vint sc)) (
Vint ofs)))
|
Op.Aglobal s ofs,
nil =>
Some (
symbol_address s ofs)
|
Op.Abased s ofs,
v1::
nil =>
Some (
Val.add (
symbol_address s ofs)
v1)
|
Op.Abasedscaled sc s ofs,
v1::
nil =>
Some (
Val.add (
symbol_address s ofs) (
Val.mul v1 (
Vint sc)))
|
Op.Ainstack ofs,
nil =>
Some(
Val.add sp (
Vint ofs))
|
_,
_ =>
None
end.
Definition eval_operation (
op:
Op.operation) (
args:
list val) :
option val :=
match op,
args with
|
Op.Omove,
v1::
nil =>
Some v1
|
Op.Ointconst n,
nil =>
Some (
Vint n)
|
Op.Ofloatconst n,
nil =>
Some (
Vfloat n)
|
Op.Osingleconst n,
nil =>
Some (
Vsingle n)
|
Op.Oindirectsymbol id,
nil =>
Some (
symbol_address id Int.zero)
|
Op.Ocast8signed,
v1 ::
nil =>
Some (
Val.sign_ext 8
v1)
|
Op.Ocast8unsigned,
v1 ::
nil =>
Some (
Val.zero_ext 8
v1)
|
Op.Ocast16signed,
v1 ::
nil =>
Some (
Val.sign_ext 16
v1)
|
Op.Ocast16unsigned,
v1 ::
nil =>
Some (
Val.zero_ext 16
v1)
|
Op.Oneg,
v1::
nil =>
Some (
Val.neg v1)
|
Op.Osub,
v1::
v2::
nil =>
Some (
Val.sub v1 v2)
|
Op.Omul,
v1::
v2::
nil =>
Some (
Val.mul v1 v2)
|
Op.Omulimm n,
v1::
nil =>
Some (
Val.mul v1 (
Vint n))
|
Op.Omulhs,
v1::
v2::
nil =>
Some (
Val.mulhs v1 v2)
|
Op.Omulhu,
v1::
v2::
nil =>
Some (
Val.mulhu v1 v2)
|
Op.Odiv,
v1::
v2::
nil =>
Val.divs v1 v2
|
Op.Odivu,
v1::
v2::
nil =>
Val.divu v1 v2
|
Op.Omod,
v1::
v2::
nil =>
Val.mods v1 v2
|
Op.Omodu,
v1::
v2::
nil =>
Val.modu v1 v2
|
Op.Oand,
v1::
v2::
nil =>
Some(
Val.and v1 v2)
|
Op.Oandimm n,
v1::
nil =>
Some (
Val.and v1 (
Vint n))
|
Op.Oor,
v1::
v2::
nil =>
Some(
Val.or v1 v2)
|
Op.Oorimm n,
v1::
nil =>
Some (
Val.or v1 (
Vint n))
|
Op.Oxor,
v1::
v2::
nil =>
Some(
Val.xor v1 v2)
|
Op.Oxorimm n,
v1::
nil =>
Some (
Val.xor v1 (
Vint n))
|
Op.Onot,
v1::
nil =>
Some(
Val.notint v1)
|
Op.Oshl,
v1::
v2::
nil =>
Some (
Val.shl v1 v2)
|
Op.Oshlimm n,
v1::
nil =>
Some (
Val.shl v1 (
Vint n))
|
Op.Oshr,
v1::
v2::
nil =>
Some (
Val.shr v1 v2)
|
Op.Oshrimm n,
v1::
nil =>
Some (
Val.shr v1 (
Vint n))
|
Op.Oshrximm n,
v1::
nil =>
Val.shrx v1 (
Vint n)
|
Op.Oshru,
v1::
v2::
nil =>
Some (
Val.shru v1 v2)
|
Op.Oshruimm n,
v1::
nil =>
Some (
Val.shru v1 (
Vint n))
|
Op.Ororimm n,
v1::
nil =>
Some (
Val.ror v1 (
Vint n))
|
Op.Oshldimm n,
v1::
v2::
nil =>
Some (
Val.or (
Val.shl v1 (
Vint n))
(
Val.shru v2 (
Vint (
Int.sub Int.iwordsize n))))
|
Op.Olea addr,
_ =>
eval_addressing addr args
|
Op.Onegf,
v1::
nil =>
Some(
Val.negf v1)
|
Op.Oabsf,
v1::
nil =>
Some(
Val.absf v1)
|
Op.Oaddf,
v1::
v2::
nil =>
Some(
Val.addf v1 v2)
|
Op.Osubf,
v1::
v2::
nil =>
Some(
Val.subf v1 v2)
|
Op.Omulf,
v1::
v2::
nil =>
Some(
Val.mulf v1 v2)
|
Op.Odivf,
v1::
v2::
nil =>
Some(
Val.divf v1 v2)
|
Op.Onegfs,
v1::
nil =>
Some(
Val.negfs v1)
|
Op.Oabsfs,
v1::
nil =>
Some(
Val.absfs v1)
|
Op.Oaddfs,
v1::
v2::
nil =>
Some(
Val.addfs v1 v2)
|
Op.Osubfs,
v1::
v2::
nil =>
Some(
Val.subfs v1 v2)
|
Op.Omulfs,
v1::
v2::
nil =>
Some(
Val.mulfs v1 v2)
|
Op.Odivfs,
v1::
v2::
nil =>
Some(
Val.divfs v1 v2)
|
Op.Osingleoffloat,
v1::
nil =>
Some(
Val.singleoffloat v1)
|
Op.Ofloatofsingle,
v1::
nil =>
Some(
Val.floatofsingle v1)
|
Op.Ointoffloat,
v1::
nil =>
Val.intoffloat v1
|
Op.Ofloatofint,
v1::
nil =>
Val.floatofint v1
|
Op.Ointofsingle,
v1::
nil =>
Val.intofsingle v1
|
Op.Osingleofint,
v1::
nil =>
Val.singleofint v1
|
Op.Omakelong,
v1::
v2::
nil =>
Some(
Val.longofwords v1 v2)
|
Op.Olowlong,
v1::
nil =>
Some(
Val.loword v1)
|
Op.Ohighlong,
v1::
nil =>
Some(
Val.hiword v1)
|
Op.Ocmp c,
_ =>
Some(
Val.of_optbool (
eval_condition c args))
|
_,
_ =>
None
end.
End EVAL.
Section REGISTER.
Variable reg :
Type.
Context (
reg_dec:
EqDec reg).
Inductive sexpr :=
|
Reg `(
reg)
|
Name `(
ident)
|
Oper (
op:
Op.operation) (
args:
list sexpr)
.
Theorem sexpr_ind (
P:
sexpr →
Prop) :
(∀
r,
P (
Reg r)) →
(∀
n,
P (
Name n)) →
(∀
op args, (∀
a,
In a args →
P a) →
P (
Oper op args)) →
∀
e,
P e.
Proof.
intros Hr Hn Ho.
refine (
fix sexpr_ind e :
P e :=
match e with
|
Reg r =>
Hr r
|
Name n =>
Hn n
|
Oper op args =>
Ho op args _
end).
revert args.
clear -
sexpr_ind.
refine (
fix args_ind args : ∀
a,
In a args →
P a :=
match args return ∀
a,
In a args →
P a with
|
nil => λ
_ X,
False_ind _ X
|
b ::
args' => λ
a IN,
match IN with
|
or_introl EQ =>
eq_ind b P (
sexpr_ind b)
a EQ
|
or_intror IN' =>
args_ind _ _ IN'
end
end).
Defined.
Instance sexpr_dec :
EqDec sexpr.
Proof.
Definition oper op args :
sexpr :=
match op,
args with
|
Op.Omove,
a ::
nil =>
a
|
Op.Osub,
x ::
Oper (
Op.Ointconst n)
nil ::
nil =>
Oper (
Op.Olea (
Op.Aindexed (
Int.neg n))) (
x ::
nil)
|
_,
_ =>
Oper op args
end.
Fixpoint map_sexpr fr (
e:
sexpr) :
sexpr :=
match e with
|
Reg r =>
fr r e
|
Name _ =>
e
|
Oper op args =>
oper op (
List.map (
map_sexpr fr)
args)
end.
Definition subst_reg (
r:
reg) (
n:
sexpr) (
e:
sexpr) :
sexpr :=
map_sexpr (λ
x e,
if reg_dec x r then n else e)
e.
Definition comp {
X}
c (
f:
X →
reg)
a :
sexpr :=
oper (
Op.Ocmp c) (
List.map (λ
r,
Reg (
f r))
a).
Definition addr {
X}
p (
f:
X →
reg)
a :
sexpr :=
oper (
Op.Olea p) (
List.map (λ
r,
Reg (
f r))
a).
Set Elimination Schemes.
Inductive assertion :
Type :=
|
True
|
Assert `(
sexpr)
|
AssertEQ (
_ _:
sexpr)
|
Implies (
_ _:
assertion)
|
Negate `(
assertion)
|
ForAll `(
reg) `(
assertion)
.
Global Instance assertion_eq_dec :
EqDec assertion.
Proof.
intros a.
elim a.
-
intros (); [
left;
reflexivity | .. ];
right;
abstract congruence.
-
intros s ();
try (
right;
abstract congruence).
intros s'.
case (
eq_dec s s').
intros EQ.
left.
exact (
f_equal Assert EQ).
intros NE.
right.
abstract congruence.
-
intros sl sr ();
try (
right;
abstract congruence).
intros sl'
sr'.
case (
eq_dec sl sl'). 2:
intros NE;
right;
abstract congruence.
intros EQl.
case (
eq_dec sr sr'). 2:
intros NE;
right;
abstract congruence.
intros EQr.
left.
exact (
f_equal2 AssertEQ EQl EQr).
-
intros p IHp q IHq.
intros ();
try (
right;
abstract congruence).
intros p'
q'.
case (
IHp p'). 2:
intros NE;
right;
abstract congruence.
intros EQp.
case (
IHq q'). 2:
intros NE;
right;
abstract congruence.
intros EQq.
left.
exact (
f_equal2 Implies EQp EQq).
-
intros b IH.
intros ();
try (
right;
abstract congruence).
intros b'.
case (
IH b'). 2:
intros NE;
right;
abstract congruence.
intros EQ.
left.
exact (
f_equal Negate EQ).
-
intros r p IHp.
intros ();
try (
right;
abstract congruence).
intros r'
p'.
case (
eq_dec r r'). 2:
intros NE;
right;
abstract congruence.
intros EQr.
case (
IHp p'). 2:
intros NE;
right;
abstract congruence.
intros EQp.
left.
exact (
f_equal2 ForAll EQr EQp).
Defined.
Fixpoint is_free (
x:
reg) (
e:
sexpr) {
struct e} :
bool :=
match e with
|
Reg r =>
reg_dec r x
|
Name _ =>
false
|
Oper _ args =>
list_exists (
is_free x)
args
end.
Fixpoint is_free' (
x:
reg) (
a:
assertion) :
bool :=
match a with
|
True =>
false
|
Assert e =>
is_free x e
|
AssertEQ e e' =>
if is_free x e then true else is_free x e'
|
Implies p q =>
if is_free'
x p then true else is_free'
x q
|
Negate p =>
is_free'
x p
|
ForAll x'
p =>
if reg_dec x'
x then false else is_free'
x p
end.
Variable (
reg_max:
reg →
reg →
reg).
Fixpoint sexpr_max_reg (
m:
reg) (
e:
sexpr) :
reg :=
match e with
|
Reg r =>
reg_max r m
|
Name _ =>
m
|
Oper _ args =>
List.fold_left sexpr_max_reg args m
end.
Fixpoint assertion_max_reg (
m:
reg) (
a:
assertion) :
reg :=
match a with
|
True =>
m
|
Assert e =>
sexpr_max_reg m e
|
AssertEQ x y =>
sexpr_max_reg (
sexpr_max_reg m x)
y
|
Implies p q =>
assertion_max_reg (
assertion_max_reg m p)
q
|
Negate p =>
assertion_max_reg m p
|
ForAll x p =>
assertion_max_reg (
reg_max x m)
p
end.
Lemma pos_max_le : ∀
x y z,
Pos.le z x ∨
Pos.le z y →
Pos.le z (
Pos.max x y).
Proof.
clear. intros. Psatz.lia. Qed.
Lemma pos_succ_le_ne : ∀
x y,
Pos.le x y →
x ≠
Pos.succ y.
Proof.
clear. intros. Psatz.lia. Qed.
Variable reg_succ:
reg →
reg.
Variable (
reg_le:
reg →
reg →
Prop).
Hypothesis reg_le_refl : ∀
x,
reg_le x x.
Hypothesis reg_le_trans : ∀
x y z,
reg_le x y →
reg_le y z →
reg_le x z.
Hypothesis reg_max_le : ∀
x y z,
reg_le z x ∨
reg_le z y →
reg_le z (
reg_max x y).
Hypothesis reg_succ_le_ne : ∀
x y,
reg_le x y →
x ≠
reg_succ y.
Lemma sexpr_max_reg_le e :
∀
r x,
is_free x e ∨
reg_le x r →
reg_le x (
sexpr_max_reg r e).
Proof.
elim e;
clear e.
-
intros r'
r x [];
simpl.
+
case reg_dec.
intros ->
_.
apply reg_max_le;
left;
apply reg_le_refl.
intros ?
H;
exact (
false_not_true H _).
+
intros H.
apply reg_max_le;
right;
exact H.
-
intros ?
r x [].
intros H;
exact (
false_not_true H _).
exact id.
-
intros op args IH r x;
revert r IH.
elim args;
clear args.
intros r _ [].
intros H;
exact (
false_not_true H _).
exact id.
intros a args IH r Hargs [];
simpl in *.
+
destruct (
is_free x a)
eqn:
Hfree;
auto.
+
auto.
Qed.
Arguments sexpr_max_reg_le :
clear implicits.
Lemma assertion_max_reg_le a :
∀
r x,
is_free'
x a ∨
reg_le x r →
reg_le x (
assertion_max_reg r a).
Proof.
elim a;
clear a.
-
intros r x [].
exact (λ
H,
false_not_true H _).
exact id.
-
intros e r x [];
simpl;
intros H;
apply sexpr_max_reg_le;
auto.
-
intros p q r x [];
simpl.
+
destruct (
is_free _ p)
eqn:
Hfree.
*
intros _.
apply sexpr_max_reg_le.
right.
apply sexpr_max_reg_le.
left.
exact Hfree.
*
intros Hfree'.
apply sexpr_max_reg_le.
left.
exact Hfree'.
+
intros H.
apply sexpr_max_reg_le.
right.
apply sexpr_max_reg_le.
right.
exact H.
-
intros a Ha a'
Ha'
r x [];
simpl.
+
destruct (
is_free'
_ a)
eqn:
Hfree;
auto.
+
intros H.
apply Ha'.
right.
apply Ha.
right.
exact H.
-
intros p IH r x [];
simpl;
intros H;
apply IH;
auto.
-
intros n p IH r x [];
simpl.
+
case reg_dec.
exact (λ
_ H,
false_not_true H _).
auto.
+
auto.
Qed.
Arguments assertion_max_reg_le :
clear implicits.
Definition fresh (
r :
reg) (
e :
sexpr) (
a:
assertion) :
reg :=
reg_succ (
assertion_max_reg (
sexpr_max_reg r e)
a).
Lemma fresh_correct r e a :
let x :=
fresh r e a in
x ≠
r ∧
is_free x e =
false ∧
is_free'
x a =
false.
Proof.
Opaque fresh.
Fixpoint assign_measure (
a:
assertion) :
nat :=
match a with
|
True
|
Assert _
|
AssertEQ _ _ =>
O
|
Implies p q =>
S (
Peano.max (
assign_measure p) (
assign_measure q))
|
ForAll _ p
|
Negate p =>
S (
assign_measure p)
end.
Definition assign_rel x y :
Prop :=
(
assign_measure x <
assign_measure y)%
nat.
Definition assign_rel_w x y :
bool :=
NPeano.leb (
assign_measure y) (
assign_measure x).
Remark assign_rel_wf :
well_founded assign_rel.
Proof.
Fixpoint assign (
r:
reg) (
n:
sexpr) (
a:
assertion) (
H:
Acc assign_rel a) {
struct H} :
sig (
assign_rel_w a).
refine (
let '
Acc_intro H'' :=
H in
match a return (∀
y :
assertion,
assign_rel y a →
Acc assign_rel y) →
sig (
assign_rel_w a)
with
|
True => λ
H',
exist _ True _
|
Assert e => λ
H',
exist _ (
Assert (
subst_reg r n e))
_
|
AssertEQ x y => λ
H',
exist _ (
AssertEQ (
subst_reg r n x) (
subst_reg r n y))
_
|
Implies p q =>
λ
H',
let '
exist p'
Hp' :=
assign r n p _ in
let '
exist q'
Hq' :=
assign r n q _ in
exist _ (
Implies p'
q')
_
|
Negate p =>
λ
H',
let '
exist p'
Hp' :=
assign r n p _ in
exist _ (
Negate p')
_
|
ForAll x p =>
λ
H',
if reg_dec x r
then exist _ (
ForAll x p)
_
else
if is_free x n
then
let x' :=
fresh r n p in
let '
exist p'
Hp' :=
assign x (
Reg x')
p _ in
let '
exist q Hq :=
assign r n p'
_ in
exist _ (
ForAll x'
q)
_
else
let '
exist q Hq :=
assign r n p _ in
exist _ (
ForAll x q)
_
end H'');
try exact eq_refl.
Proof.
-
apply H',
le_n_S,
Max.le_max_l.
-
apply H',
le_n_S,
Max.le_max_r.
-
apply NPeano.leb_le,
le_n_S,
NPeano.Nat.max_le_compat.
apply NPeano.leb_le,
Hp'.
apply NPeano.leb_le,
Hq'.
-
apply H',
le_refl.
-
exact Hp'.
-
apply NPeano.leb_le,
le_refl.
-
apply H',
lt_n_Sn.
-
apply H',
le_lt_n_Sm,
NPeano.leb_le,
Hp'.
-
apply NPeano.leb_le,
le_n_S.
etransitivity;
apply NPeano.leb_le;
eassumption.
-
apply H',
lt_n_Sn.
-
apply NPeano.leb_le,
le_n_S,
NPeano.leb_le,
Hq.
Defined.
Definition assign'
r n a :=
if is_free'
r a
then proj1_sig (@
assign r n a (
assign_rel_wf a))
else a.
Definition assert_eq_reg (
p q:
reg) :
assertion :=
AssertEQ (
Reg p) (
Reg q).
Definition boolexpr c x :=
let cnz :=
Op.Ccompuimm Cne Int.zero in
if Op.eq_condition c cnz
then x
else oper (
Op.Ocmp cnz) (
x ::
nil).
Definition assert_iff (
x x':
sexpr) :
option assertion :=
match x,
x'
with
|
Oper (
Op.Ocmp c)
_,
Oper (
Op.Ocmp c')
_ =>
Some (
AssertEQ (
boolexpr c x) (
boolexpr c'
x'))
|
_,
_ =>
None
end.
Context (
find_symbol:
ident →
option block) (
sp:
val).
Let env :
Type :=
reg →
val.
Section EVAL.
Context (
valid_pointer :
block →
Z →
bool).
Context (ε:
env).
Fixpoint eval_sexpr (
e:
sexpr) :
option val :=
match e with
|
Reg x =>
Some (ε
x)
|
Name n =>
do b <-
find_symbol n;
Some (
Vptr b Int.zero)
|
Oper op args =>
do vargs <-
map_o eval_sexpr args;
eval_operation find_symbol sp valid_pointer op vargs
end.
Lemma oper_eval op args :
eval_sexpr (
oper op args) =
eval_sexpr (
Oper op args).
Proof.
elim op;
clear op;
try reflexivity;
destruct args as [ | α
args ];
try reflexivity;
destruct args as [ | β
args ];
try reflexivity;
simpl.
-
case (
eval_sexpr _);
intros;
reflexivity.
-
case β;
try reflexivity.
intros ();
try reflexivity.
intros n [ | ? ? ]. 2:
reflexivity.
destruct args as [ | ? ? ]. 2:
reflexivity.
simpl.
case eval_sexpr;
try reflexivity.
intros v.
simpl.
now rewrite <-
Val.sub_opp_add,
Int.neg_involutive.
Qed.
Lemma eval_boolexpr {
X}
cond (
f:
X →
_)
args :
eval_sexpr (
boolexpr cond (
comp cond f args)) =
Some (
Val.of_optbool (
eval_condition valid_pointer cond (
map ε (
map f args)))).
Proof.
End EVAL.
Lemma eval_condition_m vp'
vp cond args :
(∀
b o,
vp b o =
vp'
b o) →
eval_condition vp cond args =
eval_condition vp'
cond args.
Proof.
intros E.
destruct cond; try reflexivity;
destruct args as [ | α args ]; try reflexivity;
destruct args as [ | β args ]; try reflexivity;
try (destruct args as [ | γ args ]; try reflexivity);
destruct α; try reflexivity;
try (destruct β; try reflexivity);
simpl; rewrite ! E; reflexivity.
Qed.
Lemma eval_operation_m vp'
vp op args :
(∀
b o,
vp b o =
vp'
b o) →
eval_operation find_symbol sp vp op args =
eval_operation find_symbol sp vp'
op args.
Proof.
intros E.
destruct op;
try reflexivity.
simpl.
f_equal.
f_equal.
apply eval_condition_m,
E.
Qed.
Fixpoint eval_assertion vp (ε:
env) (
a:
assertion) :
Prop :=
match a with
|
True =>
Logic.True
|
Assert b =>
eval_sexpr vp ε
b =
Some Vtrue
|
AssertEQ x x' =>
eval_sexpr vp ε
x =
eval_sexpr vp ε
x'
|
Implies x y =>
eval_assertion vp ε
x →
eval_assertion vp ε
y
|
Negate x => ¬
eval_assertion vp ε
x
|
ForAll k x => ∀
v,
eval_assertion vp (ε +[
k =>
v ])
x
end.
Fixpoint simplify_measure (
a:
assertion) :
nat :=
match a with
|
True
|
Assert _
|
AssertEQ _ _ =>
O
|
ForAll _ p
|
Implies _ p =>
S (
simplify_measure p)
|
Negate p =>
simplify_measure p
end.
Fixpoint simplify_measure_assign r e p H :
simplify_measure (
proj1_sig (@
assign r e p H)) =
simplify_measure p.
Proof.
Corollary simplify_measure_assign'
r e p :
simplify_measure (
assign'
r e p) =
simplify_measure p.
Proof.
Function simplify (
a:
assertion) {
measure simplify_measure a} :
assertion :=
match a with
|
Assert e =>
a
|
AssertEQ x y =>
if sexpr_dec x y then True else a
|
Implies (
AssertEQ (
Reg r)
e)
p =>
simplify (
assign'
r e p)
|
Implies _ p =>
match simplify p with True =>
True |
_ =>
a end
|
ForAll _ p =>
match simplify p with True =>
True |
_ =>
a end
|
_ =>
a
end.
Proof.
Lemma eval_sexpr_m {ε ε':
env} :
(∀
r, ε
r = ε'
r) →
∀
vp e,
eval_sexpr vp ε
e =
eval_sexpr vp ε'
e.
Proof.
intros EXT vp e.
elim e;
clear e;
try reflexivity.
-
intros r.
apply (
f_equal Some), (
EXT r).
-
intros op args IH.
simpl.
cut (
map_o (
eval_sexpr vp ε)
args =
map_o (
eval_sexpr vp ε')
args).
intros ->.
reflexivity.
revert IH.
clear.
elim args;
clear args.
reflexivity.
intros a args IH EXT.
simpl.
rewrite (
EXT _ (
or_introl _ eq_refl)).
case eval_sexpr. 2:
reflexivity.
intros v.
rewrite IH.
reflexivity.
intros a'
Ha'.
apply EXT,
or_intror,
Ha'.
Qed.
Lemma eval_assertion_m {ε ε':
env} :
(∀
r, ε
r = ε'
r) →
∀
vp p,
eval_assertion vp ε
p ↔
eval_assertion vp ε'
p.
Proof.
intros EXT vp p.
revert ε ε'
EXT.
elim p;
clear p;
try reflexivity.
-
intros e.
simpl.
intros ε ε'
EXT.
rewrite (
eval_sexpr_m EXT).
reflexivity.
-
intros e e'.
simpl.
intros ε ε'
EXT.
rewrite ! (
eval_sexpr_m EXT).
reflexivity.
-
intros a Ha a'
Ha'.
simpl.
intros ε ε'
EXT.
rewrite (
Ha ε ε'
EXT), (
Ha' ε ε'
EXT).
reflexivity.
-
intros a Ha.
simpl.
intros ε ε'
EXT.
rewrite (
Ha ε ε'
EXT).
reflexivity.
-
intros r a Ha.
simpl.
intros ε ε'
EXT.
assert (∀
v r', ε+[
r =>
v]
r' = ε'+[
r =>
v]
r')
as EXT'.
{
intros v r'.
unfold upd.
case eq_dec.
reflexivity.
intros _.
apply EXT. }
split;
intros X v;
generalize (
X v);
rewrite (
Ha _ _ (
EXT'
v));
exact id.
Qed.
Lemma map_simpl {
A B} (
f:
A →
B) (
m:
list A) :
map f m =
match m with nil =>
nil |
a ::
m' =>
f a ::
map f m'
end.
Proof.
case m; reflexivity. Qed.
Lemma map_o_simpl {
A B} (
f:
A →
option B) (
m:
list A) :
map_o f m =
match m with nil =>
Some nil |
a ::
m' =>
do b <-
f a;
do bs <-
map_o f m';
Some (
b ::
bs)
end.
Proof.
case m; reflexivity. Qed.
Lemma eval_subst_reg {
vp ε
e v} :
eval_sexpr vp ε
e =
Some v →
∀
r e',
eval_sexpr vp ε (
subst_reg r e e') =
eval_sexpr vp (ε +[
r =>
v])
e'.
Proof.
intros Hv r e';
revert Hv.
elim e';
clear e'.
-
intros r'
Hv.
simpl.
unfold subst_reg.
simpl.
unfold upd,
eq_dec.
now case reg_dec.
-
easy.
-
intros op args IH Hv.
unfold subst_reg.
simpl.
rewrite oper_eval.
simpl.
repeat
match goal with |-
appcontext[
map_o ?
f ?
x ] =>
let y :=
fresh "
x"
in set (
y :=
map_o f x)
end.
cut (
x =
x0).
intros ->;
reflexivity.
subst x x0.
cut (∀
a,
In a args →
eval_sexpr vp ε (
subst_reg r e a) =
eval_sexpr vp (ε +[
r =>
v])
a).
2:
eauto.
clear.
elim args;
clear args.
reflexivity.
intros a args IH Hargs.
specialize (
IH (λ
a'
H,
Hargs a' (
or_intror _ H))).
rewrite map_simpl.
rewrite map_o_simpl.
rewrite IH.
clear IH.
rewrite (
map_o_simpl _ (
a ::
_)).
rewrite <- (
Hargs _ (
or_introl _ eq_refl)).
clear Hargs.
reflexivity.
Qed.
Lemma upd_stutter {
A B} `{
EqDec A} (
f:
A →
B)
x v v'
y :
f +[
x =>
v'] +[
x =>
v]
y =
f +[
x =>
v]
y.
Proof.
Lemma upd_comm {
A B} `{
EqDec A} (
f:
A →
B)
x v x'
v' :
x ≠
x' →
∀
y,
f +[
x' =>
v'] +[
x =>
v]
y =
f +[
x =>
v] +[
x' =>
v']
y.
Proof.
intros NE y.
unfold upd.
case eq_dec;
auto.
intros ->.
case eq_dec;
congruence. Qed.
Lemma eval_sexpr_is_free x e :
is_free x e =
false →
∀
vp ε
v,
eval_sexpr vp (ε +[
x =>
v])
e =
eval_sexpr vp ε
e.
Proof.
intros H vp ε
v.
revert H.
elim e;
clear e;
simpl.
-
intros r.
unfold upd,
eq_dec.
case reg_dec.
simpl.
intros;
eq_some_inv.
reflexivity.
-
reflexivity.
-
intros op args IH H.
cut (
map_o (
eval_sexpr vp (ε +[
x =>
v]))
args =
map_o (
eval_sexpr vp ε)
args).
intros ->;
reflexivity.
revert IH H.
elim args;
clear args.
reflexivity.
intros a args IH Hargs.
simpl.
destruct (
is_free _ _)
eqn:
Hfree.
intro;
eq_some_inv.
intros H.
rewrite (
Hargs _ (
or_introl _ eq_refl)
Hfree).
case (
eval_sexpr _ _ a). 2:
reflexivity.
intros y.
specialize (
IH (λ
a IN F,
Hargs a (
or_intror _ IN)
F)
H).
clear H Hargs.
rewrite IH.
reflexivity.
Qed.
Lemma eval_assertion_is_free x a :
is_free'
x a =
false →
∀
vp ε
v,
eval_assertion vp (ε +[
x =>
v])
a ↔
eval_assertion vp ε
a.
Proof.
elim a;
clear a.
-
reflexivity.
-
intros r H vp ε
v.
simpl.
rewrite eval_sexpr_is_free.
reflexivity.
exact H.
-
intros e e'
H vp ε
v.
simpl in *.
assert (
is_free x e =
false)
as Hx.
{
revert H.
case is_free.
exact id.
reflexivity. }
rewrite Hx in H.
rewrite !
eval_sexpr_is_free;
auto.
reflexivity.
-
intros a Ha a'
Ha'
H vp ε
v.
simpl in *.
assert (
is_free'
x a =
false)
as Hx.
{
revert H.
case is_free'.
exact id.
reflexivity. }
rewrite Hx in H.
rewrite Ha,
Ha'.
reflexivity.
easy.
easy.
-
intros p IH H vp ε
v.
simpl.
rewrite IH.
reflexivity.
exact H.
-
intros r p IH H vp ε
v.
simpl in *.
destruct reg_dec.
subst.
split;
intros X v';
generalize (
X v');
apply eval_assertion_m;
intros r;
rewrite upd_stutter;
reflexivity.
specialize (
IH H vp).
split;
intros X v';
specialize (
X v').
apply eval_assertion_m in X. 2:
apply upd_comm;
auto.
apply IH in X.
exact X.
eapply eval_assertion_m.
apply upd_comm;
auto.
apply IH,
X.
Qed.
Section S.
Context (
vp :
block →
Z →
bool).
Fixpoint eval_assertion_assign r e p H :
∀ ε
v,
eval_sexpr vp ε
e =
Some v →
(
eval_assertion vp ε (
proj1_sig (@
assign r e p H)) ↔
eval_assertion vp (ε+[
r =>
v])
p).
Proof.
destruct H as [
H'].
destruct p.
-
simpl;
reflexivity.
-
simpl.
intros ε
v Hv.
now rewrite (
eval_subst_reg Hv).
-
intros ε
v Hv.
simpl.
now rewrite ! (
eval_subst_reg Hv).
-
intros ε
v Hv.
simpl.
q eval_assertion_assign.
simpl.
intros H H0.
specialize (
H ε
_ Hv).
specialize (
H0 ε
_ Hv).
tauto.
-
intros ε
v Hv.
simpl.
q eval_assertion_assign.
simpl.
intros H.
specialize (
H _ _ Hv).
tauto.
-
intros ε
v Hv.
simpl.
case reg_dec.
+
intros ->.
simpl.
split;
intros X v';
eapply eval_assertion_m.
apply upd_stutter.
apply X.
symmetry.
apply upd_stutter.
apply X.
+
intros NE.
destruct (
is_free _ _)
eqn:
Hfree;
q eval_assertion_assign;
simpl;
clear eval_assertion_assign.
{
intros H0 H1.
specialize (λ ε,
H1 ε
_ eq_refl).
set (
x' :=
fresh r e p).
fold x'
in H1.
destruct (
fresh_correct r e p)
as (
Hx'
r &
Hx'
e &
Hx'
p).
split;
intros X v';
specialize (
X v').
*
rewrite <- (
eval_assertion_is_free x'
_ Hx'
p vp _ v').
refine
(
proj2 (@
eval_assertion_m _ ((ε+[
r =>
v ] +[
x' =>
v']) +[
H => (ε+[
r =>
v ] +[
x' =>
v'])
x' ])
_ _ _)
_).
{
clear.
intros y.
unfold upd.
repeat case eq_dec;
congruence. }
apply H1.
eapply eval_assertion_m.
apply upd_comm,
Hx'
r.
apply H0.
rewrite eval_sexpr_is_free;
eauto.
exact X.
*
rewrite H0. 2:
rewrite eval_sexpr_is_free;
eauto.
clear H0 Hx'
e.
apply H1.
clear H1.
rewrite upd_o. 2:
auto.
rewrite upd_s.
eapply eval_assertion_m.
2:
apply (
eval_assertion_is_free x');
eassumption.
clear -
NE Hx'
r.
fold x'
in Hx'
r.
intros y.
unfold upd.
repeat case eq_dec;
reflexivity ||
congruence.
}
{
intros H0.
split;
intros X v';
specialize (
X v').
revert X.
rewrite H0.
apply eval_assertion_m.
apply upd_comm.
exact NE.
rewrite eval_sexpr_is_free;
eassumption.
revert X.
rewrite H0.
apply eval_assertion_m.
apply upd_comm.
auto.
rewrite eval_sexpr_is_free;
eassumption.
}
Qed.
End S.
Corollary eval_assertion_assign'
vp ε
r e p :
∀
v,
eval_sexpr vp ε
e =
Some v →
(
eval_assertion vp ε (
assign'
r e p) ↔
eval_assertion vp (ε+[
r =>
v])
p).
Proof.
Lemma simplify_correct a :
∀
vp ε,
eval_assertion vp ε (
simplify a) →
eval_assertion vp ε
a.
Proof.
functional induction (
simplify a).
- intros vp ε _. exact (trivial_correct _ e1 vp ε). *) -
exact (λ
_ _,
id).
-
intros vp ε
_.
reflexivity.
-
exact (λ
_ _,
id).
-
intros vp ε
H.
specialize (
IHa0 _ _ H).
clear H.
intros He.
fold (
eval_assertion).
simpl in He.
generalize (
proj1 (
eval_assertion_assign'
vp ε
r e p (
eq_sym He))
IHa0).
apply eval_assertion_m.
intros r'.
unfold upd.
case eq_dec;
congruence.
-
intros vp ε
_ Hx.
fold eval_assertion in *.
apply IHa0.
rewrite e0.
exact I.
-
exact (λ
_ _,
id).
-
intros vp ε
_ v.
fold eval_assertion.
apply IHa0.
rewrite e0.
exact I.
-
exact (λ
_ _,
id).
-
exact (λ
_ _,
id).
Qed.
End REGISTER.
Arguments Reg {
reg}
_.
Arguments Name {
reg}
_.
Arguments True {
reg}.