module Lava.Operators where

import Lava.Signal
import Lava.Generic
import Lava.Error

infix  4 <==>
infixr 3 <&>
infixr 2 <|>, ==>, <==
infixr 2 <=>, <#>
infixr 1 |->

----------------------------------------------------------------------
-- Gates

and2 :: (Signal Bool, Signal Bool) -> Signal Bool
and2 (x :: Signal Bool
x, y :: Signal Bool
y) = [Signal Bool] -> Signal Bool
andl [Signal Bool
x, Signal Bool
y]
or2 :: (Signal Bool, Signal Bool) -> Signal Bool
or2  (x :: Signal Bool
x, y :: Signal Bool
y) = [Signal Bool] -> Signal Bool
orl  [Signal Bool
x, Signal Bool
y]
xor2 :: (Signal Bool, Signal Bool) -> Signal Bool
xor2 (x :: Signal Bool
x, y :: Signal Bool
y) = [Signal Bool] -> Signal Bool
xorl [Signal Bool
x, Signal Bool
y]

nand2 :: (Signal Bool, Signal Bool) -> Signal Bool
nand2 = Signal Bool -> Signal Bool
inv (Signal Bool -> Signal Bool)
-> ((Signal Bool, Signal Bool) -> Signal Bool)
-> (Signal Bool, Signal Bool)
-> Signal Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signal Bool, Signal Bool) -> Signal Bool
and2
nor2 :: (Signal Bool, Signal Bool) -> Signal Bool
nor2  = Signal Bool -> Signal Bool
inv (Signal Bool -> Signal Bool)
-> ((Signal Bool, Signal Bool) -> Signal Bool)
-> (Signal Bool, Signal Bool)
-> Signal Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signal Bool, Signal Bool) -> Signal Bool
or2
xnor2 :: (Signal Bool, Signal Bool) -> Signal Bool
xnor2 = Signal Bool -> Signal Bool
inv (Signal Bool -> Signal Bool)
-> ((Signal Bool, Signal Bool) -> Signal Bool)
-> (Signal Bool, Signal Bool)
-> Signal Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signal Bool, Signal Bool) -> Signal Bool
xor2

equiv :: (Signal Bool, Signal Bool) -> Signal Bool
equiv (x :: Signal Bool
x, y :: Signal Bool
y) = (Signal Bool, Signal Bool) -> Signal Bool
xnor2 (Signal Bool
x, Signal Bool
y)
impl :: (Signal Bool, Signal Bool) -> Signal Bool
impl  (x :: Signal Bool
x, y :: Signal Bool
y) = (Signal Bool, Signal Bool) -> Signal Bool
or2   (Signal Bool -> Signal Bool
inv Signal Bool
x, Signal Bool
y)

nandl :: [Signal Bool] -> Signal Bool
nandl = Signal Bool -> Signal Bool
inv (Signal Bool -> Signal Bool)
-> ([Signal Bool] -> Signal Bool) -> [Signal Bool] -> Signal Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Signal Bool] -> Signal Bool
andl
norl :: [Signal Bool] -> Signal Bool
norl  = Signal Bool -> Signal Bool
inv (Signal Bool -> Signal Bool)
-> ([Signal Bool] -> Signal Bool) -> [Signal Bool] -> Signal Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Signal Bool] -> Signal Bool
orl

plus :: (Signal Int, Signal Int) -> Signal Int
plus  (x :: Signal Int
x, y :: Signal Int
y) = [Signal Int] -> Signal Int
plusl [Signal Int
x,Signal Int
y]
sub :: (Signal Int, Signal Int) -> Signal Int
sub   (x :: Signal Int
x, y :: Signal Int
y) = [Signal Int] -> Signal Int
plusl [Signal Int
x, Signal Int -> Signal Int
neg Signal Int
y]
times :: (Signal Int, Signal Int) -> Signal Int
times (x :: Signal Int
x, y :: Signal Int
y) = [Signal Int] -> Signal Int
timesl [Signal Int
x, Signal Int
y]
imod :: (Signal Int, Signal Int) -> Signal Int
imod  (x :: Signal Int
x, y :: Signal Int
y) = Signal Int -> Signal Int -> Signal Int
modulo Signal Int
x Signal Int
y
idiv :: (Signal Int, Signal Int) -> Signal Int
idiv  (x :: Signal Int
x, y :: Signal Int
y) = Signal Int -> Signal Int -> Signal Int
divide Signal Int
x Signal Int
y

----------------------------------------------------------------------
-- Binary Operators

x :: a
x |-> :: a -> a -> a
|->  y :: a
y = a -> a -> a
forall a. Generic a => a -> a -> a
delay  a
x  a
y
x :: a
x <==> :: a -> a -> Signal Bool
<==> y :: a
y = (a, a) -> Signal Bool
forall a. Generic a => (a, a) -> Signal Bool
equal (a
x, a
y)

x :: Signal Bool
x <&> :: Signal Bool -> Signal Bool -> Signal Bool
<&> y :: Signal Bool
y = (Signal Bool, Signal Bool) -> Signal Bool
and2  (Signal Bool
x, Signal Bool
y)
x :: Signal Bool
x <|> :: Signal Bool -> Signal Bool -> Signal Bool
<|> y :: Signal Bool
y = (Signal Bool, Signal Bool) -> Signal Bool
or2   (Signal Bool
x, Signal Bool
y)
x :: Signal Bool
x <#> :: Signal Bool -> Signal Bool -> Signal Bool
<#> y :: Signal Bool
y = (Signal Bool, Signal Bool) -> Signal Bool
xor2  (Signal Bool
x, Signal Bool
y)
x :: Signal Bool
x <=> :: Signal Bool -> Signal Bool -> Signal Bool
<=> y :: Signal Bool
y = (Signal Bool, Signal Bool) -> Signal Bool
equiv (Signal Bool
x, Signal Bool
y)
x :: Signal Bool
x ==> :: Signal Bool -> Signal Bool -> Signal Bool
==> y :: Signal Bool
y = (Signal Bool, Signal Bool) -> Signal Bool
impl  (Signal Bool
x, Signal Bool
y)
x :: Signal Bool
x <== :: Signal Bool -> Signal Bool -> Signal Bool
<== y :: Signal Bool
y = (Signal Bool, Signal Bool) -> Signal Bool
impl  (Signal Bool
y, Signal Bool
x)

x :: Signal Int
x %% :: Signal Int -> Signal Int -> Signal Int
%% y :: Signal Int
y     = (Signal Int, Signal Int) -> Signal Int
imod (Signal Int
x, Signal Int
y)
gte :: (Signal Int, Signal Int) -> Signal Bool
gte (x :: Signal Int
x, y :: Signal Int
y) = Signal Int -> Signal Int -> Signal Bool
gteInt Signal Int
x Signal Int
y
x :: Signal Int
x >>== :: Signal Int -> Signal Int -> Signal Bool
>>== y :: Signal Int
y   = (Signal Int, Signal Int) -> Signal Bool
gte (Signal Int
x, Signal Int
y)

imin :: (Signal Int, Signal Int) -> Signal Int
imin (x :: Signal Int
x, y :: Signal Int
y) = Signal Bool -> (Signal Int, Signal Int) -> Signal Int
forall a. Choice a => Signal Bool -> (a, a) -> a
ifThenElse (Signal Int
x Signal Int -> Signal Int -> Signal Bool
>>== Signal Int
y) (Signal Int
y, Signal Int
x)
imax :: (Signal Int, Signal Int) -> Signal Int
imax (x :: Signal Int
x, y :: Signal Int
y) = Signal Bool -> (Signal Int, Signal Int) -> Signal Int
forall a. Choice a => Signal Bool -> (a, a) -> a
ifThenElse (Signal Int
x Signal Int -> Signal Int -> Signal Bool
>>== Signal Int
y) (Signal Int
x, Signal Int
y)

class SignalInt a where
  toSignalInt   :: Signal a   -> Signal Int
  fromSignalInt :: Signal Int -> Signal a

instance SignalInt Int where
  toSignalInt :: Signal Int -> Signal Int
toSignalInt   = Signal Int -> Signal Int
forall a. a -> a
id
  fromSignalInt :: Signal Int -> Signal Int
fromSignalInt = Signal Int -> Signal Int
forall a. a -> a
id

instance SignalInt a => Num (Signal a) where
  x :: Signal a
x + :: Signal a -> Signal a -> Signal a
+ y :: Signal a
y    = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ (Signal Int, Signal Int) -> Signal Int
plus (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x, Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
y)
  x :: Signal a
x - :: Signal a -> Signal a -> Signal a
- y :: Signal a
y    = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ (Signal Int, Signal Int) -> Signal Int
sub (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x, Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
y)
  x :: Signal a
x * :: Signal a -> Signal a -> Signal a
* y :: Signal a
y    = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ (Signal Int, Signal Int) -> Signal Int
times (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x, Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
y)
  negate :: Signal a -> Signal a
negate x :: Signal a
x = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ Signal Int -> Signal Int
neg (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x)

  fromInteger :: Integer -> Signal a
fromInteger = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a)
-> (Integer -> Signal Int) -> Integer -> Signal a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Signal Int
int (Int -> Signal Int) -> (Integer -> Int) -> Integer -> Signal Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a. Num a => Integer -> a
fromInteger

instance SignalInt a => Fractional (Signal a) where
  x :: Signal a
x / :: Signal a -> Signal a -> Signal a
/ y :: Signal a
y = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ (Signal Int, Signal Int) -> Signal Int
idiv (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x, Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
y)

instance SignalInt a => Enum (Signal a) where
  toEnum :: Int -> Signal a
toEnum n :: Int
n = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Int -> Signal Int
int Int
n)
  fromEnum :: Signal a -> Int
fromEnum (Signal s :: Symbol
s) =
    case Symbol -> S Symbol
unsymbol Symbol
s of
      Int n :: Int
n -> Int
n
      _     -> Error -> Int
forall a. Error -> a
wrong Error
Lava.Error.EnumOnSymbols

instance SignalInt a => Ord (Signal a) where
  min :: Signal a -> Signal a -> Signal a
min x :: Signal a
x y :: Signal a
y = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ (Signal Int, Signal Int) -> Signal Int
imin (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x, Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
y)
  max :: Signal a -> Signal a -> Signal a
max x :: Signal a
x y :: Signal a
y = Signal Int -> Signal a
forall a. SignalInt a => Signal Int -> Signal a
fromSignalInt (Signal Int -> Signal a) -> Signal Int -> Signal a
forall a b. (a -> b) -> a -> b
$ (Signal Int, Signal Int) -> Signal Int
imax (Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
x, Signal a -> Signal Int
forall a. SignalInt a => Signal a -> Signal Int
toSignalInt Signal a
y)



----------------------------------------------------------------------
-- Convert

int2bit :: Signal Int -> Signal Bool
int2bit n :: Signal Int
n = Signal Int
n Signal Int -> Signal Int -> Signal Bool
forall a. Generic a => a -> a -> Signal Bool
<==> (1 :: Signal Int)
bit2int :: Signal Bool -> Signal Int
bit2int b :: Signal Bool
b = Signal Bool -> (Signal Int, Signal Int) -> Signal Int
forall a. Choice a => Signal Bool -> (a, a) -> a
ifThenElse Signal Bool
b (1 :: Signal Int, 0)

----------------------------------------------------------------------
-- the end.