Set Implicit Arguments.
Require Import MyTactics.
Require Import Arithmetic.
Require Import DeBruijn.
Require Import Layers.
Require Import Coercions.
Require Import Programs.
Require Import ValueLists.
Require Import RawPrograms.
Require Import Erasure.
-------------------------------------------------------------------------
The functions reveal_value and reveal_term indicate how values and
terms are transformed by the revelation of an extra capability.
If v has type T, then reveal_value v has type TyTensor T U. In
particular, if v is a function, then it takes and returns an extra
argument, a capability.
If t has type T, then reveal_term k t has type TyTensor T U, under
an environment where a binding of k to U has been inserted -- this
represents the extra capability that is revealed. We do not impose k = 0,
because this added flexibility simplifies the transformation of
TLetUnpack and other binding constructs.
In the definition of reveal_term, every call to reveal_value is
followed with a use of lift_value k, so as to compensate for the
insertion of the new capability at index k.
Fixpoint reveal_value (
v :
value) :=
match v with
|
VVar _
|
VUnit _ =>
v
|
VAbs t =>
The function argument x is decomposed into a pair y, z, where
y is the original argument and z is the new capability.
References to x within t are (transparently) replaced with
references to y -- this is index 1 -- and an application of
lift_term 2 is used in order to jump above the now unused
binding of x.
VAbs (
TLetPair Physical Logical (
VVar 0) (
lift_term 2 (
reveal_term 0
t)))
|
VPair layer1 layer2 v1 v2 =>
VPair layer1 layer2 (
reveal_value v1) (
reveal_value v2)
|
VTyAbs v =>
VTyAbs (
reveal_value v)
|
VPack v =>
VPack (
reveal_value v)
|
VCoApp c v =>
At coercion applications, the revelation lemma for subtyping is used.
VCoApp (
co_tensor c) (
reveal_value v)
|
VBang v =>
VBang (
reveal_value v)
|
VLoc l v =>
VLoc l (
reveal_value v)
|
VRegionCap vs =>
VRegionCap (
reveal_values vs)
|
VRegionCapPunched vs =>
VRegionCapPunched (
reveal_values vs)
|
VInhabitant v =>
VInhabitant (
reveal_value v)
end
with reveal_values (
vs :
values) :=
match vs with
|
VNil =>
VNil
|
VCons v vs =>
VCons (
reveal_value v) (
reveal_values vs)
end
with reveal_term (
k :
nat) (
t :
term) :=
match t with
|
TVal v =>
At values, we must return a pair of the original result --
the value -- and the extra capability -- which has index k.
TVal (
VMixPair (
lift_value k (
reveal_value v)) (
VVar k))
|
TApp v t =>
At function applications, the argument -- a term -- produces a pair,
and the function expects a pair, so there is nothing to do.
TApp (
lift_value k (
reveal_value v)) (
reveal_term k t)
|
TMixPair t v =>
At mixed pairs, the extra pair that the tensor creates must commute
with the pair that was there in the first place.
TCoApp CoMixPairExchange (
TMixPair (
reveal_term k t) (
lift_value k (
reveal_value v)))
|
TTyAbs t =>
At type abstractions, the natural translation produces a universally
quantified pair, whose right-hand component we must extract out of the
universal quantification -- or, conversely, we must intrude the universal
quantifier into the pair.
TCoApp (
CoForallPairLeft Physical Logical) (
TTyAbs (
reveal_term k t))
|
TCoApp c t =>
At coercion applications, the revelation lemma for subtyping is used,
but only in the left-hand side of the value/capability pair.
TCoApp (
CoMixPair (
co_tensor c)
CoId) (
reveal_term k t)
|
TLetUnpack v t =>
The easiest way of translating a binding construct is to let the new
variable have index 0, as usual -- so the extra capability, which
was at index k, now is at index k+1.
TLetUnpack (
lift_value k (
reveal_value v)) (
reveal_term (
S k)
t)
|
TLetBang v t =>
TLetBang (
lift_value k (
reveal_value v)) (
reveal_term (
S k)
t)
|
TLetPair layer1 layer2 v t =>
TLetPair layer1 layer2 (
lift_value k (
reveal_value v)) (
reveal_term (
S (
S k))
t)
|
TPrimApp p v =>
At a primitive operation, the extra capability must be framed out
while the primitive operation is carried out.
TMixPair
(
TPrimApp p (
lift_value k (
reveal_value v)))
(
VVar k)
|
THide v t =>
Let us write reveal v for reveal_value v and reveal k in t for
reveal_term k t. Let us further use informal nominal syntax. We
must now offer a definition for
reveal y in (hide x = v in t)
The definition that we propose is:
hide z = (reveal v, y) in
let (x, y) = z in
let x = CoTensorExchange 0 x in
CoComposExchange (reveal y in t)
where the replacement of x with CoTensorExchange 0 x is in fact
performed via a substitution, not via a let construct, so as to
avoid disturbing the erasure of the term.
The term reveal y in t has two free variables, namely x and y,
and we wish to place it in the scope of a hide construct, which
supports only one free variable, so we must (somewhat artifically,
but that is not a problem) pair them up before entering the hide
construct and deconstruct the pair immediately after entering it.
What is more subtle is that the type of x has two tensors -- one
created by reveal v, the other created by hide -- and they are
in the wrong order, so we must use CoTensorExchange 0 to swap them.
Symmetrically, the result produced by reveal y in t also has two
tensors, again in the wrong order, so we must use CoComposExchange
to swap them.
THide
(
VMixPair (
lift_value k (
reveal_value v)) (
VVar k))
(
lift_term (
S k) (
TLetMixPair (
VVar 0) (
lift_term 2 (
subst_term (
VCoApp (
CoTensorExchange 0) (
VVar 1)) 1 (
lift_term 2 (
TCoApp CoComposExchange (
reveal_term 0
t)
))))))
end.
Fixpoint fold_reveal_value (
nh :
nat)
v :=
match nh with
| 0 =>
v
|
S nh =>
fold_reveal_value nh (
reveal_value v)
end.
-------------------------------------------------------------------------
Up to erasure, revelation has no effect.
Hint Extern 1 =>
rewrite <-
raw_lift_subst_2_term :
erase_reveal.
Hint Extern 1 =>
rewrite <-
raw_lift_subst_2_term_rawverased :
erase_reveal.
Hint Extern 1 =>
rewrite raw_lift_lift_value :
erase_reveal.
Lemma erase_reveal:
(
forall v,
erase_value (
reveal_value v) =
erase_value v
) /\ (
forall vs :
values,
pwe vs (
reveal_values vs)
) /\ (
forall t k,
erase_term (
reveal_term k t) =
lift_raw_term k (
erase_term t)
).
Proof.
Lemma erase_reveal_value:
forall v,
erase_value (
reveal_value v) =
erase_value v.
Proof.
Lemma erase_reveal_term:
forall t k,
erase_term (
reveal_term k t) =
lift_raw_term k (
erase_term t).
Proof.
Hint Resolve (
pi2 erase_reveal).
Lemma fold_erase_reveal:
forall nh v,
erase_value (
fold_reveal_value nh v) =
erase_value v.
Proof.
-------------------------------------------------------------------------
Revelation commutes with lifting. This means, in particular, that applying
revelation to a closed value yields a closed value.
Lemma lift_reveal:
(
forall v j,
lift_value j (
reveal_value v) =
reveal_value (
lift_value j v)
) /\ (
forall vs :
values,
True
) /\ (
forall t k j,
k <=
j ->
lift_term (
S j) (
reveal_term k t) =
reveal_term k (
lift_term j t)
).
Local Hint Extern 1 (
_ =
_) =>
congruence.
Proof.
Lemma well_scoped_reveal:
forall v k,
well_scoped_lift lift_value k v ->
well_scoped_lift lift_value k (
reveal_value v).
Proof.
unfold well_scoped_lift.
intros.
rewrite (
pi1 lift_reveal).
f_equal.
eauto.
Qed.
Lemma closed_reveal:
forall v,
closed_value v ->
closed_value (
reveal_value v).
Proof.
-------------------------------------------------------------------------
A coercion that lifts a bunch of composition operators out of a pair.
This is pretty boring. One could probably avoid the need for a recursive
definition if one exploited the fact that active hide constructs extrude
only one at a time (so n is always 0 or 1).
This coercion is used in the definition of the semantics, and we do not
want the semantics to depend on the typing rules, so we must separate
the definition of the coercion and the proof of its derived typing rule.
Fixpoint CoMixPairCompossExchange (
n :
nat) (
t :
term) :
term :=
match n with
| 0 =>
t
|
S n =>
TCoApp (
co_composs n CoMixPairComposExchange) (
CoMixPairCompossExchange n t)
end.
Lemma erase_CoMixPairCompossExchange:
forall n t,
erase_term (
CoMixPairCompossExchange n t) =
erase_term t.
Proof.
induction n; simpl; eauto.
Qed.