(** * Properties related to labels *)

(** If labels are globally unique and the Linear code [c] contains
  a subsequence [Llabel lbl :: c1], then [find_label lbl c] returns [c1].
*)

Fixpoint unique_labels (c: code) : Prop :=
  match c with
  | nil => True
  | Llabel lbl :: c => ~(In (Llabel lbl) c) /\ unique_labels c
  | i :: c => unique_labels c
  end.

(* Specifications: *)
Lemma find_label_unique: forall lbl c1 c2 c3, is_tail (Llabel lbl :: c1) c2 -> unique_labels c2 -> find_label lbl c2 = Some c3 -> c1 = c3.
Lemma starts_with_correct: forall lbl c1 c2 c3 s f sp ls m, is_tail c1 c2 -> unique_labels c2 -> starts_with lbl c1 = true -> find_label lbl c2 = Some c3 -> plus step tge (State s f sp c1 ls m) E0 (State s f sp c3 ls m).
Lemma find_label_add_branch: forall lbl k s, find_label lbl (add_branch s k) = find_label lbl k.
Lemma find_label_lin_block: forall lbl k b, find_label lbl (linearize_block b k) = find_label lbl k.
Lemma label_in_add_branch: forall lbl s k, In (Llabel lbl) (add_branch s k) -> In (Llabel lbl) k.
Lemma label_in_lin_block: forall lbl k b, In (Llabel lbl) (linearize_block b k) -> In (Llabel lbl) k.
Lemma label_in_lin_rec: forall f lbl enum, In (Llabel lbl) (linearize_body f enum) -> In lbl enum.
Lemma unique_labels_add_branch: forall lbl k, unique_labels k -> unique_labels (add_branch lbl k).
Lemma unique_labels_lin_block: forall k b, unique_labels k -> unique_labels (linearize_block b k).
Lemma unique_labels_lin_rec: forall f enum, list_norepet enum -> unique_labels (linearize_body f enum).
Lemma unique_labels_transf_function: forall f tf, transf_function f = OK tf -> unique_labels (fn_code tf).
Lemma is_tail_find_label: forall lbl c2 c1, find_label lbl c1 = Some c2 -> is_tail c2 c1.
Lemma is_tail_add_branch: forall lbl c1 c2, is_tail (add_branch lbl c1) c2 -> is_tail c1 c2.
Lemma is_tail_lin_block: forall b c1 c2, is_tail (linearize_block b c1) c2 -> is_tail c1 c2.
Lemma add_branch_correct: forall lbl c k s f tf sp ls m, transf_function f = OK tf -> is_tail k tf.(fn_code) -> find_label lbl tf.(fn_code) = Some c -> plus step tge (State s tf sp (add_branch lbl k) ls m) E0 (State s tf sp c ls m).