Module executable
Require Export state operations.
Section executable.
Context `{
Env K}.
Definition assign_exec (Γ :
env K) (
m :
mem K) (
a :
addr K)
(
v :
val K) (
ass :
assign) :
option (
val K *
val K) :=
match ass with
|
Assign =>
guard (
val_cast_ok Γ
m (
type_of a)
v);
let v' :=
val_cast (
type_of a)
v in
Some (
v',
v')
|
PreOp op =>
va ←
m !!{Γ}
a;
guard (
val_binop_ok Γ
m op va v);
let v' :=
val_binop Γ
op va v in
guard (
val_cast_ok Γ
m (
type_of a)
v');
let v'' :=
val_cast (
type_of a)
v'
in
Some (
v'',
v'')
|
PostOp op =>
va ←
m !!{Γ}
a;
guard (
val_binop_ok Γ
m op va v);
let v' :=
val_binop Γ
op va v in
guard (
val_cast_ok Γ
m (
type_of a)
v');
Some (
val_cast (
type_of a)
v',
va)
end.
Fixpoint ctx_lookup (
x :
nat) (
k :
ctx K) :
option (
index *
type K) :=
match k with
| (
CStmt _ |
CExpr _ _) ::
k =>
ctx_lookup x k
|
CLocal o τ ::
k =>
match x with 0 =>
Some (
o,τ) |
S x =>
ctx_lookup x k end
|
CParams _ oτ
s ::
_ =>
oτ
s !!
x
|
_ =>
None
end.
Definition ehexec (Γ :
env K) (
k :
ctx K)
(
e :
expr K) (
m :
mem K) :
listset (
expr K *
mem K) :=
match e with
|
var x =>
'(
o,τ) ←
of_option (
ctx_lookup x k);
{[ %(
Ptr (
addr_top o τ)),
m ]}
| .* (#{Ω} (
ptrV p)) =>
guard (
ptr_alive'
m p);
{[ %{Ω}
p,
m ]}
| & (%{Ω}
p) =>
{[ #{Ω} (
ptrV p),
m ]}
| %{Ω
l} (
Ptr a) ::={
ass} #{Ω
r}
v =>
guard (
mem_writable Γ
a m);
'(
va,
v') ←
of_option (
assign_exec Γ
m a v ass);
{[ #{
lock_singleton Γ
a ∪ Ω
l ∪ Ω
r}
v',
mem_lock Γ
a (<[
a:=
va]{Γ}>
m) ]}
|
load (%{Ω} (
Ptr a)) =>
v ←
of_option (
m !!{Γ}
a);
{[ #{Ω}
v,
mem_force Γ
a m ]}
| %{Ω} (
Ptr a) %>
rs =>
guard (
addr_strict Γ
a);
{[ %{Ω} (
Ptr (
addr_elt Γ
rs a)),
m ]}
| #{Ω}
v #>
rs =>
v' ←
of_option (
v !!{Γ}
rs);
{[ #{Ω}
v',
m ]}
|
alloc{τ} (#{Ω}
intV{
_}
n) =>
let o :=
fresh (
dom indexset m)
in
let n' :=
Z.to_nat n in
guard (
n' ≠ 0);
{[ %{Ω}
Ptr (
addr_top_array o τ
n),
mem_alloc Γ
o true perm_full (
val_new Γ (τ.[
n']))
m ]}
∪ (
if alloc_can_fail then {[ %{Ω}
NULL (
TType τ),
m ]}
else ∅)
|
free (%{Ω} (
Ptr a)) =>
guard (
mem_freeable a m);
{[ #{Ω}
voidV,
mem_free (
addr_index a)
m ]}
| @{
op} #{Ω}
v =>
guard (
val_unop_ok m op v);
{[ #{Ω}
val_unop op v,
m ]}
| #{Ω
l}
vl @{
op} #{Ω
r}
vr =>
guard (
val_binop_ok Γ
m op vl vr);
{[ #{Ω
l ∪ Ω
r}
val_binop Γ
op vl vr,
m ]}
|
if{#{Ω}
VBase vb}
e2 else e3 =>
guard (
base_val_branchable m vb);
if decide (
base_val_is_0 vb)
then {[
e3,
mem_unlock Ω
m ]}
else {[
e2,
mem_unlock Ω
m ]}
| %#{Ω}
_,,
er =>
{[
er,
mem_unlock Ω
m ]}
|
cast{τ} (#{Ω}
v) =>
guard (
val_cast_ok Γ
m (
TType τ)
v);
{[ #{Ω}
val_cast (
TType τ)
v,
m ]}
| #[
r:=#{Ω1}
v1] (#{Ω2}
v2) =>
guard (
is_Some (
v2 !!{Γ}
r));
{[ #{Ω1 ∪ Ω2}
val_alter Γ (λ
_,
v1)
r v2,
m ]}
|
_ => ∅
end%
E.
Definition cexec (Γ :
env K) (δ :
funenv K)
(
S :
state K) :
listset (
state K) :=
let '
State k φ
m :=
S in
match φ
with
|
Stmt ↘
s =>
match s with
|
skip => {[
State k (
Stmt ↗
skip)
m ]}
|
goto l => {[
State k (
Stmt (↷
l) (
goto l))
m ]}
|
throw n => {[
State k (
Stmt (↑
n) (
throw n))
m ]}
|
label l => {[
State k (
Stmt ↗ (
label l))
m ]}
|
scase mx => {[
State k (
Stmt ↗ (
scase mx))
m ]}
| !
e => {[
State (
CExpr e (! □) ::
k) (
Expr e)
m ]}
|
ret e => {[
State (
CExpr e (
ret □) ::
k) (
Expr e)
m ]}
|
loop s => {[
State (
CStmt (
loop □) ::
k) (
Stmt ↘
s)
m ]}
|
s1 ;;
s2 => {[
State (
CStmt (□ ;;
s2) ::
k) (
Stmt ↘
s1)
m ]}
|
catch s => {[
State (
CStmt (
catch □) ::
k) (
Stmt ↘
s)
m ]}
|
if{
e}
s1 else s2 =>
{[
State (
CExpr e (
if{□}
s1 else s2) ::
k) (
Expr e)
m ]}
|
switch{
e}
s =>
{[
State (
CExpr e (
switch{□}
s) ::
k) (
Expr e)
m ]}
|
local{τ}
s =>
let o :=
fresh (
dom indexset m)
in
{[
State (
CLocal o τ ::
k) (
Stmt ↘
s)
(
mem_alloc Γ
o false perm_full (
val_new Γ τ)
m) ]}
end
|
Stmt ↗
s =>
match k with
|
CLocal o τ ::
k => {[
State k (
Stmt ↗ (
local{τ}
s)) (
mem_free o m) ]}
|
CStmt (□ ;;
s2) ::
k => {[
State (
CStmt (
s ;; □) ::
k) (
Stmt ↘
s2)
m ]}
|
CStmt (
s1 ;; □) ::
k => {[
State k (
Stmt ↗ (
s1 ;;
s))
m ]}
|
CStmt (
catch □) ::
k => {[
State k (
Stmt ↗ (
catch s))
m ]}
|
CStmt (
loop □) ::
k => {[
State k (
Stmt ↘ (
loop s))
m ]}
|
CStmt (
if{
e} □
else s2) ::
k => {[
State k (
Stmt ↗ (
if{
e}
s else s2))
m ]}
|
CStmt (
if{
e}
s1 else □) ::
k => {[
State k (
Stmt ↗ (
if{
e}
s1 else s))
m ]}
|
CStmt (
switch{
e} □) ::
k => {[
State k (
Stmt ↗ (
switch{
e}
s))
m ]}
|
CParams f oτ
s ::
k =>
{[
State k (
Return f voidV) (
foldr mem_free m (
oτ
s.*1)) ]}
|
_ => ∅
end
|
Stmt (⇈
v)
s =>
match k with
|
CParams f oτ
s ::
k =>
{[
State k (
Return f v) (
foldr mem_free m (
oτ
s.*1)) ]}
|
CLocal o τ ::
k => {[
State k (
Stmt (⇈
v) (
local{τ}
s)) (
mem_free o m) ]}
|
CStmt E ::
k => {[
State k (
Stmt (⇈
v) (
subst E s))
m ]}
|
_ => ∅
end
|
Stmt (↷
l)
s =>
if decide (
l ∈
labels s)
then
match s with
|
label l' => {[
State k (
Stmt ↗
s)
m ]}
|
local{τ}
s =>
let o :=
fresh (
dom indexset m)
in
{[
State (
CLocal o τ ::
k) (
Stmt (↷
l)
s)
(
mem_alloc Γ
o false perm_full (
val_new Γ τ)
m) ]}
|
catch s => {[
State (
CStmt (
catch □) ::
k) (
Stmt (↷
l)
s)
m ]}
|
s1 ;;
s2 =>
(
guard (
l ∈
labels s1);
{[
State (
CStmt (□ ;;
s2) ::
k) (
Stmt (↷
l)
s1)
m ]})
∪ (
guard (
l ∈
labels s2);
{[
State (
CStmt (
s1 ;; □) ::
k) (
Stmt (↷
l)
s2)
m ]})
|
loop s => {[
State (
CStmt (
loop □) ::
k) (
Stmt (↷
l)
s)
m ]}
|
if{
e}
s1 else s2 =>
(
guard (
l ∈
labels s1);
{[
State (
CStmt (
if{
e} □
else s2) ::
k) (
Stmt (↷
l)
s1)
m ]})
∪ (
guard (
l ∈
labels s2);
{[
State (
CStmt (
if{
e}
s1 else □) ::
k) (
Stmt (↷
l)
s2)
m ]})
|
switch{
e}
s => {[
State (
CStmt (
switch{
e} □) ::
k) (
Stmt (↷
l)
s)
m ]}
|
_ => ∅
end
else
match k with
|
CLocal o τ ::
k => {[
State k (
Stmt (↷
l) (
local{τ}
s)) (
mem_free o m) ]}
|
CStmt Es ::
k => {[
State k (
Stmt (↷
l) (
subst Es s))
m ]}
|
_ => ∅
end
|
Stmt (↓
mx)
s =>
match s with
|
scase mx' =>
guard (
mx =
mx');
{[
State k (
Stmt ↗
s)
m ]}
|
local{τ}
s =>
guard (
mx ∈
cases s);
let o :=
fresh (
dom indexset m)
in
{[
State (
CLocal o τ ::
k) (
Stmt (↓
mx)
s)
(
mem_alloc Γ
o false perm_full (
val_new Γ τ)
m) ]}
|
catch s =>
guard (
mx ∈
cases s);
{[
State (
CStmt (
catch □) ::
k) (
Stmt (↓
mx)
s)
m ]}
|
s1 ;;
s2 =>
(
guard (
mx ∈
cases s1);
{[
State (
CStmt (□ ;;
s2) ::
k) (
Stmt (↓
mx)
s1)
m ]})
∪ (
guard (
mx ∈
cases s2);
{[
State (
CStmt (
s1 ;; □) ::
k) (
Stmt (↓
mx)
s2)
m ]})
|
loop s =>
guard (
mx ∈
cases s);
{[
State (
CStmt (
loop □) ::
k) (
Stmt (↓
mx)
s)
m ]}
|
if{
e}
s1 else s2 =>
(
guard (
mx ∈
cases s1);
{[
State (
CStmt (
if{
e} □
else s2) ::
k) (
Stmt (↓
mx)
s1)
m ]})
∪ (
guard (
mx ∈
cases s2);
{[
State (
CStmt (
if{
e}
s1 else □) ::
k) (
Stmt (↓
mx)
s2)
m ]})
|
_ => ∅
end
|
Stmt (↑
n)
s =>
match k with
|
CLocal o τ ::
k => {[
State k (
Stmt (↑
n) (
local{τ}
s)) (
mem_free o m) ]}
|
CStmt Es ::
k =>
if decide (
Es =
catch □)
then
match n with
| 0 => {[
State k (
Stmt ↗ (
catch s))
m ]}
|
S n => {[
State k (
Stmt (↑
n) (
catch s))
m ]}
end
else {[
State k (
Stmt (↑
n) (
subst Es s))
m ]}
|
_ => ∅
end
|
Call f vs =>
s ←
of_option (δ !!
f);
let os :=
fresh_list (
length vs) (
dom indexset m)
in
let m2 :=
mem_alloc_list Γ
os vs m in
{[
State (
CParams f (
zip os (
type_of <$>
vs)) ::
k) (
Stmt ↘
s)
m2 ]}
|
Return f v =>
match k with
|
CFun E ::
k => {[
State k (
Expr (
subst E (#
v)%
E))
m ]}
|
_ => ∅
end
|
Expr e =>
match maybe2 EVal e with
|
Some (Ω,
inr v) =>
match k return listset (
state K)
with
|
CExpr e (! □) ::
k => {[
State k (
Stmt ↗ (!
e)) (
mem_unlock Ω
m) ]}
|
CExpr e (
ret □) ::
k =>
{[
State k (
Stmt (⇈
v) (
ret e)) (
mem_unlock Ω
m) ]}
|
CExpr e (
if{□}
s1 else s2) ::
k =>
vb ←
of_option (
maybe VBase v);
if decide (
base_val_branchable m vb)
return listset (
state K)
then
if decide (
base_val_is_0 vb)
return listset (
state K)
then
{[
State (
CStmt (
if{
e}
s1 else □) ::
k) (
Stmt ↘
s2) (
mem_unlock Ω
m)]}
else
{[
State (
CStmt (
if{
e} □
else s2) ::
k) (
Stmt ↘
s1) (
mem_unlock Ω
m)]}
else {[
State k (
Undef (
UndefBranch (
if{□}
s1 else s2) Ω
v))
m ]}
|
CExpr e (
switch{□}
s) ::
k =>
vb ←
of_option (
maybe VBase v);
if decide (
base_val_branchable m vb)
return listset (
state K)
then
'(τ
i,
x) ←
of_option (
maybe2 VInt vb);
let m' :=
mem_unlock Ω
m in
if decide (
Some x ∈
cases s)
return listset (
state K)
then
{[
State (
CStmt (
switch{
e} □) ::
k) (
Stmt (↓ (
Some x))
s)
m' ]}
else if decide (
None ∈
cases s)
return listset (
state K)
then
{[
State (
CStmt (
switch{
e} □) ::
k) (
Stmt (↓
None)
s)
m' ]}
else {[
State k (
Stmt ↗ (
switch{
e}
s))
m' ]}
else {[
State k (
Undef (
UndefBranch (
switch{□}
s) Ω
v))
m ]}
|
_ => ∅
end
|
Some (
_,
inl _) => ∅
|
None =>
'(
E,
e') ←
expr_redexes e;
match maybe_ECall_redex e'
with
|
Some (Ω,
f,
_,
_, Ω
s,
vs) =>
{[
State (
CFun E ::
k) (
Call f vs) (
mem_unlock (Ω ∪ ⋃ Ω
s)
m) ]}
|
None =>
let es :=
ehexec Γ
k e'
m in
if decide (
es ≡ ∅)
then {[
State k (
Undef (
UndefExpr E e'))
m ]}
else '(
e2,
m2) ←
es; {[
State k (
Expr (
subst E e2))
m2 ]}
end
end
|
Undef _ => ∅
end.
End executable.
Notation "Γ \ δ ⊢ₛ
S1 ⇒ₑ
S2" := (
S2 ∈
cexec Γ δ
S1)
(
at level 74, δ
at next level,
format "Γ \ δ ⊢ₛ '['
S1 '⇒ₑ' '/'
S2 ']'") :
C_scope.
Notation "Γ \ δ ⊢ₛ
S1 ⇒ₑ*
S2" := (
rtc (λ
S1'
S2', Γ \ δ ⊢ₛ
S1' ⇒ₑ
S2')
S1 S2)
(
at level 74, δ
at next level,
format "Γ \ δ ⊢ₛ '['
S1 '⇒ₑ*' '/'
S2 ']'") :
C_scope.