liquidhaskell-0.8.0.2: docs/slides/HS2014/ByteString-blank.hs
module Bytestring where
import Prelude hiding (null)
import Data.Char
import Data.Word
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr
import Foreign.Storable
import System.IO.Unsafe
import Language.Haskell.Liquid.Prelude
data ByteString = PS { bPayload :: ForeignPtr Word8
, bOffset :: !Int
, bLength :: !Int
}
{- measure fplen :: ForeignPtr a -> Int -}
{-@ data ByteString = PS
{ bPayload :: ForeignPtr Word8
, bOffset :: {v:Nat | v <= fplen bPayload}
, bLength :: {v:Nat | bOffset + v <= fplen bPayload}
}
@-}
{-@ type ByteStringN N = {v:ByteString | bLength v = N} @-}
{-@ type ForeignN a N = {v:ForeignPtr a | fplen v = N} @-}
{-@ assume mallocForeignPtrBytes :: n:Nat -> IO (ForeignN a n) @-}
bs = do fp <- mallocForeignPtrBytes 5
return $ PS fp 2 3
create l f = do
fp <- mallocForeignPtrBytes l
withForeignPtr fp $ \p -> f p
return $! PS fp 0 l
foo = create 5 $ \p -> poke (p `plusPtr` 4) (0 :: Word8)
pack str = unsafeCreate (length str) $ \p -> go p str
where
go _ [] = return ()
go p (x:xs) = poke p x >> go (p `plusPtr` 1) xs
unsafeIndex (PS x s l) i = liquidAssert (i >= 0 && i < l) $
unsafePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+i)
good = let b = pack [1,2,3]
in unsafeIndex b 2
-----------------------------------------------------------------------
-- Helper Code
-----------------------------------------------------------------------
{-@ unsafeCreate :: l:Nat -> (PtrN Word8 l -> IO ()) -> (ByteStringN l) @-}
unsafeCreate n f = unsafePerformIO $ create n f
{-@ invariant {v:ByteString | bLength v >= 0} @-}
{-@ qualif PLLen(v:a, p:b) : (len v) <= (plen p) @-}
{-@ qualif ForeignPtrN(v:ForeignPtr a, n:int): fplen v = n @-}
{-@ qualif FPLenPLen(v:Ptr a, fp:ForeignPtr a): fplen fp = plen v @-}
{-@ qualif PtrLen(v:Ptr a, xs:List b): plen v = len xs @-}
{-@ qualif PlenEq(v: Ptr a, x: int): x <= (plen v) @-}
-- Local Variables:
-- flycheck-checker: haskell-liquid
-- End:
create :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString
unsafeIndex :: ByteString -> Int -> Word8
{-@ LIQUID "--no-termination" @-}
{-@ LIQUID "--diffcheck" @-}
{-@ LIQUID "--short-names" @-}