packages feed

clr-inline-0.2.0.1: src/Clr/Inline/Types.hs

{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE TypeInType             #-}
module Clr.Inline.Types
  ( ClrPtr(..)
  , Clr(..)
  , ClrType(Con, Unit, ..)
  , ClrTypeSymbol(..)
  , renderClrType
  , TextBStr(..)
  ) where

import           Clr.Host.GCHandle
import           Clr.Host.BStr
import           Clr.Marshal
import           Data.Coerce
import           Data.List
import           Data.Text            (Text)
import           Foreign
import           GHC.TypeLits
import           System.IO.Unsafe

data ClrType = TyCon String [ClrType]
             | Fun [ClrType] ClrType
             | Array Int ClrType
  deriving (Eq, Show)

renderClrType :: ClrType -> String
renderClrType = show where
  show (Array dim x) = concat [show x, "[", replicate (pred dim) ',', "]"]
  show (TyCon con []) = con
  show (TyCon con args) = concat [con,"<",intercalate "," (map show args),">"]
  show (Fun args res) = intercalate "->" $ map show (args ++ [res])

pattern Unit :: ClrType
pattern Unit = TyCon "unit" []
pattern Con :: String -> ClrType
pattern Con x = TyCon x []

-- | A type indexed pointer to a Clr object.
newtype ClrPtr (name::Symbol)= ClrPtr (GCHandle Int)

-- | A type indexed pointer to a Clr object with GC managed lifetime.
newtype Clr (name::Symbol) = Clr (ForeignPtr Int)

-- Returning from a CLR function that was called from Haskell
instance Unmarshal (ClrPtr n) (Clr n) where
  unmarshal (ClrPtr id) = do
    ptr <- newForeignPtr (unsafeDupablePerformIO gcHandleFinalizer) (coerce id)
    return (Clr ptr)

-- Returning from a Haskell function that was called by the CLR
instance {-# OVERLAPPING #-} Unmarshal (Clr t) (ClrPtr t) where
  unmarshal (Clr x) = withForeignPtr x $ \x'-> ClrPtr <$> newHandle (coerce x')

-- Calling a CLR function from Haskell
instance Marshal (Clr n) (ClrPtr n) where
  marshal (Clr ptr) f = withForeignPtr ptr $ \p -> f (ClrPtr $ coerce p)

-- Calling a Haskell function from the CLR
instance {-# OVERLAPPING #-} Marshal (ClrPtr t) (Clr t) where
  marshal (ClrPtr x) f = do
    x' <- newHandle x
    fp <- newForeignPtr (unsafeDupablePerformIO gcHandleFinalizer) (coerce x')
    f $ Clr fp

newtype ClrTypeSymbol = ClrTypeSymbol {getClrTypeSymbol :: String} deriving Show

newtype TextBStr = TextBStr BStr
instance Unmarshal TextBStr Text where unmarshal (TextBStr t) = unmarshal t
instance Marshal Text TextBStr where marshal x f = marshal x (f . TextBStr)