Require Export operations state.
Local Open Scope expr_scope.
Local Open Scope ctype_scope.
Notation lrtype K := (
ptr_type K +
type K)%
type.
Notation rettype K := (
bool *
option (
type K))%
type.
Inductive focustype (
K :
Set) :=
|
Stmt_type :
rettype K →
focustype K
|
Expr_type :
type K →
focustype K
|
Fun_type :
funname →
focustype K.
Arguments Stmt_type {
_}
_.
Arguments Expr_type {
_}
_.
Arguments Fun_type {
_}
_.
Section typing.
Context `{
Env K}.
Notation envs := (
env K *
memenv K *
list (
type K))%
type.
Global Instance stack_item_valid :
Valid (
memenv K) (
index *
type K) := λ Δ
oτ,
Δ ⊢
oτ.1 :
oτ.2.
Global Instance rettype_valid :
Valid (
env K) (
rettype K) := λ Γ
mcτ,
match mcτ.2
with Some τ => ✓{Γ} τ |
_ =>
True end.
Inductive lrtype_valid' (Γ :
env K) :
lrtype K →
Prop :=
|
ltype_valid τ
p : ✓{Γ} τ
p →
lrtype_valid' Γ (
inl τ
p)
|
rtype_valid τ : ✓{Γ} τ →
lrtype_valid' Γ (
inr τ).
Global Instance lrtype_valid :
Valid (
env K) (
lrtype K) :=
lrtype_valid'.
Inductive lrval_typed' (Γ :
env K) (Δ :
memenv K) :
lrval K →
lrtype K →
Prop :=
|
lval_typed p τ
p : (Γ,Δ) ⊢
p : τ
p →
lrval_typed' Γ Δ (
inl p) (
inl τ
p)
|
rval_typed v τ : (Γ,Δ) ⊢
v : τ →
lrval_typed' Γ Δ (
inr v) (
inr τ).
Global Instance lrval_typed:
Typed (
env K *
memenv K) (
lrtype K) (
lrval K) :=
curry lrval_typed'.
Inductive expr_typed' (Γ :
env K) (Δ :
memenv K)
(τ
s :
list (
type K)) :
expr K →
lrtype K →
Prop :=
|
EVar_typed τ
i :
τ
s !!
i =
Some τ →
expr_typed' Γ Δ τ
s (
var i) (
inl (
TType τ))
|
EVal_typed Ω ν τ
lr :
✓{Γ,Δ} Ω → (Γ,Δ) ⊢ ν : τ
lr →
expr_typed' Γ Δ τ
s (%#{Ω} ν) τ
lr
|
ERtoL_typed e τ
p :
expr_typed' Γ Δ τ
s e (
inr (τ
p.*)) →
expr_typed' Γ Δ τ
s (.*
e) (
inl τ
p)
|
ERofL_typed e τ
p :
expr_typed' Γ Δ τ
s e (
inl τ
p) →
expr_typed' Γ Δ τ
s (&
e) (
inr (τ
p.*))
|
EAssign_typed ass e1 e2 τ1 τ2 :
assign_typed τ1 τ2
ass →
expr_typed' Γ Δ τ
s e1 (
inl (
TType τ1)) →
expr_typed' Γ Δ τ
s e2 (
inr τ2) →
expr_typed' Γ Δ τ
s (
e1 ::={
ass}
e2) (
inr τ1)
|
ECall_typed e es σ σ
s :
expr_typed' Γ Δ τ
s e (
inl (σ
s ~> σ)) →
Forall2 (
expr_typed' Γ Δ τ
s)
es (
inr <$> σ
s) →
type_complete Γ σ →
expr_typed' Γ Δ τ
s (
call e @
es) (
inr σ)
|
EAbort_typed τ :
✓{Γ} τ →
expr_typed' Γ Δ τ
s (
abort τ) (
inr τ)
|
ELoad_typed e τ :
expr_typed' Γ Δ τ
s e (
inl (
TType τ)) →
type_complete Γ τ →
expr_typed' Γ Δ τ
s (
load e) (
inr τ)
|
EEltL_typed e rs τ σ :
expr_typed' Γ Δ τ
s e (
inl (
TType τ)) → Γ ⊢
rs : τ ↣ σ →
expr_typed' Γ Δ τ
s (
e %>
rs) (
inl (
TType σ))
|
EEltR_typed e rs τ σ :
expr_typed' Γ Δ τ
s e (
inr τ) → Γ ⊢
rs : τ ↣ σ →
expr_typed' Γ Δ τ
s (
e #>
rs) (
inr σ)
|
EAlloc_typed τ
e τ
i :
✓{Γ} τ →
expr_typed' Γ Δ τ
s e (
inr (
intT τ
i)) →
expr_typed' Γ Δ τ
s (
alloc{τ}
e) (
inl (
TType τ))
|
EFree_typed e τ
p :
expr_typed' Γ Δ τ
s e (
inl τ
p) →
expr_typed' Γ Δ τ
s (
free e) (
inr voidT)
|
EUnOp_typed op e τ σ :
unop_typed op τ σ →
expr_typed' Γ Δ τ
s e (
inr τ) →
expr_typed' Γ Δ τ
s (@{
op}
e) (
inr σ)
|
EBinOp_typed op e1 e2 τ1 τ2 σ :
binop_typed op τ1 τ2 σ →
expr_typed' Γ Δ τ
s e1 (
inr τ1) →
expr_typed' Γ Δ τ
s e2 (
inr τ2) →
expr_typed' Γ Δ τ
s (
e1 @{
op}
e2) (
inr σ)
|
EIf_typed e1 e2 e3 τ
b σ
lr :
expr_typed' Γ Δ τ
s e1 (
inr (
baseT τ
b)) → τ
b ≠
TVoid →
expr_typed' Γ Δ τ
s e2 σ
lr →
expr_typed' Γ Δ τ
s e3 σ
lr →
expr_typed' Γ Δ τ
s (
if{
e1}
e2 else e3) σ
lr
|
EComma_typed e1 e2 τ
lr1 τ
lr2 :
expr_typed' Γ Δ τ
s e1 τ
lr1 →
expr_typed' Γ Δ τ
s e2 τ
lr2 →
expr_typed' Γ Δ τ
s (
e1 ,,
e2) τ
lr2
|
ECast_typed e τ σ :
expr_typed' Γ Δ τ
s e (
inr τ) →
cast_typed τ σ → ✓{Γ} σ →
expr_typed' Γ Δ τ
s (
cast{σ}
e) (
inr σ)
|
EInsert_typed r e1 e2 τ σ :
Γ ⊢
r : τ ↣ σ →
expr_typed' Γ Δ τ
s e1 (
inr σ) →
expr_typed' Γ Δ τ
s e2 (
inr τ) →
expr_typed' Γ Δ τ
s (#[
r:=
e1]
e2) (
inr τ).
Global Instance expr_typed:
Typed envs (
lrtype K) (
expr K) :=
curry3 expr_typed'.
Section expr_typed_ind.
Context (Γ :
env K) (Δ :
memenv K) (τ
s :
list (
type K)).
Context (
P :
expr K →
lrtype K →
Prop).
Context (
Pvar : ∀ τ
i, τ
s !!
i =
Some τ →
P (
var i) (
inl (
TType τ))).
Context (
Pval : ∀ Ω ν τ
lr, ✓{Γ,Δ} Ω → (Γ,Δ) ⊢ ν : τ
lr →
P (%#{Ω} ν) τ
lr).
Context (
Prtol : ∀
e τ
p,
(Γ,Δ,τ
s) ⊢
e :
inr (τ
p.*) →
P e (
inr (τ
p.*)) →
P (.*
e) (
inl τ
p)).
Context (
Profl : ∀
e τ
p,
(Γ,Δ,τ
s) ⊢
e :
inl τ
p →
P e (
inl τ
p) →
P (&
e) (
inr (τ
p.*))).
Context (
Passign : ∀
ass e1 e2 τ1 τ2,
assign_typed τ1 τ2
ass →
(Γ,Δ,τ
s) ⊢
e1 :
inl (
TType τ1) →
P e1 (
inl (
TType τ1)) →
(Γ,Δ,τ
s) ⊢
e2 :
inr τ2 →
P e2 (
inr τ2) →
P (
e1 ::={
ass}
e2) (
inr τ1)).
Context (
Pcall : ∀
e es σ σ
s,
(Γ,Δ,τ
s) ⊢
e :
inl (σ
s ~> σ) →
P e (
inl (σ
s ~> σ)) →
(Γ,Δ,τ
s) ⊢*
es :*
inr <$> σ
s →
Forall2 P es (
inr <$> σ
s) →
type_complete Γ σ →
P (
call e @
es) (
inr σ)).
Context (
Pabort : ∀ τ, ✓{Γ} τ →
P (
abort τ) (
inr τ)).
Context (
Pload : ∀
e τ,
(Γ,Δ,τ
s) ⊢
e :
inl (
TType τ) →
type_complete Γ τ →
P e (
inl (
TType τ)) →
P (
load e) (
inr τ)).
Context (
Peltl : ∀
e rs τ σ,
(Γ,Δ,τ
s) ⊢
e :
inl (
TType τ) →
P e (
inl (
TType τ)) →
Γ ⊢
rs : τ ↣ σ →
P (
e %>
rs) (
inl (
TType σ))).
Context (
Peltr : ∀
e rs τ σ,
(Γ,Δ,τ
s) ⊢
e :
inr τ →
P e (
inr τ) → Γ ⊢
rs : τ ↣ σ →
P (
e #>
rs) (
inr σ)).
Context (
Palloc : ∀ τ
e τ
i,
✓{Γ} τ → (Γ,Δ,τ
s) ⊢
e :
inr (
intT τ
i) →
P e (
inr (
intT τ
i)) →
P (
alloc{τ}
e) (
inl (
TType τ))).
Context (
Pfree : ∀
e τ
p,
(Γ,Δ,τ
s) ⊢
e :
inl τ
p →
P e (
inl τ
p) →
P (
free e) (
inr voidT)).
Context (
Punop : ∀
op e τ σ,
unop_typed op τ σ →
(Γ,Δ,τ
s) ⊢
e :
inr τ →
P e (
inr τ) →
P (@{
op}
e) (
inr σ)).
Context (
Pbinop : ∀
op e1 e2 τ1 τ2 σ,
binop_typed op τ1 τ2 σ → (Γ,Δ,τ
s) ⊢
e1 :
inr τ1 →
P e1 (
inr τ1) →
(Γ,Δ,τ
s) ⊢
e2 :
inr τ2 →
P e2 (
inr τ2) →
P (
e1 @{
op}
e2) (
inr σ)).
Context (
Pif : ∀
e1 e2 e3 τ
b σ
lr,
(Γ,Δ,τ
s) ⊢
e1 :
inr (
baseT τ
b) →
P e1 (
inr (
baseT τ
b)) → τ
b ≠
TVoid →
(Γ,Δ,τ
s) ⊢
e2 : σ
lr →
P e2 σ
lr →
(Γ,Δ,τ
s) ⊢
e3 : σ
lr →
P e3 σ
lr →
P (
if{
e1}
e2 else e3) σ
lr).
Context (
Pcomma : ∀
e1 e2 τ
lr1 τ
lr2,
(Γ,Δ,τ
s) ⊢
e1 : τ
lr1 →
P e1 τ
lr1 →
(Γ,Δ,τ
s) ⊢
e2 : τ
lr2 →
P e2 τ
lr2 →
P (
e1 ,,
e2) τ
lr2).
Context (
Pcast : ∀
e τ σ,
(Γ,Δ,τ
s) ⊢
e :
inr τ →
P e (
inr τ) →
cast_typed τ σ → ✓{Γ} σ →
P (
cast{σ}
e) (
inr σ)).
Context (
Pinsert : ∀
r e1 e2 τ σ,
Γ ⊢
r : τ ↣ σ → (Γ,Δ,τ
s) ⊢
e1 :
inr σ →
P e1 (
inr σ) →
(Γ,Δ,τ
s) ⊢
e2 :
inr τ →
P e2 (
inr τ) →
P (#[
r:=
e1]
e2) (
inr τ)).
Lemma expr_typed_ind : ∀
e τ,
expr_typed' Γ Δ τ
s e τ →
P e τ.
Proof.
fix 3; destruct 1; eauto using Forall2_impl. Qed.
End expr_typed_ind.
Inductive ectx_item_typed' (Γ :
env K) (Δ :
memenv K)
(τ
s :
list (
type K)) :
ectx_item K →
lrtype K →
lrtype K →
Prop :=
|
CRtoL_typed τ
p :
ectx_item_typed' Γ Δ τ
s (.* □) (
inr (τ
p.*)) (
inl τ
p)
|
CLtoR_typed τ
p :
ectx_item_typed' Γ Δ τ
s (& □) (
inl τ
p) (
inr (τ
p.*))
|
CAssignL_typed ass e2 τ1 τ2 :
assign_typed τ1 τ2
ass → (Γ,Δ,τ
s) ⊢
e2 :
inr τ2 →
ectx_item_typed' Γ Δ τ
s (□ ::={
ass}
e2) (
inl (
TType τ1)) (
inr τ1)
|
CAssignR_typed ass e1 τ1 τ2 :
assign_typed τ1 τ2
ass → (Γ,Δ,τ
s) ⊢
e1 :
inl (
TType τ1) →
ectx_item_typed' Γ Δ τ
s (
e1 ::={
ass} □) (
inr τ2) (
inr τ1)
|
CCallL_typed es σ
s σ :
(Γ,Δ,τ
s) ⊢*
es :*
inr <$> σ
s →
type_complete Γ σ →
ectx_item_typed' Γ Δ τ
s (
call □ @
es) (
inl (σ
s ~> σ)) (
inr σ)
|
CCallR_typed e es1 es2 σ σ
s1 τ σ
s2 :
(Γ,Δ,τ
s) ⊢
e :
inl ((σ
s1 ++ τ :: σ
s2) ~> σ) →
(Γ,Δ,τ
s) ⊢*
reverse es1 :*
inr <$> σ
s1 →
(Γ,Δ,τ
s) ⊢*
es2 :*
inr <$> σ
s2 →
type_complete Γ σ →
ectx_item_typed' Γ Δ τ
s (
call e @
es1 □
es2) (
inr τ) (
inr σ)
|
CLoad_typed τ :
type_complete Γ τ →
ectx_item_typed' Γ Δ τ
s (
load □) (
inl (
TType τ)) (
inr τ)
|
CEltL_typed rs τ σ :
Γ ⊢
rs : τ ↣ σ →
ectx_item_typed' Γ Δ τ
s (□ %>
rs) (
inl (
TType τ)) (
inl (
TType σ))
|
CEltR_typed rs τ σ :
Γ ⊢
rs : τ ↣ σ →
ectx_item_typed' Γ Δ τ
s (□ #>
rs) (
inr τ) (
inr σ)
|
CAlloc_typed τ τ
i :
✓{Γ} τ →
ectx_item_typed' Γ Δ τ
s (
alloc{τ} □) (
inr (
intT τ
i)) (
inl (
TType τ))
|
CFree_typed τ
p :
ectx_item_typed' Γ Δ τ
s (
free □) (
inl τ
p) (
inr voidT)
|
CUnOp_typed op τ σ :
unop_typed op τ σ →
ectx_item_typed' Γ Δ τ
s (@{
op} □) (
inr τ) (
inr σ)
|
CBinOpL_typed op e2 τ1 τ2 σ :
binop_typed op τ1 τ2 σ → (Γ,Δ,τ
s) ⊢
e2 :
inr τ2 →
ectx_item_typed' Γ Δ τ
s (□ @{
op}
e2) (
inr τ1) (
inr σ)
|
CBinOpR_typed op e1 τ1 τ2 σ :
binop_typed op τ1 τ2 σ → (Γ,Δ,τ
s) ⊢
e1 :
inr τ1 →
ectx_item_typed' Γ Δ τ
s (
e1 @{
op} □) (
inr τ2) (
inr σ)
|
CIf_typed e2 e3 τ
b σ
lr :
τ
b ≠
TVoid → (Γ,Δ,τ
s) ⊢
e2 : σ
lr → (Γ,Δ,τ
s) ⊢
e3 : σ
lr →
ectx_item_typed' Γ Δ τ
s (
if{□}
e2 else e3) (
inr (
baseT τ
b)) σ
lr
|
CComma_typed e2 τ
lr1 τ
lr2 :
(Γ,Δ,τ
s) ⊢
e2 : τ
lr2 →
ectx_item_typed' Γ Δ τ
s (□ ,,
e2) τ
lr1 τ
lr2
|
CCast_typed τ σ :
cast_typed τ σ → ✓{Γ} σ →
ectx_item_typed' Γ Δ τ
s (
cast{σ} □) (
inr τ) (
inr σ)
|
CInsertL_typed r e2 τ σ :
Γ ⊢
r : τ ↣ σ → (Γ,Δ,τ
s) ⊢
e2 :
inr τ →
ectx_item_typed' Γ Δ τ
s (#[
r:=□]
e2) (
inr σ) (
inr τ)
|
CInsertR_typed r e1 τ σ :
Γ ⊢
r : τ ↣ σ → (Γ,Δ,τ
s) ⊢
e1 :
inr σ →
ectx_item_typed' Γ Δ τ
s (#[
r:=
e1] □) (
inr τ) (
inr τ).
Global Instance ectx_item_typed:
PathTyped envs
(
lrtype K) (
lrtype K) (
ectx_item K) :=
curry3 ectx_item_typed'.
Inductive ectx_typed' (Γ
s :
envs) :
ectx K →
lrtype K →
lrtype K →
Prop :=
|
ectx_nil_typed_2 τ :
ectx_typed' Γ
s [] τ τ
|
ectx_cons_typed_2 Ei E τ1 τ2 τ3 :
Γ
s ⊢
Ei : τ1 ↣ τ2 →
ectx_typed' Γ
s E τ2 τ3 →
ectx_typed' Γ
s (
Ei ::
E) τ1 τ3.
Global Instance ectx_typed:
PathTyped envs (
lrtype K) (
lrtype K) (
ectx K) :=
ectx_typed'.
Inductive rettype_union :
option (
type K) →
option (
type K) →
option (
type K) →
Prop :=
|
rettype_union_idempotent mσ :
rettype_union mσ
mσ
mσ
|
rettype_union_Some_r σ :
rettype_union None (
Some σ) (
Some σ)
|
rettype_union_Some_l σ :
rettype_union (
Some σ)
None (
Some σ).
Inductive rettype_match :
rettype K →
type K →
Prop :=
|
rettype_match_true_Some σ :
rettype_match (
true,
Some σ) σ
|
rettype_match_false_Some :
rettype_match (
false,
Some voidT)
voidT
|
rettype_match_true_None σ :
rettype_match (
true,
None) σ
|
rettype_match_false_None :
rettype_match (
false,
None)
voidT.
Inductive stmt_typed' (Γ :
env K) (Δ :
memenv K)
(τ
s :
list (
type K)) :
stmt K →
rettype K →
Prop :=
|
SSkip_typed :
stmt_typed' Γ Δ τ
s skip (
false,
None)
|
SDo_typed e τ :
(Γ,Δ,τ
s) ⊢
e :
inr τ →
locks e = ∅ →
stmt_typed' Γ Δ τ
s (!
e) (
false,
None)
|
SGoto_typed l :
stmt_typed' Γ Δ τ
s (
goto l) (
true,
None)
|
SThrow_typed n :
stmt_typed' Γ Δ τ
s (
throw n) (
true,
None)
|
SReturn_typed e τ :
(Γ,Δ,τ
s) ⊢
e :
inr τ →
locks e = ∅ →
stmt_typed' Γ Δ τ
s (
ret e) (
true,
Some τ)
|
SCase_typed mx :
stmt_typed' Γ Δ τ
s (
scase mx) (
false,
None)
|
SLabel_typed l :
stmt_typed' Γ Δ τ
s (
label l) (
false,
None)
|
SLocal_typed' τ
s c mσ :
✓{Γ} τ →
stmt_typed' Γ Δ (τ :: τ
s)
s (
c,
mσ) →
stmt_typed' Γ Δ τ
s (
local{τ}
s) (
c,
mσ)
|
SComp_typed s1 s2 c1 mσ1
c2 mσ2
mσ :
stmt_typed' Γ Δ τ
s s1 (
c1,
mσ1) →
stmt_typed' Γ Δ τ
s s2 (
c2,
mσ2) →
rettype_union mσ1
mσ2
mσ →
stmt_typed' Γ Δ τ
s (
s1 ;;
s2) (
c2,
mσ)
|
SCatch_typed s c mσ :
stmt_typed' Γ Δ τ
s s (
c,
mσ) →
stmt_typed' Γ Δ τ
s (
catch s) (
false,
mσ)
|
SLoop_typed s c mσ :
stmt_typed' Γ Δ τ
s s (
c,
mσ) →
stmt_typed' Γ Δ τ
s (
loop s) (
true,
mσ)
|
SIf_typed e τ
b s1 s2 c1 mσ1
c2 mσ2
mσ :
(Γ,Δ,τ
s) ⊢
e :
inr (
baseT τ
b) → τ
b ≠
TVoid →
locks e = ∅ →
stmt_typed' Γ Δ τ
s s1 (
c1,
mσ1) →
stmt_typed' Γ Δ τ
s s2 (
c2,
mσ2) →
rettype_union mσ1
mσ2
mσ →
stmt_typed' Γ Δ τ
s (
if{
e}
s1 else s2) (
c1 &&
c2,
mσ)
|
SSwitch_typed e τ
i s c mσ :
(Γ,Δ,τ
s) ⊢
e :
inr (
intT τ
i) →
locks e = ∅ →
stmt_typed' Γ Δ τ
s s (
c,
mσ) →
stmt_typed' Γ Δ τ
s (
switch{
e}
s) (
false,
mσ).
Global Instance stmt_typed:
Typed envs (
rettype K) (
stmt K) :=
curry3 stmt_typed'.
Inductive sctx_item_typed' (Γ :
env K) (Δ :
memenv K)
(τ
s :
list (
type K)) :
sctx_item K →
relation (
rettype K) :=
|
CCompL_typed s2 c1 mσ1
c2 mσ2
mσ :
(Γ,Δ,τ
s) ⊢
s2 : (
c2,
mσ2) →
rettype_union mσ1
mσ2
mσ →
sctx_item_typed' Γ Δ τ
s (□ ;;
s2) (
c1,
mσ1) (
c2,
mσ)
|
CCompR_typed s1 c1 mσ1
c2 mσ2
mσ :
(Γ,Δ,τ
s) ⊢
s1 : (
c1,
mσ1) →
rettype_union mσ1
mσ2
mσ →
sctx_item_typed' Γ Δ τ
s (
s1 ;; □) (
c2,
mσ2) (
c2,
mσ)
|
Ccatch_typed c mσ :
sctx_item_typed' Γ Δ τ
s (
catch □) (
c,
mσ) (
false,
mσ)
|
CLoop_typed c mσ :
sctx_item_typed' Γ Δ τ
s (
loop □) (
c,
mσ) (
true,
mσ)
|
CIfL_typed e τ
b s2 c1 mσ1
c2 mσ2
mσ :
(Γ,Δ,τ
s) ⊢
e :
inr (
baseT τ
b) → τ
b ≠
TVoid →
locks e = ∅ →
(Γ,Δ,τ
s) ⊢
s2 : (
c2,
mσ2) →
rettype_union mσ1
mσ2
mσ →
sctx_item_typed' Γ Δ τ
s (
if{
e} □
else s2) (
c1,
mσ1) (
c1&&
c2,
mσ)
|
CIfR_typed e τ
b s1 c1 mσ1
c2 mσ2
mσ :
(Γ,Δ,τ
s) ⊢
e :
inr (
baseT τ
b) → τ
b ≠
TVoid →
locks e = ∅ →
(Γ,Δ,τ
s) ⊢
s1 : (
c1,
mσ1) →
rettype_union mσ1
mσ2
mσ →
sctx_item_typed' Γ Δ τ
s (
if{
e}
s1 else □) (
c2,
mσ2) (
c1&&
c2,
mσ)
|
CSWitch_typed e τ
i c mσ :
(Γ,Δ,τ
s) ⊢
e :
inr (
intT τ
i) →
locks e = ∅ →
sctx_item_typed' Γ Δ τ
s (
switch{
e} □) (
c,
mσ) (
false,
mσ).
Global Instance sctx_typed:
PathTyped envs (
rettype K)
(
rettype K) (
sctx_item K) :=
curry3 sctx_item_typed'.
Inductive esctx_item_typed' (Γ :
env K) (Δ :
memenv K)
(τ
s :
list (
type K)) :
esctx_item K →
type K →
rettype K →
Prop :=
|
CDoE_typed τ :
esctx_item_typed' Γ Δ τ
s (! □) τ (
false,
None)
|
CReturnE_typed τ :
esctx_item_typed' Γ Δ τ
s (
ret □) τ (
true,
Some τ)
|
CIfE_typed τ
b s1 s2 c1 mσ1
c2 mσ2
mσ :
τ
b ≠
TVoid → (Γ,Δ,τ
s) ⊢
s1 : (
c1,
mσ1) → (Γ,Δ,τ
s) ⊢
s2 : (
c2,
mσ2) →
rettype_union mσ1
mσ2
mσ →
esctx_item_typed' Γ Δ τ
s (
if{□}
s1 else s2)%
S (
baseT τ
b) (
c1&&
c2,
mσ)
|
CSwitchE_typed τ
i s c mσ :
(Γ,Δ,τ
s) ⊢
s : (
c,
mσ) →
esctx_item_typed' Γ Δ τ
s (
switch{□}
s) (
intT τ
i) (
false,
mσ).
Global Instance esctx_item_typed:
PathTyped envs (
type K)
(
rettype K) (
esctx_item K) :=
curry3 esctx_item_typed'.
Inductive ctx_item_typed'
(Γ :
env K) (Δ :
memenv K) (τ
s :
list (
type K)) :
ctx_item K →
focustype K →
focustype K →
Prop :=
|
CStmt_typed Es cmσ1
cmσ2 :
(Γ,Δ,τ
s) ⊢
Es :
cmσ1 ↣
cmσ2 →
ctx_item_typed' Γ Δ τ
s (
CStmt Es) (
Stmt_type cmσ1) (
Stmt_type cmσ2)
|
CLocal_typed o τ
c mσ :
Δ ⊢
o : τ →
ctx_item_typed' Γ Δ τ
s
(
CLocal o τ) (
Stmt_type (
c,
mσ)) (
Stmt_type (
c,
mσ))
|
CExpr_typed e Ee τ
cmσ :
(Γ,Δ,τ
s) ⊢
e :
inr τ →
locks e = ∅ → (Γ,Δ,τ
s) ⊢
Ee : τ ↣
cmσ →
ctx_item_typed' Γ Δ τ
s (
CExpr e Ee) (
Expr_type τ) (
Stmt_type cmσ)
|
CFun_typed E f σ
s τ σ :
Γ !!
f =
Some (σ
s,τ) → (Γ,Δ,τ
s) ⊢
E :
inr τ ↣
inr σ →
ctx_item_typed' Γ Δ τ
s (
CFun E) (
Fun_type f) (
Expr_type σ)
|
CParams_typed f σ
s os cmσ σ :
Γ !!
f =
Some (σ
s, σ) → Δ ⊢*
os :* σ
s →
rettype_match cmσ σ →
ctx_item_typed'
Γ Δ τ
s (
CParams f (
zip os σ
s)) (
Stmt_type cmσ) (
Fun_type f).
Global Instance ctx_item_typed:
PathTyped envs (
focustype K)
(
focustype K) (
ctx_item K) :=
curry3 ctx_item_typed'.
Inductive ctx_typed' (Γ
s :
env K *
memenv K) :
ctx K →
focustype K →
focustype K →
Prop :=
|
ctx_nil_typed_2 τ
f :
ctx_typed' Γ
s [] τ
f τ
f
|
ctx_cons_typed_2 Ek k τ
f1 τ
f2 τ
f3 :
(Γ
s,
locals k.*2) ⊢
Ek : τ
f1 ↣ τ
f2 →
ctx_typed' Γ
s k τ
f2 τ
f3 →
ctx_typed' Γ
s (
Ek ::
k) τ
f1 τ
f3.
Global Instance ctx_typed:
PathTyped (
env K *
memenv K)
(
focustype K) (
focustype K) (
ctx K) :=
ctx_typed'.
Inductive direction_typed' (Γ :
env K) (Δ :
memenv K) :
direction K →
rettype K →
Prop :=
|
Down_typed cmτ :
direction_typed' Γ Δ ↘
cmτ
|
Up_typed mτ :
direction_typed' Γ Δ ↗ (
false,
mτ)
|
Top_typed c v τ : (Γ,Δ) ⊢
v : τ →
direction_typed' Γ Δ (⇈
v) (
c,
Some τ)
|
Goto_typed l cmτ :
direction_typed' Γ Δ (↷
l)
cmτ
|
Throw_typed n cmτ :
direction_typed' Γ Δ (↑
n)
cmτ
|
Switch_typed mx cmτ :
direction_typed' Γ Δ (↓
mx)
cmτ.
Global Instance direction_typed:
Typed (
env K *
memenv K)
(
rettype K) (
direction K) :=
curry direction_typed'.
Inductive focus_typed' (Γ :
env K) (Δ :
memenv K)
(τ
s :
list (
type K)) :
focus K →
focustype K →
Prop :=
|
Stmt_typed d s cmσ :
(Γ,Δ,τ
s) ⊢
s :
cmσ → (Γ,Δ) ⊢
d :
cmσ →
focus_typed' Γ Δ τ
s (
Stmt d s) (
Stmt_type cmσ)
|
Expr_typed e τ :
(Γ,Δ,τ
s) ⊢
e :
inr τ →
focus_typed' Γ Δ τ
s (
Expr e) (
Expr_type τ)
|
Call_typed f vs σ
s σ :
Γ !!
f =
Some (σ
s,σ) → (Γ,Δ) ⊢*
vs :* σ
s →
focus_typed' Γ Δ τ
s (
Call f vs) (
Fun_type f)
|
Return_typed f σ
s σ
v :
Γ !!
f =
Some (σ
s, σ) →
(Γ,Δ) ⊢
v : σ →
focus_typed' Γ Δ τ
s (
Return f v) (
Fun_type f)
|
UndefExpr_typed E e τ
lr τ :
(Γ,Δ,τ
s) ⊢
e : τ
lr → (Γ,Δ,τ
s) ⊢
E : τ
lr ↣
inr τ →
focus_typed' Γ Δ τ
s (
Undef (
UndefExpr E e)) (
Expr_type τ)
|
UndefBranch_typed Es Ω
v τ
mσ :
✓{Γ,Δ} Ω → (Γ,Δ) ⊢
v : τ → (Γ,Δ,τ
s) ⊢
Es : τ ↣
mσ →
focus_typed' Γ Δ τ
s (
Undef (
UndefBranch Es Ω
v)) (
Stmt_type mσ).
Global Instance focus_typed:
Typed envs (
focustype K) (
focus K) :=
curry3 focus_typed'.
Global Instance state_typed :
Typed (
env K) (
focustype K) (
state K) := λ Γ
S σ
f, ∃ τ
f,
let '
State k φ
m :=
S in
(Γ,'{
m},
locals k.*2) ⊢ φ : τ
f ∧
(Γ,'{
m}) ⊢
k : τ
f ↣ σ
f ∧
✓{Γ}
m.
Definition funenv_prevalid (Γ :
env K) (Δ :
memenv K) (δ :
funenv K) :=
map_Forall (λ
f s, ∃ τ
s τ
cmτ,
Γ !!
f =
Some (τ
s,τ) ∧
Forall (
type_complete Γ) τ
s ∧
(Γ,Δ,τ
s) ⊢
s :
cmτ ∧
rettype_match cmτ τ ∧
gotos s ⊆
labels s ∧
throws_valid 0
s
) δ.
Global Instance funenv_valid:
Valid (
env K *
memenv K) (
funenv K) := λ ΓΔ δ,
let (Γ,Δ) := ΓΔ
in
funenv_prevalid Γ Δ δ ∧
dom funset (
env_f Γ) ⊆
dom funset δ.
End typing.
Section properties.
Context `{
EnvSpec K}.
Implicit Types Γ :
env K.
Implicit Types o :
index.
Implicit Types Δ :
memenv K.
Implicit Types m :
mem K.
Implicit Types e :
expr K.
Implicit Types s :
stmt K.
Implicit Types τ σ :
type K.
Implicit Types mτ
mσ :
option (
type K).
Implicit Types τ
lr :
lrtype K.
Implicit Types a :
addr K.
Implicit Types v :
val K.
Implicit Types ν :
lrval K.
Implicit Types Ei :
ectx_item K.
Implicit Types E :
ectx K.
Implicit Types Es :
sctx_item K.
Implicit Types Ee :
esctx_item K.
Implicit Types Ek :
ctx_item K.
Implicit Types k :
ctx K.
Implicit Types d :
direction K.
Lemma SLocal_typed Γ Δ τ
s τ
s c mσ :
✓{Γ} τ → (Γ,Δ,τ :: τ
s) ⊢
s : (
c,
mσ) → (Γ,Δ,τ
s) ⊢
local{τ}
s : (
c,
mσ).
Proof.
by constructor. Qed.
Lemma ltype_valid_inv Γ τ
p : ✓{Γ} (
inl τ
p) → ✓{Γ} τ
p.
Proof.
by inversion 1. Qed.
Lemma rtype_valid_inv Γ τ : ✓{Γ} (
inr τ) → ✓{Γ} τ.
Proof.
by inversion 1. Qed.
Lemma lval_typed_inv Γ Δ
p τ
p : (Γ,Δ) ⊢
inl p :
inl τ
p → (Γ,Δ) ⊢
p : τ
p.
Proof.
by inversion 1. Qed.
Lemma rval_typed_inv Γ Δ
v τ : (Γ,Δ) ⊢
inr v :
inr τ → (Γ,Δ) ⊢
v : τ.
Proof.
by inversion 1. Qed.
Lemma lrval_typed_type_valid Γ Δ ν τ
lr : ✓ Γ → (Γ,Δ) ⊢ ν : τ
lr → ✓{Γ} τ
lr.
Proof.
destruct 2; constructor;
eauto using val_typed_type_valid, ptr_typed_type_valid.
Qed.
Lemma expr_typed_type_valid Γ Δ τ
s e τ
lr :
✓ Γ → ✓{Γ}* τ
s → (Γ,Δ,τ
s) ⊢
e : τ
lr → ✓{Γ} τ
lr.
Proof.
induction 3 using @expr_typed_ind; decompose_Forall_hyps;
repeat match goal with
| H : ✓{_} (inl _) |- _ => valid_inversion H
| H : ✓{_} (inr _) |- _ => valid_inversion H
end; try constructor; eauto 5 using lrval_typed_type_valid,
type_valid_ptr_type_valid, unop_typed_type_valid, binop_typed_type_valid,
TBase_valid, TPtr_valid, TVoid_valid, type_valid_ptr_type_valid,
ref_seg_typed_ptr_type_valid, TBase_valid_inv, TPtr_valid_inv,
TFun_valid_inv_ret, type_complete_valid, assign_typed_type_valid.
Qed.
Lemma expr_inl_typed_type_valid Γ Δ τ
s e τ
p :
✓ Γ → ✓{Γ}* τ
s → (Γ,Δ,τ
s) ⊢
e :
inl τ
p → ✓{Γ} τ
p.
Proof.
eauto using expr_typed_type_valid, ltype_valid_inv. Qed.
Lemma expr_inr_typed_type_valid Γ Δ τ
s e τ :
✓ Γ → ✓{Γ}* τ
s → (Γ,Δ,τ
s) ⊢
e :
inr τ → ✓{Γ} τ.
Proof.
eauto using expr_typed_type_valid, rtype_valid_inv. Qed.
Lemma rettype_true_Some_valid Γ β σ : ✓{Γ} σ → ✓{Γ} (β,
Some σ).
Proof.
done. Qed.
Lemma rettype_union_type_valid Γ
mσ1
mσ2
c1 c2 mσ :
rettype_union mσ1
mσ2
mσ → ✓{Γ} (
c1,
mσ1) → ✓{Γ} (
c2,
mσ2) → ✓{Γ} (
c2,
mσ).
Proof.
destruct 1; eauto. Qed.
Lemma stmt_typed_type_valid Γ Δ τ
s s mcτ :
✓ Γ → ✓{Γ}* τ
s → (Γ,Δ,τ
s) ⊢
s :
mcτ → ✓{Γ}
mcτ.
Proof.
by induction 3; eauto; eauto using expr_inr_typed_type_valid,
rettype_union_type_valid, rettype_true_Some_valid.
Qed.
Lemma lrval_typed_weaken Γ1 Γ2 Δ1 Δ2 ν τ
lr :
✓ Γ1 → (Γ1,Δ1) ⊢ ν : τ
lr → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 → (Γ2,Δ2) ⊢ ν : τ
lr.
Proof.
destruct 2; typed_constructor; eauto using val_typed_weaken, ptr_typed_weaken.
Qed.
Lemma expr_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s1 τ
s2 e τ
lr :
✓ Γ1 → (Γ1,Δ1,τ
s1) ⊢
e : τ
lr → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
τ
s1 `
prefix_of` τ
s2 → (Γ2,Δ2,τ
s2) ⊢
e : τ
lr.
Proof.
intros ? He ?? [σs ->].
induction He using @expr_typed_ind; typed_constructor;
erewrite <-1?size_of_weaken by eauto; eauto using lrval_typed_weaken,
lookup_weaken, type_valid_weaken, lookup_app_l_Some, ref_typed_weaken,
ref_seg_typed_weaken, lockset_valid_weaken, type_complete_weaken.
Qed.
Lemma ectx_item_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s1 τ
s2 Ei τ
lr σ
lr :
✓ Γ1 → (Γ1,Δ1,τ
s1) ⊢
Ei : τ
lr ↣ σ
lr → Γ1 ⊆ Γ2 →
Δ1 ⇒ₘ Δ2 → τ
s1 `
prefix_of` τ
s2 → (Γ2,Δ2,τ
s2) ⊢
Ei : τ
lr ↣ σ
lr.
Proof.
destruct 2; typed_constructor; eauto using type_valid_weaken,
expr_typed_weaken, lookup_weaken, Forall2_impl,
ref_seg_typed_weaken, ref_typed_weaken, type_complete_weaken.
Qed.
Lemma ectx_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s1 τ
s2 E τ
lr σ
lr :
✓ Γ1 → (Γ1,Δ1,τ
s1) ⊢
E : τ
lr ↣ σ
lr → Γ1 ⊆ Γ2 →
Δ1 ⇒ₘ Δ2 → τ
s1 `
prefix_of` τ
s2 → (Γ2,Δ2,τ
s2) ⊢
E : τ
lr ↣ σ
lr.
Proof.
intros ? HE ???. revert τlr HE. induction E; intros; typed_inversion_all;
typed_constructor; eauto using ectx_item_typed_weaken.
Qed.
Lemma stmt_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s1 τ
s2 s cmτ :
✓ Γ1 → (Γ1,Δ1,τ
s1) ⊢
s :
cmτ → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
τ
s1 `
prefix_of` τ
s2 → (Γ2,Δ2,τ
s2) ⊢
s :
cmτ.
Proof.
intros ? Hs ??. revert τs2. induction Hs; typed_constructor;
erewrite <-1?size_of_weaken by eauto;
eauto using expr_typed_weaken, type_valid_weaken;
unfold typed, stmt_typed in *; simpl in *; eauto using prefix_of_cons.
Qed.
Lemma sctx_item_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s1 τ
s2 Es cmτ
cmσ :
✓ Γ1 → (Γ1,Δ1,τ
s1) ⊢
Es :
cmτ ↣
cmσ → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
τ
s1 `
prefix_of` τ
s2 → (Γ2,Δ2,τ
s2) ⊢
Es :
cmτ ↣
cmσ.
Proof.
destruct 2; typed_constructor;
eauto using stmt_typed_weaken, expr_typed_weaken.
Qed.
Lemma esctx_item_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s1 τ
s2 Ee τ
cmσ :
✓ Γ1 → (Γ1,Δ1,τ
s1) ⊢
Ee : τ ↣
cmσ → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
τ
s1 `
prefix_of` τ
s2 → (Γ2,Δ2,τ
s2) ⊢
Ee : τ ↣
cmσ.
Proof.
destruct 2; typed_constructor; eauto using stmt_typed_weaken. Qed.
Lemma ctx_item_typed_weaken Γ1 Γ2 Δ1 Δ2 τ
s Ek τ
f σ
f :
✓ Γ1 → (Γ1,Δ1,τ
s) ⊢
Ek : τ
f ↣ σ
f → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
(Γ2,Δ2,τ
s) ⊢
Ek : τ
f ↣ σ
f.
Proof.
destruct 2; typed_constructor; eauto using sctx_item_typed_weaken,
ectx_typed_weaken, esctx_item_typed_weaken, expr_typed_weaken,
Forall2_impl, lookup_fun_weaken, memenv_forward_typed.
Qed.
Lemma ctx_typed_weaken Γ1 Γ2 Δ1 Δ2
k τ
f σ
f :
✓ Γ1 → (Γ1,Δ1) ⊢
k : τ
f ↣ σ
f → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
(Γ2,Δ2) ⊢
k : τ
f ↣ σ
f.
Proof.
intros ? Hk ??. revert τf Hk. induction k; intros; typed_inversion_all;
typed_constructor; eauto using ctx_item_typed_weaken.
Qed.
Lemma direction_typed_weaken Γ1 Γ2 Δ1 Δ2
d τ
f :
✓ Γ1 → (Γ1,Δ1) ⊢
d : τ
f → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 → (Γ2,Δ2) ⊢
d : τ
f.
Proof.
destruct 2; typed_constructor; eauto using val_typed_weaken. Qed.
Lemma funenv_prevalid_weaken Γ1 Γ2 Δ1 Δ2 δ :
✓ Γ1 →
funenv_prevalid Γ1 Δ1 δ → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
funenv_prevalid Γ2 Δ2 δ.
Proof.
intros ? Hδ ?? f s ?. destruct (Hδ f s);
naive_solver eauto using stmt_typed_weaken, env_valid_args_valid,
types_valid_weaken, type_valid_weaken, lookup_fun_weaken,
types_complete_weaken, types_complete_valid.
Qed.
Lemma funenv_valid_weaken Γ Δ1 Δ2 δ :
✓ Γ → ✓{Γ,Δ1} δ → Δ1 ⇒ₘ Δ2 → ✓{Γ,Δ2} δ.
Proof.
destruct 2; split; simpl in *; eauto using funenv_prevalid_weaken. Qed.
Lemma funenv_prevalid_empty Γ Δ :
funenv_prevalid Γ Δ ∅.
Proof.
by intros ??; simpl_map. Qed.
Lemma funenv_prevalid_insert Γ Δ δ
f s τ τ
s cmτ :
funenv_prevalid Γ Δ δ →
Γ !!
f =
Some (τ
s, τ) →
Forall (
type_complete Γ) τ
s →
(Γ,Δ,τ
s) ⊢
s :
cmτ →
rettype_match cmτ τ →
gotos s ⊆
labels s →
throws_valid 0
s →
funenv_prevalid Γ Δ (<[
f:=
s]> δ).
Proof.
intros ??????? f' s'; rewrite lookup_insert_Some; naive_solver. Qed.
Lemma funenv_lookup Γ Δ δ
f τ
s τ :
✓ Γ → ✓{Γ,Δ} δ → Γ !!
f =
Some (τ
s,τ) → ∃
s cmτ,
δ !!
f =
Some s ∧
Forall (
type_complete Γ) τ
s ∧
(Γ,Δ,τ
s) ⊢
s :
cmτ ∧
rettype_match cmτ τ ∧
gotos s ⊆
labels s ∧
throws_valid 0
s.
Proof.
intros ? [Hδ HΓf] ?; simpl in *. assert (∃ s, δ !! f = Some s) as [s ?].
{ apply elem_of_dom, HΓf, elem_of_dom; eauto. }
destruct (Hδ f s) as (?&?&?&?&?); simplify_equality; eauto.
Qed.
Lemma funenv_lookup_inv Γ Δ δ
f s :
✓ Γ → ✓{Γ,Δ} δ → δ !!
f =
Some s → ∃ τ
s τ
cmτ,
Γ !!
f =
Some (τ
s,τ) ∧ (Γ,Δ,τ
s) ⊢
s :
cmτ ∧
rettype_match cmτ τ ∧
gotos s ⊆
labels s ∧
throws_valid 0
s.
Proof.
intros ? [Hδ _] ?. destruct (Hδ f s); naive_solver. Qed.
Lemma funenv_lookup_gotos Γ Δ δ
f s :
✓ Γ → ✓{Γ,Δ} δ → δ !!
f =
Some s →
gotos s ⊆
labels s.
Proof.
intros. by destruct (funenv_lookup_inv Γ Δ δ f s) as (?&?&?&?&?&?&?&?).
Qed.
Lemma funenv_lookup_throws Γ Δ δ
f s :
✓ Γ → ✓{Γ,Δ} δ → δ !!
f =
Some s →
throws_valid 0
s.
Proof.
intros. by destruct (funenv_lookup_inv Γ Δ δ f s) as (?&?&?&?&?&?&?&?).
Qed.
Lemma EVals_typed Γ Δ τ
s Ω
s vs σ
s :
length Ω
s =
length vs → ✓{Γ,Δ}* Ω
s → (Γ,Δ) ⊢*
vs :* σ
s →
(Γ,Δ,τ
s) ⊢* #{Ω
s}*
vs :*
inr <$> σ
s.
Proof.
rewrite <-Forall2_same_length. intros Hvs ?. revert σs.
induction Hvs; intros [|??] ?; decompose_Forall_hyps;
repeat constructor; auto.
Qed.
Lemma EVals_typed_inv Γ Δ τ
s Ω
s vs σ
s :
length Ω
s =
length vs →
(Γ,Δ,τ
s) ⊢* #{Ω
s}*
vs :*
inr <$> σ
s → (Γ,Δ) ⊢*
vs :* σ
s.
Proof.
rewrite <-Forall2_same_length. intros Hvs. revert σs.
induction Hvs; intros [|??] ?; decompose_Forall_hyps;
typed_inversion_all; constructor; auto.
Qed.
Lemma indexes_valid_weaken Δ1 Δ2 ρ : ✓{Δ1}* ρ → Δ1 ⇒ₘ Δ2 → ✓{Δ2}* ρ.
Proof.
unfold valid, stack_item_valid.
induction 1; eauto using memenv_forward_typed.
Qed.
Lemma ctx_typed_locals_valid Γ Δ
k τ
f σ
f :
(Γ,Δ) ⊢
k : τ
f ↣ σ
f → ✓{Δ}* (
locals k).
Proof.
assert (∀ os σs, Δ ⊢* os :* σs → ✓{Δ}* (zip os σs))
by (induction 1; simpl; eauto).
induction 1 as [|Ek k ??? []]; naive_solver.
Qed.
Lemma ectx_item_subst_typed Γ Δ τ
s Ei e τ
lr σ
lr :
(Γ,Δ,τ
s) ⊢
Ei : τ
lr ↣ σ
lr →
(Γ,Δ,τ
s) ⊢
e : τ
lr → (Γ,Δ,τ
s) ⊢
subst Ei e : σ
lr.
Proof.
destruct 1; simpl; typed_constructor; eauto.
rewrite ?fmap_app; eauto using Forall2_app, Forall2_cons.
Qed.
Lemma ectx_subst_typed Γ Δ τ
s E e τ
lr σ
lr :
(Γ,Δ,τ
s) ⊢
E : τ
lr ↣ σ
lr →
(Γ,Δ,τ
s) ⊢
e : τ
lr → (Γ,Δ,τ
s) ⊢
subst E e : σ
lr.
Proof.
intros HE. revert e. induction HE; simpl; eauto using ectx_item_subst_typed.
Qed.
Lemma ectx_item_subst_typed_rev Γ Δ τ
s Ei e σ
lr :
(Γ,Δ,τ
s) ⊢
subst Ei e : σ
lr →
∃ τ
lr, (Γ,Δ,τ
s) ⊢
e : τ
lr ∧ (Γ,Δ,τ
s) ⊢
Ei : τ
lr ↣ σ
lr.
Proof.
intros He. destruct Ei; typed_inversion He;
list_simplifier; eexists; split_ands; repeat typed_constructor; eauto.
Qed.
Lemma ectx_subst_typed_rev Γ Δ τ
s E e σ
lr :
(Γ,Δ,τ
s) ⊢
subst E e : σ
lr →
∃ τ
lr, (Γ,Δ,τ
s) ⊢
e : τ
lr ∧ (Γ,Δ,τ
s) ⊢
E : τ
lr ↣ σ
lr.
Proof.
revert e. induction E as [|Ei E IH]; simpl; intros e ?.
{ exists σlr. by repeat constructor. }
edestruct (IH (subst Ei e)) as (τlr1&?&?); auto.
destruct (ectx_item_subst_typed_rev Γ Δ τs Ei e τlr1) as (τlr2&?&?); auto.
exists τlr2; split; auto. typed_constructor; eauto.
Qed.
Lemma sctx_item_subst_typed Γ Δ τ
s Es s cmτ
cmσ :
(Γ,Δ,τ
s) ⊢
Es :
cmτ ↣
cmσ → (Γ,Δ,τ
s) ⊢
s :
cmτ →
(Γ,Δ,τ
s) ⊢
subst Es s :
cmσ.
Proof.
destruct 1; simpl; typed_constructor; eauto; esolve_elem_of. Qed.
Lemma sctx_item_subst_typed_rev Γ Δ τ
s Es s cmσ :
(Γ,Δ,τ
s) ⊢
subst Es s :
cmσ →
∃
cmτ, (Γ,Δ,τ
s) ⊢
s :
cmτ ∧ (Γ,Δ,τ
s) ⊢
Es :
cmτ ↣
cmσ.
Proof.
intros Hs. destruct Es; simpl; typed_inversion Hs;
eexists; split_ands; repeat typed_constructor; eauto.
Qed.
Lemma esctx_item_subst_typed Γ Δ τ
s Ee e τ
cmσ :
(Γ,Δ,τ
s) ⊢
Ee : τ ↣
cmσ → (Γ,Δ,τ
s) ⊢
e :
inr τ →
locks e = ∅ →
(Γ,Δ,τ
s) ⊢
subst Ee e :
cmσ.
Proof.
destruct 1; simpl; typed_constructor; eauto. Qed.
Lemma esctx_item_subst_typed_rev Γ Δ τ
s Ee e cmσ :
(Γ,Δ,τ
s) ⊢
subst Ee e :
cmσ →
∃ τ, (Γ,Δ,τ
s) ⊢
e :
inr τ ∧
locks e = ∅ ∧ (Γ,Δ,τ
s) ⊢
Ee : τ ↣
cmσ.
Proof.
intros He. destruct Ee; simpl; typed_inversion He;
eexists; split_ands; repeat typed_constructor; eauto.
Qed.
Lemma sctx_item_typed_Some_l Γ Δ τ
s Es c1 τ
cmτ :
(Γ,Δ,τ
s) ⊢
Es : (
c1,
Some τ) ↣
cmτ → ∃
c2,
cmτ = (
c2,
Some τ).
Proof.
intros HEs. typed_inversion HEs; repeat match goal with
| H : rettype_union _ _ _ |- _ => inversion_clear H
end; eauto.
Qed.
Lemma rettype_union_inv_l mτ2 τ1
mτ :
rettype_union (
Some τ1)
mτ2
mτ →
mτ =
Some τ1.
Proof.
by inversion_clear 1. Qed.
Lemma rettype_union_inv_r mτ1 τ2
mτ :
rettype_union mτ1 (
Some τ2)
mτ →
mτ =
Some τ2.
Proof.
by inversion_clear 1. Qed.
Lemma rettype_union_l mσ :
rettype_union mσ
None mσ.
Proof.
destruct mσ; constructor. Qed.
Lemma rettype_union_r mσ :
rettype_union None mσ
mσ.
Proof.
destruct mσ; constructor. Qed.
Lemma rettype_match_Some_inv c τ1 τ2 :
rettype_match (
c,
Some τ1) τ2 → τ1 = τ2.
Proof.
by inversion_clear 1. Qed.
Lemma rettype_match_false_inv mτ τ :
rettype_match (
false,
mτ) τ → τ =
voidT.
Proof.
by inversion_clear 1. Qed.
Lemma expr_typed_freeze Γ Δ β τ
s e τ
lr :
(Γ,Δ,τ
s) ⊢
e : τ
lr → (Γ,Δ,τ
s) ⊢
freeze β
e : τ
lr.
Proof.
induction 1 using @expr_typed_ind; csimpl; typed_constructor; eauto;
by apply ref_seg_typed_freeze ||
by apply ref_typed_freeze || by apply Forall2_fmap_l.
Qed.
Lemma expr_typed_lift Γ Δ τ
s e τ
lr :
(Γ,Δ,τ
s) ⊢
e↑ : τ
lr ↔ (Γ,Δ,
tail τ
s) ⊢
e : τ
lr.
Proof.
split.
* assert (∀ es σs,
Forall (λ e, ∀ τlr, (Γ,Δ,τs) ⊢ e↑ : τlr → (Γ,Δ,tail τs) ⊢ e : τlr) es →
(Γ,Δ,τs) ⊢* expr_lift <$> es :* inr <$> σs →
(Γ,Δ,tail τs) ⊢* es :* inr <$> σs).
{ intros es σs. rewrite Forall2_fmap.
induction 2; decompose_Forall_hyps; eauto. }
revert τlr. induction e using @expr_ind_alt; csimpl; intros τlr He;
typed_inversion He; typed_constructor; rewrite ?lookup_tail; eauto.
* induction 1 using @expr_typed_ind; csimpl;
typed_constructor; rewrite <-?lookup_tail; eauto.
by apply Forall2_fmap_l.
Qed.
Lemma expr_typed_var_free Γ Δ τ
s1 τ
s2 e τ
lr :
vars e = ∅ → (Γ,Δ,τ
s1) ⊢
e : τ
lr → (Γ,Δ,τ
s2) ⊢
e : τ
lr.
Proof.
assert (∀ es σs, ⋃ (vars <$> es) = ∅ →
Forall2 (λ e τlr, vars e = ∅ → (Γ,Δ,τs2) ⊢ e : τlr) es (inr <$> σs) →
(Γ,Δ,τs2) ⊢* es :* inr <$> σs).
{ induction 2; simplify_equality'; decompose_empty; eauto. }
induction 2 using @expr_typed_ind; simplify_equality';
decompose_empty; typed_constructor; eauto.
Qed.
End properties.