{-# LANGUAGE GADTs           #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_HADDOCK hide #-}
-- |
-- Module      : Data.Array.Accelerate.Representation.Tag
-- Copyright   : [2008..2020] The Accelerate Team
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module Data.Array.Accelerate.Representation.Tag
  where

import Data.Array.Accelerate.Type

import Language.Haskell.TH


-- | The type of the runtime value used to distinguish constructor
-- alternatives in a sum type.
--
type TAG = Word8

-- | This structure both witnesses the layout of our representation types
-- (as TupR does) and represents a complete path of pattern matching
-- through this type. It indicates which fields of the structure represent
-- the union tags (TagRtag) or store undefined values (TagRundef).
--
-- The function 'eltTags' produces all valid paths through the type. For
-- example the type '(Bool,Bool)' produces the following:
--
--   ghci> putStrLn . unlines . map show $ eltTags @(Bool,Bool)
--   (((),(0#,())),(0#,()))     -- (False, False)
--   (((),(0#,())),(1#,()))     -- (False, True)
--   (((),(1#,())),(0#,()))     -- (True, False)
--   (((),(1#,())),(1#,()))     -- (True, True)
--
data TagR a where
  TagRunit   :: TagR ()
  TagRsingle :: ScalarType a -> TagR a
  TagRundef  :: ScalarType a -> TagR a
  TagRtag    :: TAG -> TagR a -> TagR (TAG, a)
  TagRpair   :: TagR a -> TagR b -> TagR (a, b)

instance Show (TagR a) where
  show :: TagR a -> String
show TagR a
TagRunit         = String
"()"
  show TagRsingle{}     = String
"."
  show TagRundef{}      = String
"undef"
  show (TagRtag TAG
v TagR a
t)    = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ TAG -> String
forall a. Show a => a -> String
show TAG
v String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"#," String -> ShowS
forall a. [a] -> [a] -> [a]
++ TagR a -> String
forall a. Show a => a -> String
show TagR a
t String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  show (TagRpair TagR a
ta TagR b
tb) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ TagR a -> String
forall a. Show a => a -> String
show TagR a
ta String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ TagR b -> String
forall a. Show a => a -> String
show TagR b
tb String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

rnfTag :: TagR a -> ()
rnfTag :: TagR a -> ()
rnfTag TagR a
TagRunit         = ()
rnfTag (TagRsingle ScalarType a
t)   = ScalarType a -> ()
forall t. ScalarType t -> ()
rnfScalarType ScalarType a
t
rnfTag (TagRundef ScalarType a
t)    = ScalarType a -> ()
forall t. ScalarType t -> ()
rnfScalarType ScalarType a
t
rnfTag (TagRtag TAG
v TagR a
t)    = TAG
v TAG -> () -> ()
`seq` TagR a -> ()
forall a. TagR a -> ()
rnfTag TagR a
t
rnfTag (TagRpair TagR a
ta TagR b
tb) = TagR a -> ()
forall a. TagR a -> ()
rnfTag TagR a
ta () -> () -> ()
`seq` TagR b -> ()
forall a. TagR a -> ()
rnfTag TagR b
tb

liftTag :: TagR a -> Q (TExp (TagR a))
liftTag :: TagR a -> Q (TExp (TagR a))
liftTag TagR a
TagRunit         = [|| TagRunit ||]
liftTag (TagRsingle ScalarType a
t)   = [|| TagRsingle $$(liftScalarType t) ||]
liftTag (TagRundef ScalarType a
t)    = [|| TagRundef $$(liftScalarType t) ||]
liftTag (TagRtag TAG
v TagR a
t)    = [|| TagRtag v $$(liftTag t) ||]
liftTag (TagRpair TagR a
ta TagR b
tb) = [|| TagRpair $$(liftTag ta) $$(liftTag tb) ||]