Require Export bits.
Local Open Scope cbase_type_scope.
Inductive base_val (
K :
Set) :
Set :=
|
VIndet :
base_type K →
base_val K
|
VVoid :
base_val K
|
VInt :
int_type K →
Z →
base_val K
|
VPtr :
ptr K →
base_val K
|
VByte :
list (
bit K) →
base_val K.
Arguments VIndet {
_}
_.
Arguments VVoid {
_}.
Arguments VInt {
_}
_ _.
Arguments VPtr {
_}
_.
Arguments VByte {
_}
_.
Delimit Scope base_val_scope with B.
Bind Scope base_val_scope with base_val.
Open Scope base_val_scope.
Notation "'
voidV'" :=
VVoid :
base_val_scope.
Notation "'
indetV' τ
b" := (
VIndet τ
b) (
at level 10) :
base_val_scope.
Notation "'
intV{' τ
i }
x" := (
VInt τ
i x)
(
at level 10,
format "
intV{ τ
i }
x") :
base_val_scope.
Notation "'
ptrV'
p" := (
VPtr p) (
at level 10) :
base_val_scope.
Notation "'
byteV'
bs" := (
VByte bs) (
at level 10) :
base_val_scope.
Instance maybe_VInt {
K} :
Maybe2 (@
VInt K) := λ
vb,
match vb with VInt τ
i x =>
Some (τ
i,
x) |
_ =>
None end.
Instance maybe_VPtr {
K} :
Maybe (@
VPtr K) := λ
vb,
match vb with VPtr p =>
Some p |
_ =>
None end.
Instance base_val_eq_dec {
K :
Set} `{∀
k1 k2 :
K,
Decision (
k1 =
k2)}
(
v1 v2 :
base_val K) :
Decision (
v1 =
v2).
Proof.
solve_decision. Defined.
Section operations.
Context `{
Env K}.
Record char_byte_valid (Γ :
env K)
(Δ :
memenv K) (
bs :
list (
bit K)) :
Prop := {
char_byte_valid_indet : ¬
Forall (
BIndet =)
bs;
char_byte_valid_bit : ¬(∃ β
s,
bs =
BBit <$> β
s);
char_byte_valid_bits_valid : ✓{Γ,Δ}*
bs;
char_byte_valid_bits :
length bs =
char_bits
}.
Global Instance char_byte_valid_dec Γ Δ
bs :
Decision (
char_byte_valid Γ Δ
bs).
Proof.
refine (cast_if (decide (¬Forall (BIndet =) bs ∧
¬(∃ βs, bs = BBit <$> βs) ∧ ✓{Γ,Δ}* bs ∧ length bs = char_bits)));
abstract (constructor||intros[]; intuition).
Defined.
Inductive base_typed' (Γ :
env K) (Δ :
memenv K) :
base_val K →
base_type K →
Prop :=
|
VIndet_typed τ
b : ✓{Γ} τ
b → τ
b ≠
voidT →
base_typed' Γ Δ (
VIndet τ
b) τ
b
|
VVoid_typed :
base_typed' Γ Δ
VVoid voidT
|
VInt_typed x τ
i :
int_typed x τ
i →
base_typed' Γ Δ (
VInt τ
i x) (
intT τ
i)
|
VPtr_typed p τ
p : (Γ,Δ) ⊢
p : τ
p →
base_typed' Γ Δ (
VPtr p) (τ
p.*)
|
VByte_typed bs :
char_byte_valid Γ Δ
bs →
base_typed' Γ Δ (
VByte bs)
ucharT.
Global Instance base_typed:
Typed (
env K *
memenv K)
(
base_type K) (
base_val K) :=
curry base_typed'.
Global Instance type_of_base_val:
TypeOf (
base_type K) (
base_val K) := λ
v,
match v with
|
VIndet τ
b => τ
b
|
VVoid =>
voidT
|
VInt τ
i _ =>
intT τ
i
|
VPtr p =>
type_of p.*
|
VByte _ =>
ucharT
end.
Global Instance base_type_check:
TypeCheck (
env K *
memenv K) (
base_type K) (
base_val K) := λ ΓΔ
v,
match v with
|
VIndet τ
b =>
guard (✓{ΓΔ.1} τ
b);
guard (τ
b ≠
voidT);
Some τ
b
|
VVoid =>
Some voidT
|
VInt τ
i x =>
guard (
int_typed x τ
i);
Some (
intT τ
i)
|
VPtr p =>
TPtr <$>
type_check ΓΔ
p
|
VByte bs =>
guard (
char_byte_valid (ΓΔ.1) (ΓΔ.2)
bs);
Some ucharT
end.
Global Instance base_val_freeze :
Freeze (
base_val K) := λ β
v,
match v with VPtr p =>
VPtr (
freeze β
p) |
_ =>
v end.
Definition base_val_flatten (Γ :
env K) (
v :
base_val K) :
list (
bit K) :=
match v with
|
VIndet τ
b =>
replicate (
bit_size_of Γ τ
b)
BIndet
|
VVoid =>
replicate (
bit_size_of Γ
voidT)
BIndet
|
VInt τ
i x =>
BBit <$>
int_to_bits τ
i x
|
VPtr p =>
BPtr <$>
ptr_to_bits Γ
p
|
VByte bs =>
bs
end.
Definition base_val_unflatten (Γ :
env K)
(τ
b :
base_type K) (
bs :
list (
bit K)) :
base_val K :=
match τ
b with
|
voidT =>
VVoid
|
intT τ
i =>
match mapM (
maybe BBit)
bs with
|
Some β
s =>
VInt τ
i (
int_of_bits τ
i β
s)
|
None =>
if decide (τ
i =
ucharT%
IT ∧ ¬
Forall (
BIndet =)
bs)
then VByte bs else VIndet τ
b
end
| τ
p.* =>
default (
VIndet τ
b) (
mapM (
maybe BPtr)
bs ≫=
ptr_of_bits Γ τ
p)
VPtr
end.
End operations.
Arguments base_val_unflatten _ _ _ _ _ :
simpl never.
Section base_values.
Context `{
EnvSpec K}.
Implicit Types Γ :
env K.
Implicit Types Δ :
memenv K.
Implicit Types α :
bool.
Implicit Types τ
b :
base_type K.
Implicit Types τ
p :
ptr_type K.
Implicit Types vb :
base_val K.
Implicit Types bs :
list (
bit K).
Implicit Types β
s :
list bool.
Local Infix "⊑*" := (
Forall2 bit_weak_refine) (
at level 70).
Hint Extern 0 (
_ ⊑*
_) =>
reflexivity.
General properties of the typing judgment
Lemma base_val_typed_type_valid Γ Δ
v τ
b : ✓ Γ → (Γ,Δ) ⊢
v : τ
b → ✓{Γ} τ
b.
Proof.
destruct 2;
eauto using TVoid_valid, TInt_valid, TPtr_valid, ptr_typed_type_valid.
Qed.
Global Instance:
TypeOfSpec (
env K *
memenv K) (
base_type K) (
base_val K).
Proof.
intros [??]. destruct 1; f_equal'; auto. eapply type_of_correct; eauto.
Qed.
Global Instance:
TypeCheckSpec (
env K *
memenv K) (
base_type K) (
base_val K) (λ
_,
True).
Proof.
intros [Γ Δm] vb τb _. split.
* destruct vb; intros; simplify_option_equality;
constructor; auto; eapply type_check_sound; eauto.
* by destruct 1; simplify_option_equality;
erewrite ?type_check_complete by eauto.
Qed.
Lemma char_byte_valid_weaken Γ1 Γ2 Δ1 Δ2
bs :
✓ Γ1 →
char_byte_valid Γ1 Δ1
bs → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 →
char_byte_valid Γ2 Δ2
bs.
Proof.
destruct 2; constructor; eauto using Forall_impl, bit_valid_weaken. Qed.
Lemma base_val_typed_weaken Γ1 Γ2 Δ1 Δ2
vb τ
b :
✓ Γ1 → (Γ1,Δ1) ⊢
vb : τ
b → Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 → (Γ2,Δ2) ⊢
vb : τ
b.
Proof.
destruct 2; econstructor; eauto using ptr_typed_weaken,
char_byte_valid_weaken, base_type_valid_weaken.
Qed.
Lemma base_val_freeze_freeze β1 β2
vb :
freeze β1 (
freeze β2
vb) =
freeze β1
vb.
Proof.
destruct vb; f_equal'; auto using ptr_freeze_freeze. Qed.
Lemma base_typed_freeze Γ Δ β
vb τ
b :
(Γ,Δ) ⊢
freeze β
vb : τ
b ↔ (Γ,Δ) ⊢
vb : τ
b.
Proof.
split.
* destruct vb; inversion 1; constructor; auto.
by apply (ptr_typed_freeze _ _ β).
* destruct 1; constructor; auto. by apply ptr_typed_freeze.
Qed.
Lemma base_typed_int_frozen Γ Δ
vb τ
i : (Γ,Δ) ⊢
vb :
intT τ
i →
frozen vb.
Proof.
inversion_clear 1; constructor. Qed.
Properties of the base_val_flatten function
Lemma base_val_flatten_valid Γ Δ
vb τ
b :
(Γ,Δ) ⊢
vb : τ
b → ✓{Γ,Δ}* (
base_val_flatten Γ
vb).
Proof.
destruct 1; simpl.
* apply Forall_replicate, BIndet_valid.
* apply Forall_replicate, BIndet_valid.
* apply Forall_fmap, Forall_true. constructor.
* apply Forall_fmap; eapply (Forall_impl (✓{Γ,Δ}));
eauto using ptr_to_bits_valid, BPtr_valid.
* eauto using char_byte_valid_bits_valid.
Qed.
Lemma base_val_flatten_weaken Γ1 Γ2 Δ τ
b vb :
✓ Γ1 → (Γ1,Δ) ⊢
vb : τ
b → Γ1 ⊆ Γ2 →
base_val_flatten Γ1
vb =
base_val_flatten Γ2
vb.
Proof.
by destruct 2; intros; simpl; erewrite ?ptr_to_bits_weaken,
?bit_size_of_weaken by eauto using TBase_valid, TVoid_valid.
Qed.
Lemma base_val_flatten_freeze Γ β
vb :
base_val_flatten Γ (
freeze β
vb) =
base_val_flatten Γ
vb.
Proof.
by destruct vb; simpl; rewrite ?ptr_to_bits_freeze. Qed.
Lemma base_val_flatten_length Γ Δ
vb τ
b :
(Γ,Δ) ⊢
vb : τ
b →
length (
base_val_flatten Γ
vb) =
bit_size_of Γ τ
b.
Proof.
destruct 1; simplify_equality'.
* by rewrite replicate_length.
* by rewrite replicate_length.
* by rewrite fmap_length, bit_size_of_int, int_to_bits_length.
* by erewrite fmap_length, ptr_to_bits_length_alt, type_of_correct by eauto.
* by erewrite bit_size_of_int, int_width_char, char_byte_valid_bits by eauto.
Qed.
Properties of the base_val_unflatten function
Inductive base_val_unflatten_view Γ :
base_type K →
list (
bit K) →
base_val K →
Prop :=
|
base_val_of_void bs :
base_val_unflatten_view Γ
voidT bs VVoid
|
base_val_of_int τ
i β
s :
length β
s =
int_width τ
i →
base_val_unflatten_view Γ (
intT τ
i)
(
BBit <$> β
s) (
VInt τ
i (
int_of_bits τ
i β
s))
|
base_val_of_ptr τ
p p pbs :
ptr_of_bits Γ τ
p pbs =
Some p →
base_val_unflatten_view Γ (τ
p.*) (
BPtr <$>
pbs) (
VPtr p)
|
base_val_of_byte bs :
length bs =
char_bits → ¬
Forall (
BIndet =)
bs →
¬(∃ β
s,
bs =
BBit <$> β
s) →
base_val_unflatten_view Γ
ucharT bs (
VByte bs)
|
base_val_of_byte_indet bs :
length bs =
char_bits →
Forall (
BIndet =)
bs →
base_val_unflatten_view Γ
ucharT bs (
VIndet ucharT)
|
base_val_of_int_indet τ
i bs :
τ
i ≠
ucharT%
IT →
length bs =
int_width τ
i → ¬(∃ β
s,
bs =
BBit <$> β
s) →
base_val_unflatten_view Γ (
intT τ
i)
bs (
VIndet (
intT τ
i))
|
base_val_of_ptr_indet_1 τ
p pbs :
length pbs =
bit_size_of Γ (τ
p.*) →
ptr_of_bits Γ τ
p pbs =
None →
base_val_unflatten_view Γ (τ
p.*) (
BPtr <$>
pbs) (
VIndet (τ
p.*))
|
base_val_of_ptr_indet_2 τ
p bs :
length bs =
bit_size_of Γ (τ
p.*) → ¬(∃
pbs,
bs =
BPtr <$>
pbs) →
base_val_unflatten_view Γ (τ
p.*)
bs (
VIndet (τ
p.*)).
Lemma base_val_unflatten_spec Γ τ
b bs :
length bs =
bit_size_of Γ τ
b →
base_val_unflatten_view Γ τ
b bs (
base_val_unflatten Γ τ
b bs).
Proof.
intros Hbs. unfold base_val_unflatten. destruct τb as [|τi|τp].
* constructor.
* rewrite bit_size_of_int in Hbs.
destruct (mapM (maybe BBit) bs) as [βs|] eqn:Hβs.
{ rewrite maybe_BBits_spec in Hβs; subst. rewrite fmap_length in Hbs.
by constructor. }
assert (¬∃ βs, bs = BBit <$> βs).
{ setoid_rewrite <-maybe_BBits_spec. intros [??]; simpl in *; congruence. }
destruct (decide _) as [[-> ?]|Hτbs].
{ rewrite int_width_char in Hbs. by constructor. }
destruct (decide (τi = ucharT%IT)) as [->|?].
{ rewrite int_width_char in Hbs.
constructor; auto. apply dec_stable; naive_solver. }
by constructor.
* destruct (mapM (maybe BPtr) bs) as [pbs|] eqn:Hpbs; csimpl.
{ rewrite maybe_BPtrs_spec in Hpbs; subst. rewrite fmap_length in Hbs.
by destruct (ptr_of_bits Γ τp pbs) as [p|] eqn:?; constructor. }
constructor; auto.
setoid_rewrite <-maybe_BPtrs_spec. intros [??]; simplify_equality.
Qed.
Lemma base_val_unflatten_weaken Γ1 Γ2 τ
b bs :
✓ Γ1 → ✓{Γ1} τ
b → Γ1 ⊆ Γ2 →
base_val_unflatten Γ1 τ
b bs =
base_val_unflatten Γ2 τ
b bs.
Proof.
intros. unfold base_val_unflatten, default.
repeat match goal with
| _ => case_match
| H : context [ptr_of_bits _ _ _] |- _ =>
rewrite <-(ptr_of_bits_weaken Γ1 Γ2) in H by eauto using TPtr_valid_inv
| _ => simplify_option_equality
end; auto.
Qed.
Lemma base_val_unflatten_int Γ τ
i β
s :
length β
s =
int_width τ
i →
base_val_unflatten Γ (
intT τ
i) (
BBit <$> β
s) =
VInt τ
i (
int_of_bits τ
i β
s).
Proof.
intro. unfold base_val_unflatten. by rewrite mapM_fmap_Some by done. Qed.
Lemma base_val_unflatten_ptr Γ τ
p pbs p :
ptr_of_bits Γ τ
p pbs =
Some p →
base_val_unflatten Γ (τ
p.*) (
BPtr <$>
pbs) =
VPtr p.
Proof.
intros. feed inversion (base_val_unflatten_spec Γ (τp.*) (BPtr <$> pbs));
simplify_equality'; auto.
* by erewrite fmap_length, ptr_of_bits_length by eauto.
* naive_solver (apply Forall_fmap, Forall_true; simpl; eauto).
Qed.
Lemma base_val_unflatten_byte Γ
bs :
¬
Forall (
BIndet =)
bs → ¬(∃ β
s,
bs =
BBit <$> β
s) →
length bs =
char_bits →
base_val_unflatten Γ
ucharT bs =
VByte bs.
Proof.
intros. feed inversion (base_val_unflatten_spec Γ ucharT bs);
simplify_equality'; rewrite ?bit_size_of_int, ?int_width_char; naive_solver.
Qed.
Lemma base_val_unflatten_indet Γ τ
b bs :
τ
b ≠
voidT →
Forall (
BIndet =)
bs →
length bs =
bit_size_of Γ τ
b →
base_val_unflatten Γ τ
b bs =
VIndet τ
b.
Proof.
intros. assert (∀ τi βs,
Forall (@BIndet K =) (BBit <$> βs) → length βs ≠ int_width τi).
{ intros τi βs ??. pose proof (int_width_pos τi).
destruct βs; decompose_Forall_hyps; lia. }
assert (∀ τp pbs p,
Forall (BIndet =) (BPtr <$> pbs) → ptr_of_bits Γ τp pbs ≠ Some p).
{ intros τp pbs p ??. assert (length pbs ≠ 0).
{ erewrite ptr_of_bits_length by eauto. by apply bit_size_of_base_ne_0. }
destruct pbs; decompose_Forall_hyps; lia. }
feed inversion (base_val_unflatten_spec Γ τb bs); naive_solver.
Qed.
Lemma base_val_unflatten_int_indet Γ τ
i bs :
τ
i ≠
ucharT%
IT →
length bs =
int_width τ
i → ¬(∃ β
s,
bs =
BBit <$> β
s) →
base_val_unflatten Γ (
intT τ
i)
bs =
VIndet (
intT τ
i).
Proof.
intros. feed inversion (base_val_unflatten_spec Γ (intT τi) bs);
simplify_equality'; rewrite ?bit_size_of_int; naive_solver.
Qed.
Lemma base_val_unflatten_ptr_indet_1 Γ τ
p pbs :
length pbs =
bit_size_of Γ (τ
p.*) →
ptr_of_bits Γ τ
p pbs =
None →
base_val_unflatten Γ (τ
p.*) (
BPtr <$>
pbs) =
VIndet (τ
p.*).
Proof.
intros. feed inversion (base_val_unflatten_spec Γ (τp.*) (BPtr <$> pbs));
simplify_equality'; rewrite ?fmap_length; naive_solver.
Qed.
Lemma base_val_unflatten_ptr_indet_2 Γ τ
p bs :
length bs =
bit_size_of Γ (τ
p.*) → ¬(∃
pbs,
bs =
BPtr <$>
pbs) →
base_val_unflatten Γ (τ
p.*)
bs =
VIndet (τ
p.*).
Proof.
intros. feed inversion (base_val_unflatten_spec Γ (τp.*) bs);
simplify_equality'; naive_solver.
Qed.
Lemma base_val_unflatten_indet_elem_of Γ τ
b bs :
τ
b ≠
ucharT → τ
b ≠
voidT →
length bs =
bit_size_of Γ τ
b →
BIndet ∈
bs →
base_val_unflatten Γ τ
b bs =
VIndet τ
b.
Proof.
intros ???. feed destruct (base_val_unflatten_spec Γ τb bs);
rewrite ?elem_of_list_fmap; naive_solver.
Qed.
Lemma base_val_unflatten_typed Γ Δ τ
b bs :
✓{Γ} τ
b → ✓{Γ,Δ}*
bs →
length bs =
bit_size_of Γ τ
b →
(Γ,Δ) ⊢
base_val_unflatten Γ τ
b bs : τ
b.
Proof.
intros. feed destruct (base_val_unflatten_spec Γ τb bs);
auto; constructor; auto.
* by apply int_of_bits_typed.
* eapply ptr_of_bits_typed; eauto using BPtrs_valid_inv.
* by constructor.
Qed.
Lemma base_val_unflatten_type_of Γ τ
b bs :
type_of (
base_val_unflatten Γ τ
b bs) = τ
b.
Proof.
unfold base_val_unflatten, default.
destruct τb; repeat (simplify_option_equality || case_match || intuition).
f_equal; eauto using ptr_of_bits_type_of.
Qed.
Lemma base_val_unflatten_flatten Γ Δ
vb τ
b :
(Γ,Δ) ⊢
vb : τ
b →
base_val_unflatten Γ τ
b (
base_val_flatten Γ
vb) =
freeze true vb.
Proof.
destruct 1 as [τb| |x|p τ|bs []]; simpl.
* by rewrite base_val_unflatten_indet
by auto using Forall_replicate_eq, replicate_length.
* done.
* by rewrite base_val_unflatten_int, int_of_to_bits
by auto using int_to_bits_length.
* by erewrite base_val_unflatten_ptr by eauto using ptr_of_to_bits_typed.
* by rewrite base_val_unflatten_byte by done.
Qed.
Lemma base_val_unflatten_frozen Γ Δ τ
b bs :
✓{Γ,Δ}*
bs →
frozen (
base_val_unflatten Γ τ
b bs).
Proof.
intros. unfold base_val_unflatten, default, frozen.
destruct τb; repeat (simplify_option_equality || case_match); f_equal'.
efeed pose proof (λ bs pbs, proj1 (maybe_BPtrs_spec bs pbs)); eauto.
subst. eapply ptr_of_bits_frozen; eauto using BPtrs_valid_inv.
Qed.
Lemma base_val_flatten_inj Γ Δ β
vb1 vb2 τ
b :
(Γ,Δ) ⊢
vb1 : τ
b → (Γ,Δ) ⊢
vb2 : τ
b →
base_val_flatten Γ
vb1 =
base_val_flatten Γ
vb2 →
freeze β
vb1 =
freeze β
vb2.
Proof.
intros ?? Hv. by rewrite <-(base_val_freeze_freeze _ true vb1),
<-(base_val_freeze_freeze _ true vb2),
<-(base_val_unflatten_flatten Γ Δ vb1 τb),
<-(base_val_unflatten_flatten Γ Δ vb2 τb), Hv by done.
Qed.
Lemma base_val_flatten_unflatten Γ Δ τ
b bs :
✓{Γ,Δ}*
bs →
length bs =
bit_size_of Γ τ
b →
base_val_flatten Γ (
base_val_unflatten Γ τ
b bs) ⊑*
bs.
Proof.
intros. cut (base_val_flatten Γ (base_val_unflatten Γ τb bs) = bs
∨ base_val_unflatten Γ τb bs = VIndet τb ∨ τb = voidT).
{ intros [->|[->| ->]]; simpl; eauto using Forall2_replicate_l,
Forall_true, BIndet_weak_refine, BIndet_valid. }
feed destruct (base_val_unflatten_spec Γ τb bs); simpl; auto.
* left. by rewrite int_to_of_bits.
* left. by erewrite ptr_to_of_bits by eauto using BPtrs_valid_inv.
Qed.
Lemma base_val_flatten_unflatten_char Γ
bs :
length bs =
bit_size_of Γ
ucharT →
base_val_flatten Γ (
base_val_unflatten Γ
ucharT bs) =
bs.
Proof.
intros. feed inversion (base_val_unflatten_spec Γ ucharT bs);
simplify_equality'; auto using replicate_as_Forall_2.
by rewrite int_to_of_bits by done.
Qed.
Lemma base_val_unflatten_char_inj Γ
bs1 bs2 :
length bs1 =
bit_size_of Γ
ucharT →
length bs2 =
bit_size_of Γ
ucharT →
base_val_unflatten Γ
ucharT bs1 =
base_val_unflatten Γ
ucharT bs2 →
bs1 =
bs2.
Proof.
intros ?? Hbs. by rewrite <-(base_val_flatten_unflatten_char Γ bs1),
<-(base_val_flatten_unflatten_char Γ bs2), Hbs.
Qed.
Lemma base_val_unflatten_between Γ τ
b bs1 bs2 bs3 :
✓{Γ} τ
b →
bs1 ⊑*
bs2 →
bs2 ⊑*
bs3 →
length bs1 =
bit_size_of Γ τ
b →
base_val_unflatten Γ τ
b bs1 =
base_val_unflatten Γ τ
b bs3 →
base_val_unflatten Γ τ
b bs2 =
base_val_unflatten Γ τ
b bs3.
Proof.
intros ???? Hbs13. destruct (decide (τb = ucharT)) as [->|].
{ apply base_val_unflatten_char_inj in Hbs13; subst;
eauto using Forall2_length_l.
by rewrite (anti_symmetric (Forall2 bit_weak_refine) bs2 bs3). }
destruct (decide (τb = voidT)) as [->|]; [done|].
destruct (bits_subseteq_eq bs2 bs3) as [->|]; auto.
rewrite <-Hbs13, !(base_val_unflatten_indet_elem_of Γ);
eauto using bits_subseteq_indet, Forall2_length_l.
Qed.
End base_values.