{-# OPTIONS_GHC -Wno-redundant-constraints #-}
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
{-# LANGUAGE DefaultSignatures, TypeOperators #-}
{-# LANGUAGE TypeFamilies, DataKinds, UndecidableInstances #-}
module Language.Souffle.Marshal
( Marshal(..)
, MonadPush(..)
, MonadPop(..)
, SimpleProduct
) where
import GHC.TypeLits
import GHC.Generics
import Data.Int
import Data.Word
import Data.Kind
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
type MonadPush :: (Type -> Type) -> Constraint
class Monad m => MonadPush m where
pushInt32 :: Int32 -> m ()
pushUInt32 :: Word32 -> m ()
pushFloat :: Float -> m ()
pushString :: String -> m ()
pushText :: T.Text -> m ()
type MonadPop :: (Type -> Type) -> Constraint
class Monad m => MonadPop m where
popInt32 :: m Int32
popUInt32 :: m Word32
popFloat :: m Float
popString :: m String
popText :: m T.Text
type Marshal :: Type -> Constraint
class Marshal a where
push :: MonadPush m => a -> m ()
pop :: MonadPop m => m a
default push
:: (Generic a, SimpleProduct a, GMarshal (Rep a), MonadPush m)
=> a -> m ()
default pop
:: (Generic a, SimpleProduct a, GMarshal (Rep a), MonadPop m)
=> m a
push a
a = forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPush m) =>
f a -> m ()
gpush (forall a x. Generic a => a -> Rep a x
from a
a)
{-# INLINABLE push #-}
pop = forall a x. Generic a => Rep a x -> a
to forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPop m) =>
m (f a)
gpop
{-# INLINABLE pop #-}
instance Marshal Int32 where
push :: forall (m :: * -> *). MonadPush m => Int32 -> m ()
push = forall (m :: * -> *). MonadPush m => Int32 -> m ()
pushInt32
{-# INLINABLE push #-}
pop :: forall (m :: * -> *). MonadPop m => m Int32
pop = forall (m :: * -> *). MonadPop m => m Int32
popInt32
{-# INLINABLE pop #-}
instance Marshal Word32 where
push :: forall (m :: * -> *). MonadPush m => Word32 -> m ()
push = forall (m :: * -> *). MonadPush m => Word32 -> m ()
pushUInt32
{-# INLINABLE push #-}
pop :: forall (m :: * -> *). MonadPop m => m Word32
pop = forall (m :: * -> *). MonadPop m => m Word32
popUInt32
{-# INLINABLE pop #-}
instance Marshal Float where
push :: forall (m :: * -> *). MonadPush m => Float -> m ()
push = forall (m :: * -> *). MonadPush m => Float -> m ()
pushFloat
{-# INLINABLE push #-}
pop :: forall (m :: * -> *). MonadPop m => m Float
pop = forall (m :: * -> *). MonadPop m => m Float
popFloat
{-# INLINABLE pop #-}
instance Marshal String where
push :: forall (m :: * -> *). MonadPush m => String -> m ()
push = forall (m :: * -> *). MonadPush m => String -> m ()
pushString
{-# INLINABLE push #-}
pop :: forall (m :: * -> *). MonadPop m => m String
pop = forall (m :: * -> *). MonadPop m => m String
popString
{-# INLINABLE pop #-}
instance Marshal T.Text where
push :: forall (m :: * -> *). MonadPush m => Text -> m ()
push = forall (m :: * -> *). MonadPush m => Text -> m ()
pushText
{-# INLINABLE push #-}
pop :: forall (m :: * -> *). MonadPop m => m Text
pop = forall (m :: * -> *). MonadPop m => m Text
popText
{-# INLINABLE pop #-}
instance Marshal TL.Text where
push :: forall (m :: * -> *). MonadPush m => Text -> m ()
push = forall a (m :: * -> *). (Marshal a, MonadPush m) => a -> m ()
push forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
TL.toStrict
{-# INLINABLE push #-}
pop :: forall (m :: * -> *). MonadPop m => m Text
pop = Text -> Text
TL.fromStrict forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a (m :: * -> *). (Marshal a, MonadPop m) => m a
pop
{-# INLINABLE pop #-}
type GMarshal :: (Type -> Type) -> Constraint
class GMarshal f where
gpush :: MonadPush m => f a -> m ()
gpop :: MonadPop m => m (f a)
instance Marshal a => GMarshal (K1 i a) where
gpush :: forall (m :: * -> *) a. MonadPush m => K1 i a a -> m ()
gpush (K1 a
x) = forall a (m :: * -> *). (Marshal a, MonadPush m) => a -> m ()
push a
x
{-# INLINABLE gpush #-}
gpop :: forall (m :: * -> *) a. MonadPop m => m (K1 i a a)
gpop = forall k i c (p :: k). c -> K1 i c p
K1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a (m :: * -> *). (Marshal a, MonadPop m) => m a
pop
{-# INLINABLE gpop #-}
instance (GMarshal f, GMarshal g) => GMarshal (f :*: g) where
gpush :: forall (m :: * -> *) a. MonadPush m => (:*:) f g a -> m ()
gpush (f a
a :*: g a
b) = do
forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPush m) =>
f a -> m ()
gpush f a
a
forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPush m) =>
f a -> m ()
gpush g a
b
{-# INLINABLE gpush #-}
gpop :: forall (m :: * -> *) a. MonadPop m => m ((:*:) f g a)
gpop = forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
(:*:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPop m) =>
m (f a)
gpop forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPop m) =>
m (f a)
gpop
{-# INLINABLE gpop #-}
instance GMarshal a => GMarshal (M1 i c a) where
gpush :: forall (m :: * -> *) a. MonadPush m => M1 i c a a -> m ()
gpush (M1 a a
x) = forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPush m) =>
f a -> m ()
gpush a a
x
{-# INLINABLE gpush #-}
gpop :: forall (m :: * -> *) a. MonadPop m => m (M1 i c a a)
gpop = forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) (m :: * -> *) a.
(GMarshal f, MonadPop m) =>
m (f a)
gpop
{-# INLINABLE gpop #-}
type SimpleProduct :: Type -> Constraint
type family SimpleProduct a where
SimpleProduct a = (ProductLike a (Rep a), OnlyMarshallableFields (Rep a))
type ProductLike :: Type -> (Type -> Type) -> Constraint
type family ProductLike t f where
ProductLike t (a :*: b) = (ProductLike t a, ProductLike t b)
ProductLike t (M1 _ _ a) = ProductLike t a
ProductLike _ (K1 _ _) = ()
ProductLike t (_ :+: _) =
TypeError ( 'Text "Error while deriving marshalling code for type " ':<>: 'ShowType t ':<>: 'Text ":"
':$$: 'Text "Cannot derive sum type, only product types are supported.")
ProductLike t U1 =
TypeError ( 'Text "Error while deriving marshalling code for type " ':<>: 'ShowType t ':<>: 'Text ":"
':$$: 'Text "Cannot automatically derive code for 0 argument constructor.")
ProductLike t V1 =
TypeError ( 'Text "Error while deriving marshalling code for type " ':<>: 'ShowType t ':<>: 'Text ":"
':$$: 'Text "Cannot derive void type.")
type OnlyMarshallableFields :: (Type -> Type) -> Constraint
type family OnlyMarshallableFields f where
OnlyMarshallableFields (a :*: b) = (OnlyMarshallableFields a, OnlyMarshallableFields b)
OnlyMarshallableFields (a :+: b) = (OnlyMarshallableFields a, OnlyMarshallableFields b)
OnlyMarshallableFields (M1 _ _ a) = OnlyMarshallableFields a
OnlyMarshallableFields U1 = ()
OnlyMarshallableFields V1 = ()
OnlyMarshallableFields k = OnlyMarshallableField k
type OnlyMarshallableField :: (Type -> Type) -> Constraint
type family OnlyMarshallableField f where
OnlyMarshallableField (M1 _ _ a) = OnlyMarshallableField a
OnlyMarshallableField (K1 _ a) = Marshal a