Library label


Some definitions related to label.

Require Export prog.
Require Export List.
Export ListNotations.
Require Export Bool.

Fixpoint label_in_prog (p : prog) (l : label) : bool :=
  match p with
  | {{}}false
  | s ;; qlabel_in_stmt s l || label_in_prog q l
  end
with label_in_stmt (s : stmt) (l : label) : bool :=
  match s with
  | SKIP << l' >>Nat.eqb l l'
  | _ ::= _ << l' >>Nat.eqb l l'
  | IFB << l' >> _ THEN p1 ELSE p2 FINat.eqb l l' ||
      label_in_prog p1 l || label_in_prog p2 l
  | WHILE << l' >> _ DO p1 ENDNat.eqb l l' || label_in_prog p1 l
  | ASSERT << l' >> _ =>> _Nat.eqb l l'
  end.

Fixpoint list_of_labels_prog (p : prog) : list label :=
  match p with
  | {{}}[]
  | s ;; qlist_of_labels_stmt s ++ list_of_labels_prog q
  end
with list_of_labels_stmt (s : stmt) : list label :=
  match s with
  | SKIP << l >>[l]
  | _ ::= _ << l >>[l]
  | IFB << l >> _ THEN p1 ELSE p2 FIl :: (list_of_labels_prog p1) ++
      (list_of_labels_prog p2)
  | WHILE << l >> _ DO p1 ENDl :: (list_of_labels_prog p1)
  | ASSERT << l >> _ =>> _[l]
  end.

Fixpoint label_in (L : list label) (l : label) :=
  match L with
  | []false
  | h :: tNat.eqb l h || label_in t l
  end.

Lemma label_in_app :
   L1 L2 l, label_in (L1++L2) l = label_in L1 l || label_in L2 l.
Proof.
  intros. induction L1 as [| h t].
  Case "[]". reflexivity.
  Case "h :: t". simpl. destruct (Nat.eqb l h).
  - reflexivity.
  - exact IHt.
Qed.

Lemma label_in_prog_iff_in_list_of_labels : p l,
  label_in_prog p l = true label_in (list_of_labels_prog p) l = true.
Proof.
  intros p l. generalize dependent p.
  prog_cases (apply (prog_mutual_ind
    (fun plabel_in_prog p l = true
      label_in (list_of_labels_prog p) l = true)
    (fun slabel_in_stmt s l = true
      label_in (list_of_labels_stmt s) l = true))) Case;
    intros; simpl in *; try rewrite orb_false_r; try reflexivity.
  - Case "P_cons".
    rewrite label_in_app. rewrite 2!orb_true_iff.
    split; intros H1; destruct H1.
    + SCase "-> left". left. apply H. assumption.
    + SCase "-> right". right. apply H0. assumption.
    + SCase "<- left". left. apply H. assumption.
    + SCase "<- right". right. apply H0. assumption.
  - Case "S_ifb". rewrite label_in_app.
    destruct (Nat.eqb l l0).
    + SCase "true". reflexivity.
    + SCase "false". rewrite 2!orb_false_l. rewrite 2!orb_true_iff.
      split; intros H1; destruct H1.
      × SSCase "-> left". left. apply H. assumption.
      × SSCase "-> right". right. apply H0. assumption.
      × SSCase "<- left". left. apply H. assumption.
      × SSCase "<- right". right. apply H0. assumption.
  - Case "S_while". destruct (Nat.eqb l l0).
    + SCase "true". reflexivity.
    + SCase "false". assumption.
Qed.

Definition stmt_get_label (s : stmt) :=
  match s with
  | SKIP << l >>l
  | _ ::= _ << l >>l
  | IFB << l >> _ THEN _ ELSE _ FIl
  | WHILE << l >> _ DO _ ENDl
  | ASSERT << l >> _ =>> _l
  end.

Inductive label_inR_prog : prog label Prop :=
  | LIP_here : l s p, label_inR_stmt s l
      label_inR_prog (s;;p) l
  | LIP_after : l s p, label_inR_prog p l
      label_inR_prog (s;;p) l
with label_inR_stmt : stmt label Prop :=
  | LIS_skip : l, label_inR_stmt (SKIP << l >>) l
  | LIS_ass : i a l, label_inR_stmt (i ::= a << l >>) l
  | LIS_ifb_cond : l b p q,
      label_inR_stmt (IFB << l >> b THEN p ELSE q FI) l
  | LIS_ifb_l : l l' b p q,
      label_inR_prog p l
      label_inR_stmt (IFB << l' >> b THEN p ELSE q FI) l
  | LIS_ifb_r : l l' b p q,
      label_inR_prog q l
      label_inR_stmt (IFB << l' >> b THEN p ELSE q FI) l
  | LIS_while_cond : l b p,
      label_inR_stmt (WHILE << l >> b DO p END) l
  | LIS_while_body : l l' b p,
      label_inR_prog p l
      label_inR_stmt (WHILE << l' >> b DO p END) l
  | LIS_assert : l l' b,
      label_inR_stmt (ASSERT << l >> b =>> l') l.

Scheme label_inR_prog_mutual_ind := Induction for label_inR_prog Sort Prop
  with label_inR_stmt_mutual_ind := Induction for label_inR_stmt Sort Prop.

Lemma label_in_prog_correct : p l,
  label_in_prog p l = true label_inR_prog p l.
Proof.
  split; intros.
  - revert dependent l. revert p.
    apply (prog_mutual_ind
      (fun p l, label_in_prog p l = true label_inR_prog p l)
      (fun s l, label_in_stmt s l = true label_inR_stmt s l));
    intros.
    + inversion H.
    + simpl in H1. apply orb_true_iff in H1. destruct H1.
      × apply LIP_here. apply H; assumption.
      × apply LIP_after. apply H0; assumption.
    + simpl in H. apply Nat.eqb_eq in H. subst. constructor.
    + simpl in H. apply Nat.eqb_eq in H. subst. constructor.
    + simpl in H1. rewrite 2!orb_true_iff in H1.
      destruct H1 as [[H1 | H1] | H1].
      apply Nat.eqb_eq in H1. subst. constructor.
      apply LIS_ifb_l. apply H; assumption.
      apply LIS_ifb_r. apply H0; assumption.
    + simpl in H0. rewrite orb_true_iff in H0. destruct H0.
      apply Nat.eqb_eq in H0. subst; constructor.
      apply LIS_while_body. apply H; assumption.
    + simpl in H. apply Nat.eqb_eq in H. subst. constructor.
  - revert p l H. apply (label_inR_prog_mutual_ind
      (fun p l Hlabel_in_prog p l = true)
      (fun s l Hlabel_in_stmt s l = true)); intros; simpl.
    + rewrite H; reflexivity.
    + rewrite H; apply orb_true_r.
    + apply Nat.eqb_refl.
    + apply Nat.eqb_refl.
    + rewrite Nat.eqb_refl. reflexivity.
    + rewrite H. rewrite orb_true_r. reflexivity.
    + rewrite H. apply orb_true_r.
    + rewrite Nat.eqb_refl. reflexivity.
    + rewrite H. apply orb_true_r.
    + apply Nat.eqb_refl.
Qed.

Lemma label_inR_prog_dec : p l,
  {label_inR_prog p l} + {¬ label_inR_prog p l}.
Proof.
  apply (prog_mutual_rect
    (fun p l, {label_inR_prog p l} + {¬ label_inR_prog p l})
    (fun s l, {label_inR_stmt s l} + {¬ label_inR_stmt s l})); intros.
  - right; intros contra; inversion contra.
  - pose proof (H l). destruct H1.
    + left. apply LIP_here; assumption.
    + pose proof (H0 l). destruct H1.
      × left. apply LIP_after; assumption.
      × right. intros contra. inversion contra; contradiction.
  - destruct (Nat.eq_dec l l0).
    + subst. left. constructor.
    + right. intros contra. inversion contra; contradiction.
  - destruct (Nat.eq_dec l l0).
    + subst. left. constructor.
    + right. intros contra. inversion contra; contradiction.
  - destruct (Nat.eq_dec l l0).
    + left. subst. apply LIS_ifb_cond.
    + destruct (H l0).
      × left. apply LIS_ifb_l; assumption.
      × { destruct (H0 l0).
        - left. apply LIS_ifb_r; assumption.
        - right. intros contra. inversion contra; contradiction. }
  - destruct (Nat.eq_dec l l0).
    + left. subst. apply LIS_while_cond.
    + destruct (H l0).
      × left. apply LIS_while_body; assumption.
      × right. intros contra. inversion contra; contradiction.
  - destruct (Nat.eq_dec l l1).
    + subst. left. constructor.
    + right. intros contra. inversion contra; contradiction.
Qed.

Lemma stmt_get_label_in_stmt : s,
  label_inR_stmt s (stmt_get_label s).
Proof.
  intros. destruct s; constructor.
Qed.

Inductive label_first_inR_prog : prog label Prop :=
  | LFP_here : s p, label_first_inR_prog (s;;p) (stmt_get_label s)
  | LFP_after : l s p, label_first_inR_prog p l
      label_first_inR_prog (s;;p) l.

Tactic Notation "label_first_inR_prog_cases" tactic(first) ident(c) :=
  first;
  [ Case_aux c "LFP_here" | Case_aux c "LFP_after" ].

Lemma label_first_label_inR_prog : p l,
  label_first_inR_prog p l label_inR_prog p l.
Proof.
  intros. label_first_inR_prog_cases (induction H) Case; intros.
  - apply LIP_here. apply stmt_get_label_in_stmt.
  - apply LIP_after. assumption.
Qed.

Lemma label_inR_prog_seq : p1 p2 l,
  label_inR_prog (p1+;+p2) l label_inR_prog p1 l label_inR_prog p2 l.
Proof.
  intros. induction p1.
  - simpl. split; intros.
    + right; assumption.
    + destruct H; [inversion H | assumption].
  - split; intros.
    + simpl in H. inversion H.
      × left; apply LIP_here; assumption.
      × apply IHp1 in H3. { destruct H3.
        - left; apply LIP_after; assumption.
        - right; assumption. }
    + simpl. destruct H.
      × { inversion H.
        - apply LIP_here; assumption.
        - apply LIP_after. apply IHp1. left; assumption. }
      × apply LIP_after. apply IHp1. right; assumption.
Qed.

Fixpoint num_lab_prog (p : prog) : nat :=
  match p with
  | {{}} ⇒ 0
  | s;;p(num_lab_stmt s) + (num_lab_prog p)
  end
with num_lab_stmt (s :stmt) : nat :=
  match s with
  | SKIP << _ >> ⇒ 1
  | _ ::= _ << _ >> ⇒ 1
  | IFB << _ >> _ THEN p1 ELSE p2 FI ⇒ 1 + (num_lab_prog p1) + (num_lab_prog p2)
  | WHILE << _ >> _ DO p1 END ⇒ 1 + (num_lab_prog p1)
  | ASSERT << _ >> _ =>> _ ⇒ 1
  end.

Lemma num_lab_app : p q,
  num_lab_prog (p +;+ q) = num_lab_prog p + num_lab_prog q.
Proof.
  intros. induction p.
  - Case "PM_nil". simpl. reflexivity.
  - Case "PM_cons". simpl. rewrite IHp. apply PeanoNat.Nat.add_assoc.
Qed.

Theorem num_lab_stmt_lt : s,
  num_lab_stmt s > 0.
Proof. intros; destruct s; simpl; omega.
Qed.