Library CTPC.Flatify

Closure conversion

Require Import Arith Eqdep List.
Require Import Max.

Require Import LambdaTamer.ListUtil.
Require Import LambdaTamer.LambdaTamer.
Require Import LambdaTamer.Tactics.

Require Import CTPC.AllocMonad.
Require Import CTPC.Dict.
Require Import CTPC.Trace.

Require Import CTPC.Alloc.
Require Import CTPC.Flat.

Set Implicit Arguments.

Tactics


Hint Rewrite NatDict.sel_empty NatDict.sel_upd_eq : Flatify.
Hint Rewrite NatDict.sel_upd_ne using omega : Flatify.

Ltac simplify := repeat progress (simpl in *; intuition; autorewrite with Flatify;
  repeat match goal with
           | [ |- context[match ?E with (_, _) => _ end] ] => destruct E; simpl
         end).

The flattening translation


Fixpoint flatVar (G : list aty) (t : aty) (v : Var G t) {struct v} : nat :=
  match v with
    | First G' _ => length G'
    | Next _ _ _ v' => flatVar v'
  end.

Theorem flatVar_bound : forall G t (v : Var G t),
  flatVar v < length G.

Theorem flatVar_sel : forall G t (v : Var G t),
  NatDict.sel (flatContext G) (flatVar v) = t.

Fixpoint flatArgs G ts (args : aargs G ts) {struct args} : fargs (flatContext G) ts :=
  match args in (aargs G ts) return (fargs (flatContext G) ts) with
    | AANil _ => FANil _
    | AACons G' _ ts' v args' =>
      eq_rec _ (fun V => fargs (flatContext G') (V :: ts'))
      (FACons _ (flatArgs args'))
      _ (flatVar_sel v)
  end.

Definition flatPrimop G t (op : aprimop G t) : fprimop (flatContext G) t :=
  match op in (aprimop G t) return (fprimop (flatContext G) t) with
    | AVar G' _ v => eq_rec _ (fprimop (flatContext G')) (FSlot _ _) _ (flatVar_sel v)
    | AConst _ n => FConst _ n
    | ACodeptr _ _ n => FCodeptr _ _ n
    | ANew _ _ args => FNew (flatArgs args)
    | AProj _ _ v pos => FProj _ (flatVar_sel v) pos
  end.

Fixpoint copyType (tp : ftyping) (to from len : nat) {struct len} : ftyping :=
  match len with
    | O => tp
    | S len' => NatDict.upd (copyType tp (S to) (S from) len') to
      (NatDict.sel (copyType tp (S to) (S from) len') from)
  end.

Fixpoint copy (tp : ftyping) (to from len : nat) {struct len}
  : flinear (copyType tp to from len) -> flinear tp :=
  match len return (flinear (copyType tp to from len) -> flinear tp) with
    | O => fun lin => lin
    | S len' => fun lin => copy _ _ _ _ (FSet (FSlot (copyType _ _ _ _) _) lin)
  end.

Fixpoint stashType (tp : ftyping) (start : nat) (ts : list aty) {struct ts} : ftyping :=
  match ts with
    | nil => tp
    | t :: ts' => NatDict.upd (stashType tp (S start) ts') start t
  end.

Lemma stashType_early : forall ts tp start sl,
  sl < start
  -> NatDict.sel tp sl
  = NatDict.sel (stashType tp start ts) sl.

Lemma stashType_early' : forall ts tp start sl,
  sl < start
  -> NatDict.sel tp sl
  = NatDict.sel (stashType tp (S start) ts) sl.

Fixpoint args_early (tp : ftyping) (ts : list aty) (args : fargs tp ts) (start : nat) {struct args} : Prop :=
  match args with
    | FANil _ => True
    | FACons _ _ sl args' => sl < start /\ args_early args' start
  end.

Theorem early_bump : forall (tp : ftyping) (ts : list aty) (args : fargs tp ts) (start : nat),
  args_early args start
  -> args_early args (S start).

Implicit Arguments early_bump [tp ts args start].

Fixpoint stash (tp : ftyping) (ts : list aty) (args : fargs tp ts) (start : nat) {struct args}
  : args_early args start -> flinear (stashType tp start ts) -> flinear tp :=
  match args in (fargs tp ts) return (args_early args start -> flinear (stashType tp start ts) -> flinear tp) with
    | FANil _ => fun _ lin => lin
    | FACons _ _ sl args' => fun Hearly lin => stash args' _ (early_bump (proj2 Hearly))
      (FSet (FSlot _ sl)
        (eq_rec _ (fun V => flinear (NatDict.upd _ _ V))
          lin
          _ (stashType_early' _ _ (proj1 Hearly))))
  end.

Fixpoint args_max G ts (args : fargs G ts) {struct args} : nat :=
  match args with
    | FANil _ => 0
    | FACons _ _ sl args' => max sl (args_max args')
  end.

Definition args_bound G ts (args : fargs G ts) :=
  S (max (length ts) (args_max args)).

Theorem args_early_monotone : forall G ts (args : fargs G ts) n1 n2,
  args_early args n1
  -> n1 <= n2
  -> args_early args n2.

Theorem args_max_early : forall G ts (args : fargs G ts),
  args_early args (S (args_max args)).

Theorem args_bound_early : forall G ts (args : fargs G ts),
  args_early args (args_bound args).

Theorem stashType_sound : forall (ts : list aty) (tp : ftyping) (start : nat) n t,
  nth_error ts n = value t
  -> NatDict.sel (stashType tp start ts) (n + start) = t.

Lemma copyType_late : forall len tp to from sl,
  sl > to + len
  -> NatDict.sel (copyType tp to from len) sl
  = NatDict.sel tp sl.

Theorem copyType_sound : forall len tp to from pos,
  to + len < from
  -> pos < len
  -> NatDict.sel (copyType tp to from len) (pos + to)
  = NatDict.sel tp (pos + from).

Lemma stashType_late : forall ts tp start sl,
  sl >= start + length ts
  -> NatDict.sel tp sl
  = NatDict.sel (stashType tp start ts) sl.

Theorem flatCall_sel : forall tp bound ts t,
  NatDict.sel (copyType
    (stashType
      (NatDict.upd tp (S bound + length ts) t)
      (S bound) ts) 0
    (S bound) (length ts)) (S bound + length ts) = t.

Theorem call_precondition : forall G ts
  (args : fargs (flatContext G) ts) t,
  fprecondition
  (copyType
    (stashType
      (NatDict.upd (flatContext G) (args_bound args + length ts) t)
      (args_bound args) ts)
    0 (args_bound args) (length ts)) ts.

Lemma upd_early : forall (f : ftyping) a t sl,
  sl < a
  -> NatDict.sel (NatDict.upd f a t) sl
  = NatDict.sel f sl.

Fixpoint frob_args tp ts (args : fargs tp ts) a t {struct args}
  : args_early args a -> fargs (NatDict.upd tp a t) ts :=
  match args in (fargs tp ts) return (args_early args a -> fargs (NatDict.upd tp a t) ts) with
    | FANil _ => fun Hearly => FANil _
    | FACons _ _ sl args' => fun Hearly =>
      eq_rec _ (fun V => fargs _ (V :: _))
      (FACons sl (frob_args args' a t (proj2 Hearly)))
      _ (upd_early _ _ (proj1 Hearly))
  end.

Theorem frob_args_early : forall tp ts (args : fargs tp ts) bound,
  args_early args bound
  -> forall a t Hearly, args_early (frob_args args a t Hearly) bound.

Theorem flatCall_lemma : forall G ts (args : fargs (flatContext G) ts),
  args_early args (args_bound args + length ts).

Definition flatCall : forall G ts
  (args : fargs (flatContext G) ts) t,
  flinear
  (copyType
    (stashType
      (NatDict.upd (flatContext G) (args_bound args + length ts) t)
      (args_bound args) ts)
    0 (args_bound args) (length ts))
  -> flinear (NatDict.upd (flatContext G) (args_bound args + length ts) t).

Fixpoint flatLinear G t (lin : alinear G t) {struct lin} : flinear (flatContext G) :=
  match lin in (alinear G t) return (flinear (flatContext G)) with
    | AApply bip moop f args =>
      FSet (FSlot _ (flatVar f))
      (eq_rec _ (fun T => flinear (NatDict.upd _ _ T))
        (flatCall _ (flatArgs args) _ (FJump (flatCall_sel _ _ _ _) (call_precondition _ (flatArgs args) _)))
        _ (sym_eq (flatVar_sel _)))
    | ABind _ _ op lin' => FSet (flatPrimop op) (flatLinear lin')
  end.

Fixpoint afuncBody G ts (f : afunc G ts) {struct f} : alinear (ts +++ G) tt :=
  match f in (afunc G ts) return (alinear (ts +++ G) tt) with
    | AFBody _ lin => lin
    | AFLam _ _ _ f' => afuncBody f'
  end.

Definition flatFunc G ts (f : afunc G ts) : flinear (flatContext (ts +++ G)) :=
  flatLinear (afuncBody f).

Definition flatProg (G : list aty) (pr : aprog G) : fprog (flatContext G) :=
  Build_fprog
  (map (fun ts => flatContext (ts +++ nil)) (aFuncTys pr))
  (mapI (f:= fun ts => flatContext (ts +++ nil))
    (flatFunc (G:= nil)) (aFuncs pr))
  (flatLinear (aBody pr)).

Logical relations


Section slots_Subst.
   Variable sls : slots.

  Fixpoint slots_Subst (G : list aty) (s : Subst atyDenote G) {struct s} : Prop :=
    match s with
      | SNil => True
      | SCons t G' v s' => v = NatDict.sel sls (length G') /\ slots_Subst s'
    end.

  Definition slots_args (args : list adom) :=
    forall n tg v, nth_error args n = value (tg, v)
      -> NatDict.sel sls n = v.

  Fixpoint slots_actuals (n : nat) (ts : atys) {struct ts} : aformalsDenote ts-> Prop :=
    match ts return (aformalsDenote ts-> Prop) with
      | nil => fun _ => True
      | t :: ts' => fun args =>
        NatDict.sel sls n = fst args
        /\ slots_actuals (S n) ts' (snd args)
    end.
End slots_Subst.

Definition val_lr (t : aty) (v1 v2 : atyDenote t) := v1 = v2.

Definition args_lr G ts (args1 : aargs G ts) (args2 : fargs (flatContext G) ts) :=
  forall sls s, slots_Subst sls s
    -> aargsDenote args1 s
    = fargsDenote args2 sls.

Definition primop_lr G t (op1 : aprimop G t) (op2 : fprimop (flatContext G) t) :=
  forall sls s, slots_Subst sls s
    -> aprimopDenote op1 s
    = fprimopDenote op2 sls.

Definition linear_lr G t (lin1 : alinear G t) (lin2 : flinear (flatContext G)) :=
  forall sls s, slots_Subst sls s
    -> forall st,
      match alinearDenote lin1 s st with
        | None =>
          match flinearDenote lin2 sls st with
            | None => True
            | Some _ => False
          end
        | Some (st', (pc, argsT, args)) =>
          exists sls',
            flinearDenote lin2 sls st = Some (st', (pc, argsT, sls'))
            /\ slots_args sls' args
      end.

Definition prog_lr G (pr1 : aprog G) (pr2 : fprog (flatContext G)) :=
  forall sls s, slots_Subst sls s
    -> forall st output,
      runTrace (aprogDenote pr1 s st) output
      -> runTrace (fprogDenote pr2 sls st) output.

Tactics


Ltac my_simpl := repeat progress
  (unfold args_lr, primop_lr, linear_lr, prog_lr in *;
    autorewrite with Flatify;
      repeat inversion_Subst_any; subst).

Ltac my_inster T k := fail.

Ltac my_lr_tac := lr_tac ltac:(var_adder val_lr) my_inster my_simpl.

Soundness proofs


Lemma slots_Subst_sound : forall G t (v : Var G t) sls s,
  slots_Subst sls s
  -> VarDenote v s = NatDict.sel sls (flatVar v).

Hint Resolve flatVar_sel.

Hint Extern 1 (_ = _) =>
  match goal with
    | [ H : slots_Subst _ _ |- context[VarDenote ?V _] ] =>
      rewrite (slots_Subst_sound V _ _ H)
  end.

Theorem flatArgs_sound : forall G ts (args : aargs G ts),
  args_lr args (flatArgs args).

Hint Extern 1 (_ = _) =>
  match goal with
    | [ H : slots_Subst _ _, args : aargs _ _ |- _ ] =>
      rewrite (flatArgs_sound args _ _ H)
  end.

Theorem flatPrimop_sound : forall G t (op : aprimop G t),
  primop_lr op (flatPrimop op).

Lemma slots_Subst_upd : forall sls a n G (s : Subst atyDenote G),
  slots_Subst sls s
  -> a >= length G
  -> slots_Subst (NatDict.upd sls a n) s.

Hint Resolve slots_Subst_upd.

Fixpoint copySlots (sls : slots) (to from len : nat) {struct len} : slots :=
  match len with
    | O => sls
    | S len' => NatDict.upd (copySlots sls (S to) (S from) len') to
      (NatDict.sel (copySlots sls (S to) (S from) len') from)
  end.

Fixpoint stashSlots (sls : slots) (start : nat) (args : list adom) {struct args} : slots :=
  match args with
    | nil => sls
    | (_, v) :: args' => NatDict.upd (stashSlots sls (S start) args') start v
  end.

Hint Resolve stashType_early'.

Lemma stashSlots_early : forall ts sls start sl,
  sl < start
  -> NatDict.sel (stashSlots sls start ts) sl
  = NatDict.sel sls sl.

Theorem stash_soundness : forall (tp : ftyping) (ts : list aty) (args : fargs tp ts) (start : nat)
  (Hearly : args_early args start)
  (lin : flinear (stashType tp start ts)) sls,
  flinearDenote (stash args start Hearly lin) sls
  = flinearDenote lin (stashSlots sls start (fargsDenote args sls)).

Theorem copy_soundness : forall (len : nat) (tp : ftyping) (to from : nat)
  (lin : flinear (copyType tp to from len)) sls,
  flinearDenote (copy tp to from len lin) sls
  = flinearDenote lin (copySlots sls to from len).

Lemma copySlots_late : forall len tp to from sl,
  sl > to + len
  -> NatDict.sel (copySlots tp to from len) sl
  = NatDict.sel tp sl.

Lemma stashSlots_late : forall args sls start sl,
  sl >= start + length args
  -> NatDict.sel (stashSlots sls start args) sl
  = NatDict.sel sls sl.

Lemma fargsDenote_len : forall G ctx (e : fargs G ctx) (sls : slots),
  length (fargsDenote e sls) = length ctx.

Lemma aargsDenote_len : forall G ctx (e : aargs G ctx) s,
  length (aargsDenote e s) = length ctx.

Theorem copySlots_sound : forall len tp to from pos,
  to + len < from
  -> pos < len
  -> NatDict.sel (copySlots tp to from len) (pos + to)
  = NatDict.sel tp (pos + from).

Theorem stashSlots_sound : forall args sls (start : nat) n tg v,
  nth_error args n = value (tg, v)
  -> NatDict.sel (stashSlots sls start args) (n + start) = v.

Theorem frob_args_sound : forall tp ts (args : fargs tp ts) a t
  (Hearly : args_early args a) sls v,
  fargsDenote (frob_args args a t Hearly) (NatDict.upd sls a v)
  = fargsDenote args sls.

Theorem flatLinear_sound : forall G t (lin : alinear G t),
  linear_lr lin (flatLinear lin).

Theorem slots_args_app : forall sls args2 args1,
  slots_args sls (args1 ++ rev args2)
  -> slots_args sls args1.

Theorem slots_args_app1 : forall sls arg args1,
  slots_args sls (args1 ++ arg :: nil)
  -> slots_args sls args1.

Hint Resolve slots_args_app1.

Fixpoint augmentSubst ts G (s : Subst atyDenote G) {struct ts}
  : aformalsDenote ts -> Subst atyDenote (ts +++ G) :=
  match ts return (aformalsDenote ts -> Subst atyDenote (ts +++ G)) with
    | nil => fun _ => s
    | _ :: _ => fun args => augmentSubst _ (SCons _ (fst args) s) (snd args)
  end.

Implicit Arguments augmentSubst [ts G].

Lemma afuncBody_sound : forall G ts (f : afunc G ts) s args,
  afuncDenote f s args
  = alinearDenote (afuncBody f) (augmentSubst s args).

Section slots_Subst'.
   Variable sls : slots.
   Variable offset : nat.

  Fixpoint slots_Subst' (G : list aty) (s : Subst atyDenote G) {struct s} : Prop :=
    match s with
      | SNil => True
      | SCons t G' v s' => v = NatDict.sel sls (offset + length G') /\ slots_Subst' s'
    end.

  Definition slots_args' (args : list adom) :=
    forall n tg v, nth_error args n = value (tg, v)
      -> NatDict.sel sls (offset + n) = v.
End slots_Subst'.

Lemma slots_Subst_func : forall ts sls args G,
  slots_args' sls (length G) args
  -> forall (s : Subst atyDenote G),
    slots_Subst sls s
    -> forall Heq, slots_Subst sls
      (augmentSubst s (makeActuals ts args Heq)).

Lemma flatProg_sound' : forall tr output, runTrace tr output
  -> forall G (pr : aprog G) sls st pc argsT args,
    tr = amakeTrace pr st pc argsT args
    -> slots_args sls args
    -> runTrace (fmakeTrace (flatProg pr) st pc argsT sls) output.

Theorem flatProg_sound : forall G (pr : aprog G),
  prog_lr pr (flatProg pr).


Index
This page has been generated by coqdoc