addrDataCon,
addrTy,
addrTyCon,
+ ptrDataCon,
+ ptrTy,
+ ptrTyCon,
+ funPtrDataCon,
+ funPtrTy,
+ funPtrTyCon,
boolTy,
boolTyCon,
charDataCon,
wordTy,
wordTyCon,
- isFFIArgumentTy, -- :: Bool -> Type -> Bool
- isFFIResultTy, -- :: Type -> Bool
- isFFIExternalTy, -- :: Type -> Bool
- isFFIDynArgumentTy, -- :: Type -> Bool
- isFFIDynResultTy, -- :: Type -> Bool
- isFFILabelTy, -- :: Type -> Bool
- isAddrTy, -- :: Type -> Bool
- isForeignPtrTy -- :: Type -> Bool
+ isFFIArgumentTy, -- :: DynFlags -> Bool -> Type -> Bool
+ isFFIImportResultTy, -- :: DynFlags -> Type -> Bool
+ isFFIExportResultTy, -- :: Type -> Bool
+ isFFIExternalTy, -- :: Type -> Bool
+ isFFIDynArgumentTy, -- :: Type -> Bool
+ isFFIDynResultTy, -- :: Type -> Bool
+ isFFILabelTy, -- :: Type -> Bool
+ isAddrTy, -- :: Type -> Bool
+ isForeignPtrTy -- :: Type -> Bool
) where
import BasicTypes ( Arity, RecFlag(..), Boxity(..), isBoxed )
import Type ( Type, mkTyConTy, mkTyConApp, mkTyVarTys,
- mkArrowKinds, boxedTypeKind, unboxedTypeKind,
+ mkArrowKinds, liftedTypeKind, unliftedTypeKind,
splitTyConApp_maybe, repType,
- TauType, ClassContext )
+ TauType, ThetaType )
import Unique ( incrUnique, mkTupleTyConUnique, mkTupleDataConUnique )
import PrelNames
import CmdLineOpts
data_tycons = genericTyCons ++
[ addrTyCon
+ , ptrTyCon
+ , funPtrTyCon
, boolTyCon
, charTyCon
, doubleTyCon
gen_info
mod = nameModule name
- kind = mkArrowKinds (map tyVarKind tyvars) boxedTypeKind
+ kind = mkArrowKinds (map tyVarKind tyvars) liftedTypeKind
gen_info = mk_tc_gen_info mod (nameUnique name) name tycon
-- We generate names for the generic to/from Ids by incrementing
name1 = mkWiredInName mod occ_name1 fn1_key
name2 = mkWiredInName mod occ_name2 fn2_key
-pcDataCon :: Name -> [TyVar] -> ClassContext -> [TauType] -> TyCon -> DataCon
+pcDataCon :: Name -> [TyVar] -> ThetaType -> [TauType] -> TyCon -> DataCon
-- The unique is the first of two free uniques;
-- the first is used for the datacon itself and the worker;
-- the second is used for the wrapper.
tycon = mkTupleTyCon tc_name tc_kind arity tyvars tuple_con boxity gen_info
tc_name = mkWiredInName mod (mkOccFS tcName name_str) tc_uniq
tc_kind = mkArrowKinds (map tyVarKind tyvars) res_kind
- res_kind | isBoxed boxity = boxedTypeKind
- | otherwise = unboxedTypeKind
+ res_kind | isBoxed boxity = liftedTypeKind
+ | otherwise = unliftedTypeKind
tyvars | isBoxed boxity = take arity alphaTyVars
| otherwise = take arity openAlphaTyVars
--
-- data Void = -- No constructors!
--
--- ) It's boxed; there is only one value of this
+-- ) It's lifted; there is only one value of this
-- type, namely "void", whose semantics is just bottom.
--
-- Haskell 98 drops the definition of a Void type, so we just 'simulate'
\end{code}
\begin{code}
+ptrTy = mkTyConTy ptrTyCon
+
+ptrTyCon = pcNonRecDataTyCon ptrTyConName alpha_tyvar [(True,False)] [ptrDataCon]
+ptrDataCon = pcDataCon ptrDataConName alpha_tyvar [] [addrPrimTy] ptrTyCon
+\end{code}
+
+\begin{code}
+funPtrTy = mkTyConTy funPtrTyCon
+
+funPtrTyCon = pcNonRecDataTyCon funPtrTyConName alpha_tyvar [(True,False)] [funPtrDataCon]
+funPtrDataCon = pcDataCon funPtrDataConName alpha_tyvar [] [addrPrimTy] funPtrTyCon
+\end{code}
+
+\begin{code}
floatTy = mkTyConTy floatTyCon
floatTyCon = pcNonRecDataTyCon floatTyConName [] [] [floatDataCon]
isFFIExternalTy :: Type -> Bool
-- Types that are allowed as arguments of a 'foreign export'
-isFFIExternalTy ty = checkRepTyCon legalIncomingTyCon ty
+isFFIExternalTy ty = checkRepTyCon legalFEArgTyCon ty
-isFFIResultTy :: Type -> Bool
--- Types that are allowed as a result of a 'foreign import' or of a 'foreign export'
--- Maybe we should distinguish between import and export, but
--- here we just choose the more restrictive 'incoming' predicate
--- But we allow () as well
-isFFIResultTy ty = checkRepTyCon (\tc -> tc == unitTyCon || legalIncomingTyCon tc) ty
+isFFIImportResultTy :: DynFlags -> Type -> Bool
+isFFIImportResultTy dflags ty
+ = checkRepTyCon (legalFIResultTyCon dflags) ty
+
+isFFIExportResultTy :: Type -> Bool
+isFFIExportResultTy ty = checkRepTyCon legalFEResultTyCon ty
isFFIDynArgumentTy :: Type -> Bool
--- The argument type of a foreign import dynamic must be either Addr, or
--- a newtype of Addr.
-isFFIDynArgumentTy = checkRepTyCon (== addrTyCon)
+-- The argument type of a foreign import dynamic must be Ptr, FunPtr, Addr,
+-- or a newtype of either.
+isFFIDynArgumentTy = checkRepTyCon (\tc -> tc == ptrTyCon || tc == funPtrTyCon || tc == addrTyCon)
isFFIDynResultTy :: Type -> Bool
--- The result type of a foreign export dynamic must be either Addr, or
--- a newtype of Addr.
-isFFIDynResultTy = checkRepTyCon (== addrTyCon)
+-- The result type of a foreign export dynamic must be Ptr, FunPtr, Addr,
+-- or a newtype of either.
+isFFIDynResultTy = checkRepTyCon (\tc -> tc == ptrTyCon || tc == funPtrTyCon || tc == addrTyCon)
isFFILabelTy :: Type -> Bool
--- The type of a foreign label must be either Addr, or
--- a newtype of Addr.
-isFFILabelTy = checkRepTyCon (== addrTyCon)
+-- The type of a foreign label must be Ptr, FunPtr, Addr,
+-- or a newtype of either.
+isFFILabelTy = checkRepTyCon (\tc -> tc == ptrTyCon || tc == funPtrTyCon || tc == addrTyCon)
checkRepTyCon :: (TyCon -> Bool) -> Type -> Bool
-- look through newtypes
----------------------------------------------
\begin{code}
-legalIncomingTyCon :: TyCon -> Bool
+legalFEArgTyCon :: TyCon -> Bool
-- It's illegal to return foreign objects and (mutable)
-- bytearrays from a _ccall_ / foreign declaration
-- (or be passed them as arguments in foreign exported functions).
-legalIncomingTyCon tc
+legalFEArgTyCon tc
| getUnique tc `elem` [ foreignObjTyConKey, foreignPtrTyConKey,
byteArrayTyConKey, mutableByteArrayTyConKey ]
= False
| otherwise
= boxedMarshalableTyCon tc
+legalFIResultTyCon :: DynFlags -> TyCon -> Bool
+legalFIResultTyCon dflags tc
+ | getUnique tc `elem`
+ [ foreignObjTyConKey, foreignPtrTyConKey,
+ byteArrayTyConKey, mutableByteArrayTyConKey ] = False
+ | tc == unitTyCon = True
+ | otherwise = marshalableTyCon dflags tc
+
+legalFEResultTyCon :: TyCon -> Bool
+legalFEResultTyCon tc
+ | getUnique tc `elem`
+ [ foreignObjTyConKey, foreignPtrTyConKey,
+ byteArrayTyConKey, mutableByteArrayTyConKey ] = False
+ | tc == unitTyCon = True
+ | otherwise = boxedMarshalableTyCon tc
+
legalOutgoingTyCon :: DynFlags -> Bool -> TyCon -> Bool
-- Checks validity of types going from Haskell -> external world
-- The boolean is true for a 'safe' call (when we don't want to
|| boxedMarshalableTyCon tc
boxedMarshalableTyCon tc
- = getUnique tc `elem` [ intTyConKey, int8TyConKey, int16TyConKey, int32TyConKey, int64TyConKey
- , wordTyConKey, word8TyConKey, word16TyConKey, word32TyConKey, word64TyConKey
+ = getUnique tc `elem` [ intTyConKey, int8TyConKey, int16TyConKey
+ , int32TyConKey, int64TyConKey
+ , wordTyConKey, word8TyConKey, word16TyConKey
+ , word32TyConKey, word64TyConKey
, floatTyConKey, doubleTyConKey
- , addrTyConKey, charTyConKey, foreignObjTyConKey
+ , addrTyConKey, ptrTyConKey, funPtrTyConKey
+ , charTyConKey, foreignObjTyConKey
, foreignPtrTyConKey
, stablePtrTyConKey
, byteArrayTyConKey, mutableByteArrayTyConKey
genUnitDataCon :: DataCon
genUnitDataCon = pcDataCon genUnitDataConName [] [] [] genUnitTyCon
\end{code}
-
-
-
-
-