Lvc.IL.IL

Require Import List.
Require Export Util Relations Get Drop Var Val Exp Env Map CSet AutoIndTac MoreList OptionMap Events.
Require Import SetOperations.

Set Implicit Arguments.

Intermediate Language IL

Syntax

args is the type of the list of variables passed at a goto ...
Notation "´args´" := (list exp) (at level 0).
... while params is the type of the list of formal parameters
Notation "´params´" := (list var) (at level 0).

Inductive stmt : Type :=
| stmtLet (x : var) (e: exp) (s : stmt) : stmt
| stmtIf (e : exp) (s : stmt) (t : stmt) : stmt
| stmtApp (l : lab) (Y:args) : stmt
| stmtReturn (e : exp) : stmt
| stmtExtern (x : var) (f:external) (Y:args) (s:stmt)

| stmtFun (Z:params) (s : stmt) (t : stmt) : stmt.

Fixpoint freeVars (s:stmt) : set var :=
  match s with
    | stmtLet x e s0(freeVars s0 \ {{x}}) Exp.freeVars e
    | stmtIf e s1 s2freeVars s1 freeVars s2 Exp.freeVars e
    | stmtApp l Ylist_union (List.map Exp.freeVars Y)
    | stmtReturn eExp.freeVars e
    | stmtExtern x f Y s(freeVars s \ {{x}}) list_union (List.map Exp.freeVars Y)
    | stmtFun Z s1 s2(freeVars s1 \ of_list Z) freeVars s2
  end.

Fixpoint definedVars (s:stmt) : set var :=
  match s with
    | stmtLet x e s0{x; definedVars s0}
    | stmtIf e s1 s2definedVars s1 definedVars s2
    | stmtApp l Y
    | stmtReturn e
    | stmtExtern x f Y s{x; definedVars s}
    | stmtFun Z s1 s2definedVars s1 definedVars s2 of_list Z
  end.

Fixpoint occurVars (s:stmt) : set var :=
  match s with
    | stmtLet x e s0{x; occurVars s0} Exp.freeVars e
    | stmtIf e s1 s2occurVars s1 occurVars s2 Exp.freeVars e
    | stmtApp l Ylist_union (List.map Exp.freeVars Y)
    | stmtReturn eExp.freeVars e
    | stmtExtern x f Y s{x; occurVars s} list_union (List.map Exp.freeVars Y)
    | stmtFun Z s1 s2occurVars s1 occurVars s2 of_list Z
  end.

Lemma freeVars_occurVars s
: freeVars s occurVars s.
Proof.
  general induction s; simpl; cset_tac; intuition.
Qed.

Lemma definedVars_occurVars s
: definedVars s occurVars s.
Proof.
  general induction s; simpl; try now (cset_tac; intuition).
Qed.

Lemma occurVars_freeVars_definedVars s
: occurVars s [=] freeVars s definedVars s.
Proof.
  general induction s; simpl.
  - rewrite IHs. clear_all; cset_tac; intuition; eauto.
    decide (x === a); intuition; eauto.
  - rewrite IHs1, IHs2. clear_all; cset_tac; intuition; eauto.
  - cset_tac; intuition.
  - cset_tac; intuition.
  - rewrite IHs. clear_all; cset_tac; intuition; eauto.
    decide (x === a); intuition; eauto.
  - rewrite IHs1, IHs2. clear_all; cset_tac; intuition; eauto.
    decide (a of_list Z); intuition; eauto.
Qed.

Fixpoint rename (ϱ:env var) (s:stmt) : stmt :=
  match s with
    | stmtLet x e sstmtLet (ϱ x) (rename_exp ϱ e) (rename ϱ s)
    | stmtIf e s tstmtIf (rename_exp ϱ e) (rename ϱ s) (rename ϱ t)
    | stmtApp l YstmtApp l (List.map (rename_exp ϱ) Y)
    | stmtReturn estmtReturn (rename_exp ϱ e)
    | stmtExtern x f e sstmtExtern (ϱ x) f (List.map (rename_exp ϱ) e) (rename ϱ s)
    | stmtFun Z s tstmtFun (lookup_list ϱ Z) (rename ϱ s) (rename ϱ t)
  end.

Renaming respects function equivalence

Global Instance rename_morphism
  : Proper (@feq _ _ _eq ==> eq ==> eq) rename.
Proof.
  unfold Proper, respectful; intros; subst.
  general induction y0; simpl; f_equal; eauto; try (now rewrite H; eauto);
  eauto using rename_exp_ext, map_ext_get_eq; eauto.
Qed.

Lemma rename_agree ϱ ϱ´ s
: agree_on eq (occurVars s) ϱ ϱ´
  → rename ϱ s = rename ϱ´ s.
Proof with eauto 50 using rename_exp_agree, map_ext_get_eq with cset.
  intros. general induction s; simpl in *; f_equal...
Qed.

Fixpoint label_closed (n:nat) (s:stmt) : Prop :=
  match s with
    | stmtLet _ _ slabel_closed n s
    | stmtIf _ s tlabel_closed n s label_closed n t
    | stmtApp l _counted l < n
    | stmtReturn _True
    | stmtExtern _ _ _ slabel_closed n s
    | stmtFun _ s tlabel_closed (S n) s label_closed (S n) t
  end.

Semantics

Functional Semantics

Module F.

  Inductive block : Type :=
    blockI {
      block_E : onv val;
      block_Z : params;
      block_s : stmt
    }.

  Definition labenv := list block.
  Definition state : Type := (labenv × onv val × stmt)%type.

  Inductive step : stateeventstateProp :=
  | stepExp L E x e b v
    (def:exp_eval E e = Some v)
    : step (L, E, stmtLet x e b) EvtTau (L, E[x<-Some v], b)

  | stepIfT L E
    e (b1 b2 : stmt) v
    (def:exp_eval E e = Some v)
    (condTrue: val2bool v = true)
    : step (L, E, stmtIf e b1 b2) EvtTau (L, E, b1)

  | stepIfF L E
    e (b1 b2:stmt) v
    (def:exp_eval E e = Some v)
    (condFalse: val2bool v = false)
    : step (L, E, stmtIf e b1 b2) EvtTau (L, E, b2)

  | stepGoto L E l Y blk vl
    (Ldef:get L (counted l) blk)
    (len:length (block_Z blk) = length Y)
    (def:omap (exp_eval E) Y = Some vl)
    (updOk:(block_E blk) [block_Z blk <-- List.map Some vl] = )
    : step (L, E, stmtApp l Y)
            EvtTau
            (drop (counted l) L, , block_s blk)

  | stepLet L E
    s Z (t:stmt)
    : step (L, E, stmtFun Z s t) EvtTau (blockI E Z s::L, E, t)

  | stepExtern L E x f Y s vl v
    (def:omap (exp_eval E) Y = Some vl)
    : step (L, E, stmtExtern x f Y s)
            (EvtExtern (ExternI f vl v))
            (L, E[x <- Some v], s).

  Lemma step_internally_deterministic
  : internally_deterministic step.
  Proof.
    hnf; intros.
    inv H; inv H0; split; eauto; try get_functional; try congruence.
  Qed.

  Lemma step_externally_determined
  : externally_determined step.
  Proof.
    hnf; intros.
    inv H; inv H0; eauto; try get_functional; try congruence.
  Qed.

  Lemma step_dec
  : reddec step.
  Proof.
    hnf; intros. destruct x as [[L V] []].
    - case_eq (exp_eval V e); intros. left. do 2 eexists. eauto 20 using step.
      right. stuck.
    - case_eq (exp_eval V e); intros.
      left. case_eq (val2bool v); intros; do 2 eexists; eauto using step.
      right. stuck.
    - destruct (get_dec L (counted l)) as [[blk A]|?].
      decide (length (block_Z blk) = length Y).
      case_eq (omap (exp_eval V) Y); intros; try now (right; stuck).
      + left. do 2 eexists. econstructor; eauto.
      + right. stuck2. get_functional; subst; eauto.
      + right. stuck2. eauto.
    - right. stuck2.
    - case_eq (omap (exp_eval V) Y); intros; try now (right; stuck).
      left; eexists (EvtExtern (ExternI f l 0)). eexists; eauto using step.
    - left. eexists. eauto using step.
  Qed.

End F.

Imperative Semantics


Module I.
  Inductive block : Type :=
    blockI {
      block_Z : params;
      block_s : stmt
    }.

  Definition labenv := list block.
  Definition state : Type := (labenv × onv val × stmt)%type.

  Inductive step : stateeventstateProp :=
  | stepExp L E x e b v
    (def:exp_eval E e = Some v)
    : step (L, E, stmtLet x e b) EvtTau (L, E[x<-Some v], b)

  | stepIfT L E
    e (b1 b2 : stmt) v
    (def:exp_eval E e = Some v)
    (condTrue: val2bool v = true)
    : step (L, E, stmtIf e b1 b2) EvtTau (L, E, b1)

  | stepIfF L E
    e (b1 b2:stmt) v
    (def:exp_eval E e = Some v)
    (condFalse: val2bool v = false)
    : step (L, E, stmtIf e b1 b2) EvtTau (L, E, b2)

  | stepGoto L E l Y blk vl
    (Ldef:get L (counted l) blk)
    (len:length (block_Z blk) = length Y)
    (def:omap (exp_eval E) Y = Some vl)
    (updOk:E[block_Z blk <-- List.map Some vl] = )
    : step (L, E, stmtApp l Y)
            EvtTau
            (drop (counted l) L, , block_s blk)


  | stepLet L E
    s Z (b:stmt)
    : step (L, E, stmtFun Z s b) EvtTau (blockI Z s::L, E, b)

  | stepExtern L E x f Y s vl v
    (def:omap (exp_eval E) Y = Some vl)
    : step (L, E, stmtExtern x f Y s)
            (EvtExtern (ExternI f vl v))
            (L, E[x <- Some v], s).

  Lemma step_internally_deterministic
  : internally_deterministic step.
  Proof.
    hnf; intros.
    inv H; inv H0; split; eauto; try get_functional; try congruence.
  Qed.

  Lemma step_externally_determined
  : externally_determined step.
  Proof.
    hnf; intros.
    inv H; inv H0; eauto; try get_functional; try congruence.
  Qed.

  Lemma step_dec
  : reddec step.
  Proof.
    hnf; intros. destruct x as [[L V] []].
    - case_eq (exp_eval V e); intros. left. do 2 eexists. eauto 20 using step.
      right. stuck.
    - case_eq (exp_eval V e); intros.
      left. case_eq (val2bool v); intros; do 2 eexists; eauto using step.
      right. stuck.
    - destruct (get_dec L (counted l)) as [[blk A]|?].
      decide (length (block_Z blk) = length Y).
      case_eq (omap (exp_eval V) Y); intros; try now (right; stuck).
      + left. do 2 eexists. econstructor; eauto.
      + right. stuck2. get_functional; subst; eauto.
      + right. stuck2. eauto.
    - right. stuck2.
    - case_eq (omap (exp_eval V) Y); intros; try now (right; stuck).
      left; eexists (EvtExtern (ExternI f l 0)). eexists; eauto using step.
    - left. eexists. eauto using step.
  Qed.

End I.

Fixpoint labenvRmE (L:F.labenv) : I.labenv
  :=
  match L with
    | nilnil
    | F.blockI E Z s::LI.blockI Z s :: labenvRmE L
  end.