Variable needA : Annot -> bool.
Definition abs_and (k: kind) (f1 f2 : TFormula TX AF k)
(c : forall (k: kind), TFormula TX AF k -> TFormula TX AF k -> TFormula TX AF k) :=
match is_X f1 , is_X f2 with
| Some _  , _ | _ , Some _ => X k (aformula  (c k f1  f2))
|   _     , _ => c k f1 f2
end.
Definition abs_or (k: kind) (f1 f2 : TFormula TX AF k)
(c : forall (k: kind), TFormula TX AF k -> TFormula TX AF k -> TFormula TX AF k) :=
match is_X f1 , is_X f2 with
| Some _  , Some _ => X k (aformula (c k f1  f2))
|   _     , _ => c k f1 f2
end.
Definition abs_not (k: kind) (f1 : TFormula TX AF k)
(c : forall (k: kind), TFormula TX AF k -> TFormula TX AF k) :=
match is_X f1 with
| Some _   => X k (aformula (c k f1 ))
|   _  => c k f1
end.
Definition mk_arrow (o : option AF) (k: kind) (f1 f2: TFormula TX AF k) :=
match o with
| None => IMPL f1 None f2
| Some _ => if is_X f1 then f2 else IMPL f1 o f2
end.
Fixpoint abst_simpl  (k: kind) (f : TFormula TX AF k) : TFormula TX AF k:=
match f  with
| TT k => TT k
| FF k =>  FF k
| X k p => X k p
| A k x t => if needA t then A k x t else X k (mkA k x t)
| AND f1 f2 => AND (abst_simpl f1) (abst_simpl f2)
| OR f1 f2 =>  OR (abst_simpl f1) (abst_simpl f2)
| IMPL f1 o f2 => IMPL (abst_simpl f1) o (abst_simpl f2)
| NOT f => NOT (abst_simpl f)
| IFF f1 f2 => IFF (abst_simpl f1) (abst_simpl f2)
| EQ f1 f2  => EQ (abst_simpl f1) (abst_simpl f2)
end.
Section REC.
Variable REC : forall (pol : bool) (k: kind) (f : TFormula TX AF k), TFormula TX AF k.
Definition abst_and (pol : bool) (k: kind) (f1 f2:TFormula TX AF k) : TFormula TX AF k:=
(if pol then abs_and else abs_or) k (REC pol f1) (REC pol f2) AND.
Definition abst_or (pol : bool) (k: kind) (f1 f2:TFormula TX AF k) : TFormula TX AF k:=
(if pol then abs_or else abs_and) k (REC pol f1) (REC pol f2) OR.
Definition abst_impl (pol : bool) (o :option AF) (k: kind) (f1 f2:TFormula TX AF k) : TFormula TX AF k:=
(if pol then abs_or else abs_and) k (REC (negb pol) f1) (REC pol f2) (mk_arrow o).
Definition or_is_X (k: kind) (f1 f2: TFormula TX AF k) : bool :=
match is_X f1 , is_X f2 with
| Some _ , _
| _ , Some _ => true
|  _ , _     => false
end.
Definition abs_iff  (k: kind) (nf1  ff2 f1 tf2 : TFormula TX AF k) (r: kind) (def : TFormula TX AF r) : TFormula TX AF r :=
if andb (or_is_X nf1 ff2) (or_is_X f1 tf2)
then X r (aformula def)
else def.
Definition abst_iff (pol : bool) (k: kind) (f1 f2: TFormula TX AF k) : TFormula TX AF k :=
abs_iff   (REC (negb pol) f1) (REC false f2) (REC pol f1) (REC true f2) (IFF (abst_simpl f1) (abst_simpl f2)).
Definition abst_eq (pol : bool)  (f1 f2: TFormula TX AF isBool) : TFormula TX AF isProp :=
abs_iff   (REC (negb pol) f1) (REC false f2) (REC pol f1) (REC true f2) (EQ (abst_simpl f1) (abst_simpl f2)).
End REC.
Fixpoint abst_form  (pol : bool) (k: kind) (f : TFormula TX AF k) : TFormula TX AF k:=
match f  with
| TT k => if pol then TT k else X k (mkTT k)
| FF k => if pol then X k (mkFF k) else FF k
| X k p => X k p
| A k x t => if needA t then A k x t else X k (mkA k x t)
| AND f1 f2 => abst_and abst_form pol f1 f2
| OR f1 f2 =>  abst_or abst_form pol f1 f2
| IMPL f1 o f2 => abst_impl abst_form pol o f1 f2
| NOT f => abs_not  (abst_form (negb pol) f) NOT
| IFF f1 f2 => abst_iff abst_form  pol f1 f2
| EQ f1 f2  => abst_eq abst_form pol f1 f2
end.

(* Specifications: *)
Lemma if_same : forall {A: Type} (b: bool) (t:A),
(if b then t else t) = t.
Lemma is_cnf_tt_cnf_ff :
is_cnf_tt cnf_ff = false.
Lemma is_cnf_ff_cnf_ff :
is_cnf_ff cnf_ff = true.
Lemma is_cnf_tt_inv : forall f1,
is_cnf_tt f1 = true -> f1 = cnf_tt.
Lemma is_cnf_ff_inv : forall f1,
is_cnf_ff f1 = true -> f1 = cnf_ff.
Lemma if_cnf_tt : forall f, (if is_cnf_tt f then cnf_tt else f) = f.
Lemma or_cnf_opt_cnf_ff : forall f,
or_cnf_opt cnf_ff f = f.
Lemma abs_and_pol : forall (k: kind) (f1 f2: TFormula TX AF k) pol,
and_cnf_opt (xcnf pol f1) (xcnf pol f2) =
xcnf pol (abs_and f1 f2 (if pol then AND else OR)).
Lemma abs_or_pol : forall (k: kind) (f1 f2:TFormula TX AF k) pol,
or_cnf_opt (xcnf pol f1) (xcnf pol f2) =
xcnf pol (abs_or f1 f2 (if pol then OR else AND)).