Hs2lib-0.4.8: WinDll/Lib/Instances.hs
-----------------------------------------------------------------------------
-- |
-- Module : Windll
-- Copyright : (c) Tamar Christina 2009 - 2010
-- License : BSD3
--
-- Maintainer : tamar@zhox.com
-- Stability : experimental
-- Portability : portable
--
-- Module containing definitions for misc instances, for commonly used
-- datatypes like Maybe, Either etc
--
-----------------------------------------------------------------------------
module WinDll.Lib.Instances
(module WinDll.Lib.Instances
,module WinDll.Lib.InstancesTypes) where
import WinDll.Lib.NativeMapping
import WinDll.Lib.InstancesTypes
import WinDll.Lib.Native
import WinDll.Structs.Structures
import WinDll.Structs.MShow.HaskellSrcExts
import WinDll.Structs.MShow.MShow
import WinDll.Parsers
import Foreign
import Foreign.C
import Foreign.Ptr
import Foreign.Marshal.Alloc
import Foreign.Marshal.Utils
import Control.Monad
import Control.Monad.Instances
import Control.Arrow
import Data.List
import Data.Maybe
import Data.Generics hiding (DataType)
import qualified Language.Haskell.Exts as Exts
import Debug.Trace
-- | Constant of known instances
knownDataInstances = map fst instanceMappings
-- | Mapping of instance names to specializeable datatypes
instanceMappings = [("Maybe" , specMaybe )
,("Either" , specEither)
] -- ,("Located", specLocated)]
-- | A mapping from Type name to Specialization function
getSpecializations :: DataTypes -> [(Name,[Exts.Type])] -> DataTypes
getSpecializations _ [] = [] -- trace (unlines $ map show list) $
getSpecializations dyn list = nub $ getSpecialization list
where mapping = map (getName &&& id) dyn ++ instanceMappings
getSpecialization :: [(Name,[Exts.Type])] -> DataTypes
getSpecialization [] = []
getSpecialization ((n,t):xs) =
case lookup n mapping of
Nothing -> getSpecialization xs
Just f -> let adt = specialize t f
typ = getTypes adt
cls = concatMap (\x-> maybe [] (flip selectTypePre x) ((getHead . stripTop) x)) typ
emb = getSpecializations dyn cls
in adt : emb ++ getSpecialization xs --(map translate t)
-- | A mapping from Type name to the simple identity types that are needed
-- Since the problem with Overlapping instances in GHC only doing head matches
-- is preventing me to solve this with general classes.
getInstances :: Defs -> [(Name,Types)] -> [Types]
getInstances _ [] = []
getInstances defs ((n,t):xs) =
case lookup n instanceMappings of
Nothing -> getInstances defs xs
Just f -> map (translate defs) t : getInstances defs xs
-- | Specializable constant for Maybe
specMaybe :: DataType
specMaybe = let con = [Constr "Nothing" []
,Constr "Just" [AnnType "maybe_just_var1" ty noAnn ty]
]
ty = Exts.TyVar (Exts.Ident "a")
in DataType "Maybe" ["a"] con NoTag
specEither :: DataType
specEither = let con = [Constr "Left" [AnnType "either_left_var1" tyA noAnn tyA]
,Constr "Right" [AnnType "either_right_var1" tyB noAnn tyB]
]
tyA = Exts.TyVar (Exts.Ident "a")
tyB = Exts.TyVar (Exts.Ident "b")
in DataType "Either" ["a","b"] con NoTag
-- | Specializable constant for Located
specLocated :: DataType
specLocated = let con = [Constr "L" [AnnType "located_l_var1" tyA noAnn tyA
,AnnType "located_l_var2" tyB noAnn tyB]
]
tyA = Exts.TyCon (Exts.UnQual (Exts.Ident "SrcSpan"))
tyB = Exts.TyVar (Exts.Ident "e")
in DataType "Located" ["e"] con NoTag
-- | A function that can specialize any DataType
specialize :: [Exts.Type] -> DataType -> DataType
specialize newtypes dt@(NewType n t f g ) =
case specialize newtypes (DataType n t [f] g) of
(DataType n' t' f' g') -> NewType n' t' (head f') g'
specialize newtypes dt@(DataType n t c d)
| length t <= length newtypes = let newc = everywhere (mkT spectype) c
in DataType n (map (mshowM 2) newtypes) newc d
| otherwise = error $ "fatal error in specialization of '" ++ show n ++ "' the supplied list does not contain sufficient elements to do a specialization"
where spectype :: Type -> Type
spectype = foldr (.) id $ zipWith ($) (map swapTypes t) newtypes