-- | Module "Data.TypeLevel.Num.Aliases" is re-exported because
-- wrappers use type level numbers frequently
module Feldspar.Core.Wrap ( Wrap(..), Data'(..), module Data.TypeLevel.Num.Aliases, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9) where


import Feldspar.DSL.Network
import Feldspar.Core.Types
import Feldspar.Core.Representation

import Data.TypeLevel.Num.Aliases
import Data.TypeLevel.Num.Reps (D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 )


-- | Wrapping Feldspar functions
class Wrap t w where
    wrap :: t -> w

-- | Basic instances to handle @Data a@ input and output.
-- Other instances are located in the concerned libraries.
instance Wrap (Data a) (Data a) where
    wrap = id

instance (Wrap t u) => Wrap (Data a -> t) (Data a -> u) where
    wrap f = \x -> wrap $ f x

-- | Extended 'Data' to be used in wrappers
data Data' s a =
    Data'
    { unData'   :: Data a
    }

-- Syntactic instance for 'Data''
instance EdgeInfo (Data' s a)
  where
    type Info (Data' s a)   = EdgeSize () a
    edgeInfo                = edgeInfo . unData . unData'

instance Type a => MultiEdge (Data' s a) Feldspar EdgeSize
  where
    type Role     (Data' s a)   = ()
    type Internal (Data' s a)   = a
    toEdge                      = toEdge . unData . unData'
    fromInEdge                  = Data' . Data . fromInEdge
    fromOutEdge info            = Data' . Data . fromOutEdge info

instance (Type a) => Syntactic (Data' s a)