packages feed

vinyl-0.14.3: Data/Vinyl/ARec/Internal/SmallArray.hs

{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE BangPatterns #-}

-- | Helper functions for SmallArray#
--
-- This module exposes _unsafe_ functions to work with SmallArrays.  That means
-- that specifically neither index bounds nor element types are checked So this
-- functionality should only be used in a context that enforces them by some
-- other means, e.g. ARec's type index

module Data.Vinyl.ARec.Internal.SmallArray where

import GHC.Prim
import GHC.Types
import Unsafe.Coerce
import GHC.ST

data SmallArray = SmallArray !(SmallArray# Any)
data SmallMutableArray s = SmallMutableArray !(SmallMutableArray# s Any)

indexSmallArray :: SmallArray -> Int -> a
indexSmallArray (SmallArray arr) (I# ix) =
  case indexSmallArray# arr ix of
    (# v #) -> unsafeCoerce v
{-# INLINE indexSmallArray #-}

withNewSmallArray :: Int -> (SmallMutableArray s -> ST s ()) -> ST s SmallArray
withNewSmallArray (I# len#) f =
  ST $ \s0 ->  case newSmallArray# len# (error "withNewSmallArray exploded") s0 of
       (# s1, mArr #) ->
         case f (SmallMutableArray mArr) of
           ST st -> case st s1 of
             (# s2, () #) -> case unsafeFreezeSmallArray# mArr s2 of
               (# s3, ar #) -> (# s3, SmallArray ar #)
{-# INLINE withNewSmallArray #-}

writeSmallArray :: SmallMutableArray s -> Int -> a -> ST s ()
writeSmallArray (SmallMutableArray mArr) (I# n#) x = ST $ \s ->
  case writeSmallArray# mArr n# (unsafeCoerce x) s of
    s' -> (# s', () #)
{-# INLINE writeSmallArray #-}

withThawedSmallArray :: SmallArray
               -> (SmallMutableArray s -> ST s ())
               -> ST s SmallArray
withThawedSmallArray (SmallArray arr) f = ST $ \s0 ->
  let !(I# z#) = 0
  in case thawSmallArray# arr z# (sizeofSmallArray# arr) s0 of
       (# s1, mArr #) ->
         case f (SmallMutableArray mArr) of
           ST st -> case st s1 of
             (# s2, () #) -> case unsafeFreezeSmallArray# mArr s2 of
               (# s3, ar #) -> (# s3, SmallArray ar #)
{-# INLINE withThawedSmallArray #-}