(** * 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.
(** Here are the main correctness properties of these functions. *)

(* 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).