(** * Semantics

  - [sem e vnl vsl] is the evaluation of the expression [e] where the [i]th normal variable is
    instantiated with the [i]th value of [vnl], and the [i]th safe variable is
    instantiated with the [i]th value of [vsl].
    If a variable is not assigned a value, then it is assumed to be the empty bitstring [nil].
    Values in [vnl] and [vsl] that do not correspond to a variable are ignored.

  - [BC_ind_inf] is an induction principle that makes easier dealing with arities in inductive proofs.
*)

Fixpoint sem_rec (sem_g sem_h0 sem_h1:list bs->list bs->bs)(v:bs)(vnl vsl:list bs) :=
  match v with
    | nil => sem_g vnl vsl
    | b::v' =>
      if b then sem_h1 (v'::vnl) (sem_rec sem_g sem_h0 sem_h1 v' vnl vsl :: vsl)
      else sem_h0 (v'::vnl) (sem_rec sem_g sem_h0 sem_h1 v' vnl vsl :: vsl)
  end.Fixpoint sem (e:BC)(vnl vsl:list bs) : bs :=
  match e with
  | zero => nil
  | proj n s j => 
    if leb (S j) n then
      nth j vnl nil
      else nth (j-n) vsl nil
  | succ b => b :: hd nil vsl
  | pred => tail (hd nil vsl)
  | cond =>
      match vsl with
      | a :: b :: c :: d :: _ => 
        match a with 
          | nil => b
          | true :: _ => c
          | false :: _ => d
        end
      | a :: b :: c :: _ => 
        match a with 
          | nil => b
          | true :: _ => c
          | false :: _ => nil
        end
      | a :: b :: _ => 
        match a with 
          | nil => b
          | _ => nil
        end
      | _ => nil
      end
  | rec g h0 h1 => sem_rec (sem g) (sem h0) (sem h1) (hd nil vnl) (tail vnl) vsl
  | comp _ _ h nl sl => 
    sem h (List.map (fun ne => sem ne vnl nil) nl) 
          (List.map (fun se => sem se vnl vsl) sl)
  end.

(* Specifications: *)
Lemma sem_comp : forall n s f nel sel nl sl, sem (comp n s f nel sel) nl sl = sem f (map (fun ne => sem ne nl nil) nel) (map (fun se => sem se nl sl) sel).
Lemma sem_nth : forall i start len f d vnl vsl, 0 <= i < len -> sem (nth i (map f (seq start len)) d) vnl vsl = sem (f (i+start)) vnl vsl.
Lemma map_sem_nth : forall i f1 f2 vnl vsl d, map (fun f => sem f vnl vsl) f1 = map (fun f => sem f vnl vsl) f2 -> sem (nth i f1 d) vnl vsl = sem (nth i f2 d) vnl vsl.
Lemma sem_proj_S_normal : forall n s i f vsl vnl, i < n -> sem (proj (S n) s (S i)) (f::vnl) vsl = sem (proj n s i) vnl vsl.
Lemma sem_proj_S_safe : forall n s i f vsl vnl, n <= i -> sem (proj n (S s) (S i)) vnl (f::vsl) = sem (proj n s i) vnl vsl.
Lemma sem_firstn_safe : forall f n s vnl vsl, arities f = ok_arities n s -> sem f vnl vsl = sem f vnl (firstn s vsl).
Lemma sem_firstn_normal : forall f n s vnl vsl, arities f = ok_arities n s -> sem f vnl vsl = sem f (firstn n vnl) vsl.
Lemma sem_firstn : forall f n s vnl vsl, arities f = ok_arities n s -> sem f vnl vsl = sem f (firstn n vnl) (firstn s vsl).
Lemma sem_repeat : forall f vnl vsl n s, arities f = ok_arities n s -> sem f vnl vsl = sem f (vnl ++ repeat (n - length vnl) nil) (vsl ++ repeat (s - length vsl) nil).
Lemma map_sem_repeat : forall fl vnl vsl n s, (forall f, In f fl -> arities f = ok_arities n s) -> map (fun f => sem f vnl vsl) fl = map ( fun f => sem f (vnl ++ repeat (n - length vnl) nil) (vsl ++ repeat (s - length vsl) nil) ) fl.
Lemma map_proj_seq_normal_gen : forall n i vnl, n+i <= length vnl -> map (fun f : BC => sem f vnl nil) (map (proj (n+i) 0) (seq i n)) = firstn n (skipn i vnl).
Lemma map_proj_seq_normal : forall n vnl, map (fun f : BC => sem f vnl nil) (map (proj n 0) (seq 0 n)) = firstn n vnl ++ repeat (n - length vnl) nil.
Lemma map_proj_seq_safe_gen : forall n s i vnl vsl, s+i <= length vsl -> map (fun f : BC => sem f vnl vsl) (map (proj n (s+i)) (seq (n+i) s)) = firstn s (skipn i vsl).
Lemma map_proj_seq_safe : forall n s vnl vsl, map (fun f : BC => sem f vnl vsl) (map (proj n s) (seq n s)) = firstn s vsl ++ repeat (s - length vsl) nil.