Section MATCH.
Variable bc: block_classification.
(** * Abstracting the result of conditions (type [option bool]) *)
Inductive abool :=
| Bnone               (**r always [None] (undefined) *)
| Just (b: bool)      (**r always [Some b] (defined and known to be [b]) *)
| Maybe (b: bool)     (**r either [None] or [Some b] (known to be [b] if defined) *)
| Btop.               (**r unknown, all results are possible *)
Inductive cmatch: option bool -> abool -> Prop :=
| cmatch_none: cmatch None Bnone
| cmatch_just: forall b, cmatch (Some b) (Just b)
| cmatch_maybe_none: forall b, cmatch None (Maybe b)
| cmatch_maybe_some: forall b, cmatch (Some b) (Maybe b)
| cmatch_top: forall ob, cmatch ob Btop.
Hint Constructors cmatch : va.
Definition club (x y: abool) : abool :=
match x, y with
| Bnone, Bnone => Bnone
| Bnone, (Just b | Maybe b) => Maybe b
| (Just b | Maybe b), Bnone => Maybe b
| Just b1, Just b2 => if eqb b1 b2 then x else Btop
| Maybe b1, Maybe b2 => if eqb b1 b2 then x else Btop
| Maybe b1, Just b2 => if eqb b1 b2 then x else Btop
| Just b1, Maybe b2 => if eqb b1 b2 then y else Btop
| _, _ => Btop
end.
Definition cnot (x: abool) : abool :=
match x with
| Just b => Just (negb b)
| Maybe b => Maybe (negb b)
| _ => x
end.

Lemma cnot_sound:
forall ob x, cmatch ob x -> cmatch (option_map negb ob) (cnot x).