Module SDtoRel

From Coq Require Import BinPos List Permutation Morphisms.

From Velus Require Import Common Ident Environment Operators Clocks CoindStreams.
From Velus Require Import Lustre.StaticEnv Lustre.LSyntax Lustre.LOrdered Lustre.LSemantics Lustre.LTyping Lustre.LClocking Lustre.LCausality.

From Velus Require Import FunctionalEnvironment.
From Velus Require Import Lustre.Denot.Cpo.

Close Scope equiv_scope.

Require Import CommonList2 CommonDS SDfuns SD Infty InftyProof CheckOp OpErr Safe Abs Lp ResetMask Restr.

Import List ListNotations.

Module Type SDTOREL
       (Import Ids : IDS)
       (Import Op : OPERATORS)
       (Import 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 Typ : LTYPING Ids Op OpAux Cks Senv Syn)
       (Import Cl : LCLOCKING Ids Op OpAux Cks Senv Syn)
       (Import Caus : LCAUSALITY Ids Op OpAux Cks Senv Syn)
       (Import Lord : LORDERED Ids Op OpAux Cks Senv Syn)
       (Import Str : COINDSTREAMS Ids Op OpAux Cks)
       (Import Sem : LSEMANTICS Ids Op OpAux Cks Senv Syn Lord Str)
       (Import Den : SD Ids Op OpAux Cks Senv Syn Lord)
       (Import Restr : LRESTR Ids Op OpAux Cks Senv Syn)
       (Import Inf : LDENOTINF Ids Op OpAux Cks Senv Syn Typ Caus Lord Restr Den)
       (Import Ckop : CHECKOP Ids Op OpAux Cks Senv Syn)
       (Import OpErr : OP_ERR Ids Op OpAux Cks Senv Syn Typ Restr Lord Den Ckop)
       (Import Safe : LDENOTSAFE Ids Op OpAux Cks Senv Syn Typ Restr Cl Lord Den Ckop OpErr)
       (Import Abs : ABS_INDEP Ids Op OpAux Cks Senv Syn Typ Lord Den)
       (Import Lp : LP Ids Op OpAux Cks Senv Syn Typ Lord Den).


Global Instance : Symmetric history_equiv.
Proof.

Global Instance eq_EqSts : forall A, subrelation (@eq (list (Stream A))) (@EqSts A).
Proof.

Global Add Parametric Morphism {PSyn Prefs} (G : @global PSyn Prefs) : (sem_exp G)
    with signature history_equiv ==> @EqSt bool ==> eq ==> @EqSts svalue ==> iff
      as sem_exp_iff.
Proof.

Lemma sem_var_restrict :
  forall H Γ x s,
    IsVar Γ x ->
    sem_var H (Var x) s ->
    sem_var (restrict H Γ) (Var x) s.
Proof.

Lemma vars_of_senv_app :
  forall Γ1 Γ2,
    vars_of_senv (Γ1 ++ Γ2) = vars_of_senv Γ1 ++ vars_of_senv Γ2.
Proof.

Lemma union_restrict :
  forall Γ1 Γ2 H,
    history_equiv (restrict H Γ1 + restrict H Γ2) (restrict H (Γ1 ++ Γ2)).
Proof.

Lemma dom_restrict :
  forall H Γ,
    dom_lb H Γ ->
    dom (restrict H Γ) Γ.
Proof.

Import RelationPairs.

Global Add Parametric Morphism : merge
       with signature @EqSt _ ==> Forall2 (eq * (@EqSt _)) ==> @EqSt _ ==> Basics.impl
         as merge_morph1.
Proof.

Global Add Parametric Morphism : case
       with signature
       @EqSt _ ==> Forall2 (eq * (@EqSt _)) ==> orel (@EqSt _) ==> @EqSt _ ==> Basics.impl
         as case_morph1.
Proof.


Tactic Notation "remember_sts" constr(s) "as" ident(x) :=
  let Hx := fresh "H"x in
  remember s as x eqn:Hx;
  apply symmetry, eq_EqSts in Hx.


Dans cette section on donne une définition alternative aux règles du merge/case (LSemantics.Smerge/ScaseTotal/Scasedefault), qui ne manipule plus de Forall2Brs mais plutôt du Forall2t. Ça correspond mieux aux définitions de Denot.v, notamment denot_expss.
Section Sem_alt.

Comment obtenir le prédicat Forall2Brs de LSemantics.Smerge sans avoir à manipuler de Forall3...
  Lemma Forall2Brs_transp :
    forall {PSyn Prefs} (G : @global PSyn Prefs),
    forall H b,
    forall ess vss d Hk,
      vss <> [] ->
      Forall2
        (fun '(t, es) (vs : list (enumtag * Stream svalue)) =>
           exists xss : list (list (Stream svalue)),
             Forall2 (sem_exp G H b) es xss /\ vs = map (pair t) (concat xss)) ess vss ->
      Forall2Brs (sem_exp G H b) ess (proj1_sig (transp d vss Hk)).
  Proof.

Cette définition semble plus naturelle : vss correspond exactement à la matrice de concaténation de sem_exp sur ess, l'opérateur merge relationnel est appliqué sur les lignes de la matrice grâce à Forall2t.
  Lemma Smerge_alt :
    forall {PSyn Prefs} (G : @global PSyn Prefs),
    forall H b x tx ess lann os,
    forall d (xs : Stream svalue) (vss : list (list (enumtag * Stream svalue))),
      sem_var H (Var x) xs ->
      vss <> [] ->
      Forall (fun l => length l = length os) vss ->
      Forall2 (fun '(t,es) vs =>
                 exists xss, Forall2 (sem_exp G H b) es xss
                        /\ vs = map (pair t) (concat xss)) ess vss ->
      Forall2t d (merge xs) vss os ->
      sem_exp G H b (Emerge (x, tx) ess lann) os.
  Proof.

  Lemma ScaseTotal_alt :
    forall {PSyn Prefs} (G : @global PSyn Prefs),
    forall H b e ess tys ck os,
    forall d (s : Stream svalue) (vss : list (list (enumtag * Stream svalue))),
      vss <> [] ->
      length tys = length os ->
      sem_exp G H b e [s] ->
      Forall (fun l => length l = length os) vss ->
      Forall2 (fun '(t,es) vs =>
                 exists xss, Forall2 (sem_exp G H b) es xss
                        /\ vs = map (pair t) (concat xss)) ess vss ->
      Forall2t d (fun l => case s l None) vss os ->
      sem_exp G H b (Ecase e ess None (tys, ck)) os.
  Proof.

  Lemma ScaseDefault_alt :
    forall {PSyn Prefs} (G : @global PSyn Prefs),
    forall H b e ess eds tys ck,
    forall d (s : Stream svalue) (sds : list (list (Stream svalue))) (vss : list (list (enumtag * Stream svalue))) os,
      vss <> [] ->
      sem_exp G H b e [s] ->
      wt_streams [s] (typeof e) ->
      Forall2 (sem_exp G H b) eds sds ->
      length (concat sds) = length os ->
      Forall (fun l => length l = length os) vss ->
      Forall2 (fun '(t,es) vs =>
                 exists xss, Forall2 (sem_exp G H b) es xss
                        /\ vs = map (pair t) (concat xss)) ess vss ->
      Forall2t d (fun l dos => case s l (Some (fst dos)) (snd dos)) (vss) (combine (concat sds) os) ->
      sem_exp G H b (Ecase e ess (Some eds) (tys, ck)) os.
  Proof.

Lemma EqSts_concat_eq :
  forall (s : list (Stream svalue)) (ss : list (list (Stream svalue))),
    EqSts s (concat ss) ->
    exists ss', Forall2 EqSts ss' ss
           /\ s = concat ss'.
Proof.


Lemma Smerge_alt2 :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall H b x tx ess lann os,
  forall d (xs : Stream svalue) (vss : list (list (Stream svalue))),
    sem_var H (Var x) xs ->
    vss <> [] ->
    Forall (fun l => length l = length os) vss ->
    Forall2 (fun '(_,es) vs =>
               exists xss, EqSts vs (concat xss)
                      /\ Forall2 (sem_exp G H b) es xss) ess vss ->
    Forall2t d (fun ss => merge xs (combine (map fst ess) ss)) vss os ->
    sem_exp G H b (Emerge (x, tx) ess lann) os.
Proof.
Lemma ScaseTotal_alt2 :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall H b e ess tys ck os,
  forall d (s : Stream svalue) (vss : list (list (Stream svalue))),
    sem_exp G H b e [s] ->
    vss <> [] ->
    length tys = length os ->
    Forall (fun l => length l = length os) vss ->
    Forall2 (fun '(_,es) vs =>
               exists xss, EqSts vs (concat xss)
                      /\ Forall2 (sem_exp G H b) es xss) ess vss ->
    Forall2t d (fun ss => case s (combine (map fst ess) ss) None) vss os ->
    sem_exp G H b (Ecase e ess None (tys, ck)) os.
Proof.

Lemma ScaseDefault_alt2 :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall H b e ess eds tys ck,
  forall d (s : Stream svalue) (sds : list (list (Stream svalue))) (vss : list (list (Stream svalue))) os,
    vss <> [] ->
    sem_exp G H b e [s] ->
    wt_streams [s] (typeof e) ->
    Forall2 (sem_exp G H b) eds sds ->
    length (concat sds) = length os ->
    Forall (fun l => length l = length os) vss ->
    Forall2 (fun '(_,es) vs =>
               exists xss, EqSts vs (concat xss)
                      /\ Forall2 (sem_exp G H b) es xss) ess vss ->
    Forall2t d (fun ss dos => case s (combine (map fst ess) ss) (Some (fst dos)) (snd dos)) vss (combine (concat sds) os) ->
    sem_exp G H b (Ecase e ess (Some eds) (tys, ck)) os.
Proof.


End Sem_alt.

Section FromLClockedSemantics.
Lemma clocks_of_false :
  forall ss,
    clocks_of (List.map (fun _ : Stream svalue => Streams.const absent) ss) ≡ Streams.const false.
Proof.
Lemma clocks_of_false2 :
  forall n,
    clocks_of (repeat (Streams.const absent) n) ≡ Streams.const false.
Proof.
Lemma fby_absent {A}:
  @fby A (Streams.const absent) (Streams.const absent) (Streams.const absent).
Proof.
Corollary sem_node_cons' :
  forall {PSyn Prefs} (nd : @node PSyn Prefs),
  forall nds types externs f xs ys,
      Ordered_nodes (Global types externs (nd::nds))
      -> sem_node (Global types externs nds) f xs ys
      -> nd.(n_name) <> f
      -> sem_node (Global types externs (nd::nds)) f xs ys.
Proof.

Lemma sem_block_cons' :
  forall {PSyn Prefs} (nd : @node PSyn Prefs),
  forall nds types externs bck Hi bk,
    Ordered_nodes (Global types externs (nd::nds))
    -> sem_block (Global types externs nds) Hi bk bck
    -> ~Is_node_in_block nd.(n_name) bck
    -> sem_block (Global types externs (nd::nds)) Hi bk bck.
Proof.
End FromLClockedSemantics.


Section Sem_absent.

Lemma wt_absent : forall ty, wt_stream (Streams.const absent) ty.
Proof.

Definition sem_global_abs {PSyn Prefs} (G : @global PSyn Prefs) :=
  forall f n,
    find_node f G = Some n ->
    let ss := repeat (Streams.const absent) (length (n_in n)) in
    let os := repeat (Streams.const absent) (length (n_out n)) in
    sem_node G f ss os.

Lemma sem_exp_absent :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall Γ,
    sem_global_abs G ->
    forall e,
    restr_exp e ->
    wt_exp G Γ e ->
    let H := fun _ => Some (Streams.const absent) in
    sem_exp G H (Streams.const false) e (repeat (Streams.const absent) (numstreams e)).
Proof.

Definition abs_hist_of_vars (vars : list decl) : history :=
  fun x => match x with
        | Var x => if mem_ident x (List.map fst vars)
                  then Some (Streams.const absent)
                  else None
        | Last x => None
        end.

Lemma abs_hist_of_vars_dom :
  forall vars,
    Forall (fun '(_, (_, _, _, o)) => o = None) vars ->
    dom (abs_hist_of_vars vars) (senv_of_decls vars).
Proof.

Lemma sem_global_absent :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    sem_global_abs G.
Proof.

End Sem_absent.


Translation of DS (sampl value) to Stream svalue


Definition sval_of_sampl : sampl value -> svalue :=
  fun v => match v with
        | pres v => present v
        | abs => absent
        | err e => absent
        end.

Definition S_of_DSv := S_of_DS sval_of_sampl.

Lemma S_of_DSv_eq :
  forall (s : DS (sampl value)) Hs t (Heq : s == t),
  exists Ht,
    S_of_DSv s HsS_of_DSv t Ht.
Proof.

Lemma tl_rem :
  forall s Inf Inf',
    Streams.tl (S_of_DSv s Inf) ≡ S_of_DSv (REM _ s) Inf'.
Proof.

lift S_of_DSv on lists of streams

Definition Ss_of_nprod {n} (np : @nprod (DS (sampl value)) n)
  (Hinf : forall_nprod (@infinite _) np) : list (Stream svalue).
  induction n.
  - exact [].
  - exact (S_of_DSv (nprod_hd np) (forall_nprod_hd _ _ Hinf)
             :: IHn (nprod_tl np) (forall_nprod_tl _ _ Hinf)).
Defined.

Lemma Ss_of_nprod_length :
  forall n (np : nprod n) infn,
    length (Ss_of_nprod np infn) = n.
Proof.

Lemma _Ss_of_nprod_eq :
  forall n (np np' : nprod n) Hinf Hinf',
    np == np' ->
    EqSts (Ss_of_nprod np Hinf) (Ss_of_nprod np' Hinf').
Proof.

Corollary Ss_of_nprod_eq :
  forall {n} (np : nprod n) Hinf np',
    np == np' ->
    exists Hinf',
      EqSts (Ss_of_nprod np Hinf) (Ss_of_nprod np' Hinf').
Proof.

Lemma Ss_of_nprod_nth :
  forall n (np : nprod n) Inf k d s,
    k < n ->
    exists Inf2,
      nth k (Ss_of_nprod np Inf) sS_of_DSv (get_nth k d np) Inf2.
Proof.

Lemma _Ss_app :
  forall n m (np : nprod n) (mp : nprod m) Hnm Hn Hm,
    EqSts (Ss_of_nprod (nprod_app np mp) Hnm)
      ((Ss_of_nprod np Hn) ++ (Ss_of_nprod mp Hm)).
Proof.

Corollary Ss_app :
  forall {n m} (np : nprod n) (mp : nprod m) Hnm,
  exists Hn Hm,
    EqSts (Ss_of_nprod (nprod_app np mp) Hnm)
      ((Ss_of_nprod np Hn) ++ (Ss_of_nprod mp Hm)).
Proof.

Lemma Ss_map :
  forall f (g : DS (sampl value) -C-> DS (sampl value)),
    (forall x Inf Inf', f (S_of_DSv x Inf) ≡ S_of_DSv (g x) Inf') ->
    forall n (np : nprod n) Inf Inf',
      EqSts (map f (Ss_of_nprod np Inf)) (Ss_of_nprod (lift g np) Inf').
Proof.

Lemma Ss_of_nprod_hds :
  forall n (np : @nprod (DS (sampl value)) n) npc npi,
    map sval_of_sampl (nprod_hds np npc) = map (@Streams.hd _) (Ss_of_nprod np npi).
Proof.

comment passer de denot_exps à (concat denot_exp)
Lemma Ss_exps :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall ins envG envI env es Hinf Infe,
    EqSts (Ss_of_nprod (denot_exps G ins es envG envI env) Hinf)
      (flat_map (fun e => Ss_of_nprod (denot_exp G ins e envG envI env) (Infe e)) es).
Proof.


lift Ss_of_nprod on matrix of streams

Fixpoint Ss_of_nprods {n m} (nmp : @nprod (@nprod (DS (sampl value)) m) n) :
  forall_nprod (forall_nprod (@infinite _)) nmp -> list (list (Stream svalue)) :=
  match n return forall (nmp : nprod n), (forall_nprod (forall_nprod (@infinite _)) nmp) -> _ with
  | O => fun _ _ => []
  | S n => fun nmp Inf =>
            Ss_of_nprod (nprod_hd nmp) (forall_nprod_hd _ _ Inf)
              :: Ss_of_nprods (nprod_tl nmp) (forall_nprod_tl _ _ Inf)
  end nmp.

Lemma _Ss_of_nprods_eq :
  forall n m (np1 np2 : @nprod (@nprod (DS (sampl value)) m) n) Inf1 Inf2,
    np1 == np2 ->
    Forall2 EqSts (Ss_of_nprods np1 Inf1) (Ss_of_nprods np2 Inf2).
Proof.

Lemma Ss_of_nprods_hd :
  forall d n m (vss : @nprod (nprod (S m)) n) Inf1 Inf2,
    EqSts (map (hd d) (Ss_of_nprods vss Inf1))
      (Ss_of_nprod (lift nprod_hd vss) Inf2).
Proof.

Lemma Ss_of_nprods_tl :
  forall n m (vss : @nprod (nprod (S m)) n) Inf1 Inf2,
    Forall2 EqSts (map (@tl _) (Ss_of_nprods vss Inf1))
      (Ss_of_nprods (lift nprod_tl vss) Inf2).
Proof.

Generalizable All Variables.
Lemma Forall2t_lift_nprod :
  forall
    `{ (Proper (Forall2 (@EqSt _) ==> @EqSt _ ==> Basics.impl) P)%signature },
  forall n (F : nprod n -C-> DS (sampl value)),
  forall (Q : DS (sampl value) -> Prop),
    (forall (np : nprod n) Inf1 Inf2, Q (F np) -> P (Ss_of_nprod np Inf1) (S_of_DSv (F np) Inf2)) ->
    forall d m (vss : @nprod (@nprod (DS (sampl value)) m) n) Inf1 Inf2,
      forall_nprod Q (lift_nprod F vss) ->
      Forall2t d P (Ss_of_nprods vss Inf1) (Ss_of_nprod (lift_nprod F vss) Inf2).
Proof.

comment passer de denot_expss à (map _ (concat denot_exp))
Lemma Ss_expss :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall ins envG envI env (ess : list (enumtag * (list exp))) n Infe Inf,
    Forall (fun es => list_sum (map numstreams (snd es)) = n) ess ->
    Forall2 EqSts
      (map
         (flat_map
            (fun e => Ss_of_nprod (denot_exp G ins e envG envI env) (Infe e))) (map snd ess))
      (Ss_of_nprods (denot_expss G ins ess n envG envI env) Inf).
Proof.

Correspondence of semantic predicate for streams functions


In the lext lemmas we use the method of coinduction loading from "Circular coinduction in Coq using bisimulation-up-to techniques" by Endrullis, Hendriks and Bodin. Their idea is to push computation/rewriting in the arguments of the coinductive predicate instead of performing it at top-level, which would breaks Coq guardedness condition. Thus, instead of proving forall xs ys, P xs ys we prove forall xs ys, forall xs' ys', xs ≡ xs' -> ys ≡ ys' -> P xs' ys'

Lemma ok_const :
  forall c bs Hinf,
    S_of_DSv (sconst (Vscalar (sem_cconst c)) (DS_of_S bs)) Hinfconst bs c.
Proof.

Lemma ok_enum :
  forall c bs Hinf,
    S_of_DSv (sconst (Venum c) (DS_of_S bs)) Hinfenum bs c.
Proof.

Lemma ok_unop :
  forall op ty (xs : DS (sampl value)),
    let rs := sunop (fun v => sem_unop op v ty) xs in
    forall (xsi : infinite xs)
      (rsi : infinite rs),
      safe_DS rs ->
      lift1 op ty (S_of_DSv xs xsi) (S_of_DSv rs rsi).
Proof.

Lemma ok_binop :
  forall op ty1 ty2 (xs ys : DS (sampl value)),
    let rs := sbinop (fun v1 v2 => sem_binop op v1 ty1 v2 ty2) xs ys in
    forall (xsi : infinite xs)
      (ysi : infinite ys)
      (rsi : infinite rs),
      safe_DS rs ->
      lift2 op ty1 ty2 (S_of_DSv xs xsi) (S_of_DSv ys ysi) (S_of_DSv rs rsi).
Proof.

Lemma ok_fby1 :
  forall v (xs ys : DS (sampl value)),
    let rs := SDfuns.fby1 (Some v) xs ys in
    forall (xsi : infinite xs)
      (ysi : infinite ys)
      (rsi : infinite rs),
      safe_DS rs ->
      fby1 v (S_of_DSv xs xsi) (S_of_DSv ys ysi) (S_of_DSv rs rsi).
Proof.

Lemma ok_fby :
  forall (xs ys : DS (sampl value)),
    let rs := SDfuns.fby xs ys in
    forall (xsi : infinite xs)
      (ysi : infinite ys)
      (rsi : infinite rs),
      safe_DS rs ->
      fby (S_of_DSv xs xsi) (S_of_DSv ys ysi) (S_of_DSv rs rsi).
Proof.

Lemma ok_when :
  forall k (xs cs : DS (sampl value)),
    let rs := swhenv k xs cs in
    forall (xsi : infinite xs)
      (csi : infinite cs)
      (rsi : infinite rs),
      safe_DS rs ->
      when k (S_of_DSv xs xsi) (S_of_DSv cs csi) (S_of_DSv rs rsi).
Proof.

Lemma ok_merge :
  forall l (cs : DS (sampl value)) (np : nprod (length l)),
    let rs := smergev l cs np in
    forall (npi : forall_nprod (@infinite _) np)
      (csi : infinite cs)
      (rsi : infinite rs),
      safe_DS rs ->
      merge (S_of_DSv cs csi) (combine l (Ss_of_nprod np npi)) (S_of_DSv rs rsi).
Proof.

Lemma ok_case :
  forall l, l <> [] ->
  forall (cs : DS (sampl value)) (np : nprod (length l)),
    let rs := scasev l cs np in
    forall (npi : forall_nprod (@infinite _) np)
      (csi : infinite cs)
      (rsi : infinite rs),
      safe_DS rs ->
      case (S_of_DSv cs csi) (combine l (Ss_of_nprod np npi)) None (S_of_DSv rs rsi).
Proof.

Lemma ok_case_def :
  forall l, l <> [] ->
  forall (cs : DS (sampl value)) (dnp : nprod (S (length l))),
    let rs := scase_defv l cs dnp in
    let ds := nprod_hd dnp in
    let np := nprod_tl dnp in
    forall (npi : forall_nprod (@infinite _) np)
      (csi : infinite cs)
      (dsi : infinite ds)
      (rsi : infinite rs),
      safe_DS rs ->
      case (S_of_DSv cs csi) (combine l (Ss_of_nprod np npi)) (Some (S_of_DSv ds dsi)) (S_of_DSv rs rsi).
Proof.

Section BOOLS_OFS.

  Lemma disj_str_orb :
    forall bs bss,
      disj_str [bs; disj_str bss] ≡ map2 orb bs (disj_str bss).
  Proof.

  Lemma bools_ofs_cons :
    forall s ss b bs,
      bools_ofs ss bs ->
      bools_of s b ->
      bools_ofs (s :: ss) (map2 orb b bs).
  Proof.

  Lemma bools_of_sbool_of :
    forall s Inf1 Inf2,
      ty_DS bool_velus_type s ->
      bools_of (S_of_DSv s Inf1) (S_of_DS id (sbool_of s) Inf2).
  Proof.

  Lemma zip_map2_ :
    forall {A B C} (op : A -> B -> C) s t Inf1 Inf2 Inf3,
      S_of_DS id (ZIP op s t) Inf3map2 op (S_of_DS id s Inf1) (S_of_DS id t Inf2).
  Proof.

  Lemma zip_map2 :
    forall {A B C} (op : A -> B -> C) s t Inf3,
    exists Inf1 Inf2,
      S_of_DS id (ZIP op s t) Inf3map2 op (S_of_DS id s Inf1) (S_of_DS id t Inf2).
  Proof.

  Lemma bools_ofs_sbools_of :
    forall n (np : nprod n) Inf1 Inf2,
      forall_nprod (ty_DS bool_velus_type) np ->
      bools_ofs (Ss_of_nprod np Inf1) (S_of_DS id (sbools_of np) Inf2).
  Proof.

End BOOLS_OFS.


Section OLD_MASK.

  Import Streams.

  CoFixpoint mask {A : Type} (absent: A) (k: nat) (rs: Stream bool) (xs: Stream A) : Stream A :=
    let mask' k' := mask absent k' (tl rs) (tl xs) in
    match k, hd rs with
    | 0, true => Streams.const absent
    | 0, false => hd xsmask' O
    | 1, true => hd xsmask' O
    | S k', true => absentmask' k'
    | S _, false => absentmask' k
    end.
  Definition maskv := @mask svalue absent.

  Lemma mask'_abs :
    forall A (absent : A) k rs xs,
      O < k ->
      mask' absent O k rs xsconst absent.
  Proof.

  Lemma mask_retro_compat :
    forall k rs xs,
      maskv k rs xsStr.maskv k rs xs.
  Proof.


  Lemma mask_nth {A} (absent: A) :
    forall n k rs xs,
      (mask absent k rs xs) # n = if (count rs) # n =? k then xs # n else absent.
  Proof.

  Global Add Parametric Morphism {A} (absent: A) k : (mask absent k)
      with signature @EqSt _ ==> @EqSt _ ==> @EqSt _
        as mask_morph.
  Proof.

  Global Add Parametric Morphism k : (maskv k)
      with signature @EqSt _ ==> @EqSt _ ==> @EqSt _
        as maskv_morph.
  Proof.

  Lemma Sapp_retro_compat :
    forall {PSyn Prefs} (G : @global PSyn Prefs),
    forall (H : history) (b : Stream bool) (f : ident) (es er : list exp)
      (lann : list ann) (ss : list (list (Stream svalue))) (os : list (Stream svalue))
      (rs : list (list (Stream svalue))) (bs : Stream bool),
      Forall2 (sem_exp G H b) es ss ->
      Forall2 (sem_exp G H b) er rs ->
      bools_ofs (concat rs) bs ->
      (forall k : nat, sem_node G f (List.map (maskv k bs) (concat ss)) (List.map (maskv k bs) os)) ->
      sem_exp G H b (Eapp f es er lann) os.
  Proof.

End OLD_MASK.




Lemma smask_maskv :
  forall k R U Ri Ui Mi,
    S_of_DSv (smask k R U) Mimaskv k (S_of_DS id R Ri) (S_of_DSv U Ui).
Proof.

Lemma map_mask_ :
  forall k rs Infr l (ss : nprod (length l)) InfI InfM,
    0 < length l ->
    NoDup l ->
    EqSts
      (map (maskv k (S_of_DS id rs Infr)) (Ss_of_nprod ss InfI))
      (Ss_of_nprod (np_of_env l (smask_env k rs (env_of_np l ss))) InfM).
Proof.

Corollary map_mask :
  forall k rs Infr l (ss : nprod (length l)) InfI,
    0 < length l ->
    NoDup l ->
  exists InfM,
    EqSts
      (map (maskv k (S_of_DS id rs Infr)) (Ss_of_nprod ss InfI))
      (Ss_of_nprod (np_of_env l (smask_env k rs (env_of_np l ss))) InfM).
Proof.


Correspondance clocks_of/bss

Lemma ac_AC :
  forall s Inf,
    abstract_clock (S_of_DSv s Inf) ≡ S_of_DS id (AC s) (map_inf _ _ _ _ Inf).
Proof.

Lemma zip_zipWith :
  forall A B C (f : A -> B -> C),
    forall x y Infx Infy Infr,
      zipWith f (S_of_DS id x Infx) (S_of_DS id y Infy) ≡ S_of_DS id (ZIP f x y) Infr.
Proof.

Lemma _clocks_of_bss :
  forall env l Inf Infb,
    NoDup l ->
    clocks_of (Ss_of_nprod (np_of_env l env) Inf)
      ≡ S_of_DS id (bss l env) Infb.
Proof.

Lemma bss_env_inf :
  forall l env,
    (forall_nprod (@infinite _) (np_of_env l env)) ->
    infinite (bss l env).
Proof.

Corollary clocks_of_bss :
  forall env l Inf,
    NoDup l ->
    exists Infb,
    clocks_of (Ss_of_nprod (np_of_env l env) Inf) ≡
      S_of_DS id (bss l env) Infb.
Proof.


Section Inf_Dom.

Definition inf_dom Γ ins envI env :=
  forall x, IsVar Γ x -> infinite (denot_var ins envI env x).

Global Add Parametric Morphism Γ ins : (inf_dom Γ ins)
       with signature @Oeq (DS_prod SI) ==> @Oeq (DS_prod SI) ==> iff
         as inf_dom_morph.
Proof.

Global Add Parametric Morphism Γ ins envI : (inf_dom Γ ins envI)
       with signature @Oeq (DS_prod SI) ==> iff
         as inf_dom_morph2.
Proof.

Lemma infinite_dom_app_l :
  forall (env : DS_prod SI) l1 l2,
    infinite_dom env (l1 ++ l2) ->
    infinite_dom env l1.
Proof.

Lemma infinite_dom_np :
  forall env l,
    forall_nprod (@infinite _) (np_of_env l env) ->
    infinite_dom env l.
Proof.

Lemma inf_dom_decomp :
  forall Γ ins outs envI env,
    infinite_dom envI ins ->
    infinite_dom env outs ->
    map fst Γ = ins ++ outs ->
    inf_dom Γ ins envI env.
Proof.

End Inf_Dom.


Fonctions pour passer d'un DS_prod SI à un Str.history


Lemma IsVar_dec : forall Γ x, { IsVar Γ x } + { ~ IsVar Γ x }.
Proof.


Definition hist_of_envs Γ ins envI env (InfΓ : inf_dom Γ ins envI env) : history :=
  fun lx => match lx with
         | Var x => match IsVar_dec Γ x with
                   | left isv => Some (S_of_DSv (denot_var ins envI env x) (InfΓ x isv))
                   | _ => None
                   end
         | _ => None
         end.

Lemma sem_hist_of_envs :
  forall Γ ins envI env InfΓ x Infx,
    IsVar Γ x ->
    sem_var (hist_of_envs Γ ins envI env InfΓ) (Var x)
      (S_of_DSv (denot_var ins envI env x) Infx).
Proof.

Lemma sem_var_nins : forall Γ ins envI env InfΓ x s Inf,
    IsVar Γ x ->
    ~ In x ins ->
    s == env x ->
    sem_var (hist_of_envs Γ ins envI env InfΓ) (Var x) (S_of_DSv s Inf).
Proof.

Lemma sem_hist_of_envs' :
  forall Γ ins envI env InfΓ x s Inf,
    IsVar Γ x ->
    s == denot_var ins envI env x ->
    sem_var (hist_of_envs Γ ins envI env InfΓ) (Var x) (S_of_DSv s Inf).
Proof.

Lemma sem_var_ins : forall Γ ins envI env InfΓ x s Inf,
    IsVar Γ x ->
    In x ins ->
    s == envI x ->
    sem_var (hist_of_envs Γ ins envI env InfΓ) (Var x) (S_of_DSv s Inf).
Proof.



Hypothèse sur les entrées d'un nœud : elles doivent être bien typées et respecter leurs annotations d'horloge.
Definition wf_ins {PSyn Prefs} (n : @node PSyn Prefs) envI bs :=
  let ins := List.map fst n.(n_in) in
  let Γ := senv_of_ins (n_in n) ++ senv_of_decls (n_out n) in
  wf_env Γ ins envI bs 0.


Section Ok_node.

Context {PSyn : list decl -> block -> Prop}.
Context {Prefs : PS.t}.

Variables
  (G : @global PSyn Prefs)
  (envG : Dprodi FI).

Toutes les hypothèses de section sur G et envG seront obtenues par récurrence dans ok_global.

Hypothesis (Wtg : wt_global G).
Hypothesis (Wcg : wc_global G).
Hypothesis (Hrg : restr_global G).

Hypothesis InfG :
  forall f nd envI,
    find_node f G = Some nd ->
    infinite_dom envI (List.map fst (n_in nd)) ->
    infinite_dom (envG f envI) (List.map fst (n_out nd)).

Hypothesis AbsG :
  forall f X,
    envG f (APP_env abs_env X) <= APP_env abs_env (envG f X).

Hypothesis Hlp :
  forall f X n,
    envG f (take_env n X) == take_env n (envG f X).

Hypothesis Wfg :
  forall f n envI,
    find_node f G = Some n ->
    let ins := List.map fst n.(n_in) in
    let Γ := senv_of_ins (n_in n) ++ senv_of_decls (n_out n) ++ get_locals (n_block n) in
    forall bs, bss ins envI <= bs ->
          wf_env Γ ins envI bs 0 ->
          wf_env Γ ins envI bs (envG f envI).

Hypothesis Halign :
  forall f n,
    find_node f G = Some n ->
    let ins := List.map fst (n_in n) in
    let Γ := senv_of_ins (n_in n) ++ senv_of_decls (n_out n) ++ get_locals (n_block n) in
    forall envI,
    wf_env Γ ins envI (bss ins envI) (envG f envI) ->
    abs_alignLE envI (envG f envI).

Hypothesis Hnode :
  forall f n envI,
    find_node f G = Some n ->
    let ins := List.map fst (n_in n) in
    let outs := List.map fst (n_out n) in
    let xs := np_of_env ins envI in
    let os := np_of_env outs (envG f envI) in
    wf_ins n envI (bss ins envI) ->
    forall Infi Info,
    sem_node G f (Ss_of_nprod xs Infi) (Ss_of_nprod os Info).


On le laisse ici car il dépend des hypothèses de section
Lemma ok_reset :
  forall f n,
    find_node f G = Some n ->
    let nf := envG f in
    let nin := List.map fst (n_in n) in
    let nout := List.map fst (n_out n) in
    forall rs (ss : nprod (length nin)),
    let os := np_of_env nout (sreset nf rs (env_of_np nin ss)) in
    wf_ins n (env_of_np nin ss) (bss nin (env_of_np nin ss)) ->
    forall InfI InfO Infr,
    forall k, sem_node G f (List.map (maskv k (S_of_DS id rs Infr)) (Ss_of_nprod ss InfI))
                      (List.map (maskv k (S_of_DS id rs Infr)) (Ss_of_nprod os InfO)).
Proof.


Deux tactiques bien pratiques pour la suite

Ltac gen_infinite_exp :=
  repeat (
  simpl;
  let f := fresh "Inf" in
  match goal with
  | |- context [ infinite_exp ?H1 ?H2 ?H3 ?H4 ?H5 ?H6 ?H7 ?H8 ?H9 ?H10 ?H11 ?H12 ] =>
      generalize (infinite_exp H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 H11 H12) as f
  | |- context [ infinite_exps ?H1 ?H2 ?H3 ?H4 ?H5 ?H6 ?H7 ?H8 ?H9 ?H10 ?H11 ?H12 ?H13 ] =>
      generalize (infinite_exps H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 H11 H12 H13) as f
  | |- context [ infinite_expss ?H1 ?H2 ?H3 ?H4 ?H5 ?H6 ?H7 ?H8 ?H9 ?H10 ?H11 ?H12 ?H13 ?H14 ?H15 ?H16 ] =>
      generalize (infinite_expss H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 H11 H12 H13 H14 H15 H16) as f
  end).

Ltac save_denot_exp se Hse :=
  gen_infinite_exp;
  simpl;
  match goal with
  | |- context [ ?f1 (?f2 (?f3 (denot_exp ?e1 ?e2 ?e3) ?e4) ?e5) ?e6 ] =>
      remember (f1 (f2 (f3 (denot_exp e1 e2 e3) e4) e5) e6)
      as se eqn:Hse
  end.

Ltac gen_inf_sub_exps :=
  gen_infinite_exp;
  gen_sub_exps.


Global Add Parametric Morphism k bs : (maskv k bs)
    with signature @EqSt _ ==> @EqSt _
      as maskv_morph2.
Proof.


Lemma sem_sub_exps :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall ins H envI envG bs bsi env,
  forall (es : list exp) Infes,
    Forall (fun e => forall Infe, sem_exp G H (S_of_DS id bs bsi) e
                    (Ss_of_nprod (denot_exp G ins e envG envI env) Infe)) es ->
    exists sss,
      EqSts (concat sss) (Ss_of_nprod (denot_exps G ins es envG envI env) Infes)
      /\ Forall2 (sem_exp G H (S_of_DS id bs bsi)) es sss.
Proof.

Lemma sem_sub_expss :
  forall {PSyn Prefs} (G : @global PSyn Prefs),
  forall ins H envI envG bs bsi env,
  forall (ess : list (enumtag * list exp)) n Infes,
    Forall (fun es => length (annots (snd es)) = n) ess ->
    Forall (Forall (fun e => forall Infe, sem_exp G H (S_of_DS id bs bsi) e
                            (Ss_of_nprod (denot_exp G ins e envG envI env) Infe)))
      (map snd ess) ->
    Forall2 (fun '(_, es) ss => exists sss,
                 EqSts ss (concat sss)
                 /\ Forall2 (sem_exp G H (S_of_DS id bs bsi)) es sss)
      ess (Ss_of_nprods (denot_expss G ins ess n envG envI env) Infes).
Proof.


On traite à part le cas des appels de nœuds car il apparaît à la fois dans une expression Eapp et dans une équation de type xs=Eapp. Dand les deux cas seules les hypothèses du lemme suivant sont nécessaires. En particulier, rien à dire sur la dépendance entre les horloges de l'équation et de l'application.
Lemma ok_sem_Eapp :
  forall Γ ins env envI,
    let bs := bss ins envI in
    forall bsi (InfΓ : inf_dom Γ ins envI env),
    wf_env Γ ins envI bs env ->
    let H := hist_of_envs Γ ins envI env InfΓ in
    forall f n es er anns bck sub,
      Forall2 (fun (et : type) '(_, (t, _, _)) => et = t) (typesof es) (n_in n) ->
      Forall2 (WellInstantiated bck sub) (List.map (fun '(x, (_, ck, _)) => (x, ck)) (n_in n)) (nclocksof es) ->
      Forall (fun e : exp => numstreams e = 1) er ->
      wc_env (map (fun '(x, (_, ck, _)) => (x, ck)) n.(n_in)) ->
      find_node f G = Some n ->
      length (anns) = length (n_out n) ->
      Forall restr_exp es ->
      Forall (wt_exp G Γ) es ->
      Forall (wc_exp G Γ) es ->
      Forall (no_rte_exp G ins envG envI env) es ->
      Forall (fun e => forall Infe,
                  sem_exp G H (S_of_DS id bs bsi) e
                    (Ss_of_nprod (denot_exp G ins e envG envI env) Infe)) es ->
      Forall restr_exp er ->
      Forall (wt_exp G Γ) er ->
      Forall (fun e => typeof e = [bool_velus_type]) er ->
      Forall (wc_exp G Γ) er ->
      Forall (no_rte_exp G ins envG envI env) er ->
      Forall (fun e => forall Infe,
                  sem_exp G H (S_of_DS id bs bsi) e
                    (Ss_of_nprod (denot_exp G ins e envG envI env) Infe)) er ->
      let os := denot_exp G ins (Eapp f es er anns) envG envI env in
      forall infO,
        sem_exp G H (S_of_DS id bs bsi) (Eapp f es er anns) (Ss_of_nprod os infO).
Proof.


Morphismes rencontrés dans la preuve de ok_sem_exp. La plupart sont ad hoc, donc on les laisse ici.

Local Instance : forall k t,
    Proper ((@EqSt _) ==> (@EqSt _) ==> Basics.impl)
      (fun s => when k s t).
Proof.

Local Instance : forall s l,
    Proper (EqSts ==> EqSt (A:=svalue) ==> Basics.impl)
      (fun ss => merge s (combine l ss)).
Proof.

Local Instance : forall s l,
    Proper (EqSts ==> EqSt (A:=svalue) ==> Basics.impl)
      (fun ss : list (Stream svalue) => case s (combine l ss) None).
Proof.

Local Instance : forall s l,
    Proper (EqSts ==> (EqSt (A:=svalue) * EqSt (A:=svalue)) ==> Basics.impl)
      (fun ss dos => case s (combine l ss) (Some (fst dos)) (snd dos)).
Proof.

Local Instance : forall s l d,
    Proper (EqSts ==> EqSt (A:=svalue) ==> Basics.impl)
      (fun ss b => case s (combine l (tl ss)) (Some (hd d ss)) b).
Proof.

Lemma ty_DS_wt_stream :
  forall ty s si,
    ty_DS ty s ->
    wt_stream (S_of_DSv s si) ty.
Proof.


On redéfinit Safe.safe_exp, qui a une hypothèse de wf_env un peu différente que Wfg présente dans cette section : son Γ n'inclut pas get_locals (n_block n).
Lemma safe_exp :
  forall Γ ins envI bs env,
    wf_env Γ ins envI bs env ->
    bss ins envI <= bs ->
    forall (e : exp),
      restr_exp e ->
      wt_exp G Γ e ->
      wc_exp G Γ e ->
      no_rte_exp G ins envG envI env e ->
      let ss := denot_exp G ins e envG envI env in
      forall_nprod safe_DS ss.
Proof.

Lemma ok_sem_exp :
  forall Γ ins env envI InfΓ,
    let bs := bss ins envI in
    forall bsi,
    wf_env Γ ins envI bs env ->
    let H := hist_of_envs Γ ins envI env InfΓ in
    forall (e : exp) (Hwt : wt_exp G Γ e) (Hwc : wc_exp G Γ e) (Hr : restr_exp e),
      no_rte_exp G ins envG envI env e ->
      let ss := denot_exp G ins e envG envI env in
      forall Infe,
      sem_exp G H (S_of_DS id bs bsi) e (Ss_of_nprod ss Infe).
Proof.

Corollary ok_sem_exps :
  forall Γ ins env envI InfΓ bsi,
    let bs := bss ins envI in
    wf_env Γ ins envI bs env ->
    let H := hist_of_envs Γ ins envI env InfΓ in
    forall es,
      Forall restr_exp es ->
      Forall (wt_exp G Γ) es ->
      Forall (wc_exp G Γ) es ->
      Forall (no_rte_exp G ins envG envI env) es ->
      Forall (fun e => forall Infe,
                  sem_exp G H (S_of_DS id bs bsi) e
                    (Ss_of_nprod (denot_exp G ins e envG envI env) Infe)) es.
Proof.


Node semantics

Lemma ok_vars_equation :
  forall Γ ins (envI env : DS_prod SI) InfΓ n (np : nprod n) xs tys Inf,
    NoDup (ins ++ xs) ->
    Forall2 (HasType Γ) xs tys ->
    Forall2 (fun (x : ident) (s : DS (sampl value)) =>
               s == PROJ (DS_fam SI) x env)
      xs (list_of_nprod np) ->
    Forall2 (sem_var (hist_of_envs Γ ins envI env InfΓ))
      (map Var xs) (Ss_of_nprod np Inf).
Proof.

Lemma ok_sem_equation :
  forall Γ xs es ins envI bsi env,
    let bs := bss ins envI in
    Forall restr_exp es ->
    wc_equation G Γ (xs,es) ->
    wt_equation G Γ (xs,es) ->
    NoDup (ins ++ xs) ->
    wf_env Γ ins envI bs env ->
    Forall (no_rte_exp G ins envG envI env) es ->
    Forall2 (fun x (s : DS (sampl value)) => s == PROJ _ x env) xs
      (list_of_nprod (denot_exps G ins es envG envI env)) ->
    forall InfΓ,
      sem_equation G (hist_of_envs Γ ins envI env InfΓ) (S_of_DS id bs bsi) (xs,es).
Proof.

Lemma ok_sem_blocks :
  forall Γ ins (env : DS_prod SI) envI bsi blks,
    let bs := bss ins envI in
    env == denot_blocks G ins blks envG envI env ->
    wf_env Γ ins envI bs env ->
    Forall restr_block blks ->
    NoDup (flat_map get_defined blks ++ ins) ->
    Forall (wt_block G Γ) blks ->
    Forall (wc_block G Γ) blks ->
    Forall (no_rte_block G ins envG envI env) blks ->
    forall InfΓ,
      Forall (sem_block G (hist_of_envs Γ ins envI env InfΓ) (S_of_DS id bs bsi)) blks.
Proof.

Pour pouvoir utiliser InfG, Wfg, Hnode, on considère * l'ajout d'un nœud en tête de G.(nodes).
Lemma ok_sem_node :
  forall (n : node),
    let '(Global tys exts nds) := G in
    Ordered_nodes (Global tys exts (n :: nds)) ->
    restr_node n ->
    wc_node G n ->
    wt_node G n ->
    let f := n_name n in
    let Γ := senv_of_ins (n_in n) ++ senv_of_decls (n_out n) ++ get_locals (n_block n) in
    let ins := map fst (n_in n) in
    forall envI,
    let bs := bss ins envI in
    let envn := FIXP _ (denot_node G n envG envI) in
    let ss := np_of_env ins envI in
    let os := np_of_env (List.map fst (n_out n)) envn in
    wf_env Γ ins envI bs envn ->
    no_rte_node G ins envG envI envn n ->
    inf_dom Γ ins envI envn ->
    forall infI infO,
      sem_node (Global tys exts (n :: nds)) f (Ss_of_nprod ss infI) (Ss_of_nprod os infO).
Proof.

End Ok_node.


Theorem _ok_global :
  forall (HasCausInj : forall (Γ : static_env) (x cx : ident), HasCaus Γ x cx -> cx = x),
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    wc_global G ->
    no_rte_global G ->
    Forall node_causal (nodes G) ->
    forall f n envI,
      find_node f G = Some n ->
      let ins := map fst (n_in n) in
      let outs := map fst (n_out n) in
      let xs := np_of_env ins envI in
      let os := np_of_env outs (denot_global G f envI) in
      wf_ins n envI (bss ins envI) ->
      infinite_dom envI ins ->
      exists InfI InfO,
        sem_node G f (Ss_of_nprod xs InfI) (Ss_of_nprod os InfO).
Proof.

Autre formulation, en fournissant un nprod plutôt qu'un environnement en entrée
Corollary _ok_global2 :
  forall (HasCausInj : forall (Γ : static_env) (x cx : ident), HasCaus Γ x cx -> cx = x),
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    wc_global G ->
    no_rte_global G ->
    Forall node_causal (nodes G) ->
    forall f n (ss : nprod (length (n_in n))),
      find_node f G = Some n ->
      let ins := idents (n_in n) in
      let envI := env_of_np ins ss in
      let os := np_of_env (List.map fst (n_out n)) (denot_global G f envI) in
      let bs := bss ins envI in
      wf_ins n envI bs ->
      forall InfSs InfO,
        sem_node G f (Ss_of_nprod ss InfSs) (Ss_of_nprod os InfO).
Proof.

Definition wf_inputs
  {PSyn Prefs} (n : @node PSyn Prefs) {m} (ss : nprod m) :=
  let ins := idents (n_in n) in
  let envI := env_of_np ins ss in
  let bs := bss ins envI in
  let Γ := senv_of_ins (n_in n) ++ senv_of_decls (n_out n) in
  m = length (n_in n)
  /\ wf_env Γ ins envI bs 0.

Witness of the relational semantics
Theorem ok_global :
  forall (HasCausInj : forall (Γ : static_env) (x cx : ident), HasCaus Γ x cx -> cx = x),
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    wc_global G ->
    check_global G = true ->
    Forall node_causal (nodes G) ->
    forall f n, find_node f G = Some n ->
    forall m (xs : nprod m) InfXs,
      wf_inputs n xs ->
      exists (os : nprod ((length (n_out n)))) InfO,
        sem_node G f (Ss_of_nprod xs InfXs) (Ss_of_nprod os InfO).
Proof.


the same theorems but with the weaker no_rte_node_main hypothesis


Theorem _ok_global_main :
  forall (HasCausInj : forall (Γ : static_env) (x cx : ident), HasCaus Γ x cx -> cx = x),
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    wc_global G ->
    Forall node_causal (nodes G) ->
    forall f n envI,
      no_rte_global_main G f envI ->
      find_node f G = Some n ->
      let ins := map fst (n_in n) in
      let outs := map fst (n_out n) in
      let xs := np_of_env ins envI in
      let os := np_of_env outs (denot_global G f envI) in
      wf_ins n envI (bss ins envI) ->
      infinite_dom envI ins ->
      exists InfI InfO,
          sem_node G f (Ss_of_nprod xs InfI) (Ss_of_nprod os InfO).
Proof.

Corollary _ok_global_main2 :
  forall (HasCausInj : forall (Γ : static_env) (x cx : ident), HasCaus Γ x cx -> cx = x),
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    wc_global G ->
    Forall node_causal (nodes G) ->
    forall f n (ss : nprod (length (n_in n))),
      let ins := idents (n_in n) in
      no_rte_global_main G f (env_of_np ins ss) ->
      find_node f G = Some n ->
      let envI := env_of_np ins ss in
      let os := np_of_env (List.map fst (n_out n)) (denot_global G f envI) in
      let bs := bss ins envI in
      wf_ins n envI bs ->
      forall InfSs InfO,
        sem_node G f (Ss_of_nprod ss InfSs) (Ss_of_nprod os InfO).
Proof.


Witness of the relational semantics
Theorem ok_global_main :
  forall (HasCausInj : forall (Γ : static_env) (x cx : ident), HasCaus Γ x cx -> cx = x),
  forall {PSyn Prefs} (G : @global PSyn Prefs),
    restr_global G ->
    wt_global G ->
    wc_global G ->
    Forall node_causal (nodes G) ->
    forall f n, find_node f G = Some n ->
    forall m (xs : nprod m) InfXs,
      no_rte_global_main G f (env_of_np (List.map fst (n_in n)) xs) ->
      wf_inputs n xs ->
      exists (os : nprod ((length (n_out n)))) InfO,
        sem_node G f (Ss_of_nprod xs InfXs) (Ss_of_nprod os InfO).
Proof.

End SDTOREL.

Module SdtorelFun
       (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)
       (Typ : LTYPING Ids Op OpAux Cks Senv Syn)
       (Cl : LCLOCKING Ids Op OpAux Cks Senv Syn)
       (Caus : LCAUSALITY Ids Op OpAux Cks Senv Syn)
       (Lord : LORDERED Ids Op OpAux Cks Senv Syn)
       (Str : COINDSTREAMS Ids Op OpAux Cks)
       (Sem : LSEMANTICS Ids Op OpAux Cks Senv Syn Lord Str)
       (Den : SD Ids Op OpAux Cks Senv Syn Lord)
       (Restr : LRESTR Ids Op OpAux Cks Senv Syn)
       (Inf : LDENOTINF Ids Op OpAux Cks Senv Syn Typ Caus Lord Restr Den)
       (Ckop : CHECKOP Ids Op OpAux Cks Senv Syn)
       (OpErr : OP_ERR Ids Op OpAux Cks Senv Syn Typ Restr Lord Den Ckop)
       (Safe : LDENOTSAFE Ids Op OpAux Cks Senv Syn Typ Restr Cl Lord Den Ckop OpErr)
       (Abs : ABS_INDEP Ids Op OpAux Cks Senv Syn Typ Lord Den)
       (Lp : LP Ids Op OpAux Cks Senv Syn Typ Lord Den)
<: SDTOREL Ids Op OpAux Cks Senv Syn Typ Cl Caus Lord Str Sem Den Restr Inf Ckop OpErr Safe Abs Lp.
  Include SDTOREL Ids Op OpAux Cks Senv Syn Typ Cl Caus Lord Str Sem Den Restr Inf Ckop OpErr Safe Abs Lp.
End SdtorelFun.