-- -- (c) Susumu Katayama -- module MagicHaskeller.ShortString where import Data.ByteString.Char8 as C -- This seems quicker, except that C.cons requires O(n). import Data.ByteString.Lazy.Char8 as LC import Data.Char import MagicHaskeller.CoreLang import MagicHaskeller.Types import Data.Int import Data.Word -- LC.cons' だと多分ダメ showBriefly :: ShortString a => a -> LC.ByteString showBriefly = flip showsBriefly LC.empty readBriefly :: ShortString a => C.ByteString -> Maybe a readBriefly = fmap fst . readsBriefly class ShortString a where showsBriefly :: a -> LC.ByteString -> LC.ByteString readsBriefly :: C.ByteString -> Maybe (a,C.ByteString) -- ReadS a -- Maybe の方が速い? てゆーか,parse errorの割合はすごく少ないはずなのでerrorとしてcatchした方が速いはず.と思ったけど,lazyなデータなので正しくcatchできないか. instance ShortString a => ShortString [a] where showsBriefly [] = LC.cons ']' showsBriefly (x:xs) = showsBriefly x . showsBriefly xs readsBriefly cs = case C.uncons cs of Nothing -> fail "parse error" Just (']',ds) -> return ([],ds) _ -> do (x, ds) <- readsBriefly cs (xs,es) <- readsBriefly ds return (x:xs, es) instance ShortString Bool where showsBriefly True = LC.cons 'T' showsBriefly False = LC.cons 'F' instance ShortString CoreExpr where showsBriefly (Lambda ce) = (LC.cons '\\') . showsBriefly ce showsBriefly (X i) = (LC.cons 'X') . showsBriefly i showsBriefly (Primitive i) = (LC.cons 'p') . showsBriefly i showsBriefly (PrimCon i) = (LC.cons 'P') . showsBriefly i showsBriefly (Context _) = LC.cons 'C' showsBriefly (c :$ e) = (LC.cons '$') . showsBriefly c . showsBriefly e readsBriefly cs = case C.uncons cs of -- Int(Nat)と1文字め一緒に1バイトにできないか?あと,lambdaは続くのでまとめられそう. Just ('\\',xs) -> do (ce,ys) <- readsBriefly xs return (Lambda ce, ys) Just ('X', xs) -> do (i, ys) <- readsBriefly xs return (X i, ys) Just ('p', xs) -> do (i, ys) <- readsBriefly xs return (Primitive i, ys) Just ('P', xs) -> do (i, ys) <- readsBriefly xs return (PrimCon i, ys) Just ('$', xs) -> do (c, ys) <- readsBriefly xs (e, zs) <- readsBriefly ys return (c :$ e, zs) Just ('C', xs) -> fail "readsBriefly for classes has not been implemented. (BTW, they should be reconstructed in the implementation.)" _ -> fail "parse error" -- Only small ints are used, if I remember correctly. instance ShortString Int where showsBriefly i = LC.cons (chr (i + 128)) -- other safer options are Numeric.showHex and Numeric.showIntAtBase readsBriefly xs = case C.uncons xs of Nothing -> fail "parse error" Just (c,cs) -> return (ord c - 128, cs) instance ShortString Int16 where -- Int8 to mattaku onaji showsBriefly i = LC.cons (chr (fromIntegral i + 128)) readsBriefly xs = case C.uncons xs of Nothing -> fail "parse error" Just (c,cs) -> return (fromIntegral (ord c - 128), cs) instance ShortString Int8 where showsBriefly i = LC.cons (chr (fromIntegral i + 128)) readsBriefly xs = case C.uncons xs of Nothing -> fail "parse error" Just (c,cs) -> return (fromIntegral (ord c - 128), cs) instance ShortString Word8 where showsBriefly i = LC.cons (chr (fromIntegral i)) readsBriefly xs = case C.uncons xs of Nothing -> fail "parse error" Just (c,cs) -> return (fromIntegral (ord c), cs) instance (ShortString a, ShortString b, ShortString c) => ShortString (a,b,c) where showsBriefly (a,b,c) = showsBriefly a . showsBriefly b . showsBriefly c readsBriefly cs = do (a,ds) <- readsBriefly cs (b,es) <- readsBriefly ds (c,fs) <- readsBriefly es return ((a,b,c),fs) instance (ShortString a, ShortString b) => ShortString (a,b) where showsBriefly (a,b) = showsBriefly a . showsBriefly b readsBriefly cs = do (a,ds) <- readsBriefly cs (b,es) <- readsBriefly ds return ((a,b),es) instance ShortString () where showsBriefly () = id readsBriefly cs = return ((),cs) instance ShortString Type where showsBriefly (TV i) = LC.cons 'V' . showsBriefly i showsBriefly (TC i) = LC.cons 'C' . showsBriefly i showsBriefly (TA f x) = LC.cons 'A' . showsBriefly f . showsBriefly x showsBriefly (a :-> r) = LC.cons '>' . showsBriefly a . showsBriefly r readsBriefly cs = case C.uncons cs of Just ('V',ds) -> do (i, es) <- readsBriefly ds return (TV i, es) Just ('C',ds) -> do (i, es) <- readsBriefly ds return (TC i, es) Just ('A',ds) -> do (f, es) <- readsBriefly ds (x, fs) <- readsBriefly es return (TA f x, fs) Just ('>',ds) -> do (a, es) <- readsBriefly ds (r, fs) <- readsBriefly es return (a:->r, fs) _ -> fail "parse error"