(define-rule bool-double-not-elim ((t Bool)) (not (not t)) t)
(define-cond-rule bool-not-true ((t Bool))
  (= t false) (not t) true)
(define-cond-rule bool-not-false ((t Bool))
  (= t true) (not t) false)

(define-rule bool-eq-true ((t Bool)) (= t true) t)
(define-rule bool-eq-false ((t Bool)) (= t false) (not t))
(define-rule bool-eq-nrefl ((x Bool)) (= x (not x)) false)

(define-rule bool-impl-false1 ((t Bool)) (=> t false) (not t))
(define-rule bool-impl-false2 ((t Bool)) (=> false t) true)
(define-rule bool-impl-true1 ((t Bool)) (=> t true) true)
(define-rule bool-impl-true2 ((t Bool)) (=> true t) t)
(define-rule bool-impl-elim ((t Bool) (s Bool)) (=> t s) (or (not t) s))

; used in proof elaboration
(define-rule bool-dual-impl-eq ((t Bool) (s Bool)) (and (=> t s) (=> s t)) (= t s))

(define-rule bool-and-conf ((xs Bool :list) (w Bool) (ys Bool :list) (zs Bool :list)) (and xs w ys (not w) zs) false)
(define-rule bool-and-conf2 ((xs Bool :list) (w Bool) (ys Bool :list) (zs Bool :list)) (and xs (not w) ys w zs) false)
(define-rule bool-or-taut ((xs Bool :list) (w Bool) (ys Bool :list) (zs Bool :list)) (or xs w ys (not w) zs) true)
(define-rule bool-or-taut2 ((xs Bool :list) (w Bool) (ys Bool :list) (zs Bool :list)) (or xs (not w) ys w zs) true)

(define-rule* bool-or-de-morgan ((x Bool) (y Bool) (zs Bool :list)) 
  (not (or x y zs))
  (not (or y zs))
  (and (not x) _))
(define-rule bool-implies-de-morgan ((x Bool) (y Bool))
  (not (=> x y))
  (and x (not y)))
(define-rule* bool-and-de-morgan ((x Bool) (y Bool) (zs Bool :list)) 
  (not (and x y zs))
  (not (and y zs))
  (or (not x) _))

; We only permit distributing from the first child, or otherwise this rule
; could apply to fix point on all AND children of an OR at once.
(define-rule* bool-or-and-distrib ((y1 Bool) (y2 Bool) (ys Bool :list) (z1 Bool) (zs Bool :list))
  (or (and y1 y2 ys) z1 zs)
  (or (and y2 ys) z1 zs)
  (and (or y1 z1 zs) _))

; Used for diamonds preprocessing
(define-rule* bool-implies-or-distrib ((y1 Bool) (y2 Bool) (ys Bool :list) (z Bool))
  (=> (or y1 y2 ys) z)
  (=> (or y2 ys) z)
  (and (=> y1 z) _))

(define-rule bool-xor-refl ((x Bool)) (xor x x) false)
(define-rule bool-xor-nrefl ((x Bool)) (xor x (not x)) true)
(define-rule bool-xor-false ((x Bool)) (xor x false) x)
(define-rule bool-xor-true ((x Bool)) (xor x true) (not x))
(define-rule bool-xor-comm ((x Bool) (y Bool)) (xor x y) (xor y x))
(define-rule bool-xor-elim ((x Bool) (y Bool)) (xor x y) (= (not x) y))
(define-rule bool-not-xor-elim ((x Bool) (y Bool)) (not (xor x y)) (= x y))

(define-rule bool-not-eq-elim1 ((x Bool) (y Bool)) (not (= x y)) (= (not x) y))
(define-rule bool-not-eq-elim2 ((x Bool) (y Bool)) (not (= x y)) (= x (not y)))

(define-cond-rule ite-neg-branch ((c Bool) (x Bool) (y Bool)) (= (not y) x) (ite c x y) (= c x))

(define-rule ite-then-true ((c Bool) (x Bool)) (ite c true x) (or c x))
(define-rule ite-else-false ((c Bool) (x Bool)) (ite c x false) (and c x))
(define-rule ite-then-false ((c Bool) (x Bool)) (ite c false x) (and (not c) x))
(define-rule ite-else-true ((c Bool) (x Bool)) (ite c x true) (or (not c) x))

(define-rule ite-then-lookahead-self ((c Bool) (x Bool)) (ite c c x) (ite c true x))
(define-rule ite-else-lookahead-self ((c Bool) (x Bool)) (ite c x c) (ite c x false))

(define-rule ite-then-lookahead-not-self ((c Bool) (x Bool)) (ite c (not c) x) (ite c false x))
(define-rule ite-else-lookahead-not-self ((c Bool) (x Bool)) (ite c x (not c)) (ite c x true))

(define-rule ite-expand ((c Bool) (x Bool) (y Bool)) (ite c x y) (and (or (not c) x) (or c y)))

(define-rule bool-not-ite-elim ((c Bool) (x Bool) (y Bool)) (not (ite c x y)) (ite c (not x) (not y)))
