Module CSClocking

From Coq Require Import List.
Import List.ListNotations.
Open Scope list_scope.

From Velus Require Import Common.
From Velus Require Import CommonTyping.
From Velus Require Import Environment.
From Velus Require Import Operators.
From Velus Require Import Clocks.
From Velus Require Import Fresh.
From Velus Require Import Lustre.StaticEnv.
From Velus Require Import Lustre.LSyntax.
From Velus Require Import Lustre.LClocking.
From Velus Require Import Lustre.ClockSwitch.ClockSwitch.
From Velus Require Import Lustre.SubClock.SCClocking.

Module Type CSCLOCKING
       (Import Ids : IDS)
       (Import Op : OPERATORS)
       (OpAux : OPERATORS_AUX Ids Op)
       (Import Cks : CLOCKS Ids Op OpAux)
       (Import Senv : STATICENV Ids Op OpAux Cks)
       (Import Syn : LSYNTAX Ids Op OpAux Cks Senv)
       (Import Clo : LCLOCKING Ids Op OpAux Cks Senv Syn)
       (Import CS : CLOCKSWITCH Ids Op OpAux Cks Senv Syn).

  Module Import SCC := SCClockingFun Ids Op OpAux Cks Senv Syn Clo SC. Import SC.

  Import Fresh Facts Tactics.

  Section switch_block.

    Context {PSyn : list decl -> block -> Prop} {prefs : PS.t}.
    Variable G : @global PSyn prefs.

    Hypothesis HwG : wc_global G.

    Import Permutation.

    Lemma cond_eq_wc Γ : forall e ty ck x xcs eqs' st st',
        wc_exp G Γ e ->
        clockof e = [ck] ->
        cond_eq e ty ck st = (x, xcs, eqs', st') ->
        Forall (wc_equation G (Γ++senv_of_tyck xcs)) eqs'.
    Proof.

    Lemma cond_eq_wc_clock Γ : forall e ty ck x xcs eqs' st st',
        wc_clock Γ ck ->
        cond_eq e ty ck st = (x, xcs, eqs', st') ->
        Forall (wc_clock Γ) (map snd (Common.idck xcs)).
    Proof.

    Lemma cond_eq_In Γ : forall e ty ck x xcs eqs' st st',
        wc_exp G Γ e ->
        clockof e = [ck] ->
        cond_eq e ty ck st = (x, xcs, eqs', st') ->
        HasClock (Γ ++ senv_of_tyck xcs) x ck.
    Proof.

    Lemma new_idents_wc Γ' : forall ck x ty k ids ids' st st',
        wc_clock Γ' ck ->
        In (x, ck) Γ' ->
        new_idents ck x ty k ids st = (ids', st') ->
        Forall (fun '(_, _, (_, ck)) => wc_clock Γ' ck) ids'.
    Proof.

    Lemma when_free_wc Γ : forall x y ty ck cx tx k,
        HasClock Γ x ck ->
        HasClock Γ y (Con ck cx (tx, k)) ->
        HasClock Γ cx ck ->
        wc_block G Γ (when_free x y ty ck cx tx k).
    Proof.

    Lemma merge_defs_wc Γ : forall sub y ty ck x tx xcs,
        HasClock Γ x ck ->
        HasClock Γ (rename_var sub y) ck ->
        xcs <> [] ->
        Forall (fun '(k, sub) => HasClock Γ (rename_var sub y) (Con ck x (tx, k))) xcs ->
        wc_block G Γ (merge_defs sub y ty ck x tx xcs).
    Proof.

    Lemma new_idents_In : forall x ck cx ty k ids1 ids2 nids1 nids2 st1 st2 st3 st4,
        NoDupMembers (ids1++ids2) ->
        InMembers x (ids1++ids2) ->
        new_idents ck cx ty k ids1 st1 = (nids1, st2) ->
        new_idents ck cx ty k ids2 st3 = (nids2, st4) ->
        In (rename_var (Env.from_list (map (fun '(x, y, _) => (x, y)) (nids1 ++ nids2))) x, Con ck cx (ty, k))
           (map (fun '(_, x, (_, ck)) => (x, ck)) (nids1++nids2)).
    Proof.

    Lemma new_idents_In_inv_ck : forall ck cx tx k ids nids st st' x y ck1 ty,
        new_idents ck cx tx k ids st = (nids, st') ->
        In (x, y, (ty, ck1)) nids ->
        ck1 = Con ck cx (tx, k).
    Proof.

    Lemma switch_scope_wc {A} P_na P_nd P_wc f_switch :
      forall locs (blk: A) bck sub Γck Γck' s' st st',
        (forall x, ~ IsLast Γck x) ->
        (forall x, Env.In x sub -> InMembers x Γck) ->
        (forall x y ck, Env.find x sub = Some y -> HasClock Γck x ck -> HasClock Γck' y (subclock_clock bck sub ck)) ->
        (forall x ck, Env.find x sub = None -> HasClock Γck x ck -> HasClock Γck' x (subclock_clock bck sub ck)) ->
        NoDupMembers Γck ->
        wc_env (idck Γck) ->
        wc_clock (idck Γck') bck ->
        noauto_scope P_na (Scope locs blk) ->
        NoDupScope P_nd (map fst Γck) (Scope locs blk) ->
        wc_scope P_wc G Γck (Scope locs blk) ->
        switch_scope f_switch Γck bck sub (Scope locs blk) st = (s', st') ->
        (forall Γck Γck' blk' st st',
            (forall x, ~ IsLast Γck x) ->
            (forall x, Env.In x sub -> InMembers x Γck) ->
            (forall x y ck, Env.find x sub = Some y -> HasClock Γck x ck -> HasClock Γck' y (subclock_clock bck sub ck)) ->
            (forall x ck, Env.find x sub = None -> HasClock Γck x ck -> HasClock Γck' x (subclock_clock bck sub ck)) ->
            NoDupMembers Γck ->
            wc_env (idck Γck) ->
            wc_clock (idck Γck') bck ->
            P_na blk ->
            P_nd (map fst Γck) blk ->
            P_wc Γck blk ->
            f_switch Γck blk st = (blk', st') ->
            P_wc Γck' blk') ->
        wc_scope P_wc G Γck' s'.
    Proof.

    Lemma switch_block_wc : forall blk bck sub Γ Γ' blk' st st',
        (forall x, ~IsLast Γ x) ->
        (forall x, Env.In x sub -> InMembers x Γ) ->
        (forall x y ck, Env.find x sub = Some y -> HasClock Γ x ck -> HasClock Γ' y (subclock_clock bck sub ck)) ->
        (forall x ck, Env.find x sub = None -> HasClock Γ x ck -> HasClock Γ' x (subclock_clock bck sub ck)) ->
        NoDupMembers Γ ->
        wc_env (idck Γ) ->
        wc_clock (idck Γ') bck ->
        noauto_block blk ->
        NoDupLocals (map fst Γ) blk ->
        wc_block G Γ blk ->
        switch_block Γ bck sub blk st = (blk', st') ->
        wc_block G Γ' blk'.
    Proof.

  End switch_block.

  Fact subclock_clock_idem : forall ck,
    subclock_clock Cbase (Env.empty ident) ck = ck.
  Proof.

  Lemma switch_node_wc G1 G2 : forall n,
      wc_global G1 ->
      global_iface_incl G1 G2 ->
      wc_node G1 n ->
      wc_node G2 (switch_node n).
  Proof.

  Lemma switch_global_wc : forall G,
      wc_global G ->
      wc_global (switch_global G).
  Proof.

End CSCLOCKING.

Module CSClockingFun
       (Ids : IDS)
       (Op : OPERATORS)
       (OpAux : OPERATORS_AUX Ids Op)
       (Cks : CLOCKS Ids Op OpAux)
       (Senv : STATICENV Ids Op OpAux Cks)
       (Syn : LSYNTAX Ids Op OpAux Cks Senv)
       (Clo : LCLOCKING Ids Op OpAux Cks Senv Syn)
       (CS : CLOCKSWITCH Ids Op OpAux Cks Senv Syn)
       <: CSCLOCKING Ids Op OpAux Cks Senv Syn Clo CS.
  Include CSCLOCKING Ids Op OpAux Cks Senv Syn Clo CS.
End CSClockingFun.