Require Import List.
Require Import Arith.
Require Import Freevar.
Require Import Misc.
Require Import Psatz.
Require Import Star.
Require Import Coq.Logic.Eqdep_dec.
Require Import FEnv.
Require Import Rewrite.
Require Import STerm.
Require Import GenInd.
Require Import Beta.
Proof of the efficient convertibility test.
Definition fst3 {
A B C :
Type} (
x :
A *
B *
C) :=
fst (
fst x).
Definition snd3 {
A B C :
Type} (
x :
A *
B *
C) :=
snd (
fst x).
Definition thd3 {
A B C :
Type} (
x :
A *
B *
C) :=
snd x.
Type definitions for continuations, values, and threads.
Definition rthreadptr :=
nat.
Definition cthreadptr :=
nat.
Definition threadptr := (
nat +
nat)%
type.
Inductive cont :
Type :=
|
Kid :
cont
|
Kapp :
value ->
cont ->
cont
|
Kswitch :
list (
nat *
term) ->
list value ->
list (
list nat *
value) ->
cont ->
cont
with value :
Type :=
|
Thread :
rthreadptr ->
value
|
Neutral : (
nat *
cont *
option value) ->
value
|
Clos :
term ->
list value ->
nat ->
value ->
value
|
Block :
nat ->
list value ->
value.
Definition env :=
list value.
Definition neutral := (
nat *
cont *
option value)%
type.
Definition n_var (
n :
neutral) :=
fst3 n.
Definition n_cont (
n :
neutral) :=
snd3 n.
Definition n_unfold (
n :
neutral) :=
thd3 n.
Inductive code :=
|
Term :
term ->
env ->
code
|
Val :
value ->
code.
Record rthread :=
mkrthread {
rt_code :
code ;
rt_cont :
cont ;
}.
Inductive cthread :=
|
cthread_done :
bool ->
cthread
|
cthread_reduce :
value ->
value ->
list nat ->
list nat ->
cthread
|
cthread_and :
cthread ->
cthread ->
cthread
|
cthread_or :
cthread ->
cthread ->
cthread.
Definition addr :=
rthreadptr.
Expresses whether a given continuation or value refers to a given thread. We will ensure that the induced graph is acyclic.
Inductive cont_points_to :
cont ->
addr ->
Prop :=
|
kapp_points_to_1 :
forall v c a,
val_points_to v a ->
cont_points_to (
Kapp v c)
a
|
kapp_points_to_2 :
forall v c a,
cont_points_to c a ->
cont_points_to (
Kapp v c)
a
|
kswitch_points_to_1 :
forall bs e bds c a,
Exists (
fun v =>
val_points_to v a)
e ->
cont_points_to (
Kswitch bs e bds c)
a
|
kswitch_points_to_2 :
forall bs e bds c a,
Exists (
fun bd =>
val_points_to (
snd bd)
a)
bds ->
cont_points_to (
Kswitch bs e bds c)
a
|
kswitch_points_to_3 :
forall bs e bds c a,
cont_points_to c a ->
cont_points_to (
Kswitch bs e bds c)
a
with val_points_to :
value ->
addr ->
Prop :=
|
thread_points_to :
forall rid,
val_points_to (
Thread rid)
rid
|
neutral_points_to_1 :
forall n a,
cont_points_to (
n_cont n)
a ->
val_points_to (
Neutral n)
a
|
neutral_points_to_2 :
forall n v a,
n_unfold n =
Some v ->
val_points_to v a ->
val_points_to (
Neutral n)
a
|
clos_points_to_1 :
forall t e vn vdeep a,
Exists (
fun v =>
val_points_to v a)
e ->
val_points_to (
Clos t e vn vdeep)
a
|
clos_points_to_2 :
forall t e vn vdeep a,
val_points_to vdeep a ->
val_points_to (
Clos t e vn vdeep)
a
|
block_points_to :
forall tag l a,
Exists (
fun v =>
val_points_to v a)
l ->
val_points_to (
Block tag l)
a.
Definition cont_val_ind :=
Induction For [
cont_points_to ;
val_points_to].
Definition env_points_to e a :=
Exists (
fun v =>
val_points_to v a)
e.
Inductive code_points_to :
code ->
addr ->
Prop :=
|
term_points_to :
forall t e a,
env_points_to e a ->
code_points_to (
Term t e)
a
|
cval_points_to :
forall v a,
val_points_to v a ->
code_points_to (
Val v)
a.
Definition rthread_points_to rt a :=
code_points_to rt.(
rt_code)
a \/
cont_points_to rt.(
rt_cont)
a.
Definition points_to rthreads (
a1 a2 :
rthreadptr):=
match nth_error rthreads a1 with
|
Some rt =>
rthread_points_to rt a2
|
None =>
False
end.
Record state :=
mkstate {
st_rthreads :
list rthread ;
st_freename :
nat ;
}.
Definition points st :=
points_to st.(
st_rthreads).
Lemma points_to_updatep_rthread :
forall rthreads rid rt a1 a2,
points_to (
update rthreads rid rt)
a1 a2 <->
updatep (
points_to rthreads)
rid (
fun a =>
rid <
length rthreads /\
rthread_points_to rt a)
a1 a2.
Proof.
intros rthreads rid rt rid2 a; unfold updatep, points_to; simpl.
destruct (Nat.eq_dec rid rid2); subst.
- rewrite nth_error_update2.
destruct nth_error eqn:Hnth; [apply nth_error_Some3 in Hnth|apply nth_error_None in Hnth]; intuition lia.
- rewrite nth_error_update3; [|assumption].
intuition congruence.
Qed.
Lemma points_to_updatep_rthread_extend :
forall rthreads rt a1 a2,
points_to (
rthreads ++
rt ::
nil)
a1 a2 <->
updatep (
points_to rthreads) (
length rthreads) (
rthread_points_to rt)
a1 a2.
Proof.
intros rthreads rt rid a; unfold updatep, points_to; simpl.
destruct (le_lt_dec (length rthreads) rid).
- rewrite nth_error_app2 by assumption.
remember (rid - length rthreads) as n. destruct n as [|m] eqn:Hn.
+ simpl. assert (rid = length rthreads) by lia. intuition congruence.
+ simpl. do 2 (replace (nth_error _ _) with (@None rthread) by (symmetry; apply nth_error_None; simpl; lia)).
assert (rid <> length rthreads) by lia. intuition congruence.
- rewrite nth_error_app1 by assumption.
assert (rid <> length rthreads) by lia.
destruct nth_error; intuition congruence.
Qed.
Steps of reduction threads.
Definition update_rthread st rid rt :=
{|
st_rthreads :=
update st.(
st_rthreads)
rid rt ;
st_freename :=
st.(
st_freename) ;
|}.
Definition freevar (
st :
state) :=
({|
st_rthreads :=
st.(
st_rthreads) ;
st_freename :=
S (
st.(
st_freename)) ;
|},
st.(
st_freename)).
Definition freevars (
st :
state) (
n :
nat) :=
({|
st_rthreads :=
st.(
st_rthreads) ;
st_freename :=
n +
st.(
st_freename) ;
|},
seq st.(
st_freename)
n).
Definition extend_rthread st rt :=
{|
st_rthreads :=
st.(
st_rthreads) ++
rt ::
nil ;
st_freename :=
st.(
st_freename) ;
|}.
Definition makelazy (
st :
state) (
t :
term) (
e :
env) :=
(
extend_rthread st {|
rt_code :=
Term t e ;
rt_cont :=
Kid |},
Thread (
length st.(
st_rthreads))).
Definition exit_rthread (
st :
state) (
rid :
rthreadptr) (
v :
value) :=
update_rthread st rid {|
rt_code :=
Val v ;
rt_cont :=
Kid |}.
Definition is_finished (
st :
state) (
rid :
rthreadptr) :=
match nth_error st.(
st_rthreads)
rid with
|
None =>
None
|
Some rthread =>
match rthread.(
rt_code),
rthread.(
rt_cont)
with
|
Val v,
Kid =>
Some v
|
_,
_ =>
None
end
end.
Fixpoint compose_cont (
c c2 :
cont) :=
match c with
|
Kid =>
c2
|
Kapp v c =>
Kapp v (
compose_cont c c2)
|
Kswitch bs e bds c =>
Kswitch bs e bds (
compose_cont c c2)
end.
Fixpoint makenlazy (
st :
state) (
ts :
list term) (
e :
env) :=
match ts with
|
nil => (
st,
nil)
|
t ::
ts =>
let st2v :=
makelazy st t e in
let st3vl :=
makenlazy (
fst st2v)
ts e in
(
fst st3vl,
snd st2v ::
snd st3vl)
end.
Fixpoint makendeeps (
st :
state) (
bs :
list (
nat *
term)) (
e :
env) :=
match bs with
|
nil => (
st,
nil)
| (
p,
t) ::
bs =>
let st2xs :=
freevars st p in
let st3v :=
makelazy (
fst st2xs)
t (
map (
fun x =>
Neutral (
x,
Kid,
None)) (
snd st2xs) ++
e)
in
let st4vl :=
makendeeps (
fst st3v)
bs e in
(
fst st4vl, (
snd st2xs,
snd st3v) ::
snd st4vl)
end.
Definition step_r (
st :
state) (
rid :
rthreadptr) :
state :=
match nth_error st.(
st_rthreads)
rid with
|
None =>
st
|
Some rthread =>
match rthread.(
rt_code)
with
|
Term (
app u v)
e =>
let st2v :=
makelazy st v e in
update_rthread (
fst st2v)
rid {|
rt_code :=
Term u e ;
rt_cont :=
Kapp (
snd st2v)
rthread.(
rt_cont) |}
|
Term (
abs u)
e =>
match rthread.(
rt_cont)
with
|
Kswitch _ _ _ _ =>
st
|
Kid =>
let st2y :=
freevar st in
let st3v :=
makelazy (
fst st2y)
u ((
Neutral (
snd st2y,
Kid,
None)) ::
e)
in
exit_rthread (
fst st3v)
rid (
Clos u e (
snd st2y) (
snd st3v))
|
Kapp v c =>
update_rthread st rid {|
rt_code :=
Term u (
v ::
e) ;
rt_cont :=
c |}
end
|
Term (
var n)
e =>
match nth_error e n with
|
None =>
st
|
Some v =>
update_rthread st rid {|
rt_code :=
Val v ;
rt_cont :=
rthread.(
rt_cont) |}
end
|
Term (
dvar n)
e =>
st
|
Term (
constr tag l)
e =>
let st2vl :=
makenlazy st l e in
update_rthread (
fst st2vl)
rid {|
rt_code :=
Val (
Block tag (
snd st2vl)) ;
rt_cont :=
rthread.(
rt_cont) |}
|
Term (
switch t m)
e =>
let st2vl :=
makendeeps st m e in
update_rthread (
fst st2vl)
rid {|
rt_code :=
Term t e ;
rt_cont :=
Kswitch m e (
snd st2vl)
rthread.(
rt_cont) |}
|
Val (
Thread rid2) =>
match is_finished st rid2 with
|
None =>
st
|
Some v =>
update_rthread st rid {|
rt_code :=
Val v ;
rt_cont :=
rthread.(
rt_cont) |}
end
|
Val (
Clos u e y vdeep) =>
match rthread.(
rt_cont)
with
|
Kid =>
st
|
Kswitch _ _ _ _ =>
st
|
Kapp v c =>
update_rthread st rid {|
rt_code :=
Term u (
v ::
e) ;
rt_cont :=
c |}
end
|
Val (
Neutral (
x,
c,
uf)) =>
let st2v :=
match uf with
|
None => (
st,
None)
|
Some uf =>
(
extend_rthread st {|
rt_code :=
Val uf ;
rt_cont :=
rthread.(
rt_cont) |},
Some (
Thread (
length st.(
st_rthreads))))
end
in
exit_rthread (
fst st2v)
rid (
Neutral (
x,
compose_cont c rthread.(
rt_cont), (
snd st2v)))
|
Val (
Block tag l) =>
match rthread.(
rt_cont)
with
|
Kid =>
st
|
Kapp _ _ =>
st
|
Kswitch bs e bds c =>
match nth_error bs tag with
|
None =>
st
|
Some (
p,
t) =>
if Nat.eq_dec p (
length l)
then
update_rthread st rid {|
rt_code :=
Term t (
l ++
e) ;
rt_cont :=
c |}
else st
end
end
end
end.
Steps of convertibility threads.
Fixpoint cthread_andn (
l :
list cthread) :=
match l with
|
nil =>
cthread_done true
|
c ::
l =>
cthread_and c (
cthread_andn l)
end.
Fixpoint cmp_cont (
c1 c2 :
cont)
varmap1 varmap2 :=
match c1,
c2 with
|
Kid,
Kid =>
Some nil
|
Kapp u1 c1,
Kapp u2 c2 =>
match cmp_cont c1 c2 varmap1 varmap2 with
|
None =>
None
|
Some l =>
Some (
cthread_reduce u1 u2 varmap1 varmap2 ::
l)
end
|
Kswitch _ _ l1 c1,
Kswitch _ _ l2 c2 =>
if Nat.eqb (
length l1) (
length l2)
then
let l12 :=
combine l1 l2 in
if forallb (
fun vv =>
Nat.eqb (
length (
fst (
fst vv))) (
length (
fst (
snd vv))))
l12 then
match cmp_cont c1 c2 varmap1 varmap2 with
|
None =>
None
|
Some l =>
Some (
map (
fun vv =>
cthread_reduce (
snd (
fst vv)) (
snd (
snd vv)) (
fst (
fst vv) ++
varmap1) (
fst (
snd vv) ++
varmap2))
l12 ++
l)
end
else None
else None
|
_,
_ =>
None
end.
Definition cmp_cont_cthread (
c1 c2 :
cont)
varmap1 varmap2 :=
match cmp_cont c1 c2 varmap1 varmap2 with
|
Some l =>
cthread_andn l
|
None =>
cthread_done false
end.
Inductive cthread_red (
st :
state) :
cthread ->
cthread ->
Prop :=
|
cthread_reduce_1 :
forall rid v1 v2 varmap1 varmap2,
is_finished st rid =
Some v1 ->
cthread_red st (
cthread_reduce (
Thread rid)
v2 varmap1 varmap2) (
cthread_reduce v1 v2 varmap1 varmap2)
|
cthread_reduce_2 :
forall rid v1 v2 varmap1 varmap2,
is_finished st rid =
Some v2 ->
cthread_red st (
cthread_reduce v1 (
Thread rid)
varmap1 varmap2) (
cthread_reduce v1 v2 varmap1 varmap2)
|
cthread_reduce_clos_clos :
forall t1 t2 e1 e2 x1 x2 v1 v2 varmap1 varmap2,
cthread_red st (
cthread_reduce (
Clos t1 e1 x1 v1) (
Clos t2 e2 x2 v2)
varmap1 varmap2)
(
cthread_reduce v1 v2 (
x1 ::
varmap1) (
x2 ::
varmap2))
|
cthread_reduce_block_block_same :
forall tag l1 l2 varmap1 varmap2,
length l1 =
length l2 ->
cthread_red st (
cthread_reduce (
Block tag l1) (
Block tag l2)
varmap1 varmap2)
(
cthread_andn (
map (
fun v12 =>
cthread_reduce (
fst v12) (
snd v12)
varmap1 varmap2) (
combine l1 l2)))
|
cthread_reduce_block_block_different_lengths :
forall tag l1 l2 varmap1 varmap2,
length l1 <>
length l2 ->
cthread_red st (
cthread_reduce (
Block tag l1) (
Block tag l2)
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_block_block_different_tags :
forall tag1 tag2 l1 l2 varmap1 varmap2,
tag1 <>
tag2 ->
cthread_red st (
cthread_reduce (
Block tag1 l1) (
Block tag2 l2)
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_clos_block :
forall t e x v tag l varmap1 varmap2,
cthread_red st (
cthread_reduce (
Clos t e x v) (
Block tag l)
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_block_clos :
forall tag l t e x v varmap1 varmap2,
cthread_red st (
cthread_reduce (
Block tag l) (
Clos t e x v)
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_var_unfold_1 :
forall x c uf v varmap1 varmap2,
cthread_red st (
cthread_reduce (
Neutral (
x,
c,
Some uf))
v varmap1 varmap2)
(
cthread_reduce uf v varmap1 varmap2)
|
cthread_reduce_var_unfold_2 :
forall v x c uf varmap1 varmap2,
cthread_red st (
cthread_reduce v (
Neutral (
x,
c,
Some uf))
varmap1 varmap2)
(
cthread_reduce v uf varmap1 varmap2)
|
cthread_reduce_same_var_unfold :
forall x c1 c2 uf1 uf2 varmap1 varmap2,
cthread_red st (
cthread_reduce (
Neutral (
x,
c1,
Some uf1)) (
Neutral (
x,
c2,
Some uf2))
varmap1 varmap2)
(
cthread_or (
cthread_reduce uf1 uf2 varmap1 varmap2) (
cmp_cont_cthread c1 c2 varmap1 varmap2))
|
cthread_reduce_var_nounfold :
forall x1 x2 c1 c2 varmap1 varmap2,
index Nat.eq_dec varmap1 x1 =
index Nat.eq_dec varmap2 x2 ->
cthread_red st (
cthread_reduce (
Neutral (
x1,
c1,
None)) (
Neutral (
x2,
c2,
None))
varmap1 varmap2)
(
cmp_cont_cthread c1 c2 varmap1 varmap2)
|
cthread_reduce_different_var_nounfold :
forall x1 x2 c1 c2 varmap1 varmap2,
index Nat.eq_dec varmap1 x1 <>
index Nat.eq_dec varmap2 x2 ->
cthread_red st (
cthread_reduce (
Neutral (
x1,
c1,
None)) (
Neutral (
x2,
c2,
None))
varmap1 varmap2)
(
cthread_done false)
|
cthread_reduce_clos_var_nounfold :
forall t e x v y c varmap1 varmap2,
cthread_red st (
cthread_reduce (
Clos t e x v) (
Neutral (
y,
c,
None))
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_block_var_nounfold :
forall tag l x c varmap1 varmap2,
cthread_red st (
cthread_reduce (
Block tag l) (
Neutral (
x,
c,
None))
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_var_clos_nounfold :
forall y c t e x v varmap1 varmap2,
cthread_red st (
cthread_reduce (
Neutral (
y,
c,
None)) (
Clos t e x v)
varmap1 varmap2) (
cthread_done false)
|
cthread_reduce_var_block_nounfold :
forall x c tag l varmap1 varmap2,
cthread_red st (
cthread_reduce (
Neutral (
x,
c,
None)) (
Block tag l)
varmap1 varmap2) (
cthread_done false)
|
cthread_and_true :
cthread_red st (
cthread_and (
cthread_done true) (
cthread_done true)) (
cthread_done true)
|
cthread_and_false_1 :
forall ct,
cthread_red st (
cthread_and (
cthread_done false)
ct) (
cthread_done false)
|
cthread_and_false_2 :
forall ct,
cthread_red st (
cthread_and ct (
cthread_done false)) (
cthread_done false)
|
cthread_or_false :
cthread_red st (
cthread_or (
cthread_done false) (
cthread_done false)) (
cthread_done false)
|
cthread_or_true_1 :
forall ct,
cthread_red st (
cthread_or (
cthread_done true)
ct) (
cthread_done true)
|
cthread_or_true_2 :
forall ct,
cthread_red st (
cthread_or ct (
cthread_done true)) (
cthread_done true)
|
cthread_and_1 :
forall ct1 ct2 ct3,
cthread_red st ct1 ct2 ->
cthread_red st (
cthread_and ct1 ct3) (
cthread_and ct2 ct3)
|
cthread_and_2 :
forall ct1 ct2 ct3,
cthread_red st ct1 ct2 ->
cthread_red st (
cthread_and ct3 ct1) (
cthread_and ct3 ct2)
|
cthread_or_1 :
forall ct1 ct2 ct3,
cthread_red st ct1 ct2 ->
cthread_red st (
cthread_or ct1 ct3) (
cthread_or ct2 ct3)
|
cthread_or_2 :
forall ct1 ct2 ct3,
cthread_red st ct1 ct2 ->
cthread_red st (
cthread_or ct3 ct1) (
cthread_or ct3 ct2)
.
Inductive step : (
cthread *
state) -> (
cthread *
state) ->
Prop :=
|
step_rthread :
forall ct st rid,
rid <
length st.(
st_rthreads) ->
step (
ct,
st) (
ct, (
step_r st rid))
|
step_cthread :
forall ct1 ct2 st,
cthread_red st ct1 ct2 ->
step (
ct1,
st) (
ct2,
st).
Definition of the readback from value and threads to terms, and cont to contexts.
Inductive dvar_free x :
term ->
Prop :=
|
dvar_free_var :
forall n,
dvar_free x (
var n)
|
dvar_free_dvar :
forall y,
x <>
y ->
dvar_free x (
dvar y)
|
dvar_free_abs :
forall t,
dvar_free x t ->
dvar_free x (
abs t)
|
dvar_free_app :
forall t1 t2,
dvar_free x t1 ->
dvar_free x t2 ->
dvar_free x (
app t1 t2)
|
dvar_free_constr :
forall tag l,
Forall (
dvar_free x)
l ->
dvar_free x (
constr tag l)
|
dvar_free_switch :
forall t m,
dvar_free x t ->
Forall (
fun pt =>
dvar_free x (
snd pt))
m ->
dvar_free x (
switch t m).
Definition no_dvar t :=
forall x,
dvar_free x t.
Fixpoint lift_dvars vars k t :=
match t with
|
var n =>
var n
|
dvar n =>
match index Nat.eq_dec vars n with Some p =>
var (
k +
p) |
None =>
dvar n end
|
app t1 t2 =>
app (
lift_dvars vars k t1) (
lift_dvars vars k t2)
|
abs t =>
abs (
lift_dvars vars (
S k)
t)
|
constr tag l =>
constr tag (
map (
lift_dvars vars k)
l)
|
switch t m =>
switch (
lift_dvars vars k t) (
map (
fun pt => (
fst pt,
lift_dvars vars (
fst pt +
k) (
snd pt)))
m)
end.
Fixpoint lift_dvars_hctx vars k h :=
match h with
|
h_hole =>
h_hole
|
h_app h t =>
h_app (
lift_dvars_hctx vars k h) (
lift_dvars vars k t)
|
h_switch h m =>
h_switch (
lift_dvars_hctx vars k h) (
map (
fun pt => (
fst pt,
lift_dvars vars (
fst pt +
k) (
snd pt)))
m)
end.
Definition no_delete st1 st2 :=
forall rid,
nth_error st2.(
st_rthreads)
rid =
None ->
nth_error st1.(
st_rthreads)
rid =
None.
Lemma no_delete_refl :
forall st,
no_delete st st.
Proof.
intros st rid H; assumption.
Qed.
Lemma no_delete_iff :
forall st1 st2,
no_delete st1 st2 <->
length st1.(
st_rthreads) <=
length st2.(
st_rthreads).
Proof.
intros st1 st2. split.
- intros H.
+ specialize (H (length (st_rthreads st2))). simpl in H.
rewrite !nth_error_None in H. lia.
- intros Hlen rid H; simpl in *; rewrite nth_error_None in *; lia.
Qed.
Inductive read_thread st defs :
list nat ->
rthreadptr ->
term ->
Prop :=
|
read_thread_val :
forall varmap rid v c t h,
nth_error st.(
st_rthreads)
rid =
Some {|
rt_code :=
Val v ;
rt_cont :=
c |} ->
read_val st defs varmap v t ->
read_cont st defs varmap c h ->
read_thread st defs varmap rid (
fill_hctx h t)
|
read_thread_term :
forall varmap rid e el c t h,
nth_error st.(
st_rthreads)
rid =
Some {|
rt_code :=
Term t e ;
rt_cont :=
c |} ->
closed_at t (
length e) ->
Forall2 (
read_val st defs varmap)
e el ->
read_cont st defs varmap c h ->
no_dvar t ->
read_thread st defs varmap rid (
fill_hctx h (
subst (
read_env el)
t))
with read_val st defs :
list nat ->
value ->
term ->
Prop :=
|
read_val_thread :
forall varmap rid t,
read_thread st defs varmap rid t ->
read_val st defs varmap (
Thread rid)
t
|
read_val_clos :
forall varmap t e el x vdeep tdeep,
Forall2 (
read_val st defs varmap)
e el ->
read_val st defs (
x ::
varmap)
vdeep tdeep ->
convertible beta (
subst (
lift_subst (
read_env el))
t)
tdeep ->
no_dvar t ->
length defs <=
x <
st.(
st_freename) ->
x \
notin varmap ->
closed_at t (
S (
length e)) ->
read_val st defs varmap (
Clos t e x vdeep) (
subst (
read_env el) (
abs t))
|
read_val_block :
forall varmap tag e el,
Forall2 (
read_val st defs varmap)
e el ->
read_val st defs varmap (
Block tag e) (
constr tag el)
|
read_val_neutral :
forall varmap x c h uf tuf,
read_cont st defs varmap c h ->
if_Some3 (
fun v2 t2 def =>
read_val st defs varmap v2 t2 /\
convertible beta (
fill_hctx h def)
t2 /\
closed_at def 0)
uf tuf (
nth_error defs x) ->
x <
st.(
st_freename) ->
(
nth_error defs x =
None ->
In x varmap) ->
read_val st defs varmap (
Neutral (
x,
c,
uf)) (
fill_hctx h (
match index Nat.eq_dec varmap x with None =>
dvar x |
Some n =>
var n end))
with read_cont st defs :
list nat ->
cont ->
hctx ->
Prop :=
|
read_cont_kid :
forall varmap,
read_cont st defs varmap Kid h_hole
|
read_cont_kapp :
forall varmap v c t h,
read_val st defs varmap v t ->
read_cont st defs varmap c h ->
read_cont st defs varmap (
Kapp v c) (
compose_hctx h (
h_app h_hole t))
|
read_cont_kswitch :
forall varmap bs e bds tdeeps c el h,
Forall2 (
read_val st defs varmap)
e el ->
read_cont st defs varmap c h ->
Forall3
(
fun pt vdeeps tdeep =>
length (
fst vdeeps) =
fst pt /\
read_val st defs (
fst vdeeps ++
varmap) (
snd vdeeps)
tdeep /\
convertible beta (
subst (
liftn_subst (
fst pt) (
read_env el)) (
snd pt))
tdeep /\
closed_at (
snd pt) (
fst pt +
length e) /\
Forall (
fun x =>
length defs <=
x <
st.(
st_freename) /\
x \
notin varmap) (
fst vdeeps) /\
NoDup (
fst vdeeps) /\
no_dvar (
snd pt)
)
bs bds tdeeps ->
read_cont st defs varmap (
Kswitch bs e bds c) (
compose_hctx h (
h_switch h_hole (
map (
fun '(
p,
t) => (
p,
subst (
liftn_subst p (
read_env el))
t))
bs))).
Definition read_ind st defs :=
Induction For [
read_thread st defs ;
read_val st defs ;
read_cont st defs ].
Ltac read_thread_val_intro :=
intros varmap rid v c t h Hnth Hv Hc IHv IHc.
Ltac read_thread_term_intro :=
intros varmap rid e el c t h Hnth Hclosed He Hc Hdv IHe IHc.
Ltac read_val_thread_intro :=
intros varmap rid t Hrid IH.
Ltac read_val_clos_intro :=
intros varmap t e el x vdeep tdeep He Hvdeep Hconv Hdv Hfree1 Hfree2 Hclosed IHe IHdeep.
Ltac read_val_block_intro :=
intros varmap tag e el He IHe.
Ltac read_val_neutral_intro :=
intros varmap x c h uf tuf Hc Huf Hfree Hin IHc IHuf.
Ltac read_cont_kid_intro :=
intros varmap.
Ltac read_cont_kapp_intro :=
intros varmap v c t h Hv Hc IHv IHc.
Ltac read_cont_kswitch_intro :=
intros varmap bs e bds tdeeps c el h He Hc Hdeeps IHe IHc IHdeep.
Ltac read_ind :=
apply read_ind; [
read_thread_val_intro|
read_thread_term_intro|
read_val_thread_intro|
read_val_clos_intro|
read_val_block_intro|
read_val_neutral_intro|
read_cont_kid_intro|
read_cont_kapp_intro|
read_cont_kswitch_intro].
points is acyclic.
Lemma read_Acc_aux :
forall st defs, (
forall varmap a t,
read_thread st defs varmap a t ->
Acc (
flip (
points st))
a) /\
(
forall varmap v t,
read_val st defs varmap v t ->
forall a,
val_points_to v a ->
Acc (
flip (
points st))
a) /\
(
forall varmap c h,
read_cont st defs varmap c h ->
forall a,
cont_points_to c a ->
Acc (
flip (
points st))
a).
Proof.
intros st defs. read_ind.
- constructor. intros rid2 Hpoint. unfold flip, points, points_to in Hpoint; simpl in Hpoint.
rewrite Hnth in Hpoint. destruct Hpoint as [Hpoint | Hpoint].
+ apply IHv. inversion Hpoint; subst. assumption.
+ apply IHc. assumption.
- constructor. intros rid2 Hpoint. unfold flip, points, points_to in Hpoint; simpl in Hpoint.
rewrite Hnth in Hpoint. destruct Hpoint as [Hpoint | Hpoint].
+ inversion Hpoint; subst. eapply Forall2_Exists_left_transparent; [|eassumption|eassumption].
intros v1 t1 IH Hpoint2; apply IH, Hpoint2.
+ apply IHc, Hpoint.
- intros a Hpoint; inversion Hpoint; subst; assumption.
- intros a Hpoint.
inversion Hpoint; subst.
+ eapply Forall2_Exists_left_transparent; [|eassumption|eassumption].
intros v1 t1 IH Hpoint2; apply IH, Hpoint2.
+ apply IHdeep. assumption.
- intros a Hpoint. inversion Hpoint; subst.
eapply Forall2_Exists_left_transparent; [|eassumption|eassumption].
intros v t IH Hpoint2; apply IH, Hpoint2.
- intros a Hpoint. inversion Hpoint; subst.
+ apply IHc. assumption.
+ simpl in *. subst. inversion IHuf; subst. apply H3, H1.
- intros a Hpoint. inversion Hpoint.
- intros a Hpoint; inversion Hpoint; subst.
+ apply IHv. assumption.
+ apply IHc. assumption.
- intros a Hpoint.
inversion Hpoint; subst.
+ eapply Forall2_Exists_left_transparent; try eassumption.
intros v1 t1 IH Hpoint2; apply IH, Hpoint2.
+ eapply Forall3_Exists_2_transparent; try eassumption.
intros pt1 vd1 t1 IH Hpoint2. apply IH, Hpoint2.
+ apply IHc. assumption.
Qed.
Lemma read_thread_Acc :
forall st defs varmap a t,
read_thread st defs varmap a t ->
Acc (
flip (
points st))
a.
Proof.
intros. eapply (proj1 (read_Acc_aux st defs)); eassumption.
Qed.
Lemma read_val_Acc :
forall st defs varmap v t a,
read_val st defs varmap v t ->
val_points_to v a ->
Acc (
flip (
points st))
a.
Proof.
intros. eapply (proj1 (proj2 (read_Acc_aux st defs))); eassumption.
Qed.
Lemma read_cont_Acc :
forall st defs varmap c h a,
read_cont st defs varmap c h ->
cont_points_to c a ->
Acc (
flip (
points st))
a.
Proof.
intros. eapply (proj2 (proj2 (read_Acc_aux st defs))); eassumption.
Qed.
Lemma read_points_aux :
forall st defs, (
forall varmap a t,
read_thread st defs varmap a t ->
True) /\
(
forall varmap v t,
read_val st defs varmap v t ->
forall a,
val_points_to v a ->
exists t varmap2,
read_thread st defs (
varmap2 ++
varmap)
a t) /\
(
forall varmap c h,
read_cont st defs varmap c h ->
forall a,
cont_points_to c a ->
exists t varmap2,
read_thread st defs (
varmap2 ++
varmap)
a t).
Proof.
intros st defs. read_ind.
- tauto.
- tauto.
- intros a Hpoint; inversion Hpoint; subst. eexists; exists nil; eassumption.
- intros a Hpoint.
inversion Hpoint; subst.
+ eapply Forall2_Exists_left_transparent; [|eassumption|eassumption].
intros v1 t1 IH Hpoint2; apply IH, Hpoint2.
+ destruct (IHdeep _ H4) as (t1 & varmap2 & IH).
exists t1. exists (varmap2 ++ (x :: nil)). rewrite <- app_assoc. assumption.
- intros a Hpoint.
inversion Hpoint; subst.
eapply Forall2_Exists_left_transparent; [|eassumption|eassumption].
intros v t IH Hpoint2; apply IH, Hpoint2.
- intros a Hpoint. inversion Hpoint; subst.
+ apply IHc. assumption.
+ simpl in *. subst. inversion IHuf; subst. apply H3, H1.
- intros a Hpoint. inversion Hpoint.
- intros a Hpoint; inversion Hpoint; subst.
+ apply IHv. assumption.
+ apply IHc. assumption.
- intros a Hpoint.
inversion Hpoint; subst.
+ eapply Forall2_Exists_left_transparent; try eassumption.
intros v1 t1 IH Hpoint2; apply IH, Hpoint2.
+ eapply Forall3_Exists_2_transparent; try eassumption.
intros pt1 vd1 t1 IH Hpoint2.
destruct (IH _ Hpoint2) as (t2 & varmap2 & IH2).
exists t2. exists (varmap2 ++ fst vd1). rewrite <- app_assoc. assumption.
+ apply IHc. assumption.
Qed.
Lemma read_val_points :
forall st defs varmap v t a,
read_val st defs varmap v t ->
val_points_to v a ->
exists t varmap2,
read_thread st defs (
varmap2 ++
varmap)
a t.
Proof.
intros st defs varmap v t a H.
eapply (proj1 (proj2 (read_points_aux st defs))); eassumption.
Qed.
Lemma read_cont_points :
forall st defs varmap c h a,
read_cont st defs varmap c h ->
cont_points_to c a ->
exists t varmap2,
read_thread st defs (
varmap2 ++
varmap)
a t.
Proof.
intros st defs varmap c h a H.
eapply (proj2 (proj2 (read_points_aux st defs))); eassumption.
Qed.
Lemma read_thread_points :
forall st defs varmap a1 a2 t,
read_thread st defs varmap a1 t ->
points st a1 a2 ->
exists t varmap2,
read_thread st defs (
varmap2 ++
varmap)
a2 t.
Proof.
intros st defs varmap a1 a2 t H1 H2. inversion H1; subst; unfold points, points_to in *; rewrite H in H2; destruct H2.
- inversion H2. subst. eapply read_val_points; eassumption.
- eapply read_cont_points; eassumption.
- inversion H2; subst. eapply Forall2_Exists_left_transparent; try eassumption.
intros; simpl in *; eapply read_val_points; eassumption.
- eapply read_cont_points; eassumption.
Qed.
Expresses that a property is true for each address transitively pointed to from a given address.
Definition every_reachable st a (
P :
addr ->
Prop) :=
forall a2,
star (
points st)
a a2 ->
P a2.
Definition every_reachable_plus st a (
P :
addr ->
Prop) :=
forall a2,
plus (
points st)
a a2 ->
P a2.
Lemma every_reachable_impl :
forall st a (
P Q :
addr ->
Prop),
(
forall a2,
star (
points st)
a a2 ->
P a2 ->
Q a2) ->
every_reachable st a P ->
every_reachable st a Q.
Proof.
intros st a P Q H1 H2 a2 Hstar; apply H1; [assumption|]; apply H2; assumption.
Qed.
Lemma every_reachable_plus_impl :
forall st a (
P Q :
addr ->
Prop),
(
forall a2,
plus (
points st)
a a2 ->
P a2 ->
Q a2) ->
every_reachable_plus st a P ->
every_reachable_plus st a Q.
Proof.
intros st a P Q H1 H2 a2 Hplus; apply H1; [assumption|]; apply H2; assumption.
Qed.
Lemma every_reachable_star :
forall st a a2 P,
star (
points st)
a a2 ->
every_reachable st a P ->
every_reachable st a2 P.
Proof.
intros st a a2 P Hstar H a3 Hstar2. apply H. eapply star_compose; eassumption.
Qed.
Lemma every_reachable_plus_star :
forall st a a2 P,
star (
points st)
a a2 ->
every_reachable_plus st a P ->
every_reachable_plus st a2 P.
Proof.
intros st a a2 P Hstar H a3 Hplus. apply H. eapply plus_compose_star_left; eassumption.
Qed.
Lemma every_reachable_star_plus :
forall st a a2 P,
plus (
points st)
a a2 ->
every_reachable_plus st a P ->
every_reachable st a2 P.
Proof.
intros st a a2 P Hplus H a3 Hstar. apply H. eapply plus_compose_star_right; eassumption.
Qed.
Lemma every_reachable_plus_iff :
forall st a P,
every_reachable_plus st a P <-> (
forall a2,
points st a a2 ->
every_reachable st a2 P).
Proof.
intros st a P. split; intros H.
- intros a2 Ha2 a3 Ha3. apply H. rewrite (plus_star_iff _ _ _ _). exists a2. split; assumption.
- intros a3 Ha3. rewrite (plus_star_iff _ _ _ _) in Ha3; destruct Ha3 as (a2 & Ha2 & Ha3).
apply (H a2 Ha2 a3 Ha3).
Qed.
Lemma every_reachable_same :
forall st a P,
every_reachable st a P ->
P a.
Proof.
intros st a P H; apply H, star_refl.
Qed.
Lemma every_reachable_is_plus :
forall st a P,
every_reachable st a P ->
every_reachable_plus st a P.
Proof.
intros st a P H a2 Ha2. apply H, plus_star, Ha2.
Qed.
Lemma every_reachable_iff :
forall st a1 P,
every_reachable st a1 P <->
P a1 /\
every_reachable_plus st a1 P.
Proof.
intros st a1 P. split; intros H.
- split; [eapply every_reachable_same|eapply every_reachable_is_plus]; eassumption.
- intros a2 Ha2. inversion Ha2; subst; [tauto|].
apply H. rewrite (plus_star_iff _ _ _ _); eexists; split; eassumption.
Qed.
If all threads pointed to from an address are unchanged, the readback is still compatible.
Definition unchanged_from st1 st2 a :=
every_reachable st1 a (
fun a2 =>
nth_error st1.(
st_rthreads)
a2 =
nth_error st2.(
st_rthreads)
a2).
Definition unchanged_from_plus st1 st2 a :=
every_reachable_plus st1 a (
fun a2 =>
nth_error st1.(
st_rthreads)
a2 =
nth_error st2.(
st_rthreads)
a2).
Lemma unchanged_from_same :
forall st1 st2 a,
unchanged_from st1 st2 a ->
nth_error st1.(
st_rthreads)
a =
nth_error st2.(
st_rthreads)
a.
Proof.
intros st1 st2 a. apply every_reachable_same.
Qed.
Lemma unchanged_from_points :
forall st1 st2 a1 a2,
unchanged_from st1 st2 a1 ->
points st1 a1 a2 ->
unchanged_from st1 st2 a2.
Proof.
intros st1 st2 a1 a2 Hchanged Hpoint.
apply every_reachable_is_plus in Hchanged.
eapply every_reachable_plus_iff in Hchanged; eassumption.
Qed.
Lemma read_same_aux :
forall st1 st2 defs,
st_freename st1 <=
st_freename st2 ->
(
forall varmap a t,
read_thread st1 defs varmap a t ->
unchanged_from st1 st2 a ->
read_thread st2 defs varmap a t) /\
(
forall varmap v t,
read_val st1 defs varmap v t -> (
forall a,
val_points_to v a ->
unchanged_from st1 st2 a) ->
read_val st2 defs varmap v t) /\
(
forall varmap c h,
read_cont st1 defs varmap c h -> (
forall a,
cont_points_to c a ->
unchanged_from st1 st2 a) ->
read_cont st2 defs varmap c h).
Proof.
intros st1 st2 defs Hst12. read_ind; intros Hunchanged.
- eapply read_thread_val.
+ erewrite unchanged_from_same in Hnth; eassumption.
+ apply IHv. intros a Ha; eapply unchanged_from_points; [eassumption|].
unfold points, points_to. rewrite Hnth. left; constructor; assumption.
+ apply IHc. intros a Ha; eapply unchanged_from_points; [eassumption|].
unfold points, points_to. rewrite Hnth. right; assumption.
- eapply read_thread_term.
+ erewrite unchanged_from_same in Hnth; eassumption.
+ assumption.
+ eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v2 t2 Hin IH; simpl in *.
apply IH. intros a Ha; eapply unchanged_from_points; [eassumption|].
unfold points, points_to. rewrite Hnth. left; constructor.
apply Exists_exists; eexists; split; eassumption.
+ apply IHc. intros a Ha; eapply unchanged_from_points; [eassumption|].
unfold points, points_to. rewrite Hnth. right; assumption.
+ assumption.
- eapply read_val_thread. apply IH, Hunchanged. constructor.
- eapply read_val_clos.
+ eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v2 t2 Hin IH; simpl in *.
apply IH. intros a Ha; apply Hunchanged. eapply clos_points_to_1.
eapply Exists_exists. eexists; split; eassumption.
+ apply IHdeep. intros; apply Hunchanged; eapply clos_points_to_2; assumption.
+ assumption.
+ assumption.
+ lia.
+ assumption.
+ assumption.
- apply read_val_block.
eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v t Hin IH; simpl in *.
apply IH. intros a Ha; apply Hunchanged. apply block_points_to.
eapply Exists_exists. eexists; split; eassumption.
- eapply read_val_neutral.
+ apply IHc. intros a Ha; apply Hunchanged, neutral_points_to_1, Ha.
+ inversion IHuf; subst.
* constructor.
* constructor. inversion Huf; subst. assert (z0 = z) by congruence; subst. split; [|tauto].
apply H2. intros a Ha; eapply Hunchanged, neutral_points_to_2, Ha. reflexivity.
+ lia.
+ assumption.
- constructor.
- eapply read_cont_kapp.
+ apply IHv. intros a Ha; apply Hunchanged, kapp_points_to_1, Ha.
+ apply IHc. intros a Ha; apply Hunchanged, kapp_points_to_2, Ha.
- eapply read_cont_kswitch.
+ eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v2 t2 Hin IH; simpl in *.
apply IH. intros a Ha; apply Hunchanged. eapply kswitch_points_to_1.
eapply Exists_exists. eexists; split; eassumption.
+ apply IHc. intros a Ha; eapply Hunchanged, kswitch_points_to_3, Ha.
+ eapply Forall3_impl_In; [|eapply Forall3_and; [apply Hdeeps|apply IHdeep]].
intros pt vdeeps tdeep Hin1 Hin2 Hin3 [Hdeep IH].
repeat (split; try tauto).
* apply IH. intros a Ha; eapply Hunchanged, kswitch_points_to_2.
eapply Exists_exists. eexists; split; eassumption.
* eapply Forall_impl; [|apply Hdeep]. intros x [Hfree1 Hfree2]; split; [lia|assumption].
Qed.
Lemma read_thread_same :
forall st1 st2 defs varmap a t,
st_freename st1 <=
st_freename st2 ->
read_thread st1 defs varmap a t ->
unchanged_from st1 st2 a ->
read_thread st2 defs varmap a t.
Proof.
intros st1 st2 defs varmap a t Hst12. apply (proj1 (read_same_aux st1 st2 defs Hst12)).
Qed.
Lemma read_val_same :
forall st1 st2 defs varmap v t,
st_freename st1 <=
st_freename st2 ->
read_val st1 defs varmap v t -> (
forall a,
val_points_to v a ->
unchanged_from st1 st2 a) ->
read_val st2 defs varmap v t.
Proof.
intros st1 st2 defs varmap v t Hst12. apply (proj1 (proj2 (read_same_aux st1 st2 defs Hst12))).
Qed.
Lemma read_cont_same :
forall st1 st2 defs varmap c h,
st_freename st1 <=
st_freename st2 ->
read_cont st1 defs varmap c h -> (
forall a,
cont_points_to c a ->
unchanged_from st1 st2 a) ->
read_cont st2 defs varmap c h.
Proof.
intros st1 st2 defs varmap c h Hst12. apply (proj2 (proj2 (read_same_aux st1 st2 defs Hst12))).
Qed.
Lemma unchanged_from_trans :
forall st1 st2 st3 a,
unchanged_from st1 st2 a ->
unchanged_from st2 st3 a ->
unchanged_from st1 st3 a.
Proof.
intros st1 st2 st3 a H1 H2 rid Ha.
etransitivity; [eapply H1; eassumption|].
eapply H2. clear H2. induction Ha.
- constructor.
- econstructor; [|eapply IHHa, unchanged_from_points; eassumption].
eapply unchanged_from_same in H1. unfold points, points_to in H.
rewrite H1 in H; assumption.
Qed.
Lemma unchanged_from_plus_trans :
forall st1 st2 st3 a,
unchanged_from st1 st2 a ->
unchanged_from_plus st2 st3 a ->
unchanged_from_plus st1 st3 a.
Proof.
intros st1 st2 st3 a H12 H23.
apply every_reachable_plus_iff.
intros a2 Ha2.
eapply every_reachable_plus_iff in H23; [eapply unchanged_from_trans; [|eassumption]|].
- eapply unchanged_from_points; eassumption.
- unfold points, points_to in *. rewrite <- (unchanged_from_same _ _ _ H12). assumption.
Qed.
Expresses that we did not change existing addresses, or at most one of them.
Definition only_extended st1 st2 :=
forall rid rt,
nth_error (
st_rthreads st1)
rid =
Some rt ->
nth_error (
st_rthreads st2)
rid =
Some rt.
Definition only_changed st1 st2 rid :=
forall rid2 rt,
rid <>
rid2 ->
nth_error (
st_rthreads st1)
rid2 =
Some rt ->
nth_error (
st_rthreads st2)
rid2 =
Some rt.
Lemma only_extended_refl :
forall st,
only_extended st st.
Proof.
intros st rid rt H; assumption.
Qed.
Lemma only_changed_refl :
forall st rid,
only_changed st st rid.
Proof.
intros st rid rid2 rt H1 H2; assumption.
Qed.
Lemma only_changed_refl_eq :
forall st st2 rid,
st_rthreads st =
st_rthreads st2 ->
only_changed st st2 rid.
Proof.
intros st st2 rid Heq rid2 rt H1 H2; rewrite <- Heq; assumption.
Qed.
Lemma only_extended_trans :
forall st1 st2 st3,
only_extended st1 st2 ->
only_extended st2 st3 ->
only_extended st1 st3.
Proof.
intros st1 st2 st3 H1 H2 rid rt H; apply H2, H1, H.
Qed.
Lemma only_changed_trans :
forall st1 st2 st3 rid,
only_changed st1 st2 rid ->
only_changed st2 st3 rid ->
only_changed st1 st3 rid.
Proof.
intros st1 st2 st3 rid H1 H2 rid2 rt Hneq Hnth.
apply H2, H1; assumption.
Qed.
Lemma only_extended_changed :
forall st1 st2 rid,
only_extended st1 st2 ->
only_changed st1 st2 rid.
Proof.
intros st1 st2 rid H rid2 rt H1 H2; apply H; assumption.
Qed.
Lemma only_changed_update :
forall st rid rt,
only_changed st (
update_rthread st rid rt)
rid.
Proof.
intros st rid rt rid2 rt2 Hneq Hnth.
simpl. rewrite nth_error_update3 by assumption. assumption.
Qed.
Lemma only_extended_extend :
forall st rt,
only_extended st (
extend_rthread st rt).
Proof.
intros st rt rid rt2 Hnth.
simpl. apply nth_error_app_Some; assumption.
Qed.
Lemma only_extended_makelazy :
forall st t e,
only_extended st (
fst (
makelazy st t e)).
Proof.
intros st t e. apply only_extended_extend.
Qed.
Lemma only_extended_makenlazy :
forall st ts e,
only_extended st (
fst (
makenlazy st ts e)).
Proof.
intros st ts e; revert st; induction ts as [|t ts]; intros st.
- apply only_extended_refl.
- simpl. eapply only_extended_trans; [eapply only_extended_makelazy|].
apply IHts.
Qed.
Lemma only_changed_extend :
forall st rt rid,
only_changed st (
extend_rthread st rt)
rid.
Proof.
intros; apply only_extended_changed, only_extended_extend.
Qed.
Lemma only_changed_makelazy :
forall st t e rid,
only_changed st (
fst (
makelazy st t e))
rid.
Proof.
intros; apply only_extended_changed, only_extended_makelazy.
Qed.
Lemma only_changed_makenlazy :
forall st ts e rid,
only_changed st (
fst (
makenlazy st ts e))
rid.
Proof.
intros; apply only_extended_changed, only_extended_makenlazy.
Qed.
Lemma read_thread_star_points :
forall st defs varmap a1 a2 t,
read_thread st defs varmap a1 t ->
star (
points st)
a1 a2 ->
exists t2 varmap2,
read_thread st defs (
varmap2 ++
varmap)
a2 t2.
Proof.
intros st defs varmap a1 a2 t H1 H2.
eapply star_preserve with (P := fun a => exists t3 varmap2, read_thread st defs (varmap2 ++ varmap) a t3); [|eexists; exists nil; eassumption|eassumption].
intros ? ? ? (? & varmap2 & H3). eapply read_thread_points in H3; [|eassumption].
destruct H3 as (? & varmap3 & H3).
eexists; exists (varmap3 ++ varmap2); rewrite <- app_assoc; eassumption.
Qed.
Lemma unchanged_from_only_extended :
forall st st2 defs varmap rid t2,
read_thread st defs varmap rid t2 ->
only_extended st st2 ->
unchanged_from st st2 rid.
Proof.
intros st st2 defs varmap rid t2 Hread Hext a Ha.
simpl.
destruct (nth_error (st_rthreads st) a) eqn:H; [symmetry; apply Hext; assumption|].
exfalso.
eapply read_thread_star_points in Ha; [|eassumption].
destruct Ha as (t3 & varmap2 & Ha). inversion Ha; subst; congruence.
Qed.
Lemma unchanged_from_extend :
forall st defs varmap rt rid t2,
read_thread st defs varmap rid t2 ->
unchanged_from st (
extend_rthread st rt)
rid.
Proof.
intros. eapply unchanged_from_only_extended; [eassumption|].
apply only_extended_extend.
Qed.
Lemma unchanged_from_makelazy :
forall st defs varmap t e rid t2,
read_thread st defs varmap rid t2 ->
unchanged_from st (
fst (
makelazy st t e))
rid.
Proof.
intros. eapply unchanged_from_extend; eassumption.
Qed.
Lemma unchanged_from_freevar :
forall st rid,
unchanged_from st (
fst (
freevar st))
rid.
Proof.
intros st rid a Ha; reflexivity.
Qed.
Lemma unchanged_from_plus_only_changed :
forall st st2 defs varmap rid t2,
read_thread st defs varmap rid t2 ->
only_changed st st2 rid ->
unchanged_from_plus st st2 rid.
Proof.
intros st st2 defs varmap rid t2 Hread Hchg a Ha.
simpl.
destruct (nth_error (st_rthreads st) a) eqn:H; [symmetry; apply Hchg; [|assumption]|exfalso].
- intros Heq; subst.
eapply Acc_cycle; [eassumption|].
eapply read_thread_Acc; eassumption.
- eapply plus_star, read_thread_star_points in Ha; [|eassumption].
destruct Ha as (t3 & varmap2 & Ha). inversion Ha; subst; congruence.
Qed.
Lemma unchanged_from_plus_update :
forall st defs varmap a v t,
read_thread st defs varmap a t ->
unchanged_from_plus st (
update_rthread st a v)
a.
Proof.
intros; eapply unchanged_from_plus_only_changed; [eassumption|].
apply only_changed_update.
Qed.
Each reachable point has the same readback.
Definition same_read_plus st1 st2 defs rid :=
every_reachable_plus st1 rid (
fun a =>
forall varmap t,
read_thread st1 defs varmap a t ->
read_thread st2 defs varmap a t).
Lemma same_read_plus_aux :
forall st1 st2 defs rid,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
(
forall varmap a t,
read_thread st1 defs varmap a t ->
True) /\
(
forall varmap v t,
read_val st1 defs varmap v t -> (
forall a,
val_points_to v a ->
plus (
points st1)
rid a) ->
read_val st2 defs varmap v t) /\
(
forall varmap c h,
read_cont st1 defs varmap c h -> (
forall a,
cont_points_to c a ->
plus (
points st1)
rid a) ->
read_cont st2 defs varmap c h).
Proof.
intros st1 st2 defs rid1 Hst12 H. read_ind; try intros Hplus.
- tauto.
- tauto.
- constructor.
apply H; [|assumption]. apply Hplus. constructor.
- eapply read_val_clos; [| |eassumption|eassumption|lia|eassumption|eassumption].
+ eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v1 t1 Hin IH. apply IH.
intros a Ha; apply Hplus; apply clos_points_to_1.
apply Exists_exists; eexists; split; eassumption.
+ apply IHdeep. intros a Ha; apply Hplus.
apply clos_points_to_2. assumption.
- eapply read_val_block.
eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v1 t1 Hin IH. apply IH.
intros a Ha; apply Hplus; apply block_points_to.
apply Exists_exists; eexists; split; eassumption.
- eapply read_val_neutral.
+ apply IHc. intros a Ha; apply Hplus, neutral_points_to_1, Ha.
+ inversion IHuf; subst; [inversion Huf; subst; constructor|]. constructor.
inversion Huf; subst. assert (z0 = z) by congruence; subst.
split; [|tauto].
apply H3. intros a Ha; eapply Hplus, neutral_points_to_2; [reflexivity|eassumption].
+ lia.
+ assumption.
- eapply read_cont_kid.
- eapply read_cont_kapp.
+ apply IHv. intros a Ha; apply Hplus, kapp_points_to_1, Ha.
+ apply IHc. intros a Ha; apply Hplus, kapp_points_to_2, Ha.
- eapply read_cont_kswitch.
+ eapply Forall2_impl_In_left_transparent; [|apply IHe].
intros v1 t1 Hin IH. apply IH.
intros a Ha; apply Hplus; apply kswitch_points_to_1.
apply Exists_exists; eexists; split; eassumption.
+ apply IHc. intros a Ha; apply Hplus, kswitch_points_to_3, Ha.
+ eapply Forall3_impl_In; [|apply Forall3_and; [apply Hdeeps|apply IHdeep]].
intros ? ? ? ? ? ? [? ?].
repeat (split; try tauto).
* apply H4. intros a Ha; apply Hplus, kswitch_points_to_2.
apply Exists_exists; eexists; split; eassumption.
* eapply Forall_impl; [|apply H3]. intros ? [Hfree1 Hfree2]; split; [lia|assumption].
Qed.
Lemma same_read_plus_val :
forall st1 st2 defs varmap rid v t,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
read_val st1 defs varmap v t ->
(
forall a,
val_points_to v a ->
plus (
points st1)
rid a) ->
read_val st2 defs varmap v t.
Proof.
intros st1 st2 defs varmap rid v t Hst12 H.
apply (proj1 (proj2 (same_read_plus_aux st1 st2 defs rid Hst12 H))).
Qed.
Lemma same_read_plus_cont :
forall st1 st2 defs varmap rid c h,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
read_cont st1 defs varmap c h ->
(
forall a,
cont_points_to c a ->
plus (
points st1)
rid a) ->
read_cont st2 defs varmap c h.
Proof.
intros st1 st2 defs varmap rid c h Hst12 H.
apply (proj2 (proj2 (same_read_plus_aux st1 st2 defs rid Hst12 H))).
Qed.
Lemma same_read_plus_val_1 :
forall st1 st2 defs varmap rid v t,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
read_val st1 defs varmap v t ->
(
forall a,
val_points_to v a ->
points st1 rid a) ->
read_val st2 defs varmap v t.
Proof.
intros st1 st2 defs varmap rid v t Hst12 H1 H2 H3.
eapply same_read_plus_val; try eassumption.
intros; apply plus_1, H3; assumption.
Qed.
Lemma same_read_plus_cont_1 :
forall st1 st2 defs varmap rid c h,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
read_cont st1 defs varmap c h ->
(
forall a,
cont_points_to c a ->
points st1 rid a) ->
read_cont st2 defs varmap c h.
Proof.
intros st1 st2 defs varmap rid v t Hst12 H1 H2 H3.
eapply same_read_plus_cont; try eassumption.
intros; apply plus_1, H3; assumption.
Qed.
Lemma same_read_plus_val_Forall2 :
forall st1 st2 defs varmap e el rid,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
Forall2 (
read_val st1 defs varmap)
e el ->
(
forall v a,
In v e ->
val_points_to v a ->
plus (
points st1)
rid a) ->
Forall2 (
read_val st2 defs varmap)
e el.
Proof.
intros st1 st2 defs varmap e el rid Hst12 H1 H2 H3.
eapply Forall2_impl_In_left_transparent; [|eassumption].
intros; eapply same_read_plus_val; try eassumption.
intros; eapply H3; eassumption.
Qed.
Lemma same_read_plus_val_Forall2_1 :
forall st1 st2 defs varmap e el rid,
st_freename st1 <=
st_freename st2 ->
same_read_plus st1 st2 defs rid ->
Forall2 (
read_val st1 defs varmap)
e el ->
(
forall v a,
In v e ->
val_points_to v a ->
points st1 rid a) ->
Forall2 (
read_val st2 defs varmap)
e el.
Proof.
intros st1 st2 defs varmap e el rid Hst12 H1 H2 H3.
eapply same_read_plus_val_Forall2; try eassumption.
intros; eapply plus_1, H3; eassumption.
Qed.
Lemma same_read_unchanged :
forall st st2 defs rid,
st_freename st <=
st_freename st2 ->
unchanged_from_plus st st2 rid ->
same_read_plus st st2 defs rid.
Proof.
intros st st2 defs rid Hst12 H.
eapply every_reachable_plus_impl; [|apply H].
intros a Ha Heq varmap t Ht; eapply read_thread_same; [eassumption|eassumption|].
eapply every_reachable_star_plus; eassumption.
Qed.
Lemma same_read_update :
forall st defs varmap rid t rt,
read_thread st defs varmap rid t ->
same_read_plus st (
update_rthread st rid rt)
defs rid.
Proof.
intros st defs varmap rid t rt Hread.
eapply same_read_unchanged, unchanged_from_plus_update; try eassumption.
simpl. lia.
Qed.
Lemma only_extended_makendeeps :
forall st bs e,
only_extended st (
fst (
makendeeps st bs e)).
Proof.
intros st bs e; revert st; induction bs as [|[p t] bs]; intros st.
- apply only_extended_refl.
- simpl. eapply only_extended_trans; [|eapply IHbs].
eapply only_extended_trans; [|eapply only_extended_makelazy].
intros rid rt H; assumption.
Qed.
step_r only changes the thread passed to it.
Lemma only_changed_step_r :
forall st rid,
only_changed st (
step_r st rid)
rid.
Proof.
intros st rid.
unfold step_r; simpl in *.
destruct (nth_error (st_rthreads st) rid) eqn:H; [|apply only_changed_refl].
destruct (rt_code r).
- destruct t.
+ destruct (nth_error e n); [|apply only_changed_refl].
apply only_changed_update.
+ apply only_changed_refl.
+ destruct (rt_cont r); simpl.
* eapply only_changed_trans; [|apply only_changed_update].
eapply only_changed_trans; [|apply only_changed_makelazy].
apply only_changed_refl_eq; reflexivity.
* apply only_changed_update.
* apply only_changed_refl.
+ eapply only_changed_trans; [|apply only_changed_update].
apply only_changed_makelazy.
+ eapply only_changed_trans; [|apply only_changed_update].
apply only_changed_makenlazy.
+ eapply only_changed_trans; [|apply only_changed_update].
apply only_extended_changed. apply only_extended_makendeeps.
- destruct v.
+ destruct is_finished.
* simpl. apply only_changed_update.
* apply only_changed_refl.
+ destruct p as [[x c] [uf|]]; simpl.
* eapply only_changed_trans; [|apply only_changed_update].
apply only_changed_extend.
* apply only_changed_update.
+ destruct (rt_cont r); try apply only_changed_refl.
apply only_changed_update.
+ destruct (rt_cont r); try apply only_changed_refl.
destruct (nth_error l0 n) as [[p t]|] eqn:Hn; [|apply only_changed_refl].
destruct Nat.eq_dec; [|apply only_changed_refl].
apply only_changed_update.
Qed.
Initial state computation.
Definition defs_ok (
defs :
list term)
st :=
length defs <=
st.(
st_freename).
Fixpoint init_at (
k :
nat) (
t :
term) :=
match t with
|
var n =>
var n
|
dvar i =>
var (
k +
i)
|
app t1 t2 =>
app (
init_at k t1) (
init_at k t2)
|
abs t =>
abs (
init_at (
S k)
t)
|
constr tag l =>
constr tag (
map (
init_at k)
l)
|
switch t m =>
switch (
init_at k t) (
map (
fun '(
p,
t) => (
p,
init_at (
p +
k)
t))
m)
end.
Lemma init_at_no_dvar :
forall t k,
no_dvar (
init_at k t).
Proof.
induction t using term_ind2; simpl; intros k x; constructor.
- apply IHt.
- apply IHt1.
- apply IHt2.
- rewrite Forall_map. eapply Forall_impl; [|eassumption]. intros t H1; apply H1.
- apply IHt.
- rewrite Forall_map. eapply Forall_impl; [|eassumption].
intros [p t2] H1; apply H1.
Qed.
Inductive dvar_below :
nat ->
term ->
Prop :=
|
dvar_below_var :
forall k n,
dvar_below k (
var n)
|
dvar_below_dvar :
forall k k2,
k2 <
k ->
dvar_below k (
dvar k2)
|
dvar_below_app :
forall k t1 t2,
dvar_below k t1 ->
dvar_below k t2 ->
dvar_below k (
app t1 t2)
|
dvar_below_abs :
forall k t,
dvar_below k t ->
dvar_below k (
abs t)
|
dvar_below_constr :
forall k tag l,
Forall (
dvar_below k)
l ->
dvar_below k (
constr tag l)
|
dvar_below_switch :
forall k t m,
dvar_below k t ->
Forall (
fun pt =>
dvar_below k (
snd pt))
m ->
dvar_below k (
switch t m).
Lemma init_at_correct_aux :
forall k p t,
closed_at t p ->
dvar_below k t ->
t =
subst (
liftn_subst p (
read_env (
map dvar (
seq 0
k)))) (
init_at p t).
Proof.
intros k p t H1 H2. revert p H1; induction t using term_ind2; intros p H1.
- simpl. inversion H1; subst.
unfold liftn_subst, read_env; simpl.
destruct le_lt_dec; [lia|]. reflexivity.
- simpl. inversion H2; subst.
unfold liftn_subst, read_env; simpl.
destruct le_lt_dec; [|lia]. rewrite nth_error_map.
erewrite nth_error_nth' with (d := 0) by (rewrite seq_length; lia).
rewrite seq_nth by lia. simpl. f_equal. lia.
- simpl. f_equal.
erewrite subst_ext; [|symmetry; apply liftn_subst_1].
erewrite subst_ext; [|apply liftn_subst_add]. simpl.
apply IHt; [inversion H2|inversion H1]; subst; assumption.
- simpl. inversion H1; inversion H2; subst. f_equal; [apply IHt1|apply IHt2]; assumption.
- simpl. f_equal. rewrite map_map.
erewrite map_ext_Forall, map_id; [reflexivity|].
inversion H1; inversion H2; subst.
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|erewrite <- Forall_and; split; [apply H8|apply Forall_forall, H5]]].
intros t (Ht1 & Ht2 & Ht3); simpl. symmetry.
apply Ht1; assumption.
- simpl. inversion H1; inversion H2; subst. f_equal.
+ apply IHt; assumption.
+ rewrite map_map.
erewrite map_ext_Forall, map_id; [reflexivity|].
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|erewrite <- Forall_and; split; [apply H11|apply Forall_forall with (P := (fun pt => closed_at (snd pt) (fst pt + p))); intros [? ?]; apply H6]]].
intros [p2 t2] (Hpt1 & Hpt2 & Hpt3). simpl in *.
f_equal. symmetry.
erewrite subst_ext; [|apply liftn_subst_add].
apply Hpt1; assumption.
Qed.
Lemma init_at_correct :
forall k t,
closed_at t 0 ->
dvar_below k t ->
t =
subst (
read_env (
map dvar (
seq 0
k))) (
init_at 0
t).
Proof.
intros k t H1 H2. etransitivity; [apply init_at_correct_aux; eassumption|].
apply subst_ext, liftn_subst_0.
Qed.
Lemma init_at_closed :
forall p k t,
closed_at t p ->
dvar_below k t ->
closed_at (
init_at p t) (
p +
k).
Proof.
intros p k t H1 H2. revert p H1; induction t using term_ind2; intros p H1; simpl.
- constructor. inversion H1; subst. lia.
- constructor. inversion H2; subst. lia.
- constructor. apply IHt; [inversion H2|inversion H1]; subst; assumption.
- inversion H1; subst; inversion H2; subst. constructor; [apply IHt1|apply IHt2]; assumption.
- constructor. apply Forall_forall. rewrite Forall_map.
inversion H1; inversion H2; subst.
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|erewrite <- Forall_and; split; [apply H8|apply Forall_forall, H5]]].
intros t (Ht1 & Ht2 & Ht3); simpl. apply Ht1; assumption.
- inversion H1; inversion H2; subst. f_equal.
constructor.
+ apply IHt; assumption.
+ intros p2 t3. remember (p2, t3) as pt3.
replace p2 with (fst pt3) by (subst; reflexivity). replace t3 with (snd pt3) by (subst; reflexivity).
clear p2 t3 Heqpt3. revert pt3.
apply Forall_forall. rewrite Forall_map.
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|erewrite <- Forall_and; split; [apply H11|apply Forall_forall with (P := (fun pt => closed_at (snd pt) (fst pt + p))); intros [? ?]; apply H6]]].
intros [p2 t3] (Hpt1 & Hpt2 & Hpt3); simpl in *.
rewrite plus_assoc.
apply Hpt1; assumption.
Qed.
Fixpoint init_all (
st :
state) (
l :
list value) (
defs :
list term) :=
match defs with
|
nil => (
st,
l)
|
t ::
defs =>
let (
st2,
v) :=
makelazy st (
init_at 0
t)
l in
init_all st2 (
l ++
Neutral (
length l,
Kid,
Some v) ::
nil)
defs
end.
Definition init_term (
defs :
list term) (
t :
term) :=
let (
st,
vs) :=
init_all {|
st_rthreads :=
nil ;
st_freename :=
length defs |}
nil defs in
makelazy st (
init_at 0
t)
vs.
Lemma init_all_correct :
forall st st2 defs1 defs2 l l2,
Forall2 (
fun t i =>
closed_at t 0 /\
dvar_below i t)
defs2 (
seq (
length defs1) (
length defs2)) ->
Forall2 (
read_val st (
defs1 ++
defs2)
nil)
l (
map dvar (
seq 0 (
length defs1))) ->
length defs1 +
length defs2 <=
st_freename st ->
init_all st l defs2 = (
st2,
l2) ->
Forall2 (
read_val st2 (
defs1 ++
defs2)
nil)
l2 (
map dvar (
seq 0 (
length defs1 +
length defs2))).
Proof.
intros st st2 defs1 defs2. revert st st2 defs1; induction defs2 as [|t defs2]; intros st st2 defs1 l l2 Hclosed H1 Hfree H2.
- simpl in *. injection H2 as H2; subst.
replace (length defs1 + 0) with (length defs1) by (apply plus_n_O).
assumption.
- simpl in *. eapply IHdefs2 in H2.
+ erewrite <- app_assoc with (m := t :: nil), app_length, plus_assoc_reverse in H2.
apply H2.
+ inversion Hclosed; subst. rewrite app_length, plus_comm; simpl. assumption.
+ rewrite app_length, seq_app, map_app.
apply Forall2_app.
* eapply Forall2_impl; [|eassumption].
intros v2 t2 H; simpl. eapply read_val_same; [|rewrite <- app_assoc; eassumption|]; [simpl; lia|].
intros a Ha. eapply read_val_points in Ha; [|eassumption]. destruct Ha as (? & ? & ?).
eapply unchanged_from_makelazy; eassumption.
* constructor; [|constructor]. simpl.
assert (Hlen : length l = length defs1) by (apply Forall2_length in H1; rewrite map_length, seq_length in H1; apply H1).
rewrite <- Hlen.
eapply read_val_neutral with (h := h_hole); [constructor| |simpl; lia|rewrite <- app_assoc, Hlen; simpl; rewrite nth_error_select; congruence].
rewrite Hlen.
rewrite nth_error_app1 by (rewrite app_length; simpl; lia).
rewrite nth_error_app2 by lia.
rewrite Nat.sub_diag. simpl.
constructor.
split; [|split; [apply star_refl|inversion Hclosed; subst; tauto]].
constructor.
refine (eq_rect _ (read_thread _ _ _ _) _ t _);
[eapply read_thread_term with (h := h_hole)|symmetry; apply init_at_correct]; simpl.
-- apply nth_error_extend.
-- inversion Hclosed; subst. rewrite <- Hlen in H4. apply init_at_closed with (p := 0); apply H4.
-- eapply Forall2_impl; [|eassumption].
intros v2 t2 H; simpl. eapply read_val_same; [|rewrite <- app_assoc; eassumption|]; [simpl; lia|].
intros a Ha. eapply read_val_points in Ha; [|eassumption]. destruct Ha as (? & ? & ?).
eapply unchanged_from_makelazy; eassumption.
-- constructor.
-- apply init_at_no_dvar.
-- inversion Hclosed; subst. tauto.
-- inversion Hclosed; subst. tauto.
+ simpl. rewrite app_length; simpl. lia.
Qed.
Definition defs_wf defs :=
Forall2 (
fun t i =>
closed_at t 0 /\
dvar_below i t)
defs (
seq 0 (
length defs)).
Lemma init_term_correct :
forall defs t st v,
defs_wf defs ->
closed_at t 0 ->
dvar_below (
length defs)
t ->
init_term defs t = (
st,
v) ->
read_val st defs nil v t.
Proof.
intros defs t st v H1 H2 H3 H4.
unfold init_term in H4; simpl in *.
destruct init_all as [st2 vs] eqn:Hinit; simpl in *.
apply init_all_correct with (defs1 := nil) in Hinit.
- unfold makelazy in H4; simpl in *; injection H4 as H4; subst.
constructor.
refine (eq_rect _ (read_thread _ _ _ _) _ t _);
[eapply read_thread_term with (h := h_hole)|symmetry; apply init_at_correct]; simpl.
+ apply nth_error_extend.
+ apply Forall2_length in Hinit. rewrite Hinit, map_length, seq_length.
apply init_at_closed with (p := 0); assumption.
+ eapply Forall2_impl; [|eassumption].
intros v2 t2 H; simpl. eapply read_val_same; [|eassumption|]; [simpl; lia|].
intros a Ha. eapply read_val_points in Ha; [|eassumption]. destruct Ha as (? & ? & ?).
eapply unchanged_from_makelazy; eassumption.
+ constructor.
+ apply init_at_no_dvar.
+ assumption.
+ assumption.
- simpl. assumption.
- simpl. constructor.
- simpl. lia.
Qed.
Properties about contexts and reduction.
Lemma compose_hctx_hole_r :
forall h,
compose_hctx h h_hole =
h.
Proof.
induction h; simpl in *; f_equal; (reflexivity || assumption).
Qed.
Lemma compose_hctx_assoc :
forall h1 h2 h3,
compose_hctx (
compose_hctx h1 h2)
h3 =
compose_hctx h1 (
compose_hctx h2 h3).
Proof.
intros h1 h2 h3; induction h1; simpl in *; f_equal; assumption.
Qed.
Lemma compose_cont_ctx :
forall st defs varmap c1 c2 h1 h2,
read_cont st defs varmap c1 h1 ->
read_cont st defs varmap c2 h2 ->
read_cont st defs varmap (
compose_cont c1 c2) (
compose_hctx h2 h1).
Proof.
intros st defs varmap c1 c2 h1 h2 Hread1 Hread2. induction Hread1.
- simpl. rewrite compose_hctx_hole_r. assumption.
- simpl. rewrite <- compose_hctx_assoc. constructor; tauto.
- simpl. rewrite <- compose_hctx_assoc. econstructor; try eassumption. tauto.
Qed.
Lemma beta_fill :
forall t1 t2 h,
beta t1 t2 ->
beta (
fill_hctx h t1) (
fill_hctx h t2).
Proof.
intros t1 t2 h H; induction h; simpl in *.
- assumption.
- constructor. assumption.
- constructor. assumption.
Qed.
Lemma convertible_fill :
forall t1 t2 h,
convertible beta t1 t2 ->
convertible beta (
fill_hctx h t1) (
fill_hctx h t2).
Proof.
intros t1 t2 h H. eapply star_map_impl; [|eassumption].
intros t3 t4 [Ht34 | Ht34]; [left | right]; apply beta_fill; assumption.
Qed.
Proof that readback is compatible with step_r.
Lemma read_val_only_extended :
forall st st2 defs varmap v t,
st_freename st <=
st_freename st2 ->
only_extended st st2 ->
read_val st defs varmap v t ->
read_val st2 defs varmap v t.
Proof.
intros st st2 defs varmap v t Hst12 H1 H2.
eapply read_val_same; [eassumption|eassumption|].
intros a Ha. eapply read_val_points in Ha; [|eassumption].
destruct Ha as (? & ? & ?); eapply unchanged_from_only_extended; eassumption.
Qed.
Lemma read_thread_only_extended :
forall st st2 defs varmap rid t,
st_freename st <=
st_freename st2 ->
only_extended st st2 ->
read_thread st defs varmap rid t ->
read_thread st2 defs varmap rid t.
Proof.
intros st st2 defs varmap rid t Hst12 H1 H2.
eapply read_thread_same; [eassumption|eassumption|].
eapply unchanged_from_only_extended; eassumption.
Qed.
Lemma read_val_makelazy :
forall st defs varmap t e el,
no_dvar t ->
closed_at t (
length e) ->
Forall2 (
read_val st defs varmap)
e el ->
read_val (
fst (
makelazy st t e))
defs varmap (
snd (
makelazy st t e)) (
subst (
read_env el)
t).
Proof.
intros st defs varmap t e el Hdv Hclosed H.
simpl. constructor.
eapply read_thread_term with (h := h_hole).
- apply nth_error_extend.
- assumption.
- eapply Forall2_impl; [|eassumption].
intros t2 v2 H2; simpl.
eapply read_val_only_extended; [| |eassumption]; [simpl; lia|].
apply only_extended_extend.
- constructor.
- assumption.
Qed.
Lemma makenlazy_freename :
forall st ts e,
st_freename st <=
st_freename (
fst (
makenlazy st ts e)).
Proof.
intros st ts; revert st; induction ts; intros st e; simpl.
- lia.
- etransitivity; [|apply IHts]. simpl. lia.
Qed.
Lemma read_val_makenlazy :
forall st defs varmap ts e el,
Forall no_dvar ts ->
Forall (
fun t =>
closed_at t (
length e))
ts ->
Forall2 (
read_val st defs varmap)
e el ->
Forall2 (
read_val (
fst (
makenlazy st ts e))
defs varmap) (
snd (
makenlazy st ts e)) (
map (
subst (
read_env el))
ts).
Proof.
intros st defs varmap ts e el.
revert st; induction ts as [|t ts].
- intros st Hdv Hclosed H; simpl in *; constructor.
- intros st Hdv Hclosed H; simpl in *. inversion Hdv; subst. inversion Hclosed; subst. constructor.
+ eapply read_val_only_extended; [simpl; apply makenlazy_freename|apply only_extended_makenlazy|].
apply read_val_makelazy; assumption.
+ apply IHts; [assumption|assumption|]. eapply Forall2_impl; [|eassumption].
intros v2 t2 H6; simpl.
eapply read_val_only_extended; [| |eassumption]; [simpl; lia|].
apply only_extended_makelazy.
Qed.
Lemma read_val_makenlazy_new :
forall st defs varmap ts e el,
Forall no_dvar ts ->
Forall (
fun t =>
closed_at t (
length e))
ts ->
Forall2 (
read_val st defs varmap)
e el ->
forall rid,
nth_error (
st_rthreads st)
rid =
None ->
nth_error (
st_rthreads (
fst (
makenlazy st ts e)))
rid <>
None ->
exists t2 varmap2,
read_thread (
fst (
makenlazy st ts e))
defs varmap2 rid t2.
Proof.
intros st defs varmap ts e el.
revert st; induction ts as [|t ts].
- intros st Hdv Hclosed H; simpl in *. intros; tauto.
- intros st Hdv Hclosed H; simpl in *. inversion Hdv; subst. inversion Hclosed; subst.
intros rid Hrid1 Hrid2.
destruct (nth_error (st_rthreads (extend_rthread st {| rt_code := Term t e; rt_cont := Kid |})) rid) eqn:Hrid3.
+ simpl in Hrid3. rewrite nth_error_app2 in Hrid3; [|rewrite nth_error_None in Hrid1; assumption].
remember (rid - length (st_rthreads st)) as n.
destruct n; [|destruct n; simpl in *; congruence]. simpl in Hrid3. injection Hrid3 as Hrid3; subst.
assert (rid = length (st_rthreads st)) by (rewrite nth_error_None in Hrid1; lia). subst.
eexists. eexists. eapply read_thread_only_extended; [simpl; apply makenlazy_freename|apply only_extended_makenlazy|].
eapply read_thread_term.
* apply nth_error_extend.
* assumption.
* eapply Forall2_impl; [|eassumption]. intros; eapply read_val_only_extended; [| |eassumption]; [simpl; lia|].
apply only_extended_makelazy.
* constructor.
* assumption.
+ apply IHts; try eassumption.
eapply Forall2_impl; [|eassumption].
intros; simpl.
eapply read_val_only_extended; [| |eassumption]; [simpl; lia|].
apply only_extended_makelazy.
Qed.
Lemma makenlazy_points :
forall st ts e v a,
In v (
snd (
makenlazy st ts e)) ->
val_points_to v a ->
length (
st_rthreads st) <=
a.
Proof.
intros st ts; revert st; induction ts as [|t ts]; intros st e v a H1 H2; simpl in *.
- tauto.
- destruct H1; subst.
+ inversion H2. lia.
+ eapply IHts in H; [|eassumption]. simpl in H. rewrite app_length in H. lia.
Qed.
Lemma only_extended_points :
forall st st2 a1 a2,
only_extended st st2 ->
points st a1 a2 ->
points st2 a1 a2.
Proof.
intros st st2 a1 a2 H1 H2. unfold points, points_to in *.
destruct nth_error eqn:H3; [|tauto].
apply H1 in H3. rewrite H3; assumption.
Qed.
Lemma only_changed_read_thread_ind :
forall st st2 defs varmap varmap2 rid rid2 t t2,
st_freename st <=
st_freename st2 ->
only_changed st st2 rid ->
read_thread st defs varmap rid t ->
read_thread st defs varmap2 rid2 t2 ->
rid <>
rid2 ->
(
forall a,
points st rid2 a ->
plus (
points st)
rid a) ->
read_thread st2 defs varmap2 rid2 t2.
Proof.
intros st st2 defs varmap varmap2 rid rid2 t t2 Hst12 H1 H2 H3 H4 H5.
inversion H3; subst.
- eapply read_thread_val.
+ eapply H1; eassumption.
+ eapply read_val_same; [eassumption|eassumption|].
intros a Ha. eapply unchanged_from_plus_only_changed in H1; [|eassumption].
eapply every_reachable_star_plus; [|eassumption].
apply H5. unfold points, points_to. rewrite H. left. constructor. assumption.
+ eapply read_cont_same; [eassumption|eassumption|].
intros a Ha. eapply unchanged_from_plus_only_changed in H1; [|eassumption].
eapply every_reachable_star_plus; [|eassumption].
apply H5. unfold points, points_to. rewrite H. right. assumption.
- eapply read_thread_term.
+ eapply H1; eassumption.
+ assumption.
+ eapply Forall2_impl_In_left_transparent; [|eassumption].
intros v t2 Hv Hread; eapply read_val_same; [eassumption|eassumption|].
intros a Ha. eapply unchanged_from_plus_only_changed in H1; [|eassumption].
eapply every_reachable_star_plus; [|eassumption].
apply H5. unfold points, points_to. rewrite H. left. constructor.
apply Exists_exists; eexists; split; eassumption.
+ eapply read_cont_same; [eassumption|eassumption|].
intros a Ha. eapply unchanged_from_plus_only_changed in H1; [|eassumption].
eapply every_reachable_star_plus; [|eassumption].
apply H5. unfold points, points_to. rewrite H. right. assumption.
+ assumption.
Qed.
Lemma only_changed_read_thread_ind_1 :
forall st st2 defs varmap varmap2 rid rid2 t t2,
st_freename st <=
st_freename st2 ->
only_changed st st2 rid ->
read_thread st defs varmap rid t ->
read_thread st defs varmap2 rid2 t2 ->
rid <>
rid2 ->
(
forall a,
points st rid2 a ->
points st rid a) ->
read_thread st2 defs varmap2 rid2 t2.
Proof.
intros; eapply only_changed_read_thread_ind; try eassumption.
intros a Ha; apply plus_1, H4; assumption.
Qed.
Lemma read_val_makenlazy_changed :
forall st st2 defs varmap ts e el rid t2,
st_freename st <=
st_freename st2 ->
Forall no_dvar ts ->
Forall (
fun t =>
closed_at t (
length e))
ts ->
read_thread st defs varmap rid t2 ->
Forall (
fun v =>
forall a,
val_points_to v a ->
points st rid a)
e ->
only_changed (
fst (
makenlazy st ts e))
st2 rid ->
Forall2 (
read_val st defs varmap)
e el ->
Forall2 (
read_val st2 defs varmap) (
snd (
makenlazy st ts e)) (
map (
subst (
read_env el))
ts).
Proof.
intros st st2 defs varmap ts e el rid t2 Hst12 Hdv Hclosed Hread Hpoint Hchange H.
revert st st2 Hst12 Hread Hpoint Hchange H; induction ts as [|t ts]; intros st st2 Hst12 Hread Hpoint Hchange H; simpl in *; constructor.
- constructor.
eapply only_changed_read_thread_ind_1; cycle 1.
+ eapply only_changed_trans; [|eassumption].
apply only_extended_changed, only_extended_makenlazy.
+ eapply read_thread_only_extended; [|apply only_extended_extend|eassumption]; simpl; lia.
+ eapply read_thread_term with (h := h_hole); [apply nth_error_extend|inversion Hclosed; subst; assumption| |constructor|inversion Hdv; subst; assumption].
eapply Forall2_impl; [|eassumption].
intros; eapply read_val_only_extended; [| |eassumption]; [simpl; lia|]. apply only_extended_extend.
+ inversion Hread; subst; apply nth_error_Some3 in H0; lia.
+ intros a Ha. eapply only_extended_points; [apply only_extended_makelazy|].
unfold points, points_to in Ha. simpl in Ha. rewrite nth_error_extend in Ha; simpl in Ha.
destruct Ha as [Ha | Ha]; inversion Ha; subst.
eapply Forall_Exists; [|eassumption|eassumption].
intros v H4 H5; apply H4, H5.
+ simpl; assumption.
- apply IHts; cycle 3.
+ eapply read_thread_only_extended; [| |eassumption]; [simpl; lia|]. apply only_extended_extend.
+ eapply Forall_impl; [|eassumption].
intros v Hv a Ha. apply Hv in Ha. eapply only_extended_points; [|eassumption]. apply only_extended_extend.
+ assumption.
+ eapply Forall2_impl; [|eassumption].
intros; eapply read_val_only_extended; [| |eassumption]; [simpl; lia|]. apply only_extended_extend.
+ inversion Hdv; subst; assumption.
+ inversion Hclosed; subst; assumption.
+ simpl. assumption.
Qed.
Lemma makendeeps_freename :
forall st bs e,
st_freename st <=
st_freename (
fst (
makendeeps st bs e)).
Proof.
intros st bs e; revert st e; induction bs as [|[? ?] ?]; intros st e; simpl.
- lia.
- etransitivity; [|apply IHbs]. simpl. lia.
Qed.
Fixpoint subst_hctx us h :=
match h with
|
h_hole =>
h_hole
|
h_app h t =>
h_app (
subst_hctx us h) (
subst us t)
|
h_switch h m =>
h_switch (
subst_hctx us h) (
map (
fun pt => (
fst pt,
subst (
liftn_subst (
fst pt)
us) (
snd pt)))
m)
end.
Lemma subst_hctx_fill :
forall us h t,
subst us (
fill_hctx h t) =
fill_hctx (
subst_hctx us h) (
subst us t).
Proof.
intros us h t; induction h.
- reflexivity.
- simpl. f_equal. assumption.
- simpl. f_equal. assumption.
Qed.
Lemma subst_liftn_closed_at :
forall us k t,
closed_at t k ->
subst (
liftn_subst k us)
t =
t.
Proof.
intros us k t Ht. erewrite subst_closed_at_ext, subst_id; [reflexivity|eassumption|].
intros n Hn. unfold liftn_subst. destruct le_lt_dec; [lia|reflexivity].
Qed.
Definition remap varmap1 varmap2 n :=
match nth_error varmap1 n with
|
Some x =>
option_default (
index Nat.eq_dec varmap2 x) 0
|
None =>
n
end.
Definition remap_subst varmap1 varmap2 n :=
var (
remap varmap1 varmap2 n).
Definition is_remap_ok freename varmap1 varmap2 :=
Forall (
fun x =>
In x varmap2)
varmap1 /\
Forall (
fun x =>
freename <=
x \/
In x varmap1)
varmap2.
Lemma is_remap_ok_cons :
forall freename varmap1 varmap2 x,
is_remap_ok freename varmap1 varmap2 ->
is_remap_ok freename (
x ::
varmap1) (
x ::
varmap2).
Proof.
intros freename varmap1 varmap2 x [H1 H2]. split; constructor.
- simpl. tauto.
- eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
- simpl. tauto.
- eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
Qed.
Lemma is_remap_ok_app :
forall freename varmap1 varmap2 varmap3,
is_remap_ok freename varmap2 varmap3 ->
is_remap_ok freename (
varmap1 ++
varmap2) (
varmap1 ++
varmap3).
Proof.
intros freename varmap1; induction varmap1; intros varmap2 varmap3 H; [assumption|].
simpl; apply is_remap_ok_cons. apply IHvarmap1. assumption.
Qed.
Lemma remap_cons_S :
forall x freename varmap1 varmap2 n,
x \
notin varmap1 ->
is_remap_ok freename varmap1 varmap2 ->
remap (
x ::
varmap1) (
x ::
varmap2) (
S n) =
S (
remap varmap1 varmap2 n).
Proof.
intros x freename varmap1 varmap2 n Hx Hok. unfold remap.
simpl. destruct nth_error eqn:Hn; [|reflexivity].
destruct Nat.eq_dec.
- subst. apply nth_error_In in Hn. tauto.
- destruct index eqn:Hidx.
+ reflexivity.
+ apply index_in_not_None in Hidx; [tauto|].
destruct Hok as [Hok1 Hok2]. eapply Forall_forall in Hok1; [eassumption|].
apply nth_error_In in Hn; eassumption.
Qed.
Lemma remap_cons_subst_ren :
forall freename varmap1 varmap2 x t,
x \
notin varmap1 ->
is_remap_ok freename varmap1 varmap2 ->
subst (
remap_subst (
x ::
varmap1) (
x ::
varmap2)) (
ren_term (
plus_ren 1)
t) =
ren_term (
plus_ren 1) (
subst (
remap_subst varmap1 varmap2)
t).
Proof.
intros freename varmap1 varmap2 x t Hx Hok.
rewrite !ren_term_is_subst, !subst_subst. apply subst_ext. intros n; unfold comp; simpl.
unfold remap_subst, ren. f_equal. erewrite plus_ren_correct, remap_cons_S; try eassumption.
simpl. f_equal. f_equal. lia.
Qed.
Lemma remap_app_1 :
forall varmap1 varmap2 varmap3 n,
n <
length varmap1 ->
NoDup varmap1 ->
remap (
varmap1 ++
varmap2) (
varmap1 ++
varmap3)
n =
n.
Proof.
intros varmap1 varmap2 varmap3 n Hn Hvarmap1.
unfold remap. rewrite nth_error_app1 by assumption.
destruct nth_error as [x|] eqn:Hx; [|reflexivity].
rewrite index_app. erewrite index_nth_error by eassumption.
reflexivity.
Qed.
Lemma remap_app_2 :
forall freename varmap1 varmap2 varmap3 n,
length varmap1 <=
n ->
Forall (
fun x =>
x \
notin varmap2)
varmap1 ->
is_remap_ok freename varmap2 varmap3 ->
remap (
varmap1 ++
varmap2) (
varmap1 ++
varmap3)
n =
length varmap1 +
remap varmap2 varmap3 (
n -
length varmap1).
Proof.
intros freename varmap1 varmap2 varmap3 n Hn Hvarmap1 Hok. unfold remap.
rewrite nth_error_app2 by assumption.
destruct nth_error as [x|] eqn:Hx; [|lia].
rewrite index_app. rewrite index_notin_None.
- destruct index eqn:Hx2; simpl; [reflexivity|].
apply index_in_not_None in Hx2; [tauto|].
destruct Hok as [Hok1 Hok2]. eapply Forall_forall in Hok1; [eassumption|].
eapply nth_error_In in Hx; eassumption.
- intros Hx2. eapply Forall_forall in Hvarmap1; [|eassumption].
eapply nth_error_In in Hx; tauto.
Qed.
Lemma remap_app_subst_ren :
forall freename varmap1 varmap2 varmap3 t,
Forall (
fun x =>
x \
notin varmap2)
varmap1 ->
is_remap_ok freename varmap2 varmap3 ->
subst (
remap_subst (
varmap1 ++
varmap2) (
varmap1 ++
varmap3)) (
ren_term (
plus_ren (
length varmap1))
t) =
ren_term (
plus_ren (
length varmap1)) (
subst (
remap_subst varmap2 varmap3)
t).
Proof.
intros freename varmap1 varmap2 varmap3 t Hvarmap1 Hok.
rewrite !ren_term_is_subst, !subst_subst. apply subst_ext. intros n; unfold comp; simpl.
unfold remap_subst, ren. f_equal. erewrite !plus_ren_correct, remap_app_2; try eassumption; [|lia].
f_equal. f_equal. lia.
Qed.
Lemma beta_convertible_subst :
forall us t1 t2,
convertible beta t1 t2 ->
convertible beta (
subst us t1) (
subst us t2).
Proof.
intros us t1 t2 H. eapply star_map_impl; [|eassumption].
intros t3 t4 [H1 | H1]; constructor; apply beta_subst1; assumption.
Qed.
Lemma betaiota_convertible_subst :
forall defs us t1 t2,
convertible (
betaiota defs)
t1 t2 ->
convertible (
betaiota defs) (
subst us t1) (
subst us t2).
Proof.
intros defs us t1 t2 H. eapply star_map_impl; [|eassumption].
intros t3 t4 [H1 | H1]; destruct H1; constructor; constructor; ((apply beta_subst1; assumption) || (apply iota_subst_left; assumption)).
Qed.
Lemma subst_hctx_compose :
forall us h1 h2,
subst_hctx us (
compose_hctx h1 h2) =
compose_hctx (
subst_hctx us h1) (
subst_hctx us h2).
Proof.
intros us h1 h2; induction h1; simpl in *; f_equal; assumption.
Qed.
Lemma read_extend_varmap_aux :
forall st defs,
(
forall varmap a t,
read_thread st defs varmap a t ->
forall varmap2,
is_remap_ok (
st_freename st)
varmap varmap2 ->
read_thread st defs varmap2 a (
subst (
remap_subst varmap varmap2)
t)) /\
(
forall varmap v t,
read_val st defs varmap v t ->
forall varmap2,
is_remap_ok (
st_freename st)
varmap varmap2 ->
read_val st defs varmap2 v (
subst (
remap_subst varmap varmap2)
t)) /\
(
forall varmap c h,
read_cont st defs varmap c h ->
forall varmap2,
is_remap_ok (
st_freename st)
varmap varmap2 ->
read_cont st defs varmap2 c (
subst_hctx (
remap_subst varmap varmap2)
h)).
Proof.
intros st defs. read_ind; intros varmap2 Hremap.
- rewrite subst_hctx_fill.
eapply read_thread_val; eauto.
- rewrite subst_hctx_fill.
rewrite subst_read_env, subst_liftn_closed_at; [|apply Forall2_length in He; rewrite <- He; assumption].
eapply read_thread_term; try solve [eauto].
rewrite Forall2_map_right. eapply Forall2_impl; [|eassumption].
intros; eauto.
- constructor. eauto.
- rewrite subst_read_env, subst_liftn_closed_at; [|constructor; apply Forall2_length in He; rewrite <- He; assumption].
eapply read_val_clos.
+ rewrite Forall2_map_right. eapply Forall2_impl; [|eassumption].
intros; simpl in *; eauto.
+ apply IHdeep. apply is_remap_ok_cons. assumption.
+ eapply star_compose; [|eapply beta_convertible_subst; eassumption].
apply star_same. symmetry.
rewrite subst_subst. eapply subst_closed_at_ext; [eassumption|].
intros [|n] Hn; unfold lift_subst; simpl; unfold comp; simpl.
* unfold remap_subst. f_equal. unfold remap. simpl. destruct Nat.eq_dec; [reflexivity|tauto].
* unfold read_env; rewrite nth_error_map. destruct nth_error eqn:Hnth.
-- eapply remap_cons_subst_ren; eassumption.
-- simpl. apply nth_error_None in Hnth. apply Forall2_length in He; rewrite He in Hn. lia.
+ assumption.
+ assumption.
+ destruct Hremap as [Hremap1 Hremap2].
intros Hx. eapply Forall_forall in Hremap2; [|eassumption]. destruct Hremap2; [lia|tauto].
+ assumption.
- simpl. eapply read_val_block.
rewrite Forall2_map_right. eapply Forall2_impl; [|apply IHe].
intros v1 t1 IH. apply IH. assumption.
- simpl. rewrite subst_hctx_fill.
replace (subst (remap_subst varmap varmap2) (match index Nat.eq_dec varmap x with Some n => var n | None => dvar x end)) with (match index Nat.eq_dec varmap2 x with Some n => var n | None => dvar x end).
+ eapply read_val_neutral with (tuf := match tuf with None => None | Some tuf => Some (subst (remap_subst varmap varmap2) tuf) end).
* apply IHc. assumption.
* inversion Huf; subst; inversion IHuf; subst; [constructor|].
constructor. split; [apply H4; assumption|].
split; [|tauto].
eapply star_compose; [|eapply beta_convertible_subst; apply H2].
rewrite subst_hctx_fill. apply convertible_fill, star_same.
symmetry; eapply subst_closed_at_id; [apply H2|].
intros n Hn; lia.
* assumption.
* intros Hndef. apply Hin in Hndef. destruct Hremap as [Hremap1 Hremap2].
eapply Forall_forall in Hremap1; eassumption.
+ destruct (index Nat.eq_dec varmap x) as [n|] eqn:Hx; simpl.
* unfold remap_subst, remap. apply nth_error_index in Hx. rewrite Hx.
destruct index eqn:Hx2; [reflexivity|].
eapply index_in_not_None in Hx2; [tauto|].
destruct Hremap as [Hremap1 Hremap2]. eapply Forall_forall in Hremap1; [eassumption|].
eapply nth_error_In in Hx; eassumption.
* rewrite index_notin_None; [reflexivity|].
intros Hx2. destruct Hremap as [Hremap1 Hremap2].
eapply Forall_forall in Hremap2; [|eassumption].
destruct Hremap2 as [Hremap2 | Hremap2]; [lia|].
eapply index_in_not_None in Hx; tauto.
- apply read_cont_kid.
- rewrite subst_hctx_compose.
eapply read_cont_kapp.
+ apply IHv; assumption.
+ apply IHc; assumption.
- rewrite subst_hctx_compose. simpl.
erewrite map_map, map_ext_in; [eapply read_cont_kswitch|].
+ erewrite Forall2_map_right. eapply Forall2_impl; [|apply IHe].
intros v1 t1 IH; apply IH. assumption.
+ apply IHc. assumption.
+ erewrite Forall3_map3 with (f := fun '(vdeeps, tdeep) => _). apply Forall3_combine23_3.
eapply Forall3_impl; [|eapply Forall3_and; [apply Hdeeps|apply IHdeep]].
intros pt vdeeps tdeep [Hdeep IH].
repeat (split; try tauto).
* apply (IH (fst vdeeps ++ varmap2)). apply is_remap_ok_app. assumption.
* eapply star_compose; [|eapply beta_convertible_subst; apply Hdeep].
apply star_same. symmetry. rewrite subst_subst.
eapply subst_closed_at_ext; [apply Hdeep|].
intros n Hn; unfold comp, liftn_subst. destruct le_lt_dec.
-- unfold read_env. rewrite nth_error_map. destruct nth_error eqn:Hnth.
++ rewrite <- !(proj1 Hdeep). eapply remap_app_subst_ren; [|eassumption].
eapply Forall_impl; [|apply Hdeep]. intros; simpl in *; tauto.
++ simpl. apply nth_error_None in Hnth. apply Forall2_length in He; rewrite He in Hn. lia.
-- simpl. unfold remap_subst. f_equal. apply remap_app_1; [lia|apply Hdeep].
* eapply Forall_impl; [|apply Hdeep].
intros x [Hx1 Hx2]; split; [assumption|].
intros Hx3. destruct Hremap as [Hremap1 Hremap2].
eapply Forall_forall in Hremap2; [|eassumption].
destruct Hremap2; [lia|tauto].
+ intros [p t2] Hpt2. simpl. f_equal. rewrite subst_subst.
erewrite subst_ext; [|apply liftn_subst_comp].
eapply Forall3_impl, Forall3_select1, Forall_forall in Hdeeps; [|apply Hpt2|intros ? ? ? (? & ? & ? & Hclosed & ?); exact Hclosed]. simpl in Hdeeps.
eapply subst_closed_at_ext; [eassumption|].
intros n Hn. unfold liftn_subst. destruct le_lt_dec; [|reflexivity].
f_equal. unfold comp. unfold read_env. rewrite nth_error_map.
destruct nth_error eqn:Hnth; [reflexivity|].
eapply nth_error_None in Hnth. apply Forall2_length in He; rewrite He in Hn; lia.
Qed.
Lemma read_extend_varmap_thread :
forall st defs varmap varmap2 a t,
read_thread st defs varmap a t ->
is_remap_ok (
st_freename st)
varmap varmap2 ->
read_thread st defs varmap2 a (
subst (
remap_subst varmap varmap2)
t).
Proof.
intros st defs varmap varmap2 a t H. apply (proj1 (read_extend_varmap_aux st defs)); assumption.
Qed.
Lemma read_extend_varmap_val :
forall st defs varmap varmap2 v t,
read_val st defs varmap v t ->
is_remap_ok (
st_freename st)
varmap varmap2 ->
read_val st defs varmap2 v (
subst (
remap_subst varmap varmap2)
t).
Proof.
intros st defs varmap varmap2 v t H. apply (proj1 (proj2 (read_extend_varmap_aux st defs))); assumption.
Qed.
Lemma read_extend_varmap_cont :
forall st defs varmap varmap2 c h,
read_cont st defs varmap c h ->
is_remap_ok (
st_freename st)
varmap varmap2 ->
read_cont st defs varmap2 c (
subst_hctx (
remap_subst varmap varmap2)
h).
Proof.
intros st defs varmap varmap2 c h H. apply (proj2 (proj2 (read_extend_varmap_aux st defs))); assumption.
Qed.
Lemma prefix_varmap_ok :
forall freename varmap1 varmap2,
Forall (
fun x =>
freename <=
x)
varmap2 ->
is_remap_ok freename varmap1 (
varmap2 ++
varmap1).
Proof.
intros freename varmap1 varmap2 H. split.
- rewrite Forall_forall. intros x Hx; rewrite in_app_iff; tauto.
- rewrite Forall_app. split.
+ eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
+ rewrite Forall_forall. intros x Hx; tauto.
Qed.
Lemma prefix_varmap_remap :
forall freename varmap1 varmap2 n,
Forall (
fun x =>
freename <=
x)
varmap2 ->
Forall (
fun x =>
x <
freename)
varmap1 ->
NoDup varmap1 ->
n <
length varmap1 ->
remap varmap1 (
varmap2 ++
varmap1)
n =
length varmap2 +
n.
Proof.
intros freename varmap1 varmap2 n H2 H1 Hnodup Hn. unfold remap.
destruct nth_error as [x|] eqn:Hx; [|rewrite nth_error_None in Hx; lia].
rewrite index_app, index_notin_None.
- erewrite index_nth_error by eassumption. reflexivity.
- intros Hx2. apply nth_error_In in Hx.
rewrite Forall_forall in H1, H2.
specialize (H2 _ Hx2); specialize (H1 _ Hx). lia.
Qed.
Lemma read_closed_at_aux :
forall st defs,
(
forall varmap a t,
read_thread st defs varmap a t ->
closed_at t (
length varmap)) /\
(
forall varmap v t,
read_val st defs varmap v t ->
closed_at t (
length varmap)) /\
(
forall varmap c h,
read_cont st defs varmap c h ->
forall t,
closed_at t (
length varmap) ->
closed_at (
fill_hctx h t) (
length varmap)).
Proof.
intros st defs. read_ind.
- apply IHc, IHv.
- apply IHc. apply closed_at_subst_read_env.
+ eapply Forall2_select2, Forall2_impl; [|apply IHe].
intros; assumption.
+ eapply closed_at_mono; [|eassumption].
apply Forall2_length in He; lia.
- assumption.
- apply closed_at_subst_read_env.
+ eapply Forall2_select2, Forall2_impl; [|apply IHe].
intros; assumption.
+ constructor.
eapply closed_at_mono; [|eassumption].
apply Forall2_length in He; lia.
- constructor. rewrite <- Forall_forall.
eapply Forall2_select2, Forall2_impl; [|apply IHe].
intros; assumption.
- apply IHc. destruct index eqn:Hidx; [|constructor].
constructor. apply index_length in Hidx. assumption.
- intros t Ht; assumption.
- intros t1 Ht1. rewrite fill_compose. apply IHc.
simpl. constructor; assumption.
- intros t Ht. rewrite fill_compose. apply IHc.
simpl. constructor; [assumption|].
intros p t2 Hpt2; rewrite in_map_iff in Hpt2; destruct Hpt2 as [[p2 t3] [Hpt2 Hpt3]]; injection Hpt2 as Hpt2; subst.
eapply closed_at_subst_read_env_lift.
+ eapply Forall2_select2, Forall2_impl; [|apply IHe].
intros; assumption.
+ eapply Forall3_impl in Hdeeps; [|intros ? ? ? (? & ? & ? & H & ?); exact H].
apply Forall3_select12, Forall2_select1 in Hdeeps. rewrite Forall_forall in Hdeeps; specialize (Hdeeps _ Hpt3).
simpl in Hdeeps. eapply closed_at_mono; [|eassumption].
apply Forall2_length in He; lia.
Qed.
Lemma read_closed_at_thread :
forall st defs varmap a t,
read_thread st defs varmap a t ->
closed_at t (
length varmap).
Proof.
intros st defs. apply (proj1 (read_closed_at_aux st defs)).
Qed.
Lemma read_closed_at_val :
forall st defs varmap v t,
read_val st defs varmap v t ->
closed_at t (
length varmap).
Proof.
intros st defs. apply (proj1 (proj2 (read_closed_at_aux st defs))).
Qed.
Lemma read_prefix_varmap_thread :
forall st defs varmap1 varmap2 a t,
read_thread st defs varmap1 a t ->
Forall (
fun x =>
st_freename st <=
x)
varmap2 ->
Forall (
fun x =>
x <
st_freename st)
varmap1 ->
NoDup varmap1 ->
read_thread st defs (
varmap2 ++
varmap1)
a (
subst (
ren (
plus_ren (
length varmap2)))
t).
Proof.
intros st defs varmap1 varmap2 a t Hread H2 H1 Hnodup.
assert (Hread2 := Hread).
eapply read_extend_varmap_thread in Hread; [|apply prefix_varmap_ok; eassumption].
erewrite subst_closed_at_ext; [eassumption|apply read_closed_at_thread in Hread2; eassumption|].
intros n Hn; simpl. unfold ren, remap_subst. f_equal.
rewrite plus_ren_correct. erewrite prefix_varmap_remap; try eassumption. reflexivity.
Qed.
Lemma read_prefix_varmap_val :
forall st defs varmap1 varmap2 v t,
read_val st defs varmap1 v t ->
Forall (
fun x =>
st_freename st <=
x)
varmap2 ->
Forall (
fun x =>
x <
st_freename st)
varmap1 ->
NoDup varmap1 ->
read_val st defs (
varmap2 ++
varmap1)
v (
subst (
ren (
plus_ren (
length varmap2)))
t).
Proof.
intros st defs varmap1 varmap2 v t Hread H2 H1 Hnodup.
assert (Hread2 := Hread).
eapply read_extend_varmap_val in Hread; [|apply prefix_varmap_ok; eassumption].
erewrite subst_closed_at_ext; [eassumption|apply read_closed_at_val in Hread2; eassumption|].
intros n Hn; simpl. unfold ren, remap_subst. f_equal.
rewrite plus_ren_correct. erewrite prefix_varmap_remap; try eassumption. reflexivity.
Qed.
Lemma read_val_makendeeps_changed :
forall st st2 defs varmap bs e el rid t,
st_freename (
fst (
makendeeps st bs e)) <=
st_freename st2 ->
Forall (
fun pt =>
closed_at (
snd pt) (
fst pt +
length e) /\
no_dvar (
snd pt))
bs ->
read_thread st defs varmap rid t ->
Forall (
fun v =>
forall a,
val_points_to v a ->
points st rid a)
e ->
only_changed (
fst (
makendeeps st bs e))
st2 rid ->
Forall2 (
read_val st defs varmap)
e el ->
length defs <=
st_freename st ->
Forall (
fun x =>
x <
st_freename st)
varmap ->
NoDup varmap ->
Forall2 (
fun pt vdeeps =>
length (
fst vdeeps) =
fst pt /\
read_val st2 defs (
fst vdeeps ++
varmap) (
snd vdeeps) (
subst (
liftn_subst (
fst pt) (
read_env el)) (
snd pt)))
bs (
snd (
makendeeps st bs e)).
Proof.
intros st st2 defs varmap bs. revert st st2.
induction bs as [|[p t2]]; intros st st2 e el rid t Hst12 Hbs H1 H2 H3 H4 H5 Hvarmap1 Hvarmap2; simpl; constructor; simpl.
- split; [apply seq_length|]. constructor.
eapply only_changed_read_thread_ind_1; cycle 1.
+ eapply only_changed_trans; [|eassumption]. simpl.
apply only_extended_changed, only_extended_makendeeps.
+ eapply read_thread_only_extended; [| |eassumption]; [simpl; lia|].
eapply only_extended_trans; [|apply only_extended_makelazy].
intros ? ? ?; assumption.
+ inversion Hbs; subst. rewrite liftn_subst_read_env by (apply Forall2_length in H4; rewrite <- H4; tauto).
eapply read_thread_term with (h := h_hole); [apply nth_error_extend| |apply Forall2_app|constructor|tauto].
* rewrite app_length, map_length, seq_length. tauto.
* rewrite seq_is_shiftn, !Forall2_map_left, Forall2_map_right, Forall2_map_same.
rewrite <- seq_is_shiftn.
rewrite Forall_forall. intros x Hx. rewrite in_seq in Hx.
replace (var x) with (match index Nat.eq_dec (seq (st_freename st) p ++ varmap) (x + st_freename st) with None => dvar (x + st_freename st) | Some n => var n end) by (rewrite index_app, index_seq; [f_equal|]; lia).
eapply read_val_neutral with (h := h_hole); [constructor| |simpl; lia|rewrite in_app_iff, in_seq; lia].
rewrite nth_error_None_rw by lia.
constructor.
* rewrite Forall2_map_right.
eapply Forall2_impl; [|eassumption].
intros; eapply read_val_only_extended;
[| |replace (plus_ren p) with (plus_ren (length (seq (st_freename st) p))) by
(rewrite seq_length; reflexivity); eapply read_prefix_varmap_val]; [| |eassumption| | |].
-- simpl. lia.
-- eapply only_extended_trans; [|apply only_extended_makelazy].
intros ? ? ?; assumption.
-- rewrite Forall_forall. intros u Hu; rewrite in_seq in Hu; lia.
-- assumption.
-- assumption.
+ inversion H1; subst; apply nth_error_Some3 in H; lia.
+ intros a Ha. eapply only_extended_points; [apply only_extended_makelazy|].
unfold points, points_to in Ha. simpl in Ha. rewrite nth_error_extend in Ha; simpl in Ha.
destruct Ha as [Ha | Ha]; inversion Ha; subst.
unfold env_points_to in H7. rewrite Exists_app in H7.
destruct H7 as [H7 | H7]; [rewrite Exists_map, Exists_exists in H7; destruct H7 as (x & H7 & H8); inversion H8; subst; inversion H0|].
eapply Forall_Exists; [|apply H2|eassumption].
intros v H8 H9; apply H8, H9.
+ etransitivity; [|eassumption]. simpl. etransitivity; [|apply makendeeps_freename]. simpl. lia.
- eapply IHbs.
+ assumption.
+ inversion Hbs; subst; assumption.
+ eapply read_thread_only_extended; [| |eassumption]; [simpl; lia|].
eapply only_extended_trans; [|eapply only_extended_makelazy].
intros ? ? ?; assumption.
+ eapply Forall_impl; [|eassumption]. intros v Hv a Ha.
eapply only_extended_points; [|apply Hv, Ha].
eapply only_extended_trans; [|eapply only_extended_makelazy].
intros ? ? ?; assumption.
+ eassumption.
+ eapply Forall2_impl; [|eassumption].
intros v t3 H; eapply read_val_only_extended; [| |eassumption]; [simpl; lia|].
eapply only_extended_trans; [|eapply only_extended_makelazy].
intros ? ? ?; assumption.
+ simpl. lia.
+ eapply Forall_impl; [|eassumption].
intros; simpl in *; lia.
+ assumption.
Qed.
Lemma step_r_freename :
forall st rid,
st_freename st <=
st_freename (
step_r st rid).
Proof.
intros st rid. unfold step_r.
destruct nth_error; [|lia].
destruct rt_code as [t e|v]; [destruct t | destruct v].
- destruct nth_error; simpl; lia.
- lia.
- destruct rt_cont; simpl; lia.
- simpl; lia.
- simpl. apply makenlazy_freename.
- simpl. apply makendeeps_freename.
- destruct is_finished; simpl; lia.
- destruct p as [[x c] uf]. destruct uf; simpl; lia.
- destruct rt_cont; simpl; lia.
- destruct rt_cont; try lia.
destruct nth_error as [[p t]|]; [|lia].
destruct Nat.eq_dec; simpl; lia.
Qed.
Lemma dvar_below_free :
forall k t,
dvar_below k t <-> (
forall x,
k <=
x ->
dvar_free x t).
Proof.
intros k t; split.
- induction t using term_ind2; intros H1; inversion H1; subst; intros x Hx; constructor.
+ lia.
+ apply IHt; assumption.
+ apply IHt1; assumption.
+ apply IHt2; assumption.
+ eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H3]].
simpl; intros t [H4 H5]; apply H4; assumption.
+ apply IHt; assumption.
+ eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H5]].
simpl; intros [p t2] [H6 H7]; apply H6; assumption.
- induction t using term_ind2; intros H1; constructor.
+ specialize (H1 n). destruct (le_lt_dec k n) as [Hkn | Hkn]; [|assumption].
specialize (H1 Hkn); inversion H1. lia.
+ apply IHt. intros x Hx; specialize (H1 x Hx); inversion H1; subst; assumption.
+ apply IHt1. intros x Hx; specialize (H1 x Hx); inversion H1; subst; assumption.
+ apply IHt2. intros x Hx; specialize (H1 x Hx); inversion H1; subst; assumption.
+ eapply Forall_forall. intros t Ht; eapply Forall_forall in H; [|eassumption].
apply H. intros x Hx; specialize (H1 x Hx); inversion H1; subst.
eapply Forall_forall in H2; eassumption.
+ apply IHt. intros x Hx; specialize (H1 x Hx); inversion H1; subst; assumption.
+ eapply Forall_forall. intros [p t2] Hpt2; eapply Forall_forall in H; [|eassumption].
simpl in *. apply H. intros x Hx; specialize (H1 x Hx); inversion H1; subst.
eapply Forall_forall in H4; [|eassumption]. assumption.
Qed.
Lemma dvar_free_ren :
forall x t r,
dvar_free x t ->
dvar_free x (
ren_term r t).
Proof.
intros x t. induction t using term_ind2; intros r Ht; simpl.
- constructor.
- assumption.
- constructor. apply IHt. inversion Ht; subst; assumption.
- constructor; [apply IHt1 | apply IHt2]; inversion Ht; subst; assumption.
- constructor. rewrite Forall_map. inversion Ht; subst.
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H1]].
intros t [H2 H3]; apply H2, H3.
- inversion Ht; subst. constructor; [apply IHt; assumption|].
rewrite Forall_map.
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H3]].
intros [p t2] [H4 H5]; apply H4, H5.
Qed.
Lemma dvar_free_liftn_subst :
forall x us p, (
forall n,
dvar_free x (
us n)) -> (
forall n,
dvar_free x (
liftn_subst p us n)).
Proof.
intros x us p H n. unfold liftn_subst.
destruct le_lt_dec; [|constructor].
apply dvar_free_ren, H.
Qed.
Lemma dvar_free_lift_subst :
forall x us, (
forall n,
dvar_free x (
us n)) -> (
forall n,
dvar_free x (
lift_subst us n)).
Proof.
intros x us H n. rewrite <- liftn_subst_1. apply dvar_free_liftn_subst. assumption.
Qed.
Lemma dvar_below_liftn_subst :
forall k us p, (
forall n,
dvar_below k (
us n)) -> (
forall n,
dvar_below k (
liftn_subst p us n)).
Proof.
intros k us p H n. rewrite dvar_below_free. intros x Hx.
apply dvar_free_liftn_subst. intros n1; eapply dvar_below_free; [|eassumption].
apply H.
Qed.
Lemma dvar_free_subst :
forall x t us, (
forall n,
dvar_free x (
us n)) ->
dvar_free x t ->
dvar_free x (
subst us t).
Proof.
intros x t. induction t using term_ind2; intros us Hus Ht; simpl.
- apply Hus.
- assumption.
- constructor. apply IHt; [|inversion Ht; subst; assumption].
apply dvar_free_lift_subst, Hus.
- constructor; [apply IHt1 | apply IHt2]; inversion Ht; subst; assumption.
- constructor. inversion Ht; subst.
rewrite Forall_map. eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H1]].
intros t [H2 H3]; apply H2, H3; assumption.
- inversion Ht; subst. constructor; [apply IHt; assumption|].
rewrite Forall_map. eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H3]].
intros [p t2] [H4 H5]. simpl. apply H4, H5.
apply dvar_free_liftn_subst, Hus.
Qed.
Lemma dvar_below_subst :
forall k t us, (
forall n,
dvar_below k (
us n)) ->
dvar_below k t ->
dvar_below k (
subst us t).
Proof.
intros k t us Hus Ht. rewrite dvar_below_free. intros x Hx; apply dvar_free_subst.
- intros n; eapply dvar_below_free; [|eassumption]. apply Hus.
- eapply dvar_below_free; eassumption.
Qed.
Lemma dvar_below_no_dvar :
forall t k,
no_dvar t ->
dvar_below k t.
Proof.
intros t k Ht. apply dvar_below_free. intros x Hx. apply Ht.
Qed.
Lemma dvar_free_read_env :
forall x l,
Forall (
dvar_free x)
l -> (
forall n,
dvar_free x (
read_env l n)).
Proof.
intros x l H n. unfold read_env.
destruct nth_error eqn:H1.
- rewrite Forall_forall in H. apply H. eapply nth_error_In; eassumption.
- constructor.
Qed.
Lemma dvar_below_read_env :
forall k l,
Forall (
dvar_below k)
l -> (
forall n,
dvar_below k (
read_env l n)).
Proof.
intros k l H n. unfold read_env.
destruct nth_error eqn:H1.
- rewrite Forall_forall in H. apply H. eapply nth_error_In; eassumption.
- constructor.
Qed.
Lemma makendeeps_dvar_below :
forall l st e,
Forall (
fun vdeep =>
Forall (
fun x =>
st_freename st <=
x) (
fst vdeep)) (
snd (
makendeeps st l e)).
Proof.
intros l; induction l as [|[p t2] l]; intros st e; simpl in *; constructor.
- simpl. rewrite Forall_forall. intros x Hx; rewrite in_seq in Hx. lia.
- eapply Forall_impl; [|apply IHl].
intros [vs v] H; simpl in *. eapply Forall_impl; [|eassumption]. intros; simpl in *; lia.
Qed.
Lemma makendeeps_dvar_above :
forall l st e,
Forall (
fun vdeep =>
Forall (
fun x =>
x <
st_freename (
fst (
makendeeps st l e))) (
fst vdeep)) (
snd (
makendeeps st l e)).
Proof.
intros l; induction l as [|[p t2] l]; intros st e; simpl in *; constructor; simpl.
- rewrite Forall_forall. intros x Hx; rewrite in_seq in Hx.
eapply lt_le_trans; [|apply makendeeps_freename]. simpl. lia.
- apply IHl.
Qed.
Lemma makendeeps_dvar_nodup :
forall l st e,
Forall (
fun vdeep =>
NoDup (
fst vdeep)) (
snd (
makendeeps st l e)).
Proof.
intros l; induction l as [|[p t2] l]; intros st e; simpl in *; constructor; simpl.
- apply seq_NoDup.
- apply IHl.
Qed.
Lemma makenlazy_new_threads :
forall st ts e rid,
nth_error (
st_rthreads st)
rid =
None ->
nth_error (
st_rthreads (
fst (
makenlazy st ts e)))
rid <>
None ->
In (
Thread rid) (
snd (
makenlazy st ts e)).
Proof.
intros st ts e rid; revert st; induction ts as [|t ts]; intros st Hrid1 Hrid2; simpl in *.
- tauto.
- destruct (nth_error (st_rthreads (extend_rthread st {| rt_code := Term t e; rt_cont := Kid |})) rid) eqn:Hrid3.
+ simpl in Hrid3. rewrite nth_error_app2 in Hrid3; [|rewrite nth_error_None in Hrid1; assumption].
remember (rid - length (st_rthreads st)) as n.
destruct n; [|destruct n; simpl in *; congruence]. simpl in Hrid3. injection Hrid3 as Hrid3; subst.
assert (rid = length (st_rthreads st)) by (rewrite nth_error_None in Hrid1; lia). subst.
tauto.
+ right. apply IHts; assumption.
Qed.
Lemma makendeeps_new_threads :
forall st l e rid,
nth_error (
st_rthreads st)
rid =
None ->
nth_error (
st_rthreads (
fst (
makendeeps st l e)))
rid <>
None ->
exists vs,
NoDup vs /\
Forall (
fun v =>
st_freename st <=
v <
st_freename (
fst (
makendeeps st l e)))
vs /\
In (
vs,
Thread rid) (
snd (
makendeeps st l e)).
Proof.
intros st l e rid; revert st; induction l as [|[p t2] l]; intros st Hrid1 Hrid2; simpl in *.
- tauto.
- match goal with [ |- context[ extend_rthread ?st ?t ] ] =>
destruct (nth_error (st_rthreads (extend_rthread st t)) rid) eqn:Hrid3 end.
+ simpl in Hrid3. rewrite nth_error_app2 in Hrid3; [|rewrite nth_error_None in Hrid1; assumption].
remember (rid - length (st_rthreads st)) as n.
destruct n; [|destruct n; simpl in *; congruence]. simpl in Hrid3. injection Hrid3 as Hrid3; subst.
assert (rid = length (st_rthreads st)) by (rewrite nth_error_None in Hrid1; lia). subst.
eexists. repeat split; [apply seq_NoDup| |left; reflexivity].
rewrite Forall_forall. intros x Hx; rewrite in_seq in Hx.
split; [lia|]. eapply lt_le_trans; [|apply makendeeps_freename]. simpl. lia.
+ destruct (IHl _ Hrid3) as (vs & Hvs1 & Hvs2 & Hvs3); [assumption|].
exists vs. repeat split; [assumption| |right; assumption].
eapply Forall_impl; [|eassumption]. intros; simpl in *; lia.
Qed.
Definition varmap_ok freename varmap :=
Forall (
fun x =>
x <
freename)
varmap /\
NoDup varmap.
Lemma varmap_ok_cons :
forall freename varmap x,
varmap_ok freename varmap ->
x <
freename ->
x \
notin varmap ->
varmap_ok freename (
x ::
varmap).
Proof.
intros freename varmap x [H1 H2] H3 H4; split; constructor; assumption.
Qed.
Lemma varmap_ok_app :
forall freename varmap varmap2,
varmap_ok freename varmap ->
Forall (
fun x =>
x <
freename /\
x \
notin varmap)
varmap2 ->
NoDup varmap2 ->
varmap_ok freename (
varmap2 ++
varmap).
Proof.
intros freename varmap varmap2 Hok Hvarmap2 Hnodup. split.
- rewrite Forall_app; split; [|apply Hok].
eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
- apply NoDup_app; [assumption|apply Hok|].
eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
Qed.
Lemma step_r_beta_hnf :
forall st st2 defs varmap rid t,
defs_ok defs st ->
Forall (
fun x =>
x <
st_freename st)
varmap ->
NoDup varmap ->
step_r st rid =
st2 ->
read_thread st defs varmap rid t ->
same_read_plus st st2 defs rid /\
(
forall rid2,
nth_error (
st_rthreads st)
rid2 =
None ->
nth_error (
st_rthreads st2)
rid2 <>
None ->
exists t2 varmap2,
varmap_ok (
st_freename st2)
varmap2 /\
read_thread st2 defs varmap2 rid2 t2) /\
exists t2,
read_thread st2 defs varmap rid t2 /\
reflc beta_hnf t t2.
Proof.
intros st st2 defs varmap rid t Hdefsok Hvarmap1 Hvarmap2 <- Hread.
match goal with [ |- ?G1 /\ ?G2 /\ ?G3 ] =>
assert (Hsame : every_reachable st rid (fun a => forall varmap2 t, read_thread st defs varmap2 a t -> read_thread (step_r st rid) defs varmap2 a t) -> G2 -> G1 /\ G2 /\ G3) end.
{
intros H Hnew. rewrite every_reachable_iff in H; destruct H as [H1 H2].
split; [apply H2|]. split; [assumption|]. eexists; split; [|right; reflexivity]. apply H1, Hread.
}
match goal with [ |- ?G ] => assert (Hid : step_r st rid = st -> G) end.
{
intros Heq; rewrite Heq in *. apply Hsame; [intros ? ? ? ? ?; assumption|].
intros; congruence.
}
assert (Hfree := step_r_freename st rid).
unfold step_r in *.
inversion Hread; subst.
- rewrite H in *; simpl in *.
inversion H0; subst.
+ destruct is_finished eqn:Hfinished; [|apply Hid; reflexivity].
and_left as Hreach; [eapply same_read_update; eassumption|].
unfold is_finished in Hfinished.
inversion H2; subst; rewrite H3 in Hfinished; simpl in *; [|congruence].
inversion H5; simpl in *; subst; simpl in *; try congruence.
injection Hfinished as Hfinished; subst.
split; [intros rid2 Hrid2a Hrid2b; rewrite nth_error_update_None in Hrid2b; tauto|].
eexists. split; [|right; reflexivity].
eapply read_thread_val; [eapply nth_error_update; eassumption| |].
* eapply same_read_plus_val; [eassumption|eassumption|eassumption|].
intros a Ha. eapply plus_S; [|apply plus_1]; unfold points, points_to.
-- rewrite H. left. constructor. constructor.
-- rewrite H3. left. constructor. assumption.
* eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to. rewrite H. right. assumption.
+ inversion H1; subst; try (apply Hid; reflexivity).
and_left as Hreach; [eapply same_read_update; eassumption|].
split; [simpl; intros rid2 Hrid2a Hrid2b; rewrite nth_error_update_None in Hrid2b; tauto|].
eexists; split; [|left; rewrite fill_compose; simpl; apply beta_hnf_ctx, beta_hnf_red, beta_red_lam].
unfold subst1, lift_subst. rewrite subst_subst.
erewrite subst_ext; [eapply read_thread_term|].
* eapply nth_error_update; eassumption.
* simpl. assumption.
* constructor.
-- eapply same_read_plus_val_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; right; apply kapp_points_to_1, Ha.
-- eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; left; constructor; apply clos_points_to_1.
apply Exists_exists; eexists; split; eassumption.
* eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; right; apply kapp_points_to_2, Ha.
* assumption.
* intros [|n]; unfold comp; simpl; [rewrite read_env_0; reflexivity|].
rewrite read_env_S. rewrite subst_ren.
erewrite subst_ext; [apply subst_id|].
intros n2; unfold comp; simpl. destruct n2; reflexivity.
+ destruct c; try (apply Hid; reflexivity).
destruct (nth_error l tag) as [[p t]|] eqn:Hpt; [|apply Hid; reflexivity].
destruct Nat.eq_dec; [|apply Hid; reflexivity].
and_left as Hreach; [eapply same_read_update; eassumption|].
inversion H1; subst. rewrite fill_compose; simpl.
split; [intros rid2 Hrid2a Hrid2b; rewrite nth_error_update_None in Hrid2b; tauto|].
eexists; split; cycle 1.
{
left. apply beta_hnf_ctx, beta_hnf_red.
apply nth_error_decompose in Hpt; destruct Hpt as (l2 & l3 & Hpt1 & Hpt2); rewrite Hpt1, <- Hpt2.
erewrite map_app, <- map_length. simpl.
replace (length e) with (length el) by (apply Forall2_length in H2; symmetry; assumption).
apply beta_red_switch.
}
erewrite subst_subst, <- subst_ext; [|apply read_env_app].
eapply read_thread_term; [eapply nth_error_update; eassumption| |apply Forall2_app| |].
* eapply Forall3_impl in H11; [|intros ? ? ? (? & ? & ? & Hclosed & ?); exact Hclosed].
apply Forall3_select12, Forall2_select1 in H11. rewrite Forall_forall in H11.
rewrite app_length. apply nth_error_In, H11 in Hpt. assumption.
* eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; left; constructor; apply block_points_to.
apply Exists_exists; eexists; split; eassumption.
* eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; right. apply kswitch_points_to_1.
apply Exists_exists; eexists; split; eassumption.
* eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; right. apply kswitch_points_to_3. assumption.
* eapply Forall3_impl, Forall3_select12, Forall2_select1 in H11; [|intros ? ? ? (? & ? & ? & ? & ? & ? & Hdv); exact Hdv].
eapply Forall_forall in H11; [|eapply nth_error_In; eassumption]. assumption.
+ and_left as Hreach.
{
destruct uf as [uf|]; simpl in *; [|eapply same_read_update; eassumption].
eapply same_read_unchanged; [simpl; lia|].
dedup common; [eapply unchanged_from_plus_trans; [|eapply unchanged_from_plus_update, read_thread_same; [|eapply Hread|]; [simpl; lia|]]; exact common|].
eapply unchanged_from_extend; eassumption.
}
inversion H3; subst.
* split; [intros rid2 Hrid2a Hrid2b; unfold exit_rthread in Hrid2b; simpl in *; rewrite nth_error_update_None in Hrid2b; tauto|].
eexists; split; [|right; reflexivity].
eapply read_thread_val with (h := h_hole); [eapply nth_error_update; eassumption| |constructor].
rewrite <- fill_compose.
econstructor.
-- apply compose_cont_ctx; eapply same_read_plus_cont_1; try eassumption;
intros a Ha; unfold points, points_to; rewrite H;
(left; constructor; constructor; assumption) || (right; assumption).
-- rewrite <- H9. constructor.
-- simpl. assumption.
-- simpl. assumption.
* refine ((fun (Hreadnew : read_thread _ _ varmap (length (st_rthreads st)) _) => _) _).
-- split. {
intros rid2 Hrid2a Hrid2b. unfold exit_rthread in Hrid2b; simpl in Hrid2b.
rewrite nth_error_update3 in Hrid2b by congruence.
rewrite nth_error_app2 in Hrid2b by (rewrite nth_error_None in Hrid2a; assumption).
destruct (rid2 - length (st_rthreads st)) as [|n] eqn:Hr; simpl in *; [|destruct n; simpl in *; congruence].
assert (rid2 = length (st_rthreads st)) by (rewrite nth_error_None in Hrid2a; lia). subst.
eexists. eexists. split; [|apply Hreadnew].
split; assumption.
}
eexists; split; [|right; reflexivity].
eapply read_thread_val with (h := h_hole);
[eapply nth_error_update; eapply nth_error_app_Some; eassumption| |constructor].
rewrite <- fill_compose.
econstructor;
try (apply compose_cont_ctx; eapply same_read_plus_cont_1; try eassumption;
intros a Ha; unfold points, points_to; rewrite H;
(left; constructor; constructor; assumption) || (right; assumption));
try (simpl; assumption).
rewrite <- H6. constructor.
split; [|split; [rewrite fill_compose; apply convertible_fill, H9|tauto]].
apply read_val_thread. apply Hreadnew.
-- eapply read_thread_val.
++ unfold exit_rthread; simpl. rewrite nth_error_update3; [apply nth_error_extend|].
apply nth_error_Some3 in H; lia.
++ eapply same_read_plus_val_1; [eassumption|eassumption|apply H9|].
intros a Ha; unfold points, points_to. rewrite H; left; constructor.
eapply neutral_points_to_2; [reflexivity|eassumption].
++ eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to. rewrite H; right; assumption.
- rewrite H in *; cbv beta delta [rt_code] iota in *.
destruct t0; cbv delta [rt_code rt_cont] iota in *.
+ destruct (nth_error e n) eqn:He; [|apply Hid; reflexivity].
and_left as Hreach; [eapply same_read_update; eassumption|].
split; [simpl; intros rid2 Hrid2a Hrid2b; rewrite nth_error_update_None in Hrid2b; tauto|].
eexists; split; [|right; reflexivity].
econstructor.
* eapply nth_error_update; eassumption.
* simpl.
eapply nth_error_Forall2 in H1; [|eassumption].
destruct H1 as (vv & Hvv1 & Hvv2). unfold read_env; rewrite Hvv1.
eapply same_read_plus_val_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to. rewrite H; left; constructor.
apply Exists_exists; eexists; split; [eapply nth_error_In|]; eassumption.
* eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to. rewrite H; right; assumption.
+ apply Hid. reflexivity.
+ destruct c.
* and_left as Hreach. {
eapply same_read_unchanged; [eassumption|].
dedup common; [eapply unchanged_from_plus_trans;
[|eapply unchanged_from_plus_update, read_thread_same; [|eapply Hread|]; [simpl; lia|]]; exact common|].
dedup common; [eapply unchanged_from_trans;
[|eapply unchanged_from_makelazy, read_thread_same; [|eapply Hread|]; [simpl; lia|]]; exact common|].
eapply unchanged_from_freevar.
}
match goal with [ Hreach : same_read_plus st ?st2 defs rid |- _ ] =>
refine ((fun (Hreadnew : read_thread st2 defs (st_freename st :: varmap) (length (st_rthreads st)) _) => _) _) end; cycle 1.
{
eapply read_thread_term.
-- unfold exit_rthread; simpl. rewrite nth_error_update3; [apply nth_error_extend|].
apply nth_error_Some3 in H; lia.
-- simpl. inversion H0; assumption.
-- constructor.
++ eapply read_val_neutral; [constructor| |simpl; lia|simpl; tauto].
rewrite nth_error_None_rw; [|apply Hdefsok]. constructor.
++ eapply same_read_plus_val_Forall2_1; [eassumption|eassumption| |].
** rewrite Forall2_map_right. eapply Forall2_impl; [|eassumption].
intros v t Hvt. eapply read_prefix_varmap_val with (varmap2 := st_freename st :: nil); try eassumption.
constructor; [lia|]. constructor.
** intros a Ha; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
-- constructor.
-- intros x; specialize (H3 x); inversion H3; assumption.
}
split. {
intros rid2 Hrid2a Hrid2b. unfold exit_rthread in Hrid2b; simpl in Hrid2b.
rewrite nth_error_update3 in Hrid2b by congruence.
rewrite nth_error_app2 in Hrid2b by (rewrite nth_error_None in Hrid2a; assumption).
destruct (rid2 - length (st_rthreads st)) as [|n] eqn:Hr; simpl in *; [|destruct n; simpl in *; congruence].
assert (rid2 = length (st_rthreads st)) by (rewrite nth_error_None in Hrid2a; lia). subst.
eexists. eexists. split; [|apply Hreadnew].
apply varmap_ok_cons; [split; [eapply Forall_impl; [|eassumption]; intros; simpl in *; lia|assumption]|lia|].
intros Hin. rewrite Forall_forall in Hvarmap1. apply Hvarmap1 in Hin. lia.
}
eexists; split; [|right; reflexivity].
simpl. eapply read_thread_val.
-- eapply nth_error_update, nth_error_app_Some; eassumption.
-- eapply read_val_clos.
++ eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
++ apply read_val_thread, Hreadnew.
++ simpl index. destruct Nat.eq_dec; [|tauto]. simpl.
apply star_same. erewrite subst_ext; [|symmetry; apply liftn_subst_1].
apply liftn_subst_read_env. inversion H0; subst. eapply Forall2_length in H1. rewrite <- H1; assumption.
++ intros x; specialize (H3 x); inversion H3; assumption.
++ simpl. unfold defs_ok in Hdefsok. lia.
++ intros Hin. rewrite Forall_forall in Hvarmap1. apply Hvarmap1 in Hin. lia.
++ inversion H0; subst; assumption.
-- inversion H2; subst. constructor.
* and_left as Hreach; [eapply same_read_update; eassumption|].
inversion H2; subst; simpl in *.
split; [simpl; intros rid2 Hrid2a Hrid2b; rewrite nth_error_update_None in Hrid2b; tauto|].
eexists; split; [|left; rewrite fill_compose; simpl; apply beta_hnf_ctx, beta_hnf_red, beta_red_lam].
unfold subst1, lift_subst. rewrite subst_subst.
erewrite subst_ext; [eapply read_thread_term|].
-- eapply nth_error_update; eassumption.
-- inversion H0; subst. assumption.
-- constructor.
++ eapply same_read_plus_val_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H. right; constructor; assumption.
++ eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
-- eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H. right; constructor; assumption.
-- intros x; specialize (H3 x); inversion H3; subst; assumption.
-- intros [|n]; unfold comp; simpl; [rewrite read_env_0; reflexivity|].
rewrite read_env_S. rewrite subst_ren.
erewrite subst_ext; [apply subst_id|].
intros n2; unfold comp; simpl. destruct n2; reflexivity.
* apply Hid; reflexivity.
+ and_left as Hreach. {
eapply same_read_unchanged; [assumption|].
dedup common; [eapply unchanged_from_plus_trans;
[|eapply unchanged_from_plus_update, read_thread_same; [|eapply Hread|]; [simpl; lia|]]; exact common|].
eapply unchanged_from_makelazy; eassumption.
}
match goal with [ Hreach : same_read_plus st ?st2 defs rid |- _ ] =>
refine ((fun (Hreadnew : read_thread st2 defs varmap (length (st_rthreads st)) _) => _) _) end; cycle 1.
{
eapply read_thread_term; simpl.
* rewrite nth_error_update3 by (apply nth_error_Some3 in H; lia).
apply nth_error_extend.
* inversion H0; subst; assumption.
* eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
* constructor.
* intros x; specialize (H3 x); inversion H3; subst; assumption.
}
split.
{
intros rid2 Hrid2a Hrid2b. unfold exit_rthread in Hrid2b; simpl in Hrid2b.
rewrite nth_error_update3 in Hrid2b by congruence.
rewrite nth_error_app2 in Hrid2b by (rewrite nth_error_None in Hrid2a; assumption).
destruct (rid2 - length (st_rthreads st)) as [|n] eqn:Hr; simpl in *; [|destruct n; simpl in *; congruence].
assert (rid2 = length (st_rthreads st)) by (rewrite nth_error_None in Hrid2a; lia). subst.
eexists. eexists. split; [|apply Hreadnew]. split; assumption.
}
eexists. split.
* eapply read_thread_term; [eapply nth_error_update, nth_error_app_Some; eassumption| | | |].
-- inversion H0; subst; assumption.
-- eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
-- constructor.
++ eapply read_val_thread. apply Hreadnew.
++ eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H. right; assumption.
-- intros x; specialize (H3 x); inversion H3; subst; assumption.
* right. rewrite fill_compose. reflexivity.
+ and_left as Hreach. {
eapply same_read_unchanged; [assumption|].
dedup common; [eapply unchanged_from_plus_trans;
[|eapply unchanged_from_plus_update, read_thread_same; [apply makenlazy_freename|eapply Hread|]]; exact common|].
eapply unchanged_from_only_extended; [eassumption|].
apply only_extended_makenlazy.
}
and_right; cycle 1.
* eexists; split; [|right; reflexivity].
eapply read_thread_val.
-- eapply nth_error_update, only_extended_makenlazy; eassumption.
-- simpl. constructor. eapply read_val_makenlazy_changed.
++ eassumption.
++ eapply Forall_forall. intros t Ht x; specialize (H3 x); inversion H3; subst; eapply Forall_forall; eassumption.
++ inversion H0; subst. rewrite Forall_forall. assumption.
++ eassumption.
++ eapply Forall_forall. intros v Hv a Ha.
unfold points, points_to. rewrite H. simpl. left. constructor.
eapply Exists_exists; eexists; split; eassumption.
++ eapply only_changed_update.
++ eassumption.
-- eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; right; assumption.
* intros (t2 & Ht2 & _).
inversion Ht2; subst; simpl in *; erewrite nth_error_update in H4;
try (eapply only_extended_makenlazy; eassumption); try congruence; injection H4 as H4; subst.
inversion H5; subst.
intros rid2 Hrid2a Hrid2b.
rewrite nth_error_update3 in Hrid2b by congruence.
apply makenlazy_new_threads in Hrid2b; [|eassumption].
eapply Forall2_In_left_transparent; [|eassumption|eassumption].
intros t Ht. exists t. exists varmap. inversion Ht; subst. split; [|assumption].
split; [|eassumption]. eapply Forall_impl; [|eassumption].
intros; simpl in *. eapply lt_le_trans; [eassumption|].
apply makenlazy_freename.
+ and_left as Hreach. {
eapply same_read_unchanged; [assumption|]. eapply unchanged_from_plus_only_changed; [eassumption|].
eapply only_changed_trans; [|eapply only_changed_update].
apply only_extended_changed, only_extended_makendeeps.
}
and_right.
{
intros (t2 & Ht2 & _).
inversion Ht2; subst; simpl in *; erewrite nth_error_update in H4;
try (eapply only_extended_makendeeps; eassumption); try congruence. injection H4 as H4; subst.
inversion H7; subst.
intros rid2 Hrid2a Hrid2b.
rewrite nth_error_update3 in Hrid2b by congruence.
apply makendeeps_new_threads in Hrid2b; [|eassumption].
destruct Hrid2b as (vs & Hvs1 & Hvs2 & Hvs3).
eapply Forall3_impl, Forall3_select23 in H16; [|intros pt vdeeps tdeep (_ & Hreaddeep & _); exact Hreaddeep].
eapply Forall2_In_left_transparent; [|apply H16|apply Hvs3].
intros t3 Ht3. inversion Ht3; subst. eexists; eexists. split; [|eassumption].
apply varmap_ok_app.
* split; [|assumption]. eapply Forall_impl; [|eassumption].
intros; simpl in *. eapply lt_le_trans; [|apply makendeeps_freename]. assumption.
* eapply Forall_impl; [|eassumption]. intros x Hx; simpl in *; split; [tauto|].
intros Hx2. rewrite Forall_forall in Hvarmap1. apply Hvarmap1 in Hx2. lia.
* assumption.
}
eexists; split; [|right; reflexivity].
simpl.
refine (eq_rect _ (read_thread _ _ _ _) _ _ _); [|apply fill_compose with (h2 := h_switch h_hole _)].
eapply read_thread_term.
* simpl. erewrite nth_error_update; [reflexivity|].
eapply only_extended_makendeeps; eassumption.
* inversion H0; subst; assumption.
* eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros v a Ha1 Ha2; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
* erewrite map_ext; [econstructor|].
-- eapply same_read_plus_val_Forall2_1; [eassumption|eassumption|eassumption|].
intros v a Ha1 Ha2; unfold points, points_to; rewrite H; left; constructor.
apply Exists_exists; eexists; split; eassumption.
-- eapply same_read_plus_cont_1; [eassumption|eassumption|eassumption|].
intros a Ha; unfold points, points_to; rewrite H; right; assumption.
-- eapply Forall3_map3 with (f := fun '(pt, vdeeps) => _).
eapply Forall2_select12combine.
eapply Forall2_impl; [|eapply Forall2_and_Forall_left; [eapply Forall2_and_Forall_right; [eapply read_val_makendeeps_changed|]|]].
++ simpl. intros pt2 vdeeps [[[Hlen Hreadval] Hdeeps] Hpt2].
repeat split; cycle 2.
** apply star_refl.
** eapply (proj1 Hpt2).
** eapply (proj1 Hdeeps).
** eapply (proj2 Hdeeps).
** eapply (proj2 Hpt2).
** apply Hlen.
** eapply Hreadval.
++ simpl. lia.
++ rewrite Forall_forall. intros pt Hpt.
split.
** inversion H0; subst. apply H8. destruct pt; assumption.
** intros x. specialize (H3 x); inversion H3; subst.
rewrite Forall_forall in H7. apply H7; eassumption.
++ eassumption.
++ eapply Forall_forall; intros v Hv a Ha.
unfold points, points_to. rewrite H. left. constructor.
eapply Exists_exists; eexists; split; eassumption.
++ eapply only_changed_update.
++ assumption.
++ apply Hdefsok.
++ assumption.
++ assumption.
++ apply -> Forall_and; split; [|apply makendeeps_dvar_nodup].
eapply Forall_impl; [|rewrite <- Forall_and; split; [apply makendeeps_dvar_below|apply makendeeps_dvar_above]].
intros [vs v] [Hvs1 Hvs2]; simpl in *.
apply -> Forall_and; split; [apply -> Forall_and; split; [|assumption]|].
** eapply Forall_impl; [|apply Hvs1]. intros x Hx; unfold defs_ok in Hdefsok; simpl in *; lia.
** eapply Forall_impl; [|apply Hvs1]. intros x Hx1 Hx2.
rewrite Forall_forall in Hvarmap1; apply Hvarmap1 in Hx2. simpl in *; lia.
++ eapply Forall_forall. intros [p t2] Hpt2.
split.
** inversion H0; subst. apply H8. assumption.
** intros x. specialize (H3 x); inversion H3; subst.
rewrite Forall_forall in H7. apply H7; assumption.
-- intros [p t2]; simpl; reflexivity.
* intros x; specialize (H3 x); inversion H3; subst; assumption.
Qed.
Lemma beta_hctx :
forall h t1 t2,
beta t1 t2 ->
beta (
fill_hctx h t1) (
fill_hctx h t2).
Proof.
induction h; intros t1 t2 Hbeta.
- assumption.
- simpl. constructor. apply IHh; assumption.
- simpl. constructor. apply IHh; assumption.
Qed.
Lemma star_beta_hctx :
forall h t1 t2,
star beta t1 t2 ->
star beta (
fill_hctx h t1) (
fill_hctx h t2).
Proof.
intros h t1 t2 H. eapply star_map_impl with (f := fun t => fill_hctx h t); [|eassumption].
apply beta_hctx.
Qed.
Lemma star_beta_read_env :
forall e1 e2,
Forall2 (
star beta)
e1 e2 ->
forall n,
star beta (
read_env e1 n) (
read_env e2 n).
Proof.
intros e1 e2 H n. unfold read_env.
destruct (nth_error e1 n) eqn:Hn.
* eapply nth_error_Forall2 in Hn; [|eassumption].
destruct Hn as (? & -> & Hn). assumption.
* replace (nth_error e2 n) with (@None term) by (symmetry; apply (nth_error_Forall2_None H); assumption).
apply Forall2_length in H. rewrite H. constructor.
Qed.
Lemma read_inj_aux :
forall st defs, (
forall varmap a t,
read_thread st defs varmap a t ->
forall t2,
read_thread st defs varmap a t2 ->
t =
t2) /\
(
forall varmap v t,
read_val st defs varmap v t ->
forall t2,
read_val st defs varmap v t2 ->
t =
t2) /\
(
forall varmap c h,
read_cont st defs varmap c h ->
forall h2,
read_cont st defs varmap c h2 ->
h =
h2).
Proof.
intros st defs. read_ind.
- intros t2 Ht2. inversion Ht2; subst; try congruence.
assert (v0 = v) by congruence; subst.
assert (c0 = c) by congruence; subst.
f_equal; [apply IHc|apply IHv]; assumption.
- intros t2 Ht2. inversion Ht2; subst; try congruence.
assert (t0 = t) by congruence; subst.
assert (e0 = e) by congruence; subst.
assert (c0 = c) by congruence; subst.
f_equal; [apply IHc; assumption|].
f_equal. f_equal.
assert (Heq := Forall3_from_Forall2 _ _ _ _ _ _ _ _ IHe H1).
eapply Forall3_impl in Heq; [|intros v t1 t2 [IH Hread]; apply IH, Hread].
apply Forall3_select23, Forall2_eq in Heq. assumption.
- intros t2 Ht2; inversion Ht2; subst.
apply IH; assumption.
- intros t2 Ht2. inversion Ht2; subst.
assert (Heq := Forall3_from_Forall2 _ _ _ _ _ _ _ _ IHe H3).
eapply Forall3_impl in Heq; [|intros v t1 t2 [IH Hread]; apply IH, Hread].
apply Forall3_select23, Forall2_eq in Heq. congruence.
- intros t2 Ht2. inversion Ht2; subst.
assert (Heq := Forall3_from_Forall2 _ _ _ _ _ _ _ _ IHe H3).
eapply Forall3_impl in Heq; [|intros v t1 t2 [IH Hread]; apply IH, Hread].
apply Forall3_select23, Forall2_eq in Heq. congruence.
- intros t2 Ht2. inversion Ht2; subst. f_equal.
apply IHc. assumption.
- intros h2 H; inversion H; reflexivity.
- intros h2 H. inversion H; subst.
f_equal; [apply IHc; assumption|].
f_equal. apply IHv; assumption.
- intros h2 H. inversion H; subst.
f_equal; [apply IHc; assumption|].
assert (Heq := Forall3_from_Forall2 _ _ _ _ _ _ _ _ IHe H6).
eapply Forall3_impl in Heq; [|intros v t1 t2 [IH Hread]; apply IH, Hread].
apply Forall3_select23, Forall2_eq in Heq. subst. reflexivity.
Qed.
Lemma read_inj_thread :
forall st defs varmap a t1 t2,
read_thread st defs varmap a t1 ->
read_thread st defs varmap a t2 ->
t1 =
t2.
Proof.
intros st defs varmap a t1 t2 H1 H2. eapply (proj1 (read_inj_aux st defs)); eassumption.
Qed.
Lemma dvar_free_beta :
forall x t1 t2,
beta t1 t2 ->
dvar_free x t1 ->
dvar_free x t2.
Proof.
intros x t1 t2 H; induction H; intros Hdv.
- inversion Hdv; subst. constructor; tauto.
- inversion Hdv; subst. constructor; tauto.
- inversion Hdv; subst. constructor; tauto.
- inversion Hdv; subst. inversion H1; subst. apply dvar_free_subst; [|assumption].
intros [|n]; simpl; [assumption|constructor].
- inversion Hdv; subst. constructor.
rewrite Forall_app_iff, Forall_cons_iff in *. tauto.
- inversion Hdv; subst. constructor; tauto.
- inversion Hdv; subst. constructor; [assumption|].
rewrite Forall_app_iff, Forall_cons_iff in *. simpl in *; tauto.
- inversion Hdv; subst. rewrite Forall_app_iff, Forall_cons_iff in H2. simpl in *.
apply dvar_free_subst; [|tauto].
apply dvar_free_read_env.
inversion H1; subst. assumption.
Qed.
Lemma dvar_free_star_beta :
forall x t1 t2,
star beta t1 t2 ->
dvar_free x t1 ->
dvar_free x t2.
Proof.
intros. eapply star_preserve; [|eassumption|eassumption].
apply dvar_free_beta.
Qed.
Lemma stable_beta_hnf_aux :
forall st st2 defs rid,
st_freename st <=
st_freename st2 ->
same_read_plus st st2 defs rid ->
only_changed st st2 rid ->
(
forall varmap t,
varmap_ok (
st_freename st)
varmap ->
read_thread st defs varmap rid t ->
exists t2,
read_thread st2 defs varmap rid t2 /\
reflc beta_hnf t t2) ->
(
forall varmap2 rid2 t,
read_thread st defs varmap2 rid2 t ->
varmap_ok (
st_freename st)
varmap2 ->
exists t2,
read_thread st2 defs varmap2 rid2 t2 /\
star beta t t2) /\
(
forall varmap2 v t,
read_val st defs varmap2 v t ->
varmap_ok (
st_freename st)
varmap2 ->
exists t2,
read_val st2 defs varmap2 v t2 /\
star beta t t2) /\
(
forall varmap2 c h,
read_cont st defs varmap2 c h ->
varmap_ok (
st_freename st)
varmap2 ->
exists h2,
read_cont st2 defs varmap2 c h2 /\ (
forall t,
star beta (
fill_hctx h t) (
fill_hctx h2 t))).
Proof.
intros st st2 defs rid2 Hst12 Hsame Honly Hred.
read_ind; intros Hvok.
- destruct (Nat.eq_dec rid2 rid).
{
subst.
assert (Hread : read_thread st defs varmap rid (fill_hctx h t)) by (eapply read_thread_val; eassumption).
apply Hred in Hread; [|assumption].
destruct Hread as (t2 & Ht2a & Ht2b); exists t2; split; [assumption|].
destruct Ht2b; [|subst; constructor]. apply star_1, beta_hnf_beta, H.
}
destruct IHv as (t2 & IHv1 & IHv2); [assumption|].
destruct IHc as (h2 & IHc1 & IHc2); [assumption|].
exists (fill_hctx h2 t2).
split.
+ apply Honly in Hnth; [|assumption].
eapply read_thread_val; eassumption.
+ eapply star_compose; [apply IHc2|].
apply star_beta_hctx. assumption.
- destruct (Nat.eq_dec rid2 rid).
{
subst.
assert (Hread : read_thread st defs varmap rid (fill_hctx h (subst (read_env el) t))) by
(eapply read_thread_term; eassumption).
apply Hred in Hread; [|assumption].
destruct Hread as (t2 & Ht2a & Ht2b); exists t2; split; [assumption|].
destruct Ht2b; [|subst; constructor]. apply star_1, beta_hnf_beta, H.
}
destruct IHc as (h2 & IHc1 & IHc2); [assumption|].
eapply Forall2_impl in IHe; [|intros ? ? IH; exact (IH Hvok)].
apply Forall2_exists_Forall3 in IHe. destruct IHe as (el2 & IHe).
exists (fill_hctx h2 (subst (read_env el2) t)).
split.
+ apply Honly in Hnth; [|assumption].
eapply read_thread_term; try eassumption.
eapply Forall3_select13, Forall3_impl, IHe. intros; simpl in *; tauto.
+ eapply star_compose; [apply IHc2|].
apply star_beta_hctx. apply beta_subst2.
apply star_beta_read_env.
eapply Forall3_select23, Forall3_impl, IHe. intros; simpl in *; tauto.
- destruct IH as (t2 & IH1 & IH2); [assumption|].
exists t2. split; [|assumption]. constructor. assumption.
- eapply Forall2_impl in IHe; [|intros ? ? IH; exact (IH Hvok)].
eapply Forall2_exists_Forall3 in IHe. destruct IHe as (el2 & IHe).
destruct IHdeep as (tdeep2 & IHdeep1 & IHdeep2); [apply varmap_ok_cons; tauto|].
exists (subst (read_env el2) (abs t)). split.
+ eapply read_val_clos; try eassumption.
* eapply Forall3_select13, Forall3_impl, IHe; intros; simpl in *; tauto.
* eapply star_compose; [|eapply star_impl; [|eassumption]; intros; left; assumption].
eapply star_compose; [|eassumption]. eapply convertible_sym. eapply star_impl; [intros ? ? H; left; exact H|].
eapply beta_subst2. intros [|n1]; [constructor|]. simpl. unfold comp; simpl.
rewrite !ren_term_is_subst. eapply star_map_impl; [intros; apply beta_subst1; eassumption|].
apply star_beta_read_env.
eapply Forall3_select23, Forall3_impl, IHe. intros; simpl in *; tauto.
* lia.
+ eapply beta_subst2.
apply star_beta_read_env.
eapply Forall3_select23, Forall3_impl, IHe. intros; simpl in *; tauto.
- eapply Forall2_impl in IHe; [|intros ? ? IH; exact (IH Hvok)].
eapply Forall2_exists_Forall3 in IHe. destruct IHe as (el2 & IHe).
exists (constr tag el2). split.
+ constructor. eapply Forall3_select13, Forall3_impl; [|eassumption].
intros; simpl in *; tauto.
+ apply star_beta_constr. eapply Forall3_select23, Forall3_impl; [|eassumption].
intros; simpl in *; tauto.
- destruct IHc as (h2 & IHc1 & IHc2); [assumption|].
exists (fill_hctx h2 (match index Nat.eq_dec varmap x with Some n => var n | None => dvar x end)).
split; [|apply IHc2].
inversion IHuf; subst; [econstructor; [eassumption|rewrite <- H2; constructor|lia|eassumption]|].
rewrite <- H in *.
inversion Huf; subst. destruct H2 as (tuf & IHuf1 & IHuf2); [assumption|].
econstructor; [eassumption| |lia|congruence]. rewrite <- H. econstructor; split; [eassumption|].
split; [|tauto].
eapply star_compose; [|eapply star_impl; [|eassumption]; intros; left; assumption].
eapply star_compose; [|apply H4].
eapply convertible_sym. eapply star_impl; [|apply IHc2]. intros; left; assumption.
- exists h_hole. split; [constructor|]. intros; simpl; constructor.
- destruct IHv as (t2 & IHv1 & IHv2); [assumption|].
destruct IHc as (h2 & IHc1 & IHc2); [assumption|].
exists (compose_hctx h2 (h_app h_hole t2)). split.
+ constructor; assumption.
+ intros t5. rewrite !fill_compose; simpl.
eapply star_compose; [apply IHc2|]. apply star_beta_hctx, star_beta_app; [constructor|assumption].
- destruct IHc as (h2 & IHc1 & IHc2); [assumption|].
eapply Forall2_impl in IHe; [|intros ? ? IH; exact (IH Hvok)].
eapply Forall2_exists_Forall3 in IHe. destruct IHe as (el2 & IHe).
exists (compose_hctx h2 (h_switch h_hole (map (fun '(p, t0) => (p, subst (liftn_subst p (read_env el2)) t0)) bs))).
split.
+ eapply Forall3_and in IHdeep; [|apply Hdeeps].
eapply Forall3_impl in IHdeep; cycle 1.
{ intros ? ? ? [IH1 IH2]. refine (IH2 _). apply varmap_ok_app; try tauto.
eapply Forall_impl; [|apply IH1]. intros; simpl in *; tauto. }
apply Forall3_exists_Forall4 in IHdeep. destruct IHdeep as (tdeeps2 & IHdeep).
econstructor.
* eapply Forall3_select13, Forall3_impl; [|eassumption]. intros; simpl in *; tauto.
* assumption.
* eapply Forall4_select124, Forall4_impl, Forall4_and; [|eapply Forall4_unselect123; eassumption|apply IHdeep].
intros pt vdeeps tdeep tdeep2 ((Hlen & Hread & Hconv & Hclosed & Hvars1 & Hvars2 & Hdv) & (Hread2 & Hstar)); simpl in *.
repeat split; try assumption.
-- eapply star_compose; [|eapply star_impl; [|eassumption]; intros; left; assumption].
eapply star_compose; [|eassumption]. eapply convertible_sym. eapply star_impl; [intros ? ? H; left; exact H|].
apply beta_subst2.
intros n. unfold liftn_subst. destruct le_lt_dec; [|apply star_refl].
rewrite !ren_term_is_subst. apply star_beta_subst1.
apply star_beta_read_env.
eapply Forall3_select23, Forall3_impl, IHe. intros; simpl in *; tauto.
-- eapply Forall_impl; [|eassumption].
intros x [Hx1 Hx2]; simpl in *; split; [lia|assumption].
+ intros t5. rewrite !fill_compose; simpl.
eapply star_compose; [apply IHc2|]. apply star_beta_hctx, star_beta_switch; [constructor|].
rewrite Forall2_map_left, Forall2_map_right, Forall2_map_same. apply Forall_True. intros [p t0]; simpl.
split; [reflexivity|]. apply beta_subst2.
intros n. unfold liftn_subst. destruct le_lt_dec; [|apply star_refl].
rewrite !ren_term_is_subst. apply star_beta_subst1.
apply star_beta_read_env.
eapply Forall3_select23, Forall3_impl, IHe. intros; simpl in *; tauto.
Qed.
Definition state_wf st defs :=
forall rid,
nth_error (
st_rthreads st)
rid <>
None ->
exists t varmap,
varmap_ok (
st_freename st)
varmap /\
read_thread st defs varmap rid t.
Lemma stable_beta_hnf_aux2 :
forall st defs varmap rid t,
defs_ok defs st ->
varmap_ok (
st_freename st)
varmap ->
read_thread st defs varmap rid t ->
(
forall varmap2 rid2 t,
read_thread st defs varmap2 rid2 t ->
varmap_ok (
st_freename st)
varmap2 ->
exists t2,
read_thread (
step_r st rid)
defs varmap2 rid2 t2 /\
star beta t t2) /\
(
forall varmap2 v t,
read_val st defs varmap2 v t ->
varmap_ok (
st_freename st)
varmap2 ->
exists t2,
read_val (
step_r st rid)
defs varmap2 v t2 /\
star beta t t2) /\
(
forall varmap2 c h,
read_cont st defs varmap2 c h ->
varmap_ok (
st_freename st)
varmap2 ->
exists h2,
read_cont (
step_r st rid)
defs varmap2 c h2 /\ (
forall t,
star beta (
fill_hctx h t) (
fill_hctx h2 t))).
Proof.
intros st defs varmap rid t H1 H2 H3.
eapply stable_beta_hnf_aux.
- apply step_r_freename.
- eapply step_r_beta_hnf.
+ assumption.
+ apply H2.
+ apply H2.
+ reflexivity.
+ eassumption.
- apply only_changed_step_r.
- intros varmap2 t2 Hvarmap2 Hread.
eapply step_r_beta_hnf.
+ eassumption.
+ apply Hvarmap2.
+ apply Hvarmap2.
+ reflexivity.
+ assumption.
Qed.
Lemma stable_beta_hnf_aux3 :
forall st defs rid,
defs_ok defs st ->
state_wf st defs ->
(
forall varmap2 rid2 t,
read_thread st defs varmap2 rid2 t ->
varmap_ok (
st_freename st)
varmap2 ->
exists t2,
read_thread (
step_r st rid)
defs varmap2 rid2 t2 /\
star beta t t2) /\
(
forall varmap2 v t,
read_val st defs varmap2 v t ->
varmap_ok (
st_freename st)
varmap2 ->
exists t2,
read_val (
step_r st rid)
defs varmap2 v t2 /\
star beta t t2) /\
(
forall varmap2 c h,
read_cont st defs varmap2 c h ->
varmap_ok (
st_freename st)
varmap2 ->
exists h2,
read_cont (
step_r st rid)
defs varmap2 c h2 /\ (
forall t,
star beta (
fill_hctx h t) (
fill_hctx h2 t))).
Proof.
intros st defs rid H1 H2. specialize (H2 rid).
destruct nth_error eqn:Hrid.
- destruct H2 as (t & varmap & Hvarmap & Ht); [congruence|].
eapply stable_beta_hnf_aux2; eassumption.
- unfold step_r; rewrite Hrid.
repeat split; intros; eexists; split; try eassumption; intros; apply star_refl.
Qed.
Lemma state_wf_preserve :
forall st defs rid,
defs_ok defs st ->
state_wf st defs ->
state_wf (
step_r st rid)
defs.
Proof.
intros st defs rid H1 H2. destruct (nth_error (st_rthreads st) rid) eqn:Hrid; [|unfold step_r; rewrite Hrid; assumption].
destruct (H2 rid) as (t & varmap & Hvarmap & Ht); [congruence|].
intros rid2 Hrid2. destruct (nth_error (st_rthreads st) rid2) eqn:Hrid3.
- destruct (H2 rid2) as (t2 & varmap2 & Hvarmap2 & Ht2); [congruence|].
eapply stable_beta_hnf_aux2 in Ht; try assumption.
destruct Ht as (Ht & _ & _). apply Ht in Ht2; [|assumption].
destruct Ht2 as (t3 & Ht3 & _). exists t3. exists varmap2. split; [|assumption].
split; [|apply Hvarmap2]. eapply Forall_impl; [|apply Hvarmap2].
intros; simpl in *; eapply lt_le_trans; [eassumption|]. apply step_r_freename.
- eapply step_r_beta_hnf.
+ eassumption.
+ apply Hvarmap.
+ apply Hvarmap.
+ reflexivity.
+ eassumption.
+ eassumption.
+ eassumption.
Qed.
Lemma step_r_correct_val :
forall st defs rid varmap v t,
defs_ok defs st ->
state_wf st defs ->
read_val st defs varmap v t ->
varmap_ok (
st_freename st)
varmap ->
exists t2,
read_val (
step_r st rid)
defs varmap v t2 /\
star beta t t2.
Proof.
intros st defs rid varmap v t Hdefsok Hwf Hread Hvarmap.
refine (proj1 (proj2 (stable_beta_hnf_aux3 st defs rid _ _)) _ _ _ Hread Hvarmap); assumption.
Qed.
Readback of convertibility threads.
Inductive read_cthread st defs :
cthread ->
bool ->
Prop :=
|
read_cthread_done :
forall b,
read_cthread st defs (
cthread_done b)
b
|
read_cthread_and_true :
forall ct1 ct2,
read_cthread st defs ct1 true ->
read_cthread st defs ct2 true ->
read_cthread st defs (
cthread_and ct1 ct2)
true
|
read_cthread_and_false_1 :
forall ct1 ct2,
read_cthread st defs ct1 false ->
read_cthread st defs (
cthread_and ct1 ct2)
false
|
read_cthread_and_false_2 :
forall ct1 ct2,
read_cthread st defs ct2 false ->
read_cthread st defs (
cthread_and ct1 ct2)
false
|
read_cthread_or_false :
forall ct1 ct2,
read_cthread st defs ct1 false ->
read_cthread st defs ct2 false ->
read_cthread st defs (
cthread_or ct1 ct2)
false
|
read_cthread_or_true_1 :
forall ct1 ct2,
read_cthread st defs ct1 true ->
read_cthread st defs (
cthread_or ct1 ct2)
true
|
read_cthread_or_true_2 :
forall ct1 ct2,
read_cthread st defs ct2 true ->
read_cthread st defs (
cthread_or ct1 ct2)
true
|
read_cthread_reduce :
forall v1 v2 varmap1 varmap2 b,
(
forall t1 t2,
read_val st defs varmap1 v1 t1 ->
read_val st defs varmap2 v2 t2 ->
reflect (
convertible (
betaiota defs)
t1 t2)
b) ->
read_cthread st defs (
cthread_reduce v1 v2 varmap1 varmap2)
b.
Lemma lift_dvars_app :
forall t k vars1 vars2,
lift_dvars (
vars1 ++
vars2)
k t =
lift_dvars vars2 (
length vars1 +
k) (
lift_dvars vars1 k t).
Proof.
intros t; induction t using term_ind2; intros k vars1 vars2; simpl in *.
- reflexivity.
- rewrite index_app.
destruct (index _ vars1 n); [reflexivity|].
simpl. destruct (index _ vars2 n); simpl; [|reflexivity].
f_equal. lia.
- f_equal. rewrite IHt. f_equal. lia.
- f_equal; [apply IHt1|apply IHt2].
- f_equal. rewrite map_map.
eapply map_ext_in; rewrite Forall_forall in H; intros; apply H; assumption.
- f_equal; [apply IHt|].
rewrite map_map.
eapply map_ext_in; rewrite Forall_forall in H; intros [p t2] Hpt2; f_equal.
specialize (H (p, t2) Hpt2). rewrite H. f_equal; simpl.
lia.
Qed.
Lemma lift_dvars_cons :
forall t k x vars,
lift_dvars (
x ::
vars)
k t =
lift_dvars vars (
S k) (
lift_dvars (
x ::
nil)
k t).
Proof.
intros; apply lift_dvars_app with (vars1 := x :: nil).
Qed.
Lemma betaiota_abs_red :
forall defs t1 t2,
betaiota defs (
abs t1)
t2 ->
exists t3,
t2 =
abs t3 /\
betaiota defs t1 t3.
Proof.
intros defs t1 t2 [H | H]; inversion H; subst; eexists; split; try reflexivity; constructor; assumption.
Qed.
Lemma betaiota_star_abs_red :
forall defs t1 t2,
star (
betaiota defs) (
abs t1)
t2 ->
exists t3,
t2 =
abs t3 /\
star (
betaiota defs)
t1 t3.
Proof.
intros defs t1 t2 H; remember (abs t1) as t3; revert t1 Heqt3; induction H; intros t1 ->.
- exists t1. split; [reflexivity|apply star_refl].
- apply betaiota_abs_red in H. destruct H as (t2 & -> & H).
destruct (IHstar _ eq_refl) as (t3 & Ht3 & Hstar).
exists t3. split; [assumption|]. econstructor; eassumption.
Qed.
Lemma convertible_abs_iff :
forall defs t1 t2,
convertible (
betaiota defs) (
abs t1) (
abs t2) <->
convertible (
betaiota defs)
t1 t2.
Proof.
intros defs t1 t2; split; intros H.
- apply convertible_confluent_common_reduce in H; [|apply beta_iota_confluent].
destruct H as (t3 & Ht3a & Ht3b).
apply betaiota_star_abs_red in Ht3a. destruct Ht3a as (t4 & -> & Ht4a).
apply betaiota_star_abs_red in Ht3b. destruct Ht3b as (t5 & [=<-] & Ht4b).
eapply common_reduce_convertible; eassumption.
- eapply star_map_impl; [|eassumption].
intros t3 t4 [H1 | H1]; destruct H1 as [H1 | H1]; constructor; constructor; constructor; assumption.
Qed.
Lemma betaiota_constr_red_weak :
forall defs tag l1 t2,
betaiota defs (
constr tag l1)
t2 ->
exists l2,
t2 =
constr tag l2 /\
Forall2 (
star (
betaiota defs))
l1 l2.
Proof.
intros defs tag l1 t2 [H | H]; inversion H; subst; eexists; split; try reflexivity;
apply Forall2_app; try constructor; try apply Forall2_map_same, Forall_True, star_refl;
apply star_1; constructor; assumption.
Qed.
Lemma betaiota_star_constr_red :
forall defs tag l1 t2,
star (
betaiota defs) (
constr tag l1)
t2 ->
exists l2,
t2 =
constr tag l2 /\
Forall2 (
star (
betaiota defs))
l1 l2.
Proof.
intros defs tag l1 t2 H; remember (constr tag l1) as t3; revert l1 Heqt3; induction H; intros l1 ->.
- exists l1. split; [reflexivity|apply Forall2_map_same, Forall_True, star_refl].
- apply betaiota_constr_red_weak in H. destruct H as (l2 & -> & H).
destruct (IHstar _ eq_refl) as (l3 & Hl3 & Hstar).
exists l3. split; [assumption|].
eapply Forall3_select23. eapply Forall3_impl; [|eapply Forall3_from_Forall2; [apply Forall2_comm in H|]; eassumption].
intros t1 t2 t3 H123; simpl in *. eapply star_compose; apply H123.
Qed.
Lemma star_betaiota_constr :
forall defs tag (
l1 l2 :
list term),
Forall2 (
star (
betaiota defs))
l1 l2 ->
star (
betaiota defs) (
constr tag l1) (
constr tag l2).
Proof.
intros defs tag l1 l2 H. eapply star_list; [|eassumption].
intros l3 l4 x y [Hxy | Hxy]; [left|right]; constructor; assumption.
Qed.
Lemma convertible_constr_iff :
forall defs tag1 tag2 l1 l2,
convertible (
betaiota defs) (
constr tag1 l1) (
constr tag2 l2) <-> (
tag1 =
tag2 /\
Forall2 (
convertible (
betaiota defs))
l1 l2).
Proof.
intros defs tag1 tag2 l1 l2; split; intros H.
- apply convertible_confluent_common_reduce in H; [|apply beta_iota_confluent].
destruct H as (t3 & Ht3a & Ht3b).
apply betaiota_star_constr_red in Ht3a. destruct Ht3a as (l4 & -> & Ht5a).
apply betaiota_star_constr_red in Ht3b. destruct Ht3b as (l5 & [=<- <-] & Ht5b).
split; [reflexivity|].
apply Forall2_comm in Ht5a, Ht5b. eapply Forall3_select23.
eapply Forall3_impl; [|eapply Forall3_from_Forall2; eassumption].
intros t1 t2 t3 Ht123. eapply common_reduce_convertible; apply Ht123.
- destruct H as [-> H].
assert (H1 : exists l3, Forall3 (fun t1 t2 t3 => star (betaiota defs) t1 t3 /\ star (betaiota defs) t2 t3) l1 l2 l3).
+ apply Forall2_exists_Forall3. eapply Forall2_impl; [|eassumption].
intros t1 t2 Ht12. eapply convertible_confluent_common_reduce in Ht12; [|apply beta_iota_confluent]. assumption.
+ destruct H1 as (l3 & Hl3).
eapply common_reduce_convertible; apply star_betaiota_constr; [eapply Forall3_select13|eapply Forall3_select23];
eapply Forall3_impl; try eassumption; intros; simpl in *; tauto.
Qed.
Lemma abs_constr_not_convertible :
forall defs tag l t, ~
convertible (
betaiota defs) (
abs t) (
constr tag l).
Proof.
intros defs tag l t H.
apply convertible_confluent_common_reduce in H; [|apply beta_iota_confluent].
destruct H as (t3 & Ht3a & Ht3b).
apply betaiota_star_abs_red in Ht3a. destruct Ht3a as (t4 & -> & _).
apply betaiota_star_constr_red in Ht3b. destruct Ht3b as (l4 & Habsurd & _). congruence.
Qed.
Lemma constr_abs_not_convertible :
forall defs tag l t, ~
convertible (
betaiota defs) (
constr tag l) (
abs t).
Proof.
intros defs tag l t H. apply convertible_sym in H. eapply abs_constr_not_convertible; eassumption.
Qed.
Inductive hctx_red defs :
hctx ->
hctx ->
Prop :=
|
hctx_red_app_1 :
forall h1 h2 t,
hctx_red defs h1 h2 ->
hctx_red defs (
h_app h1 t) (
h_app h2 t)
|
hctx_red_app_2 :
forall h t1 t2,
betaiota defs t1 t2 ->
hctx_red defs (
h_app h t1) (
h_app h t2)
|
hctx_red_switch_1 :
forall h1 h2 m,
hctx_red defs h1 h2 ->
hctx_red defs (
h_switch h1 m) (
h_switch h2 m)
|
hctx_red_switch_2 :
forall h m1 m2 p t1 t2,
betaiota defs t1 t2 ->
hctx_red defs (
h_switch h (
m1 ++ (
p,
t1) ::
m2)) (
h_switch h (
m1 ++ (
p,
t2) ::
m2)).
Lemma hctx_red_fill :
forall defs h1 h2,
hctx_red defs h1 h2 ->
forall t,
betaiota defs (
fill_hctx h1 t) (
fill_hctx h2 t).
Proof.
intros defs h1 h2 H t; induction H; simpl in *.
- inversion IHhctx_red; subst; constructor; constructor; assumption.
- inversion H; subst; constructor; constructor; assumption.
- inversion IHhctx_red; subst; constructor; constructor; assumption.
- inversion H; subst; constructor; constructor; assumption.
Qed.
Definition is_neutral_var (
defs :
list term)
x :=
match x with var _ =>
True |
dvar n =>
nth_error defs n =
None |
_ =>
False end.
Lemma fill_hctx_var_red :
forall defs h x t,
is_neutral_var defs x ->
betaiota defs (
fill_hctx h x)
t ->
exists h2,
t =
fill_hctx h2 x /\
hctx_red defs h h2.
Proof.
intros defs h x t Hx H. destruct H as [H | H]; revert t H; induction h; intros t3 H; simpl in *.
- destruct x; simpl in *; try tauto; inversion H; subst; congruence.
- inversion H; subst.
+ apply IHh in H3. destruct H3 as (h2 & -> & Hh2).
exists (h_app h2 t); split; [reflexivity|].
constructor; assumption.
+ exists (h_app h t2). split; [reflexivity|].
constructor; constructor; assumption.
- inversion H; subst.
+ apply IHh in H3. destruct H3 as (h2 & -> & Hh2).
exists (h_switch h2 l). split; [reflexivity|].
constructor; assumption.
+ exists (h_switch h (l1 ++ (p, t2) :: l2)). split; [reflexivity|].
constructor; constructor; assumption.
- destruct x; simpl in *; try tauto; inversion H.
- inversion H; subst.
+ apply IHh in H3. destruct H3 as (h2 & -> & Hh2).
exists (h_app h2 t); split; [reflexivity|].
constructor; assumption.
+ exists (h_app h t2). split; [reflexivity|].
constructor; constructor; assumption.
+ destruct h; destruct x; simpl in *; try tauto; congruence.
- inversion H; subst.
+ apply IHh in H3. destruct H3 as (h2 & -> & Hh2).
exists (h_switch h2 l). split; [reflexivity|].
constructor; assumption.
+ exists (h_switch h (l1 ++ (p, t2) :: l2)). split; [reflexivity|].
constructor; constructor; assumption.
+ destruct h; destruct x; simpl in *; try tauto; congruence.
Qed.
Lemma fill_hctx_var_star_red :
forall defs h x t,
is_neutral_var defs x ->
star (
betaiota defs) (
fill_hctx h x)
t ->
exists h2,
t =
fill_hctx h2 x /\
star (
hctx_red defs)
h h2.
Proof.
intros defs h x t Hx H; remember (fill_hctx h x) as t3; revert h Heqt3; induction H; intros h ->.
- exists h. split; [reflexivity|apply star_refl].
- apply fill_hctx_var_red in H; [|assumption]. destruct H as (h2 & -> & H).
destruct (IHstar _ eq_refl) as (h3 & Hh3 & Hstar).
exists h3. split; [assumption|]. econstructor; eassumption.
Qed.
Definition is_var x :=
match x with var _ |
dvar _ =>
True |
_ =>
False end.
Lemma fill_hctx_var_eq :
forall x1 x2 h1 h2,
is_var x1 ->
is_var x2 ->
fill_hctx h1 x1 =
fill_hctx h2 x2 <->
h1 =
h2 /\
x1 =
x2.
Proof.
intros x1 x2; induction h1; intros h2 Hx1 Hx2; destruct h2; simpl in *; try (destruct x1; destruct x2; simpl in *; intuition congruence).
- specialize (IHh1 h2). split.
+ intros [=]; intuition congruence.
+ intros [[=] ?]; intuition congruence.
- specialize (IHh1 h2). split.
+ intros [=]; intuition congruence.
+ intros [[=] ?]; intuition congruence.
Qed.
Definition hctx_convertible defs h1 h2 :=
exists h3,
star (
hctx_red defs)
h1 h3 /\
star (
hctx_red defs)
h2 h3.
Lemma iota_hctx :
forall defs h t1 t2,
iota defs t1 t2 ->
iota defs (
fill_hctx h t1) (
fill_hctx h t2).
Proof.
intros defs h t1 t2 H; induction h; simpl in *.
- assumption.
- constructor; assumption.
- constructor; assumption.
Qed.
Lemma star_betaiota_hctx :
forall defs h t1 t2,
star (
betaiota defs)
t1 t2 ->
star (
betaiota defs) (
fill_hctx h t1) (
fill_hctx h t2).
Proof.
intros defs h t1 t2 H. eapply star_map_impl; [|eassumption].
intros t3 t4 [H1 | H1]; [left | right].
- apply iota_hctx. assumption.
- apply beta_hctx. assumption.
Qed.
Lemma fill_hctx_star :
forall defs h1 h2 t1 t2,
star (
betaiota defs)
t1 t2 ->
star (
hctx_red defs)
h1 h2 ->
star (
betaiota defs) (
fill_hctx h1 t1) (
fill_hctx h2 t2).
Proof.
intros defs h1 h2 t1 t2 Ht Hh. eapply star_compose; [|eapply star_betaiota_hctx; eassumption].
eapply star_map_impl with (f := fun h => fill_hctx h _); [|eassumption].
intros h3 h4 H1; apply hctx_red_fill, H1.
Qed.
Lemma convertible_neutral_iff :
forall defs h1 h2 x1 x2,
is_neutral_var defs x1 ->
is_neutral_var defs x2 ->
convertible (
betaiota defs) (
fill_hctx h1 x1) (
fill_hctx h2 x2) <-> (
x1 =
x2 /\
hctx_convertible defs h1 h2).
Proof.
intros defs h1 h2 x1 x2 Hx1 Hx2. split.
- intros H. apply convertible_confluent_common_reduce in H; [|apply beta_iota_confluent].
destruct H as (t3 & Ht3a & Ht3b).
apply fill_hctx_var_star_red in Ht3a; [|assumption]. destruct Ht3a as (h4 & -> & Ht5a).
apply fill_hctx_var_star_red in Ht3b; [|assumption]. destruct Ht3b as (h5 & Heq & Ht5b).
apply fill_hctx_var_eq in Heq; [|destruct x1; simpl in *; tauto|destruct x2; simpl in *; tauto]. destruct Heq; subst.
split; [reflexivity|]. eexists; split; eassumption.
- intros [-> (h3 & Hh3a & Hh3b)]. eapply common_reduce_convertible; eapply fill_hctx_star; try eassumption; apply star_refl.
Qed.
Lemma abs_neutral_not_convertible :
forall defs h x t,
is_neutral_var defs x -> ~
convertible (
betaiota defs) (
abs t) (
fill_hctx h x).
Proof.
intros defs h x t Hx H.
apply convertible_confluent_common_reduce in H; [|apply beta_iota_confluent].
destruct H as (t3 & Ht3a & Ht3b).
apply betaiota_star_abs_red in Ht3a. destruct Ht3a as (t4 & -> & _).
apply fill_hctx_var_star_red in Ht3b; [|assumption]. destruct Ht3b as (h4 & Habsurd & _).
destruct h4; destruct x; simpl in *; try tauto; congruence.
Qed.
Lemma neutral_abs_not_convertible :
forall defs h x t,
is_neutral_var defs x -> ~
convertible (
betaiota defs) (
fill_hctx h x) (
abs t).
Proof.
intros defs h x t Hx H. apply convertible_sym in H. eapply abs_neutral_not_convertible; eassumption.
Qed.
Lemma constr_neutral_not_convertible :
forall defs h x tag l,
is_neutral_var defs x -> ~
convertible (
betaiota defs) (
constr tag l) (
fill_hctx h x).
Proof.
intros defs h x tag l Hx H.
apply convertible_confluent_common_reduce in H; [|apply beta_iota_confluent].
destruct H as (t3 & Ht3a & Ht3b).
apply betaiota_star_constr_red in Ht3a. destruct Ht3a as (l4 & -> & _).
apply fill_hctx_var_star_red in Ht3b; [|assumption]. destruct Ht3b as (h4 & Habsurd & _).
destruct h4; destruct x; simpl in *; try tauto; congruence.
Qed.
Lemma neutral_constr_not_convertible :
forall defs h x tag l,
is_neutral_var defs x -> ~
convertible (
betaiota defs) (
fill_hctx h x) (
constr tag l).
Proof.
intros defs h x tag l Hx H. apply convertible_sym in H. eapply constr_neutral_not_convertible; eassumption.
Qed.
Lemma convertible_convertible_left :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
t1 t2 t3,
convertible R t1 t2 ->
convertible R t1 t3 <->
convertible R t2 t3.
Proof.
intros A R t1 t2 t3 H. split; intros H2.
- eapply star_compose; [|eassumption].
eapply star_sym; [apply symc_sym|]. assumption.
- eapply star_compose; eassumption.
Qed.
Lemma convertible_convertible_right :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
t1 t2 t3,
convertible R t1 t2 ->
convertible R t3 t1 <->
convertible R t3 t2.
Proof.
intros A R t1 t2 t3 H. split; intros H2.
- eapply star_compose; eassumption.
- eapply star_compose; [eassumption|].
eapply star_sym; [apply symc_sym|]. assumption.
Qed.
Lemma convertible_convertible_leftright :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
t1 t2 t3 t4,
convertible R t1 t2 ->
convertible R t3 t4 ->
convertible R t1 t3 <->
convertible R t2 t4.
Proof.
intros. etransitivity; [apply convertible_convertible_left|apply convertible_convertible_right]; assumption.
Qed.
Lemma lift_dvars_fill :
forall vars k t h,
lift_dvars vars k (
fill_hctx h t) =
fill_hctx (
lift_dvars_hctx vars k h) (
lift_dvars vars k t).
Proof.
intros vars k t h; induction h.
- reflexivity.
- simpl. f_equal. assumption.
- simpl. f_equal. assumption.
Qed.
Lemma lift_dvars_ren_aux :
forall vars k1 k2 k3 t,
ren_term (
liftn k1 (
plus_ren k3)) (
lift_dvars vars (
k1 +
k2)
t) =
lift_dvars vars (
k3 +
k1 +
k2) (
ren_term (
liftn k1 (
plus_ren k3))
t).
Proof.
intros vars k1 k2 k3 t; revert k1; induction t using term_ind2; intros k1; simpl in *.
- simpl. reflexivity.
- destruct index; [|reflexivity]. simpl.
rewrite liftn_renv_large by lia.
rewrite plus_ren_correct. f_equal. lia.
- f_equal. rewrite lift_liftn_1, liftn_liftn.
specialize (IHt (S k1)). simpl in *.
rewrite IHt. f_equal. lia.
- f_equal; [apply IHt1|apply IHt2].
- f_equal. rewrite !map_map. apply map_ext_in.
intros t Ht; rewrite Forall_forall in H; apply H; assumption.
- f_equal; [apply IHt|].
rewrite !map_map. apply map_ext_in.
intros [p2 t2] Hpt2; rewrite Forall_forall in H; specialize (H _ Hpt2). simpl. f_equal.
rewrite liftn_liftn. specialize (H (p2 + k1)). simpl in *.
rewrite plus_assoc, H. f_equal. lia.
Qed.
Lemma lift_dvars_ren :
forall vars k1 k2 t,
ren_term (
plus_ren k2) (
lift_dvars vars k1 t) =
lift_dvars vars (
k2 +
k1) (
ren_term (
plus_ren k2)
t).
Proof.
intros vars k1 k2 t. assert (H := lift_dvars_ren_aux vars 0 k1 k2 t).
rewrite liftn_0 in H. simpl in H.
rewrite H. f_equal. lia.
Qed.
Lemma lift_dvars_read_env_aux :
forall vars k p l t,
lift_dvars vars (
p +
k) (
subst (
liftn_subst p (
read_env l))
t) =
subst (
liftn_subst p (
read_env (
map (
lift_dvars vars k)
l))) (
lift_dvars vars (
p +
length l +
k)
t).
Proof.
intros vars k p l t; revert p; induction t using term_ind2; intros p; simpl in *.
- unfold read_env, liftn_subst. rewrite nth_error_map, map_length.
destruct le_lt_dec.
+ destruct nth_error; simpl; [|reflexivity].
rewrite lift_dvars_ren. reflexivity.
+ reflexivity.
- destruct index; simpl; [|reflexivity].
unfold read_env, liftn_subst.
destruct le_lt_dec; [|lia].
rewrite nth_error_map, nth_error_None_rw by lia.
simpl. rewrite plus_ren_correct, map_length. f_equal. lia.
- f_equal.
rewrite <- !liftn_subst_1_subst, !liftn_subst_add_subst.
specialize (IHt (S p)); simpl in *. assumption.
- f_equal; [apply IHt1|apply IHt2].
- f_equal. rewrite !map_map. eapply map_ext_in.
intros t Ht. rewrite Forall_forall in H. apply H. assumption.
- f_equal; [apply IHt|].
rewrite !map_map. apply map_ext_in.
intros [p2 t2] Hpt2. simpl. f_equal.
rewrite !liftn_subst_add_subst. rewrite Forall_forall in H; specialize (H _ Hpt2 (p2 + p)); simpl in H.
rewrite plus_assoc, H. f_equal. f_equal. lia.
Qed.
Lemma lift_dvars_read_env :
forall vars k l t,
lift_dvars vars k (
subst (
read_env l)
t) =
subst (
read_env (
map (
lift_dvars vars k)
l)) (
lift_dvars vars (
length l +
k)
t).
Proof.
intros vars k l t. assert (H := lift_dvars_read_env_aux vars k 0 l t).
rewrite !liftn_subst_0_subst in H. assumption.
Qed.
Lemma beta_lift_dvars :
forall t1 t2 vars k,
beta t1 t2 ->
beta (
lift_dvars vars k t1) (
lift_dvars vars k t2).
Proof.
intros t1 t2 vars k H; revert k; induction H; intros k.
- constructor; apply IHbeta.
- constructor; apply IHbeta.
- constructor; apply IHbeta.
- simpl. rewrite subst1_read_env, lift_dvars_read_env. simpl. rewrite <- subst1_read_env.
constructor.
- simpl. rewrite !map_app; simpl. constructor; apply IHbeta.
- simpl. constructor; apply IHbeta.
- simpl. rewrite !map_app; simpl. constructor; apply IHbeta.
- simpl. rewrite lift_dvars_read_env.
rewrite map_app; simpl.
erewrite <- map_length with (l := l). erewrite <- map_length with (l := l1). constructor.
Qed.
Lemma lift_dvars_below :
forall vars k n t,
Forall (
fun x =>
n <=
x)
vars ->
dvar_below n t ->
lift_dvars vars k t =
t.
Proof.
intros vars k n t H1 H2. revert k; induction t using term_ind2; intros k.
- reflexivity.
- simpl. rewrite index_notin_None; [reflexivity|].
intros Hn. rewrite Forall_forall in H1. apply H1 in Hn.
inversion H2; subst. lia.
- simpl. f_equal. apply IHt. inversion H2; assumption.
- simpl. f_equal; [apply IHt1|apply IHt2]; inversion H2; assumption.
- simpl. f_equal. erewrite map_ext_in; [apply map_id|].
intros t Ht; rewrite Forall_forall in H; apply H; [assumption|].
inversion H2; subst. rewrite Forall_forall in H4. apply H4; assumption.
- simpl. f_equal; [apply IHt; inversion H2; assumption|].
erewrite map_ext_in; [apply map_id|].
intros [p t2] Hpt2; f_equal; rewrite Forall_forall in H; apply (H _ Hpt2).
inversion H2; subst. rewrite Forall_forall in H6. apply (H6 _ Hpt2).
Qed.
Lemma dvar_below_impl :
forall t k1 k2,
k1 <=
k2 ->
dvar_below k1 t ->
dvar_below k2 t.
Proof.
intros t k1 k2 H1 H2; revert k2 H1; induction t using term_ind2; intros k3 H1.
- constructor.
- constructor. inversion H2; lia.
- constructor; apply IHt; inversion H2; subst; assumption.
- constructor; [apply IHt1|apply IHt2]; inversion H2; subst; assumption.
- constructor. inversion H2; subst. eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H4]].
intros t [Ht1 Ht2]; apply Ht1; [assumption|lia].
- inversion H2; subst. constructor; [apply IHt; assumption|].
eapply Forall_impl; [|erewrite <- Forall_and; split; [apply H|apply H6]].
intros [p t2] [Hpt1 Hpt2]; apply Hpt1; [assumption|lia].
Qed.
Lemma iota_lift_dvars :
forall defs t1 t2 vars k,
Forall (
fun x =>
length defs <=
x)
vars ->
defs_wf defs ->
iota defs t1 t2 ->
iota defs (
lift_dvars vars k t1) (
lift_dvars vars k t2).
Proof.
intros defs t1 t2 vars k H1 H2 H; revert k; induction H; intros k1.
- simpl.
rewrite index_notin_None; [|rewrite Forall_forall in H1; intros Hk; specialize (H1 _ Hk); apply nth_error_Some3 in H; lia].
assert (H3 : lift_dvars vars k1 t = t).
+ eapply lift_dvars_below; [eassumption|]. unfold defs_wf in H2.
eapply nth_error_Forall2 in H2; [|eassumption].
destruct H2 as (y & Hy1 & Hy2). apply nth_error_nth with (d := y) in Hy1.
rewrite seq_nth in Hy1 by (eapply nth_error_Some3; eassumption). subst; simpl in *.
eapply dvar_below_impl; [|apply Hy2]. apply nth_error_Some3 in H. lia.
+ constructor; rewrite H3; assumption.
- simpl. constructor. apply IHiota.
- simpl. constructor. apply IHiota.
- simpl. constructor. apply IHiota.
- simpl. rewrite !map_app. constructor. apply IHiota.
- simpl. constructor. apply IHiota.
- simpl. rewrite !map_app. constructor. apply IHiota.
Qed.
Lemma convertible_lift_dvars :
forall defs vars k t1 t2,
Forall (
fun x =>
length defs <=
x)
vars ->
defs_wf defs ->
convertible (
betaiota defs)
t1 t2 ->
convertible (
betaiota defs) (
lift_dvars vars k t1) (
lift_dvars vars k t2).
Proof.
intros defs vars k t1 t2 H1 H2 H.
eapply star_map_impl; [|eassumption].
intros t3 t4 [[Ht34 | Ht34] | [Ht34 | Ht34]];
(eapply beta_lift_dvars in Ht34 || eapply iota_lift_dvars in Ht34; try eassumption);
constructor; constructor; eassumption.
Qed.
Lemma convertible_beta_betaiota :
forall defs t1 t2,
convertible beta t1 t2 ->
convertible (
betaiota defs)
t1 t2.
Proof.
intros defs t1 t2 H. eapply star_impl; [|eassumption].
intros t3 t4 [Ht34 | Ht34]; constructor; right; assumption.
Qed.
Lemma lift_dvars_subst :
forall vars k t,
NoDup vars ->
closed_at t (
k +
length vars) ->
Forall (
fun x =>
dvar_free x t)
vars ->
lift_dvars vars k (
subst (
liftn_subst k (
read_env (
map dvar vars)))
t) =
t.
Proof.
intros vars k t Hdup; revert k; induction t using term_ind2; intros k Hclosed Hfree.
- simpl. unfold read_env, liftn_subst.
destruct le_lt_dec; [|reflexivity].
rewrite nth_error_map, map_length. destruct nth_error eqn:Hnk.
+ simpl. erewrite index_nth_error; [|eassumption|eassumption].
f_equal. lia.
+ inversion Hclosed; subst. apply nth_error_None in Hnk. lia.
- simpl. rewrite index_notin_None; [reflexivity|].
intros Hn. rewrite Forall_forall in Hfree; apply Hfree in Hn. inversion Hn; tauto.
- simpl. f_equal. rewrite <- liftn_subst_1_subst, liftn_subst_add_subst. simpl. apply IHt.
+ inversion Hclosed; subst; assumption.
+ eapply Forall_impl; [|eassumption].
intros x Hx; inversion Hx; subst; assumption.
- inversion Hclosed; subst.
simpl; f_equal; [apply IHt1|apply IHt2]; try assumption; eapply Forall_impl; try eassumption; intros x Hx; inversion Hx; subst; assumption.
- simpl. f_equal. rewrite map_map. erewrite map_ext_in; [apply map_id|].
intros t Ht. rewrite Forall_forall in H; apply H; [assumption| |].
+ inversion Hclosed; subst. apply H3. assumption.
+ eapply Forall_impl; [|eassumption].
intros x Hx; inversion Hx; subst. eapply Forall_forall; eassumption.
- inversion Hclosed; subst. simpl.
f_equal; [apply IHt; [assumption|eapply Forall_impl; [|eassumption]; intros x Hx; inversion Hx; subst; assumption]|].
rewrite map_map. erewrite map_ext_in; [apply map_id|].
intros [p t2] Hpt2. f_equal. simpl.
rewrite liftn_subst_add_subst. rewrite Forall_forall in H.
apply (H _ Hpt2).
+ specialize (H4 _ _ Hpt2). rewrite <- plus_assoc; assumption.
+ eapply Forall_impl; [|eassumption].
intros x Hx; inversion Hx; subst. rewrite Forall_forall in H5; apply H5 in Hpt2; assumption.
Qed.
Lemma lift_dvars_subst_0 :
forall vars t,
NoDup vars ->
closed_at t (
length vars) ->
Forall (
fun x =>
dvar_free x t)
vars ->
lift_dvars vars 0 (
subst (
read_env (
map dvar vars))
t) =
t.
Proof.
intros vars t H1 H2 H3. assert (H4 := lift_dvars_subst vars 0 t H1 H2 H3). rewrite liftn_subst_0_subst in H4. assumption.
Qed.
Lemma lift_dvars_subst_0_1 :
forall x t,
closed_at t 1 ->
dvar_free x t ->
lift_dvars (
x ::
nil) 0 (
subst (
read_env (
dvar x ::
nil))
t) =
t.
Proof.
intros x t H1 H2. apply lift_dvars_subst_0.
- constructor; [|constructor]. simpl. tauto.
- assumption.
- constructor; [assumption|constructor].
Qed.
Well-formedness of convertibility threads.
Inductive cthread_wf st (
defs :
list term) :
cthread ->
Prop :=
|
cthread_wf_done :
forall b,
cthread_wf st defs (
cthread_done b)
|
cthread_wf_and :
forall c1 c2,
cthread_wf st defs c1 ->
cthread_wf st defs c2 ->
cthread_wf st defs (
cthread_and c1 c2)
|
cthread_wf_or :
forall c1 c2,
cthread_wf st defs c1 ->
cthread_wf st defs c2 ->
cthread_wf st defs (
cthread_or c1 c2)
|
cthread_wf_reduce :
forall v1 v2 t1 t2 varmap1 varmap2,
Forall (
fun v =>
length defs <=
v)
varmap1 ->
Forall (
fun v =>
length defs <=
v)
varmap2 ->
varmap_ok (
st_freename st)
varmap1 ->
varmap_ok (
st_freename st)
varmap2 ->
length varmap1 =
length varmap2 ->
read_val st defs varmap1 v1 t1 ->
read_val st defs varmap2 v2 t2 ->
cthread_wf st defs (
cthread_reduce v1 v2 varmap1 varmap2).
Lemma cthread_andn_wf :
forall st defs l,
Forall (
cthread_wf st defs)
l ->
cthread_wf st defs (
cthread_andn l).
Proof.
intros freename defs l H; induction H; simpl in *; constructor; assumption.
Qed.
Lemma is_finished_read_thread :
forall st rid v defs varmap t,
is_finished st rid =
Some v ->
read_thread st defs varmap rid t ->
read_val st defs varmap v t.
Proof.
intros st rid v defs varmap t H1 H2; unfold is_finished in H1.
inversion H2; subst; rewrite H in H1; simpl in *; [|congruence].
destruct c; try congruence. injection H1 as H1; subst.
inversion H3; subst. simpl in *. assumption.
Qed.
Lemma Forall_combine_lists :
forall (
A B :
Type) (
P :
A ->
Prop) (
Q :
B ->
Prop)
l1 l2,
Forall P l1 ->
Forall Q l2 ->
Forall (
fun ab =>
P (
fst ab) /\
Q (
snd ab)) (
combine l1 l2).
Proof.
intros A B P Q l1 l2 H1 H2; revert l2 H2; induction H1; intros l2 H2; inversion H2; subst; simpl; constructor.
- split; assumption.
- apply IHForall; assumption.
Qed.
Lemma cmp_cont_wf :
forall st defs c1 c2 h1 h2 varmap1 varmap2 l,
Forall (
fun v =>
length defs <=
v)
varmap1 ->
Forall (
fun v =>
length defs <=
v)
varmap2 ->
varmap_ok (
st_freename st)
varmap1 ->
varmap_ok (
st_freename st)
varmap2 ->
length varmap1 =
length varmap2 ->
read_cont st defs varmap1 c1 h1 ->
read_cont st defs varmap2 c2 h2 ->
cmp_cont c1 c2 varmap1 varmap2 =
Some l ->
Forall (
cthread_wf st defs)
l.
Proof.
intros st defs c1 c2 h1 h2 varmap1 varmap2 l Hdefs1 Hdefs2 Hok1 Hok2 Hlen Hread1 Hread2 Hcmp.
revert c2 h2 l Hread2 Hcmp; induction Hread1; intros c2 h2 l Hread2 Hcmp; simpl in *; inversion Hread2; subst; simpl in *; try congruence.
- injection Hcmp as Hcmp; subst. constructor.
- destruct cmp_cont eqn:Hcmp1; [|congruence].
injection Hcmp as Hcmp; subst. constructor.
+ econstructor; eassumption.
+ eapply IHHread1; eassumption.
- destruct Nat.eqb eqn:Heq; [|congruence].
destruct forallb eqn:Hforallb; [|congruence].
destruct cmp_cont eqn:Hcmp1; [|congruence].
injection Hcmp as Hcmp; subst. rewrite Forall_app. split; [|eapply IHHread1; eassumption].
rewrite Forall_map. rewrite forallb_forall, <- Forall_forall in Hforallb.
eapply Forall3_impl, Forall3_select12, Forall2_select2 in H0;
[|intros pt vdeeps tdeep (_ & Hpt1 & _ & _ & Hpt2 & Hpt3 & _); refine (ex_intro (fun tdeep => _) tdeep _); exact (conj Hpt1 (conj Hpt2 Hpt3))].
eapply Forall3_impl, Forall3_select12, Forall2_select2 in H3;
[|intros pt vdeeps tdeep (_ & Hpt1 & _ & _ & Hpt2 & Hpt3 & _); refine (ex_intro (fun tdeep => _) tdeep _); exact (conj Hpt1 (conj Hpt2 Hpt3))].
eapply Forall_impl; [|rewrite <- Forall_and; split; [apply Hforallb|apply Forall_combine_lists; eassumption]].
intros [vdeeps1 vdeeps2] (Heq1 & (tdeep1 & Hdeep1 & Hvd1a & Hvd1b) & (tdeep2 & Hdeep2 & Hvd2a & Hvd2b)). simpl in *.
econstructor.
+ rewrite Forall_app. split; [|assumption].
eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
+ rewrite Forall_app. split; [|assumption].
eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
+ apply varmap_ok_app; try eassumption.
eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
+ apply varmap_ok_app; try eassumption.
eapply Forall_impl; [|eassumption]. intros; simpl in *; tauto.
+ rewrite !app_length. f_equal; [|assumption].
apply Nat.eqb_eq; assumption.
+ eassumption.
+ eassumption.
Qed.
Lemma cmp_cont_cthread_wf :
forall st defs c1 c2 h1 h2 varmap1 varmap2,
Forall (
fun v =>
length defs <=
v)
varmap1 ->
Forall (
fun v =>
length defs <=
v)
varmap2 ->
varmap_ok (
st_freename st)
varmap1 ->
varmap_ok (
st_freename st)
varmap2 ->
length varmap1 =
length varmap2 ->
read_cont st defs varmap1 c1 h1 ->
read_cont st defs varmap2 c2 h2 ->
cthread_wf st defs (
cmp_cont_cthread c1 c2 varmap1 varmap2).
Proof.
intros. unfold cmp_cont_cthread. destruct cmp_cont eqn:Hcmp.
- eapply cthread_andn_wf, cmp_cont_wf with (varmap1 := varmap1) (varmap2 := varmap2); eassumption.
- constructor.
Qed.
Lemma cthread_red_wf :
forall st defs ct1 ct2,
cthread_wf st defs ct1 ->
cthread_red st ct1 ct2 ->
cthread_wf st defs ct2.
Proof.
intros st defs ct1 ct2 H1 H2; induction H2; subst; inversion H1; subst; try (constructor; tauto).
- inversion H10; subst.
eapply is_finished_read_thread in H3; [|eassumption].
econstructor; eassumption.
- inversion H11; subst.
eapply is_finished_read_thread in H3; [|eassumption].
econstructor; eassumption.
- inversion H9; subst.
inversion H10; subst.
econstructor.
+ constructor; [|assumption]. tauto.
+ constructor; [|assumption]. tauto.
+ apply varmap_ok_cons; tauto.
+ apply varmap_ok_cons; tauto.
+ simpl; congruence.
+ eassumption.
+ eassumption.
- apply cthread_andn_wf. rewrite Forall_map.
inversion H10; subst. inversion H11; subst.
rewrite Forall_forall. intros [v1 v2] Hv12.
eapply Forall2_In_left in H12; [|eapply in_combine_l; eassumption].
eapply Forall2_In_left in H13; [|eapply in_combine_r; eassumption].
destruct H12 as (t1 & Ht1a & Ht1b).
destruct H13 as (t2 & Ht2a & Ht2b).
econstructor; eassumption.
- inversion H9; subst. inversion H12; subst.
econstructor; try eassumption. apply H11.
- inversion H10; subst. inversion H12; subst.
econstructor; try eassumption. apply H11.
- constructor.
+ inversion H9; subst. inversion H12; subst.
inversion H10; subst. inversion H18; subst.
econstructor; try eassumption; [apply H11|apply H17].
+ inversion H9; subst. inversion H10; subst.
eapply cmp_cont_cthread_wf; eassumption.
- inversion H10; subst. inversion H11; subst.
eapply cmp_cont_cthread_wf; eassumption.
Qed.
Proof of compatibility of readback for convertibility threads.
Lemma read_cthread_andn_true :
forall st defs l,
read_cthread st defs (
cthread_andn l)
true <->
Forall (
fun c =>
read_cthread st defs c true)
l.
Proof.
intros st defs. induction l; split; intros H; simpl in *; inversion H; subst; constructor; tauto.
Qed.
Lemma read_cthread_andn_false :
forall st defs l,
read_cthread st defs (
cthread_andn l)
false <->
Exists (
fun c =>
read_cthread st defs c false)
l.
Proof.
intros st defs. induction l; split; intros H; simpl in *; inversion H; subst; constructor; tauto.
Qed.
Lemma hctx_red_hole :
forall defs h,
hctx_red defs h_hole h ->
h =
h_hole.
Proof.
intros defs h H. inversion H; reflexivity.
Qed.
Lemma hctx_red_hole_star :
forall defs h,
star (
hctx_red defs)
h_hole h ->
h =
h_hole.
Proof.
intros defs h H. apply star_preserve with (P := fun h => h = h_hole) in H; [assumption| |reflexivity].
intros; subst; eapply hctx_red_hole; eassumption.
Qed.
Lemma hctx_red_app_star :
forall defs h1 t1 h,
star (
hctx_red defs) (
h_app h1 t1)
h ->
exists h2 t2,
h =
h_app h2 t2 /\
star (
hctx_red defs)
h1 h2 /\
star (
betaiota defs)
t1 t2.
Proof.
intros defs h1 t1 h H.
eapply star_preserve with (P := fun h => exists h2 t2, h = h_app h2 t2 /\ _ /\ _); [| |eassumption].
- intros h3 h4 H34 (h2 & t2 & -> & Hh & Ht).
inversion H34; subst.
+ eexists; eexists; split; [reflexivity|]. split; [|assumption].
eapply star_compose; [eassumption|]. apply star_1. assumption.
+ eexists; eexists; split; [reflexivity|]. split; [assumption|].
eapply star_compose; [eassumption|]. apply star_1. assumption.
- eexists; eexists; split; [reflexivity|]. split; apply star_refl.
Qed.
Inductive hctx_conv defs :
hctx ->
hctx ->
Prop :=
|
hctx_conv_hole :
hctx_conv defs h_hole h_hole
|
hctx_conv_app :
forall h1 h2 t1 t2,
hctx_conv defs h1 h2 ->
convertible (
betaiota defs)
t1 t2 ->
hctx_conv defs (
h_app h1 t1) (
h_app h2 t2)
|
hctx_conv_switch :
forall h1 h2 m1 m2,
hctx_conv defs h1 h2 ->
Forall2 (
fun '(
p1,
t1) '(
p2,
t2) =>
p1 =
p2 /\
convertible (
betaiota defs)
t1 t2)
m1 m2 ->
hctx_conv defs (
h_switch h1 m1) (
h_switch h2 m2).
Lemma hctx_conv_refl :
forall defs h,
hctx_conv defs h h.
Proof.
intros defs h; induction h; constructor; simpl in *; try assumption.
- apply convertible_refl.
- apply Forall2_map_same. eapply Forall_True; intros [p t]; simpl; split; [reflexivity|apply convertible_refl].
Qed.
Lemma hctx_conv_sym :
forall defs h1 h2,
hctx_conv defs h1 h2 ->
hctx_conv defs h2 h1.
Proof.
intros defs h1 h2 H; induction H; constructor; simpl in *; try assumption.
- apply convertible_sym. assumption.
- apply Forall2_comm. eapply Forall2_impl; [|eassumption].
intros [p1 t1] [p2 t2] [H1 H2]; simpl; split; [congruence|].
apply convertible_sym. assumption.
Qed.
Lemma hctx_conv_trans :
forall defs h1 h2 h3,
hctx_conv defs h1 h2 ->
hctx_conv defs h2 h3 ->
hctx_conv defs h1 h3.
Proof.
intros defs h1 h2 h3 H12; revert h3; induction H12; intros h3 H23; inversion H23; subst; constructor.
- eapply IHhctx_conv; eassumption.
- eapply star_compose; eassumption.
- eapply IHhctx_conv; eassumption.
- apply Forall2_comm in H. eapply Forall3_select23.
eapply Forall3_impl, Forall3_from_Forall2; [|apply H|apply H4].
intros [p2 t2] [p1 t1] [p3 t3] [[Heq12 Hconv12] [Heq23 Hconv23]].
split; [congruence|]. eapply star_compose; eassumption.
Qed.
Lemma hctx_red_is_conv :
forall defs h1 h2,
hctx_red defs h1 h2 ->
hctx_conv defs h1 h2.
Proof.
intros defs h1 h2 H. induction H; constructor.
- assumption.
- apply convertible_refl.
- apply hctx_conv_refl.
- apply star_1. left. assumption.
- assumption.
- rewrite Forall2_map_same. eapply Forall_True; intros [p t]; simpl; split; [reflexivity|apply convertible_refl].
- apply hctx_conv_refl.
- apply Forall2_app; [|constructor]; try (rewrite Forall2_map_same; eapply Forall_True; intros [p3 t3]; simpl; split; (reflexivity || apply convertible_refl)).
split; [reflexivity|].
apply star_1. left. assumption.
Qed.
Lemma hctx_star_red_is_conv :
forall defs h1 h2,
star (
hctx_red defs)
h1 h2 ->
hctx_conv defs h1 h2.
Proof.
intros defs h1 h2 H. induction H.
- apply hctx_conv_refl.
- eapply hctx_conv_trans; [|eassumption].
apply hctx_red_is_conv; assumption.
Qed.
Lemma hctx_convertible_conv :
forall defs h1 h2,
hctx_convertible defs h1 h2 ->
hctx_conv defs h1 h2.
Proof.
intros defs h1 h2 (h3 & H1 & H2).
apply hctx_star_red_is_conv in H1, H2.
apply hctx_conv_sym in H2. eapply hctx_conv_trans; eassumption.
Qed.
Lemma hctx_conv_convertible :
forall defs h1 h2,
hctx_conv defs h1 h2 ->
hctx_convertible defs h1 h2.
Proof.
intros defs h1 h2 H. induction H.
- exists h_hole. split; apply star_refl.
- destruct IHhctx_conv as (h3 & H1 & H2).
eapply convertible_confluent_common_reduce in H0; [|apply beta_iota_confluent].
destruct H0 as (t3 & H3 & H4).
exists (h_app h3 t3).
split; eapply star_compose.
+ eapply star_map_impl; [|eassumption]. intros; constructor; eassumption.
+ eapply star_map_impl with (f := fun h => h_app h _); [|eassumption]. intros; constructor; eassumption.
+ eapply star_map_impl; [|eassumption]. intros; constructor; eassumption.
+ eapply star_map_impl with (f := fun h => h_app h _); [|eassumption]. intros; constructor; eassumption.
- destruct IHhctx_conv as (h3 & H1 & H2).
eapply Forall2_impl in H0; [apply Forall2_exists_Forall3 in H0|].
+ destruct H0 as (m3 & Hm3). exists (h_switch h3 m3).
split; eapply star_compose.
* eapply star_map_impl with (f := fun h => h_switch h _); [|eassumption]. intros; constructor; eassumption.
* eapply star_list with (RA := fun pt1 pt2 => fst pt1 = fst pt2 /\ betaiota defs (snd pt1) (snd pt2));
[|eapply Forall3_select13, Forall3_impl; [|eassumption]; intros x y z Hxyz; refine (proj1 Hxyz); shelve].
intros l1 l2 [p1 t1] [p2 t2] [Hp Ht]; simpl in *.
subst. constructor. assumption.
* eapply star_map_impl with (f := fun h => h_switch h _); [|eassumption]. intros; constructor; eassumption.
* eapply star_list with (RA := fun pt1 pt2 => fst pt1 = fst pt2 /\ betaiota defs (snd pt1) (snd pt2));
[|eapply Forall3_select23, Forall3_impl; [|eassumption]; intros x y z Hxyz; refine (proj2 Hxyz)].
intros l1 l2 [p1 t1] [p2 t2] [Hp Ht]; simpl in *.
subst. constructor. assumption.
+ intros [p1 t1] [p2 t2] [Hp Hconv].
eapply convertible_confluent_common_reduce in Hconv; [|apply beta_iota_confluent].
destruct Hconv as (t3 & Hconv1 & Hconv2); subst.
exists (p2, t3).
split; eapply star_map_impl with (f := fun t => (p2, t)); try eassumption;
intros; split; try reflexivity; assumption.
Qed.
Fixpoint hctx_length h :=
match h with
|
h_hole => 0
|
h_app h _ =>
S (
hctx_length h)
|
h_switch h _ =>
S (
hctx_length h)
end.
Lemma hctx_conv_length :
forall defs h1 h2,
hctx_conv defs h1 h2 ->
hctx_length h1 =
hctx_length h2.
Proof.
intros defs h1 h2 H; induction H; simpl in *; congruence.
Qed.
Lemma hctx_compose_length :
forall h1 h2,
hctx_length (
compose_hctx h1 h2) =
hctx_length h1 +
hctx_length h2.
Proof.
intros h1 h2; induction h1; simpl; lia.
Qed.
Lemma hctx_convertible_compose_r :
forall defs h1 h2 h3 h4,
hctx_length h1 =
hctx_length h2 ->
hctx_conv defs (
compose_hctx h3 h1) (
compose_hctx h4 h2) ->
hctx_conv defs h3 h4 /\
hctx_conv defs h1 h2.
Proof.
intros defs h1 h2 h3 h4 Hlen; revert h4; induction h3; intros h4 H; simpl in *; destruct h4; simpl in *.
- split; [constructor|]. assumption.
- apply hctx_conv_length in H. simpl in H; rewrite hctx_compose_length in H.
lia.
- apply hctx_conv_length in H. simpl in H; rewrite hctx_compose_length in H.
lia.
- apply hctx_conv_length in H. simpl in H; rewrite hctx_compose_length in H.
lia.
- inversion H; subst. apply IHh3 in H3.
split; [|tauto]. constructor; tauto.
- inversion H.
- apply hctx_conv_length in H. simpl in H; rewrite hctx_compose_length in H.
lia.
- inversion H.
- inversion H; subst. apply IHh3 in H3.
split; [|tauto]. constructor; tauto.
Qed.
Lemma hctx_convertible_compose :
forall defs h1 h2 h3 h4,
hctx_conv defs h3 h4 ->
hctx_conv defs h1 h2 ->
hctx_conv defs (
compose_hctx h3 h1) (
compose_hctx h4 h2).
Proof.
intros defs h1 h2 h3 h4 H34 H12; induction H34; simpl.
- assumption.
- constructor; assumption.
- constructor; assumption.
Qed.
Lemma cmp_cont_cthread_correct_None :
forall st defs c1 c2 varmap1 varmap2 h1 h2,
read_cont st defs varmap1 c1 h1 ->
read_cont st defs varmap2 c2 h2 ->
cmp_cont c1 c2 varmap1 varmap2 =
None ->
~ (
hctx_conv defs h1 h2).
Proof.
intros st defs c1 c2 varmap1 varmap2 h1 h2 Hread1 Hread2 Hcmp.
revert c2 h2 Hread2 Hcmp; induction Hread1; intros c2 h2 Hread2 Hcmp; inversion Hread2; subst; simpl in *;
simpl in Hcmp; try congruence.
- intros Hconv; inversion Hconv.
destruct h; simpl in *; congruence.
- intros Hconv; inversion Hconv.
destruct h; simpl in *; congruence.
- intros Hconv; inversion Hconv.
destruct h; simpl in *; congruence.
- intros Hconv.
apply hctx_convertible_compose_r in Hconv; [|reflexivity].
destruct cmp_cont eqn:Hcmp1; [congruence|]. eapply IHHread1 in Hcmp1; [|eassumption].
tauto.
- intros Hconv.
apply hctx_convertible_compose_r in Hconv; [|reflexivity].
destruct Hconv as [Hconv1 Hconv2]; inversion Hconv2.
- intros Hconv; inversion Hconv.
destruct h; simpl in *; congruence.
- intros Hconv.
apply hctx_convertible_compose_r in Hconv; [|reflexivity].
destruct Hconv as [Hconv1 Hconv2]; inversion Hconv2.
- intros Hconv.
apply hctx_convertible_compose_r in Hconv; [|reflexivity].
destruct Hconv as [Hconv1 Hconv2]; inversion Hconv2; subst.
destruct Nat.eqb eqn:Heq; [|rewrite Nat.eqb_neq in Heq].
+ destruct forallb eqn:Hforallb.
* destruct cmp_cont eqn:Hcmp1; [congruence|].
eapply IHHread1 in Hcmp1; [|eassumption].
tauto.
* rewrite <- Bool.not_true_iff_false in Hforallb. apply Hforallb.
rewrite forallb_forall, <- Forall_forall.
apply Forall_combine_from_Forall2. simpl.
eapply Forall2_impl; [|eapply Forall_square;
[eapply Forall3_select12, Forall3_impl, H0; intros pt vdeeps tdeep Hpt; exact (proj1 Hpt)|
eapply Forall3_select12, Forall3_impl, H3; intros pt vdeeps tdeep Hpt; exact (proj1 Hpt)|
rewrite Forall2_map_left, Forall2_map_right in H9; apply H9]].
intros vdeep1 vdeep2 ([p1 t1] & [p2 t2] & Hp1 & Hp2 & Hp & _). simpl in *.
apply Nat.eqb_eq. congruence.
+ rewrite Forall2_map_left, Forall2_map_right in H9; eapply Forall2_length in H9.
eapply Forall3_impl, Forall3_select12, Forall2_length in H0; [|intros; exact I].
eapply Forall3_impl, Forall3_select12, Forall2_length in H3; [|intros; exact I].
congruence.
Qed.
Lemma cmp_cont_cthread_correct_Some_false :
forall st defs c1 c2 varmap1 varmap2 h1 h2 l,
read_cont st defs varmap1 c1 h1 ->
read_cont st defs varmap2 c2 h2 ->
cmp_cont c1 c2 varmap1 varmap2 =
Some l ->
Exists (
fun c =>
read_cthread st defs c false)
l ->
~ (
hctx_conv defs h1 h2).
Proof.
intros st defs c1 c2 varmap1 varmap2 h1 h2 l Hread1 Hread2 Hcmp.
revert l c2 h2 Hread2 Hcmp; induction Hread1; intros l c2 h2 Hread2 Hcmp Hexist; inversion Hread2; subst; simpl in *;
simpl in Hcmp; try congruence.
- injection Hcmp as Hcmp; subst. inversion Hexist.
- destruct cmp_cont eqn:Hcmp1; [|congruence]. injection Hcmp as Hcmp; subst.
intros Hconv. apply hctx_convertible_compose_r in Hconv; [|reflexivity].
destruct Hconv as [Hconv1 Hconv2]; inversion Hconv2; subst.
inversion Hexist; subst.
+ inversion H3; subst. specialize (H10 _ _ H H0). inversion H10; subst. tauto.
+ eapply IHHread1 in H3; try eassumption. tauto.
- destruct Nat.eqb eqn:Heq; [|congruence]. rewrite Nat.eqb_eq in Heq.
destruct forallb eqn:Hforallb; [|congruence]. rewrite forallb_forall, <- Forall_forall in Hforallb.
apply Forall2_from_combine in Hforallb; [|assumption]. simpl in Hforallb.
destruct cmp_cont eqn:Hcmp1; [|congruence]. injection Hcmp as Hcmp; subst.
intros Hconv. apply hctx_convertible_compose_r in Hconv; [|reflexivity].
destruct Hconv as [Hconv1 Hconv2]; inversion Hconv2; subst.
rewrite Exists_app in Hexist; destruct Hexist as [Hexist | Hexist].
+ rewrite Exists_map in Hexist.
rewrite Forall2_map_left, Forall2_map_right in H9.
eapply Forall3_impl in H0; [|intros pt vdeeps tdeep (_ & Hread & Hconv & _);
refine (ex_intro (fun tdeep => _) tdeep _); exact (conj Hread Hconv)].
apply Forall3_select12 in H0.
eapply Forall3_impl in H3; [|intros pt vdeeps tdeep (_ & Hread & Hconv & _);
refine (ex_intro (fun tdeep => _) tdeep _); exact (conj Hread Hconv)].
apply Forall3_select12 in H3.
eapply Forall_Exists_neg; [|eassumption].
apply Forall_combine_from_Forall2.
eapply Forall2_impl; [|eapply Forall_square; eassumption].
intros vdeeps1 vdeeps2 ([p1 t1] & [p2 t2] & (tdeep1 & Ht1a & Ht1b) & (tdeep2 & Ht2a & Ht2b) & Hp & Hcv).
simpl in *.
intros Hreadc. inversion Hreadc; subst. specialize (H11 _ _ Ht1a Ht2a). inversion H11; subst.
apply H4. eapply star_compose; [|apply convertible_beta_betaiota; eassumption].
eapply star_compose; [apply convertible_sym, convertible_beta_betaiota; eassumption|].
assumption.
+ eapply IHHread1 in Hexist; try eassumption. tauto.
Qed.
Lemma cmp_cont_cthread_correct_Some_true :
forall st defs c1 c2 varmap1 varmap2 h1 h2 l,
read_cont st defs varmap1 c1 h1 ->
read_cont st defs varmap2 c2 h2 ->
cmp_cont c1 c2 varmap1 varmap2 =
Some l ->
Forall (
fun c =>
read_cthread st defs c true)
l ->
hctx_conv defs h1 h2.
Proof.
intros st defs c1 c2 varmap1 varmap2 h1 h2 l Hread1 Hread2 Hcmp.
revert l c2 h2 Hread2 Hcmp; induction Hread1; intros l c2 h2 Hread2 Hcmp Hforall; inversion Hread2; subst; simpl in *;
simpl in Hcmp; try congruence.
- injection Hcmp as Hcmp; subst. constructor.
- destruct cmp_cont eqn:Hcmp1; [|congruence]. injection Hcmp as Hcmp; subst.
inversion Hforall; subst.
apply hctx_convertible_compose; [|constructor; [constructor|]].
+ eapply IHHread1 in H5; eassumption.
+ inversion H4; subst. specialize (H9 _ _ H H0). inversion H9; subst. assumption.
- destruct Nat.eqb eqn:Heq; [|congruence]. rewrite Nat.eqb_eq in Heq.
destruct forallb eqn:Hforallb; [|congruence]. rewrite forallb_forall, <- Forall_forall in Hforallb.
apply Forall2_from_combine in Hforallb; [|assumption]. simpl in Hforallb.
destruct cmp_cont eqn:Hcmp1; [|congruence]. injection Hcmp as Hcmp; subst.
rewrite Forall_app_iff in Hforall; destruct Hforall as [Hforall1 Hforall2].
apply hctx_convertible_compose; [|constructor; [constructor|]].
+ eapply IHHread1 in Hforall2; eassumption.
+ rewrite Forall_map in Hforall1.
rewrite Forall2_map_left, Forall2_map_right.
eapply Forall3_impl in H0; [|intros pt vdeeps tdeep (Hlen & Hread & Hconv & _);
refine (ex_intro (fun tdeep => _) tdeep _); exact (conj Hlen (conj Hread Hconv))].
apply Forall3_select12, Forall2_comm in H0.
eapply Forall3_impl in H3; [|intros pt vdeeps tdeep (Hlen & Hread & Hconv & _);
refine (ex_intro (fun tdeep => _) tdeep _); exact (conj Hlen (conj Hread Hconv))].
apply Forall3_select12, Forall2_comm in H3.
eapply Forall2_from_combine in Hforall1; [|eassumption].
eapply Forall2_impl; [|eapply Forall_square; [eassumption|eassumption|eapply Forall2_and; [apply Hforallb|apply Hforall1]]].
intros [p1 t1] [p2 t2] (vdeeps1 & vdeeps2 & (tdeep1 & Hlen1 & Ht1a & Ht1b) & (tdeep2 & Hlen2 & Ht2a & Ht2b) & (Hlen & Hreadc)).
simpl in *.
inversion Hreadc; subst. specialize (H9 _ _ Ht1a Ht2a). inversion H9; subst.
split.
* rewrite Nat.eqb_eq in Hlen. congruence.
* eapply star_compose; [apply convertible_beta_betaiota; eassumption|].
eapply star_compose; [|apply convertible_sym, convertible_beta_betaiota; eassumption].
assumption.
Qed.
Lemma cmp_cont_cthread_correct :
forall st defs c1 c2 varmap1 varmap2 h1 h2 b,
read_cont st defs varmap1 c1 h1 ->
read_cont st defs varmap2 c2 h2 ->
read_cthread st defs (
cmp_cont_cthread c1 c2 varmap1 varmap2)
b ->
reflect (
hctx_convertible defs h1 h2)
b.
Proof.
intros st defs c1 c2 varmap1 varmap2 h1 h2 b Hread1 Hread2 Hread.
unfold cmp_cont_cthread in Hread. destruct cmp_cont eqn:Hcmp.
- destruct b.
+ constructor. apply hctx_conv_convertible.
eapply cmp_cont_cthread_correct_Some_true; try eassumption.
apply read_cthread_andn_true in Hread. assumption.
+ constructor. intros Hconv; apply hctx_convertible_conv in Hconv; revert Hconv.
eapply cmp_cont_cthread_correct_Some_false; try eassumption.
apply read_cthread_andn_false in Hread. assumption.
- inversion Hread; subst. constructor.
intros Hconv; apply hctx_convertible_conv in Hconv; revert Hconv.
eapply cmp_cont_cthread_correct_None; eassumption.
Qed.
Lemma convertible_fill_betaiota :
forall defs h1 h2 t1 t2,
hctx_convertible defs h1 h2 ->
convertible (
betaiota defs)
t1 t2 ->
convertible (
betaiota defs) (
fill_hctx h1 t1) (
fill_hctx h2 t2).
Proof.
intros defs h1 h2 t1 t2 Hh Ht.
destruct Hh as (h3 & Hh1 & Hh2).
apply convertible_confluent_common_reduce in Ht; [|apply beta_iota_confluent].
destruct Ht as (t3 & Ht1 & Ht2).
apply common_reduce_convertible with (z := fill_hctx h3 t3); apply fill_hctx_star; assumption.
Qed.
Lemma cthread_red_correct :
forall st defs ct1 ct2 b,
defs_wf defs ->
cthread_wf st defs ct1 ->
cthread_red st ct1 ct2 ->
read_cthread st defs ct2 b ->
read_cthread st defs ct1 b.
Proof.
intros st defs ct1 ct2 b Hdefs Hwf H1 H2.
revert H2; induction H1; intros H2; subst.
- inversion H2; subst; constructor.
intros t1 t2 Ht1 Ht2. apply H6; [|assumption].
inversion Ht1; subst.
eapply is_finished_read_thread in H3; [|eassumption].
assumption.
- inversion H2; subst; constructor.
intros t1 t2 Ht1 Ht2. apply H6; [assumption|].
inversion Ht2; subst.
eapply is_finished_read_thread in H3; [|eassumption].
assumption.
- inversion H2; subst. eapply cthread_red_wf in Hwf; [|constructor].
constructor.
intros t3 t4 Ht3 Ht4.
inversion Ht3; subst.
inversion Ht4; subst.
specialize (H5 _ _ H6 H10). simpl in *.
eapply reflect_iff; [|eassumption].
rewrite convertible_abs_iff.
etransitivity; [|eapply convertible_convertible_left, convertible_beta_betaiota, H7; assumption].
etransitivity; [|eapply convertible_convertible_right, convertible_beta_betaiota, H14; assumption].
reflexivity.
- constructor. intros t3 t4 Ht3 Ht4. inversion Ht3; subst. inversion Ht4; subst.
eapply reflect_iff; [apply convertible_constr_iff|].
eapply reflect_iff; [split; [intros [Heq Hconv]; exact Hconv|tauto]|].
destruct b; constructor; simpl.
+ rewrite read_cthread_andn_true in H2. rewrite Forall_map in H2.
apply Forall2_from_combine in H2; [|assumption]; simpl in H2.
eapply Forall2_impl; [|eapply Forall_square; eassumption].
intros t1 t2 (v1 & v2 & (Hread1 & Hread2 & Hread)). inversion Hread; subst.
specialize (H8 _ _ Hread1 Hread2). inversion H8. assumption.
+ rewrite read_cthread_andn_false in H2. rewrite Exists_map in H2.
apply Exists_neg_Forall2.
eapply Exists_impl; [|eapply Exists_square; eassumption].
intros [t1 t2] (v1 & v2 & (Hread1 & Hread2 & Hread)). simpl in *. inversion Hread; subst.
specialize (H8 _ _ Hread1 Hread2). inversion H8. assumption.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2; inversion Ht1; inversion Ht2; subst. constructor.
simpl. rewrite convertible_constr_iff.
intros [_ Hconv]. apply Forall2_length in H5, H10, Hconv. congruence.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2; inversion Ht1; inversion Ht2; subst. constructor.
simpl. rewrite convertible_constr_iff. tauto.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2; inversion Ht1; inversion Ht2; subst. constructor.
simpl. apply abs_constr_not_convertible.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2; inversion Ht1; inversion Ht2; subst. constructor.
simpl. apply constr_abs_not_convertible.
- constructor. intros t1 t2 Ht1 Ht2.
inversion H2; subst.
inversion Ht1; subst. inversion H6; subst.
eapply reflect_iff; [|apply H5; [apply H4|apply Ht2]].
apply convertible_convertible_left.
eapply star_compose; [|eapply star_impl; [|apply H4]; intros u1 u2 [Hu | Hu]; [left | right]; right; assumption].
apply star_1. left. left. apply iota_hctx.
rewrite index_notin_None; [constructor; [congruence|tauto]|].
intros Hx. inversion Hwf; subst.
rewrite Forall_forall in H11. apply H11 in Hx. symmetry in H0. apply nth_error_Some3 in H0. lia.
- constructor. intros t1 t2 Ht1 Ht2.
inversion H2; subst.
inversion Ht2; subst. inversion H6; subst.
eapply reflect_iff; [|apply H5; [apply Ht1|apply H4]].
apply convertible_convertible_right.
eapply star_compose; [|eapply star_impl; [|apply H4]; intros u1 u2 [Hu | Hu]; [left | right]; right; assumption].
apply star_1. left. left. apply iota_hctx.
rewrite index_notin_None; [constructor; [congruence|tauto]|].
intros Hx. inversion Hwf; subst.
rewrite Forall_forall in H12. apply H12 in Hx. symmetry in H0. apply nth_error_Some3 in H0. lia.
- constructor. intros t1 t2 Ht1 Ht2.
inversion H2; subst.
+ inversion H1; subst.
inversion Ht1; subst. inversion Ht2; subst. inversion H8; subst. inversion H12; subst.
eapply reflect_iff; [|apply H7; [apply H9|apply H16]].
inversion Hwf; subst.
apply convertible_convertible_leftright; try assumption.
* eapply star_compose; [|eapply star_impl; [|apply H9]; intros u1 u2 [Hu | Hu]; [left | right]; right; assumption].
apply star_1. left. left. apply iota_hctx.
rewrite index_notin_None; [constructor; [congruence|tauto]|].
intros Hx. rewrite Forall_forall in H19. apply H19 in Hx. symmetry in H0. apply nth_error_Some3 in H0. lia.
* eapply star_compose; [|eapply star_impl; [|apply H16]; intros u1 u2 [Hu | Hu]; [left | right]; right; assumption].
apply star_1. left. left. apply iota_hctx.
rewrite index_notin_None; [constructor; [congruence|tauto]|].
intros Hx. rewrite Forall_forall in H20. apply H20 in Hx. symmetry in H3. apply nth_error_Some3 in H3. lia.
+ inversion H3; subst.
inversion Ht1; subst. inversion Ht2; subst. inversion H7; subst. inversion H11; subst.
eapply reflect_iff; [|apply H6; [apply H8|apply H15]].
inversion Hwf; subst.
apply convertible_convertible_leftright; try assumption.
* eapply star_compose; [|eapply star_impl; [|apply H8]; intros u1 u2 [Hu | Hu]; [left | right]; right; assumption].
apply star_1. left. left. apply iota_hctx.
rewrite index_notin_None; [constructor; [congruence|tauto]|].
intros Hx. rewrite Forall_forall in H18. apply H18 in Hx. symmetry in H0. apply nth_error_Some3 in H0. lia.
* eapply star_compose; [|eapply star_impl; [|apply H15]; intros u1 u2 [Hu | Hu]; [left | right]; right; assumption].
apply star_1. left. left. apply iota_hctx.
rewrite index_notin_None; [constructor; [congruence|tauto]|].
intros Hx. rewrite Forall_forall in H19. apply H19 in Hx. symmetry in H1. apply nth_error_Some3 in H1. lia.
+ constructor.
inversion Ht1; subst. inversion Ht2; subst.
eapply cmp_cont_cthread_correct in H3; try eassumption. inversion H3; subst.
apply convertible_fill_betaiota; [assumption|]. apply star_same.
inversion Hwf; subst.
assert (x < length defs) by (inversion H6; subst; eapply nth_error_Some3; symmetry; eassumption).
rewrite !index_notin_None; [reflexivity| |].
* intros Hx. rewrite Forall_forall in H15. apply H15 in Hx. lia.
* intros Hx. rewrite Forall_forall in H14. apply H14 in Hx. lia.
- constructor. intros t1 t2 Ht1 Ht2. inversion Ht1; subst. inversion Ht2; subst.
eapply reflect_iff; [apply convertible_neutral_iff|].
+ simpl; destruct (index Nat.eq_dec varmap1 x1); simpl; [tauto|]. inversion H6; subst; reflexivity.
+ simpl; destruct (index Nat.eq_dec varmap2 x2); simpl; [tauto|]. inversion H10; subst; reflexivity.
+ simpl. eapply reflect_iff.
* split; [intros [_ Hctx]; exact Hctx|].
intros Hctx; split; [|assumption].
inversion H6; subst. inversion H10; subst.
symmetry in H0; symmetry in H1. apply H9 in H0; apply H13 in H1.
destruct index eqn:Hidx1; rewrite <- H; [reflexivity|].
eapply index_in_not_None in Hidx1; tauto.
* eapply cmp_cont_cthread_correct; eassumption.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2. inversion Ht1; subst. inversion Ht2; subst.
constructor.
inversion Hwf; subst.
rewrite convertible_neutral_iff.
+ intros [Heq Hconv]. apply H.
destruct (index Nat.eq_dec varmap1 x1); destruct (index Nat.eq_dec varmap2 x2); congruence.
+ destruct (index Nat.eq_dec varmap1 x1); simpl; [tauto|]. inversion H6; subst; reflexivity.
+ destruct (index Nat.eq_dec varmap2 x2); simpl; [tauto|]. inversion H10; subst; reflexivity.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2. inversion Ht1; subst. inversion Ht2; subst.
constructor. simpl.
apply abs_neutral_not_convertible. destruct index; simpl; [tauto|].
inversion H9; subst. reflexivity.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2. inversion Ht1; subst. inversion Ht2; subst.
constructor. simpl.
apply constr_neutral_not_convertible. destruct index; simpl; [tauto|].
inversion H6; subst. reflexivity.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2. inversion Ht1; subst. inversion Ht2; subst.
constructor. simpl.
apply neutral_abs_not_convertible. destruct index; simpl; [tauto|].
inversion H5; subst. reflexivity.
- inversion H2; subst. constructor.
intros t1 t2 Ht1 Ht2. inversion Ht1; subst. inversion Ht2; subst.
constructor. simpl.
apply neutral_constr_not_convertible. destruct index; simpl; [tauto|].
inversion H5; subst. reflexivity.
- inversion H2; subst. constructor; constructor.
- inversion H2; subst. constructor; constructor.
- inversion H2; subst. constructor; constructor.
- inversion H2; subst. constructor; constructor.
- inversion H2; subst. constructor; constructor.
- inversion H2; subst. constructor; constructor.
- inversion Hwf; subst. inversion H2; subst; constructor; tauto.
- inversion Hwf; subst. inversion H2; subst; constructor; tauto.
- inversion Hwf; subst. inversion H2; subst; constructor; tauto.
- inversion Hwf; subst. inversion H2; subst; constructor; tauto.
Qed.
Lemma read_cthread_step_r :
forall st defs rid ct b,
defs_wf defs ->
defs_ok defs st ->
state_wf st defs ->
cthread_wf st defs ct ->
read_cthread (
step_r st rid)
defs ct b ->
read_cthread st defs ct b.
Proof.
intros st defs rid ct b Hdefswf Hdefsok Hstwf Hwf Hread. induction Hread; subst.
- constructor; assumption.
- inversion Hwf; subst. constructor; tauto.
- inversion Hwf; subst. constructor; tauto.
- inversion Hwf; subst. constructor; tauto.
- inversion Hwf; subst. constructor; tauto.
- inversion Hwf; subst. constructor; tauto.
- inversion Hwf; subst. constructor; tauto.
- constructor. intros t1 t2 Ht1 Ht2.
inversion Hwf; subst.
eapply step_r_correct_val in Ht1; try eassumption.
eapply step_r_correct_val in Ht2; try eassumption.
destruct Ht1 as (t5 & Hread5 & Ht15).
destruct Ht2 as (t6 & Hread6 & Ht26).
specialize (H _ _ Hread5 Hread6).
eapply reflect_iff; [|eassumption].
apply convertible_convertible_leftright.
+ eapply star_impl; [|eassumption]. intros; constructor; constructor; assumption.
+ eapply star_impl; [|eassumption]. intros; constructor; constructor; assumption.
Qed.
Lemma cthread_wf_step_r :
forall st defs rid ct,
defs_wf defs ->
defs_ok defs st ->
state_wf st defs ->
cthread_wf st defs ct ->
cthread_wf (
step_r st rid)
defs ct.
Proof.
intros st defs rid ct Hdefswf Hdefsok Hstwf Hwf. induction Hwf.
- constructor.
- constructor; assumption.
- constructor; assumption.
- eapply step_r_correct_val in H4; try eassumption.
destruct H4 as (t3 & Ht3 & _).
eapply step_r_correct_val in H5; try eassumption.
destruct H5 as (t4 & Ht4 & _).
econstructor; try eassumption.
+ split; [|apply H1]. eapply Forall_impl; [|apply H1].
intros; simpl in *. eapply lt_le_trans; [eassumption|apply step_r_freename].
+ split; [|apply H2]. eapply Forall_impl; [|apply H2].
intros; simpl in *. eapply lt_le_trans; [eassumption|apply step_r_freename].
Qed.
Definition complete_wf defs ctst :=
defs_wf defs /\
defs_ok defs (
snd ctst) /\
state_wf (
snd ctst)
defs /\
cthread_wf (
snd ctst)
defs (
fst ctst).
Lemma step_wf :
forall ctst1 ctst2 defs,
step ctst1 ctst2 ->
complete_wf defs ctst1 ->
complete_wf defs ctst2.
Proof.
intros ctst1 ctst2 defs Hstep Hwf.
repeat split.
- apply Hwf.
- unfold defs_ok. eapply le_trans; [apply Hwf|].
inversion Hstep; subst; simpl; [|lia].
apply step_r_freename.
- inversion Hstep; subst; simpl; [|apply Hwf].
apply state_wf_preserve; apply Hwf.
- inversion Hstep; subst; simpl.
+ apply cthread_wf_step_r; apply Hwf.
+ eapply cthread_red_wf; [|eassumption]. apply Hwf.
Qed.
Lemma step_correct :
forall st1 st2 defs ct1 ct2 b,
complete_wf defs (
ct1,
st1) ->
step (
ct1,
st1) (
ct2,
st2) ->
read_cthread st2 defs ct2 b ->
read_cthread st1 defs ct1 b.
Proof.
intros st1 st2 defs ct1 ct2 b Hwf Hstep Hread.
inversion Hstep; subst.
- eapply read_cthread_step_r; try eassumption; apply Hwf.
- eapply cthread_red_correct; try eassumption; apply Hwf.
Qed.
Lemma star_step_correct :
forall ctst1 ctst2 defs b,
complete_wf defs ctst1 ->
star step ctst1 ctst2 ->
read_cthread (
snd ctst2)
defs (
fst ctst2)
b ->
read_cthread (
snd ctst1)
defs (
fst ctst1)
b.
Proof.
intros ctst1 ctst2 defs b Hwf Hstep Hread.
induction Hstep.
- assumption.
- destruct x, y, z; simpl in *. apply IHHstep in Hread.
+ eapply step_correct; eassumption.
+ eapply step_wf; eassumption.
Qed.
Initialisation for convertibility and correctness of the machine.
Definition init_conv (
defs :
list term) (
t1 t2 :
term) :=
let (
st,
vs) :=
init_all {|
st_rthreads :=
nil ;
st_freename :=
length defs |}
nil defs in
let (
st1,
v1) :=
makelazy st (
init_at 0
t1)
vs in
let (
st2,
v2) :=
makelazy st1 (
init_at 0
t2)
vs in
(
cthread_reduce v1 v2 nil nil,
st2).
Lemma init_all_freename :
forall st defs1 defs2,
st_freename (
fst (
init_all st defs1 defs2)) =
st_freename st.
Proof.
intros st defs1 defs2; revert st defs1; induction defs2; intros st defs1; simpl in *.
- reflexivity.
- rewrite IHdefs2. reflexivity.
Qed.
Lemma init_all_incl :
forall st defs1 defs2 v,
In v defs1 ->
In v (
snd (
init_all st defs1 defs2)).
Proof.
intros st defs1 defs2 v. revert st defs1; induction defs2; intros st defs1 H; simpl.
- assumption.
- apply IHdefs2. rewrite in_app_iff; tauto.
Qed.
Lemma init_all_new_threads :
forall st defs1 defs2 rid,
nth_error (
st_rthreads st)
rid =
None ->
nth_error (
st_rthreads (
fst (
init_all st defs1 defs2)))
rid <>
None ->
exists x,
In (
Neutral (
x,
Kid,
Some (
Thread rid))) (
snd (
init_all st defs1 defs2)).
Proof.
intros st defs1 defs2 rid; revert st defs1; induction defs2; intros st defs1 H1 H2; simpl in *.
- tauto.
- destruct (nth_error (st_rthreads (extend_rthread st {| rt_code := Term (init_at 0 a) defs1; rt_cont := Kid |})) rid) eqn:Hnth.
+ simpl in Hnth. rewrite nth_error_app2 in Hnth; [|apply nth_error_None; eassumption].
apply nth_error_None in H1.
destruct (_ - _) as [|n] eqn:Hn; [|destruct n; simpl in *; congruence].
replace rid with (length (st_rthreads st)) by lia.
eexists.
eapply init_all_incl. rewrite in_app_iff; simpl.
right; left. reflexivity.
+ eapply IHdefs2; eassumption.
Qed.
Lemma init_conv_correct :
forall defs t1 t2 st c,
defs_wf defs ->
closed_at t1 0 ->
closed_at t2 0 ->
dvar_below (
length defs)
t1 ->
dvar_below (
length defs)
t2 ->
init_conv defs t1 t2 = (
c,
st) ->
complete_wf defs (
c,
st) /\ (
forall b,
read_cthread st defs c b ->
reflect (
convertible (
betaiota defs)
t1 t2)
b).
Proof.
intros defs t1 t2 st c Hdefswf Hclosed1 Hclosed2 Hbelow1 Hbelow2 Hcv.
unfold init_conv in Hcv; simpl in *.
destruct init_all as [st2 vs] eqn:Hinit; simpl in *.
assert (Hinit2 := Hinit).
apply init_all_correct with (defs1 := nil) in Hinit; simpl; [|assumption|constructor|lia].
assert (Ht1 : read_thread st defs nil (length (st_rthreads st2)) t1).
{
injection Hcv as Hcv; subst.
refine (eq_rect _ (read_thread _ _ _ _) _ t1 _);
[eapply read_thread_term with (h := h_hole)|symmetry; apply init_at_correct]; simpl.
+ rewrite nth_error_app1; [|rewrite app_length; simpl; lia].
apply nth_error_extend.
+ apply Forall2_length in Hinit. rewrite Hinit, map_length, seq_length.
apply init_at_closed with (p := 0); assumption.
+ eapply Forall2_impl; [|eassumption].
intros v3 t3 H; simpl. eapply read_val_same; [|eassumption|]; [simpl; lia|].
intros a Ha. eapply read_val_points in Ha; [|eassumption]. destruct Ha as (? & ? & ?).
eapply unchanged_from_only_extended; [eassumption|].
eapply only_extended_trans; eapply only_extended_makelazy.
+ constructor.
+ apply init_at_no_dvar.
+ assumption.
+ assumption.
}
assert (Ht2 : read_thread st defs nil (length (st_rthreads st2) + 1) t2).
{
injection Hcv as Hcv; subst.
refine (eq_rect _ (read_thread _ _ _ _) _ t2 _);
[eapply read_thread_term with (h := h_hole)|symmetry; apply init_at_correct]; simpl.
+ rewrite nth_error_app2; [|rewrite app_length; simpl; lia].
rewrite app_length; simpl. destruct (_ - _) eqn:Heq; [|lia].
reflexivity.
+ apply Forall2_length in Hinit. rewrite Hinit, map_length, seq_length.
apply init_at_closed with (p := 0); assumption.
+ eapply Forall2_impl; [|eassumption].
intros v3 t3 H; simpl. eapply read_val_same; [|eassumption|]; [simpl; lia|].
intros a Ha. eapply read_val_points in Ha; [|eassumption]. destruct Ha as (? & ? & ?).
eapply unchanged_from_only_extended; [eassumption|].
eapply only_extended_trans; eapply only_extended_makelazy.
+ constructor.
+ apply init_at_no_dvar.
+ assumption.
+ assumption.
}
repeat split.
- assumption.
- simpl. unfold defs_ok. simpl.
injection Hcv as Hcv; subst; simpl.
replace st2 with (fst (st2, vs)) by reflexivity. rewrite <- Hinit2, init_all_freename.
simpl. lia.
- simpl. intros rid Hrid.
injection Hcv as Hcv; subst; simpl.
simpl in Hrid. destruct (le_lt_dec (length (st_rthreads st2) + 1) rid).
+ rewrite nth_error_app2 in Hrid by (rewrite app_length; simpl; lia).
rewrite app_length in Hrid; simpl in Hrid.
destruct (_ - _) as [|n] eqn:Heq; [|destruct n; simpl in *; congruence].
eexists. eexists. replace rid with (length (st_rthreads st2) + 1) by lia.
split; [|eassumption]. split; constructor.
+ rewrite nth_error_app1 in Hrid by (rewrite app_length; simpl; lia).
destruct (le_lt_dec (length (st_rthreads st2)) rid).
* replace rid with (length (st_rthreads st2)) by lia.
eexists. eexists. split; [|eassumption]. split; constructor.
* rewrite nth_error_app1 in Hrid by assumption.
replace st2 with (fst (st2, vs)) in Hrid by reflexivity.
rewrite <- Hinit2 in Hrid.
eapply init_all_new_threads in Hrid; [|simpl; destruct rid; reflexivity].
destruct Hrid as (x & Hx). rewrite Hinit2 in Hx; simpl in Hx.
eapply Forall2_In_left_transparent; [|eassumption|eassumption].
intros t Ht. inversion Ht; subst. inversion H4; subst. destruct H3 as (H3 & _ & _).
inversion H3; subst.
eexists; eexists.
split; [|eapply read_thread_only_extended; [simpl|eapply only_extended_trans; eapply only_extended_makelazy|eassumption]; lia].
split; constructor.
- injection Hcv as Hcv; subst; simpl. econstructor.
+ constructor.
+ constructor.
+ split; constructor.
+ split; constructor.
+ reflexivity.
+ constructor; eassumption.
+ constructor. rewrite app_length; simpl. eassumption.
- intros b Hb. injection Hcv as Hcv; subst; simpl.
inversion Hb; subst. apply H4.
+ constructor. assumption.
+ constructor. rewrite app_length; simpl. assumption.
Qed.
Lemma all_correct :
forall defs t1 t2 st b,
defs_wf defs ->
closed_at t1 0 ->
closed_at t2 0 ->
dvar_below (
length defs)
t1 ->
dvar_below (
length defs)
t2 ->
star step (
init_conv defs t1 t2) (
cthread_done b,
st) ->
reflect (
convertible (
betaiota defs)
t1 t2)
b.
Proof.
intros defs t1 t2 st b H1 H2 H3 H4 H5 H6.
eapply star_step_correct in H6; simpl; [| |constructor].
- eapply init_conv_correct in H6; try eassumption.
destruct init_conv; reflexivity.
- eapply init_conv_correct with (t1 := t1) (t2 := t2); try eassumption.
destruct init_conv; reflexivity.
Qed.
Print Assumptions all_correct.