(** * The compilation function *)

(** We now define a function that takes a well-formed parallel move [mu]
  and returns a sequence of elementary moves [tau] that is semantically
  equivalent.  We start by defining a number of auxiliary functions. *)

Fixpoint split_move (m: moves) (r: reg) {struct m} : option (moves * reg * moves) :=
  match m with
  | nil => None
  | (s, d) :: tl =>
      if reg_eq s r
      then Some (nil, d, tl)
      else match split_move tl r with
           | None => None
           | Some (before, d', after) => Some ((s, d) :: before, d', after)
           end
  end.Fixpoint is_last_source (r: reg) (m: moves) {struct m} : bool :=
  match m with
  | nil => false
  | (s, d) :: nil =>
      if reg_eq s r then true else false
  | (s, d) :: tl =>
      is_last_source r tl
  end.Fixpoint replace_last_source (r: reg) (m: moves) {struct m} : moves :=
  match m with
  | nil => nil
  | (s, d) :: nil => (r, d) :: nil
  | s_d :: tl => s_d :: replace_last_source r tl
  end.Definition final_state (st: state) : bool :=
  match st with
  | State nil nil _ => true
  | _ => false
  end.Definition parmove_step (st: state) : state :=
  match st with
  | State nil nil _ => st
  | State ((s, d) :: tl) nil l =>
      if reg_eq s d
      then State tl nil l
      else State tl ((s, d) :: nil) l
  | State t ((s, d) :: b) l =>
      match split_move t d with
      | Some (t1, r, t2) =>
          State (t1 ++ t2) ((d, r) :: (s, d) :: b) l
      | None =>
          match b with
          | nil => State t nil ((s, d) :: l)
          | _ =>
              if is_last_source d b
              then State t (replace_last_source (temp d) b) ((s, d) :: (d, temp d) :: l)
              else State t b ((s, d) :: l)
          end
      end
  end.

(* Specifications: *)
Lemma split_move_charact: forall m r, match split_move m r with | Some (before, d, after) => m = before ++ (r, d) :: after /\ no_read before r | None => no_read m r end.
Lemma is_last_source_charact: forall r s d m, if is_last_source r (m ++ (s, d) :: nil) then s = r else s <> r.
Lemma replace_last_source_charact: forall s d s' m, replace_last_source s' (m ++ (s, d) :: nil) = m ++ (s', d) :: nil.
Lemma parmove_step_compatible: forall st, final_state st = false -> dtransition st (parmove_step st).
Lemma split_move_charact: forall m r, match split_move m r with | Some (before, d, after) => m = before ++ (r, d) :: after /\ no_read before r | None => no_read m r end.
Lemma is_last_source_charact: forall r s d m, if is_last_source r (m ++ (s, d) :: nil) then s = r else s <> r.
Lemma replace_last_source_charact: forall s d s' m, replace_last_source s' (m ++ (s, d) :: nil) = m ++ (s', d) :: nil.
Lemma parmove_step_compatible: forall st, final_state st = false -> dtransition st (parmove_step st).