--
import "Bits.html"  -- see Bits.html source here.


-----------------------------------------------------

add3Bits:: Bit i -> Bit j -> Bit k -> Seq Bit 2t {plus i {plus j k}}
add3Bits Zero Zero Zero = [Zero,Zero]b
add3Bits Zero Zero One  = [One,Zero]b
add3Bits Zero One  Zero = [One,Zero]b
add3Bits Zero One  One  = [Zero,One]b
add3Bits One  Zero Zero = [One,Zero]b
add3Bits One  Zero One  = [Zero,One]b
add3Bits One  One  Zero = [Zero,One]b
add3Bits One  One  One  = [One,One]b


adder':: Bit i -> Seq Bit n j -> Seq Bit n k -> Seq Bit (S n) {plus i {plus j k}}
adder' carry Nil Nil = Cons carry Nil
  where theorem plusZ
adder' carry (Cons b xs) (Cons c ys) = Cons ans tail
   where [ans,carry2]b = add3Bits carry b c
         tail = adder' carry2 xs ys
         theorem plusAssoc, plusNorm

-- When you're just getting started don't need to specifiy a carry bit

adder:: Seq Bit n i -> Seq Bit n j -> Seq Bit (S n) {plus i j}
adder x y = adder' Zero x y

---------------------------------------------------
-- Now lets make an adder using symbolic bits.
-- We'll need a very specific lemma, but it is
-- easy to prove by exhaustive analysis.

lemma:: Bit a -> Bit b -> Bit c ->
  Equal {plus {plus {or {and a b}
                        {or {and a c} {and b c}}}
                    {or {and a b} {or {and a c} {and b c}}}}
                        {xor a {xor b c}}}
        {plus a {plus b c}}
lemma Zero Zero Zero = Eq
lemma Zero Zero One = Eq
lemma Zero One  Zero = Eq
lemma Zero One  One = Eq
lemma One  Zero Zero = Eq
lemma One  Zero One = Eq
lemma One  One  Zero = Eq
lemma One  One  One = Eq

add3SymBits:: SymBit i -> SymBit j -> SymBit k -> Seq SymBit 2t {plus i {plus j k}}
add3SymBits i j k = check
     [Xor i (Xor j k),
           Or (And i j) (Or (And i k) (And j k))]b
  where theorem hyp = lemma (eval i) (eval j) (eval k)


adderS:: SymBit i -> Seq SymBit n j -> Seq SymBit n k -> Seq SymBit (S n) {plus i {plus j k}}
adderS carry Nil Nil = Cons carry Nil
  where theorem plusZ
adderS carry (Cons b xs) (Cons c ys) = Cons ans tail
   where [ans,carry2]b = add3SymBits carry b c
         tail = adderS carry2 xs ys
         theorem plusAssoc, plusNorm

two = [Var "x",Var "y"]b
one = [Var "m", Var "n"]b
three = [I,I,O]b

ans = (adderS O two one)
ans2 = adderS O (adderS O two one) three

--