|
From: <cod...@go...> - 2008-10-01 22:06:25
|
Author: wol...@gm...
Date: Wed Oct 1 14:40:28 2008
New Revision: 324
Modified:
trunk/hoc/InterfaceGenerator2/BinaryInstances.hs
Log:
Re-implement BinaryInstances using Data.Generics. Much more fun this way.
Modified: trunk/hoc/InterfaceGenerator2/BinaryInstances.hs
==============================================================================
--- trunk/hoc/InterfaceGenerator2/BinaryInstances.hs (original)
+++ trunk/hoc/InterfaceGenerator2/BinaryInstances.hs Wed Oct 1 14:40:28
2008
@@ -1,183 +1,78 @@
-module BinaryInstances where
+{-# LANGUAGE PatternGuards, PatternSignatures, ExistentialQuantification
#-}
+module BinaryInstances() where
-import Entities
-import SyntaxTree
-import CTypeToHaskell
import Data.Binary
+import Data.Generics
+import Control.Monad.Fix ( mfix )
+import Control.Monad ( msum )
+import Data.ByteString.Char8 ( ByteString )
+import Data.Maybe ( fromJust, fromMaybe )
+
+import Entities
+data BinaryType = forall a. (Binary a, Typeable a) => BinaryType a
-instance Binary SyntaxTree.EnumValue where
- put NextValue = putWord8 0
- put (GivenValue a) = putWord8 1 >> put a
- put (TooComplicatedValue a) = putWord8 2 >> put a
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> return NextValue
- 1 -> get >>= \a -> return (GivenValue a)
- 2 -> get >>= \a -> return (TooComplicatedValue a)
- _ -> fail "no parse"
-
-instance Binary SyntaxTree.CType where
- put (CTIDType a) = putWord8 0 >> put a
- put (CTSimple a) = putWord8 1 >> put a
- put (CTPointer a) = putWord8 2 >> put a
- put CTUnknown = putWord8 3
- put (CTEnum a b) = putWord8 4 >> put a >> put b
- put (CTStruct a b) = putWord8 5 >> put a >> put b
- put (CTUnion a b) = putWord8 6 >> put a >> put b
- put (CTBuiltin a b c) = putWord8 7 >> put a >> put b >> put c
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> return (CTIDType a)
- 1 -> get >>= \a -> return (CTSimple a)
- 2 -> get >>= \a -> return (CTPointer a)
- 3 -> return CTUnknown
- 4 -> get >>= \a -> get >>= \b -> return (CTEnum a b)
- 5 -> get >>= \a -> get >>= \b -> return (CTStruct a b)
- 6 -> get >>= \a -> get >>= \b -> return (CTUnion a b)
- 7 -> get >>= \a -> get >>= \b -> get >>= \c -> return (CTBuiltin a b
c)
- _ -> fail "no parse"
-
-instance Binary SyntaxTree.Length where
- put LongLong = putWord8 0
- put Long = putWord8 1
- put Short = putWord8 2
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> return LongLong
- 1 -> return Long
- 2 -> return Short
- _ -> fail "no parse"
-
-instance Binary SyntaxTree.Selector where
- put (Selector a b c d) = put a >> put b >> put c >> put d
- get = get >>= \a -> get >>= \b -> get >>= \c -> get >>= \d -> return
(Selector a b c d)
-
-instance Binary CTypeToHaskell.HSelectorType where
- put (HSelectorType a b c d) = put a >> put b >> put c >> put d
- get = get >>= \a -> get >>= \b -> get >>= \c -> get >>= \d -> return
(HSelectorType a b c d)
-
-instance Binary CTypeToHaskell.HType where
- put (HType a b c) = put a >> put b >> put c
- get = get >>= \a -> get >>= \b -> get >>= \c -> return (HType a b c)
-
-instance Binary CTypeToHaskell.HTypeTerm where
- put (Con a) = putWord8 0 >> put a
- put (a :$ b) = putWord8 1 >> put a >> put b
- put (Var a) = putWord8 2 >> put a
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> return (Con a)
- 1 -> get >>= \a -> get >>= \b -> return (a :$ b)
- 2 -> get >>= \a -> return (Var a)
- _ -> fail "no parse"
-
-instance Binary Entities.EntityID where
- put (LocalEntity a) = putWord8 0 >> put a
- put (FrameworkEntity a b) = putWord8 1 >> put a >> put b
- put (DelayedClassLookup a) = putWord8 2 >> put a
- put (DelayedProtocolLookup a) = putWord8 3 >> put a
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> return (LocalEntity a)
- 1 -> get >>= \a -> get >>= \b -> return (FrameworkEntity a b)
- 2 -> get >>= \a -> return (DelayedClassLookup a)
- 3 -> get >>= \a -> return (DelayedProtocolLookup a)
- _ -> fail "no parse"
-
-instance Binary Entities.Module where
- put (LocalModule a) = putWord8 0 >> put a
- put (FrameworkModule a b) = putWord8 1 >> put a >> put b
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> return (LocalModule a)
- 1 -> get >>= \a -> get >>= \b -> return (FrameworkModule a b)
- _ -> fail "no parse"
-
-instance (Binary a, Binary b) => Binary (Entities.HaskellType a b) where
- put (ConvertedType a b) = putWord8 0 >> put a >> put b
- put (UnconvertedType a) = putWord8 1 >> put a
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> get >>= \b -> return (ConvertedType a b)
- 1 -> get >>= \a -> return (UnconvertedType a)
- _ -> fail "no parse"
-
-instance Binary Entities.EntityInfo where
- put (ClassEntity a) = putWord8 0 >> put a
- put (TypeSynonymEntity a) = putWord8 1 >> put a
- put (EnumEntity a b) = putWord8 2 >> put a >> put b
- put AdditionalTypeEntity = putWord8 3
- put (SelectorEntity a) = putWord8 4 >> put a
- put (ProtocolEntity a b) = putWord8 5 >> put a >> put b
- put MethodEntity = putWord8 6
- put ProtocolAdoptionEntity = putWord8 7
- put (ExternVarEntity a) = putWord8 8 >> put a
- put (ExternFunEntity a) = putWord8 9 >> put a
- put (ReexportEntity a) = putWord8 10 >> put a
- put (AdditionalCodeEntity a b c d) = putWord8 11 >> put a >> put b >>
put c >> put d
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> return (ClassEntity a)
- 1 -> get >>= \a -> return (TypeSynonymEntity a)
- 2 -> get >>= \a -> get >>= \b -> return (EnumEntity a b)
- 3 -> return AdditionalTypeEntity
- 4 -> get >>= \a -> return (SelectorEntity a)
- 5 -> get >>= \a -> get >>= \b -> return (ProtocolEntity a b)
- 6 -> return MethodEntity
- 7 -> return ProtocolAdoptionEntity
- 8 -> get >>= \a -> return (ExternVarEntity a)
- 9 -> get >>= \a -> return (ExternFunEntity a)
- 10 -> get >>= \a -> return (ReexportEntity a)
- 11 -> get >>= \a -> get >>= \b -> get >>= \c -> get >>= \d -> return
(AdditionalCodeEntity a b c d)
- _ -> fail "no parse"
-
-instance Binary Entities.Name where
- put (CName a) = putWord8 0 >> put a
- put (ProtocolName a) = putWord8 1 >> put a
- put (SelectorName a) = putWord8 2 >> put a
- put (ProtocolAdoptionName a b) = putWord8 3 >> put a >> put b
- put (SelectorInstanceName a b c) = putWord8 4 >> put a >> put b >> put c
- put Anonymous = putWord8 5
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> get >>= \a -> return (CName a)
- 1 -> get >>= \a -> return (ProtocolName a)
- 2 -> get >>= \a -> return (SelectorName a)
- 3 -> get >>= \a -> get >>= \b -> return (ProtocolAdoptionName a b)
- 4 -> get >>= \a -> get >>= \b -> get >>= \c -> return
(SelectorInstanceName a b c)
- 5 -> return Anonymous
- _ -> fail "no parse"
-
-instance Binary Entities.Entity where
- put (Entity a b c d e) = put a >> put b >> put c >> put d >> put e
- get = get >>= \a -> get >>= \b -> get >>= \c -> get >>= \d -> get >>= \e
-> return (Entity a b c d e)
-
-instance Binary Entities.EntityPile where
- put (EntityPile a b c) = put a >> put b >> put c
- get = get >>= \a -> get >>= \b -> get >>= \c -> return (EntityPile a b c)
-
-instance Binary CTypeToHaskell.SelectorKind where
- put PlainSelector = putWord8 0
- put CovariantSelector = putWord8 1
- put CovariantInstanceSelector = putWord8 2
- put AllocSelector = putWord8 3
- put InitSelector = putWord8 4
- get = do
- tag_ <- getWord8
- case tag_ of
- 0 -> return PlainSelector
- 1 -> return CovariantSelector
- 2 -> return CovariantInstanceSelector
- 3 -> return AllocSelector
- 4 -> return InitSelector
- _ -> fail "no parse"
+-- list of types that are handled by their real Binary instance
+-- instead of the generic code below
+specialTypes = [
+ BinaryType (undefined :: ByteString),
+ BinaryType (undefined :: String),
+ BinaryType (undefined :: Int)
+ ]
+
+gput :: Data a => a -> Put
+gput thing
+ = fromMaybe gput0 $ msum $ map gput1 specialTypes
+ where
+ gput0 = case constrRep (toConstr thing) of
+ IntConstr i -> put i
+ FloatConstr f -> put f
+ StringConstr s -> put s
+ AlgConstr i -> do
+ putWord8 (fromIntegral i)
+ gmapM (\x -> gput x >> return x) thing
+ return ()
+
+ gput1 (BinaryType t) = fmap put $ cast thing `asTypeOf` Just t
+
+gget :: Data a => Get a
+gget
+ = mfix gget' where
+
+ gget' result =
+ fromMaybe gget0 $ msum $ map gget1 specialTypes
+ where
+ dataType = dataTypeOf result
+ resultType = typeOf result
+
+ gget0 = do
+ constr <- case dataTypeRep dataType of
+ IntRep -> do
+ i <- get
+ return $ mkIntConstr dataType i
+ FloatRep -> do
+ f <- get
+ return $ mkFloatConstr dataType f
+ StringRep -> do
+ s <- get
+ return $ mkStringConstr dataType s
+ AlgRep constrs -> do
+ i <- getWord8
+ return (constrs !! (fromIntegral i - 1))
+ fromConstrM gget constr
+
+ gget1 :: Data a => BinaryType -> Maybe (Get a)
+ gget1 (BinaryType t)
+ | typeOf t == resultType
+ = Just (get >>= \x -> return $ fromJust $ cast $ x
`asTypeOf` t)
+ | otherwise = Nothing
+
+
+-- use gget and ggput to declare Binary instances for the types we need
+
+instance Binary Entity where
+ put = gput
+ get = gget
+instance Binary EntityID where
+ put = gput
+ get = gget
|