alpha-1.0.13: src/Serialize.hs
{-# LANGUAGE DeriveGeneric, StandaloneDeriving, NoMonomorphismRestriction #-}
module Serialize() where
import Context as C
import Data.Bits
import qualified Data.Bimap as BM
import Data.Maybe
import Data.Monoid
import Data.Serialize
import Data.Word
import GHC.Generics
import ID
import My.Control.Monad
import PCode
deriving instance Generic Builtin
deriving instance Generic C.Value
deriving instance Generic Axiom
deriving instance Generic (Range a)
instance Serialize Builtin
instance Serialize C.Value
instance Serialize Axiom
instance Serialize a => Serialize (Range a)
newtype SquashedI = SqI { unSqI :: Int }
newtype SquashedL a = SqL { unSqL :: [a] }
newtype SquashedM a = SqM { unSqM :: BM.Bimap String a }
instance Serialize SquashedI where
put (SqI n) = putWord8 (fromIntegral $ length bytes) >> mapM_ putWord8 bytes
where bytes = map fromIntegral $ takeWhile (>0) $ iterate (`shiftR`8) n
get = getWord8 >>= \n -> do
bytes <- mapM (const getWord8) [1..n]
return $ SqI $ sum (zipWith shiftL (map fromIntegral bytes) [0,8..])
instance Serialize a => Serialize (SquashedL a) where
put (SqL l) = put (SqI $ length l) >> mapM_ put l
get = get >>= \(SqI n) -> SqL $< mapM (const get) [1..n]
instance (Ord a,Serialize a) => Serialize (SquashedM a) where
put (SqM m) = put $ SqL [(SqL n,v) | (n,v) <- BM.toList m]
get = get >§ \(SqL l) -> SqM (BM.fromList [(n,v) | (SqL n,v) <- l])
typeCodes = [(Value,0),(GValue,1),(Address,2),(Size,3),(SymID,4)]
instance Serialize PCode.Value where
put (SymVal t n) = putWord8 (fromJust (lookup t typeCodes)) >> put n
put (IntVal n) = putWord8 5 >> put n
put NullVal = putWord8 6
get = getWord8 >>= \n -> case lookup n (map (\(a,b) -> (b,a)) typeCodes) of
Just t -> SymVal t $< get
Nothing -> case n of
5 -> IntVal $< get
6 -> return NullVal
instance Serialize Code where
put (Code [] [Branch _ []] Nothing) = putWord8 0
put (Code [] instrs ret) = putWord8 1 >> put (SqL instrs,ret)
put (Code args instrs ret) = putWord8 2 >> put (SqL args,SqL instrs,ret)
get = getWord8 >>= \n -> case n of
0 -> return $ Code [] [Branch NullVal []] Nothing
1 -> get >§ \(SqL instrs,ret) -> Code [] instrs ret
2 -> get >§ \(SqL args,SqL instrs,ret) -> Code args instrs ret
instance Serialize Instruction where
put (Op b d [x]) = putWord8 0 >> put (b,d,x)
put (Op b d [x,y]) = putWord8 1 >> put (b,d,x,y)
put (Op b d l) = putWord8 2 >> put (b,d,SqL l)
put (Branch _ []) = putWord8 3
put (Branch _ [x]) = putWord8 4 >> put x
put (Branch v [x,y]) = putWord8 5 >> put (v,x,y)
put (Branch v l) = putWord8 6 >> put (v,SqL (map SqI l))
put (Bind bv x) = putWord8 7 >> put (bv,x)
put Noop = putWord8 8
get = getWord8 >>= \x -> case x of
0 -> get >§ \(b,d,x) -> Op b d [x]
1 -> get >§ \(b,d,x,y) -> Op b d [x,y]
2 -> get >§ \(b,d,SqL l) -> Op b d l
3 -> return $ Branch NullVal []
4 -> get >§ \x -> Branch NullVal [x]
5 -> get >§ \(v,x,y) -> Branch v [x,y]
6 -> get >§ \(v,SqL l) -> Branch v (map unSqI l)
7 -> get >§ \(bv,x) -> Bind bv x
8 -> return Noop
instance Serialize BindVar where
put (BindVar sym (0,1) 0 []) = putWord8 0 >> put sym
put (BindVar sym (n,nr) pad []) = putWord8 1 >> put (sym,SqI n,SqI nr,SqI pad)
put (BindVar sym (n,nr) pad subs) = putWord8 2 >> put (sym,SqI n,SqI nr,SqI pad,SqL subs)
get = getWord8 >>= \n -> case n of
0 -> get >§ \sym -> BindVar sym (0,1) 0 []
1 -> get >§ \(sym,SqI n,SqI nr,SqI pad) -> BindVar sym (n,nr) pad []
2 -> get >§ \(sym,SqI n,SqI nr,SqI pad,SqL subs) -> BindVar sym (n,nr) pad subs
instance Serialize ID where
put (ID n) = put (SqI n)
get = ID . unSqI $< get
instance Serialize Language where
put l = put (maxIDL l,SqM (symbolsL l),valuesL l,SqM (languagesL l))
get = get >§ \(mi,SqM syms,vals,SqM langs) -> mempty{ maxIDL = mi, symbolsL = syms, valuesL = vals, languagesL = langs }