packages feed

signals-0.2.0.1: src/Signal/Compiler/Linker/Names.hs

{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Signal.Compiler.Linker.Names where

import Signal.Core  (S)
import Signal.Core.Witness

import Control.Monad.Identity
import Data.Hashable
import Data.Ref.Map (Name)

--------------------------------------------------------------------------------
-- * Distributing
--------------------------------------------------------------------------------

-- | ...
type family Distributed (node :: * -> *) a where
  Distributed node (S sym i (Identity a)) = node (S sym i (Identity a))
  Distributed node (S sym i (a, b))       = ( Distributed node (S sym i a)
                                            , Distributed node (S sym i b))

-- | ...
data Named a
  where
    Named  :: Name  (S sym i a)      -> Named (S sym i a)
    Lefty  :: Named (S sym i (a, b)) -> Named (S sym i a)
    Righty :: Named (S sym i (a, b)) -> Named (S sym i b)

instance Hashable (Named a)
  where
    hashWithSalt s (Named  n) = s `hashWithSalt` n
    hashWithSalt s (Lefty  l) = s `hashWithSalt` (0 :: Int) `hashWithSalt` l
    hashWithSalt s (Righty r) = s `hashWithSalt` (1 :: Int) `hashWithSalt` r

--------------------------------------------------------------------------------
-- ** Naming wires, i.e distributing one wire's name over its subwires

-- | Shorthand for distributed names
type Names a = Distributed Named a

-- | Takes a composite name and creates unique names for each part
name :: forall sym i a. Witness i a => Name (S sym i a) -> Names (S sym i a)
name n = go (witness :: Wit i a) (Named n)
  where
    go :: Wit i x -> Named (S sym i x) -> Names (S sym i x)
    go (WE)     n = n
    go (WP l r) n = (go l (Lefty n), go r (Righty n))

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