clr-bindings-0.2.0: src/Clr/Bindings/DynImports.hs
{-# LANGUAGE TypeInType, FlexibleInstances, MultiParamTypeClasses, TypeFamilies, TypeApplications, ScopedTypeVariables, AllowAmbiguousTypes, UndecidableInstances #-}
module Clr.Bindings.DynImports where
import Clr.Bridge
import Clr.Constructor
import Clr.Method.Instance
import Clr.Method.Static
import Clr.Property
import Clr.TypeString
import Clr.Host
import Clr.Host.Method
import Data.Kind
import Foreign.Ptr
--
-- DynamicImportType t is the type of a function from a `FunPtr t` to a `t`
--
type family DynamicImportType t where
DynamicImportType t = FunPtr t -> t
--
-- IgnoreUnitType a r is the type of a function from `a` to `r`,
-- unless `a` is `()`, in which case it evaluates to just `r`
--
type family IngoreUnitType a r where
IngoreUnitType () r = r
IngoreUnitType x r = x -> r
--
-- HandleUnit does the term level application of an argument,
-- providing that argument is not unit
--
class HandleUnit f x r where
handleUnit :: f -> x -> r
instance HandleUnit a () a where
handleUnit a () = a
instance HandleUnit (x -> r) x r where
handleUnit f x = f x
--
-- Each method signature needs its own seperate `foreign import "dynamic"`,
-- which is specified by implementing a _DynImport_ class
--
class MethodDynImportI1 t m arg0 where
methodDynImportI1 :: DynamicImportType (BridgeType t -> IngoreUnitType (BridgeType arg0) (IO (BridgeType (ResultTypeI1 t m arg0))))
class MethodDynImportI2 t m arg0 arg1 where
methodDynImportI2 :: DynamicImportType (BridgeType t -> BridgeType arg0 -> BridgeType arg1 -> IO (BridgeType (ResultTypeI2 t m arg0 arg1)))
class MethodDynImportI3 t m arg0 arg1 arg2 where
methodDynImportI3 :: DynamicImportType (BridgeType t -> BridgeType arg0 -> BridgeType arg1 -> BridgeType arg2 -> IO (BridgeType (ResultTypeI3 t m arg0 arg1 arg2)))
class MethodDynImportS1 t m arg0 where
methodDynImportS1 :: DynamicImportType (IngoreUnitType (BridgeType arg0) (IO (BridgeType (ResultTypeS1 t m arg0))))
class MethodDynImportS2 t m arg0 arg1 where
methodDynImportS2 :: DynamicImportType (BridgeType arg0 -> BridgeType arg1 -> IO (BridgeType (ResultTypeS2 t m arg0 arg1)))
class MethodDynImportS3 t m arg0 arg1 arg2 where
methodDynImportS3 :: DynamicImportType (BridgeType arg0 -> BridgeType arg1 -> BridgeType arg2 -> IO (BridgeType (ResultTypeS3 t m arg0 arg1 arg2)))
class ConstructorDynImport1 t arg0 where
constructorDynImport1 :: DynamicImportType (IngoreUnitType (BridgeType arg0) (IO (BridgeType t)))
class ConstructorDynImport2 t arg0 arg1 where
constructorDynImport2 :: DynamicImportType (BridgeType arg0 -> BridgeType arg1 -> IO (BridgeType t))
class ConstructorDynImport3 t arg0 arg1 arg2 where
constructorDynImport3 :: DynamicImportType (BridgeType arg0 -> BridgeType arg1 -> BridgeType arg2 -> IO (BridgeType t))
class PropertyDynImportGetI t m where
propertyDynImportGetI :: DynamicImportType (BridgeType t -> IO (BridgeType (PropertyTypeI t m)))
class PropertyDynImportSetI t m where
propertyDynImportSetI :: DynamicImportType (BridgeType t -> BridgeType (PropertyTypeI t m) -> IO ())
class PropertyDynImportGetS t m where
propertyDynImportGetS :: DynamicImportType (IO (BridgeType (PropertyTypeS t m)))
class PropertyDynImportSetS t m where
propertyDynImportSetS :: DynamicImportType (BridgeType (PropertyTypeS t m) -> IO ())
--
-- An instance of both MethodResult and MethodDynImport provides an instance for MethodInvoke.
-- NB: the 1 argument variants contain additional complexity for mapping both actual arguments
-- and unit type placeholders to the dynamic entry points, which don't take unit placeholders
--
instance ( TString t
, TString m
, TString arg0
, MethodResultI1 t m arg0
, MethodDynImportI1 t m arg0
, HandleUnit (IngoreUnitType (BridgeType arg0) (IO (BridgeType (ResultTypeI1 t m arg0)))) (BridgeType arg0) (IO (BridgeType (ResultTypeI1 t m arg0)))
) => MethodInvokeI1 t m arg0 where
rawInvokeI1 obj x = do
fp <- getMethodStub (tString @t) (tString @m) (tString @arg0)
let f = methodDynImportI1 @t @m @arg0 fp
handleUnit @(IngoreUnitType (BridgeType arg0) (IO (BridgeType (ResultTypeI1 t m arg0)))) @(BridgeType arg0) @(IO (BridgeType (ResultTypeI1 t m arg0))) (f obj) x
instance ( TString t
, TString m
, TString arg0
, TString arg1
, MethodResultI2 t m arg0 arg1
, MethodDynImportI2 t m arg0 arg1
) => MethodInvokeI2 t m arg0 arg1 where
rawInvokeI2 obj x y = getMethodStub (tString @t) (tString @m) ((tString @arg0) ++ ";" ++ (tString @arg1)) >>= return . (methodDynImportI2 @t @m @arg0 @arg1) >>= \f-> f obj x y
instance ( TString t
, TString m
, TString arg0
, TString arg1
, TString arg2
, MethodResultI3 t m arg0 arg1 arg2
, MethodDynImportI3 t m arg0 arg1 arg2
) => MethodInvokeI3 t m arg0 arg1 arg2 where
rawInvokeI3 obj x y z = getMethodStub (tString @t) (tString @m) ((tString @arg0) ++ ";" ++ (tString @arg1) ++ ";" ++ (tString @arg2)) >>= return . (methodDynImportI3 @t @m @arg0 @arg1 @arg2) >>= \f-> f obj x y z
instance ( TString t
, TString m
, TString arg0
, MethodResultS1 t m arg0
, MethodDynImportS1 t m arg0
, HandleUnit (IngoreUnitType (BridgeType arg0) (IO (BridgeType (ResultTypeS1 t m arg0)))) (BridgeType arg0) (IO (BridgeType (ResultTypeS1 t m arg0)))
) => MethodInvokeS1 t m arg0 where
rawInvokeS1 x = do
fp <- getMethodStub (tString @t) (tString @m) (tString @arg0)
let f = methodDynImportS1 @t @m @arg0 fp
handleUnit @(IngoreUnitType (BridgeType arg0) (IO (BridgeType (ResultTypeS1 t m arg0)))) @(BridgeType arg0) @(IO (BridgeType (ResultTypeS1 t m arg0))) f x
instance ( TString t
, TString m
, TString arg0
, TString arg1
, MethodResultS2 t m arg0 arg1
, MethodDynImportS2 t m arg0 arg1
) => MethodInvokeS2 t m arg0 arg1 where
rawInvokeS2 x y = getMethodStub (tString @t) (tString @m) ((tString @arg0) ++ ";" ++ (tString @arg1)) >>= return . (methodDynImportS2 @t @m @arg0 @arg1) >>= \f-> f x y
instance ( TString t
, TString m
, TString arg0
, TString arg1
, TString arg2
, MethodResultS3 t m arg0 arg1 arg2
, MethodDynImportS3 t m arg0 arg1 arg2
) => MethodInvokeS3 t m arg0 arg1 arg2 where
rawInvokeS3 x y z = getMethodStub (tString @t) (tString @m) ((tString @arg0) ++ ";" ++ (tString @arg1) ++ ";" ++ (tString @arg2)) >>= return . (methodDynImportS3 @t @m @arg0 @arg1 @arg2) >>= \f-> f x y z
ctorString :: String
ctorString = ".ctor"
instance ( TString t
, TString arg0
, ConstructorDynImport1 t arg0
, HandleUnit (IngoreUnitType (BridgeType arg0) (IO (BridgeType t))) (BridgeType arg0) (IO (BridgeType t))
) => Constructor1 t arg0 where
rawNew1 x = do
fp <- getMethodStub (tString @t) ctorString (tString @arg0)
let f = constructorDynImport1 @t @arg0 fp
handleUnit @(IngoreUnitType (BridgeType arg0) (IO (BridgeType t))) @(BridgeType arg0) @(IO (BridgeType t)) f x
instance ( TString t
, TString arg0
, TString arg1
, ConstructorDynImport2 t arg0 arg1
) => Constructor2 t arg0 arg1 where
rawNew2 x y = getMethodStub (tString @t) ctorString ((tString @arg0) ++ ";" ++ (tString @arg1)) >>= return . (constructorDynImport2 @t @arg0 @arg1) >>= \f-> f x y
instance ( TString t
, TString arg0
, TString arg1
, TString arg2
, ConstructorDynImport3 t arg0 arg1 arg2
) => Constructor3 t arg0 arg1 arg2 where
rawNew3 x y z = getMethodStub (tString @t) ctorString ((tString @arg0) ++ ";" ++ (tString @arg1) ++ ";" ++ (tString @arg2)) >>= return . (constructorDynImport3 @t @arg0 @arg1 @arg2) >>= \f-> f x y z
instance ( TString t
, TString m
, PropertyI t m
, PropertyDynImportGetI t m
) => PropertyGetI t m where
rawGetPropI obj = getMethodStub (tString @t) (tStringGet @m) (tString @()) >>= return . (propertyDynImportGetI @t @m) >>= \f-> f obj
instance ( TString t
, TString m
, PropertyI t m
, TString (PropertyTypeI t m)
, PropertyDynImportSetI t m
) => PropertySetI t m where
rawSetPropI obj x = getMethodStub (tString @t) (tStringSet @m) (tString @(PropertyTypeI t m)) >>= return . (propertyDynImportSetI @t @m) >>= \f-> f obj x
instance ( TString t
, TString m
, PropertyS t m
, PropertyDynImportGetS t m
) => PropertyGetS t m where
rawGetPropS = getMethodStub (tString @t) (tStringGet @m) (tString @()) >>= return . (propertyDynImportGetS @t @m) >>= \f-> f
instance ( TString t
, TString m
, PropertyS t m
, TString (PropertyTypeS t m)
, PropertyDynImportSetS t m
) => PropertySetS t m where
rawSetPropS x = getMethodStub (tString @t) (tStringSet @m) (tString @(PropertyTypeS t m)) >>= return . (propertyDynImportSetS @t @m) >>= \f-> f x