mirror of
https://github.com/haskell-effectful/effectful.git
synced 2024-11-26 15:25:46 +03:00
Make envRefs store Refs instead of juggling Ints
This commit is contained in:
parent
703e637807
commit
c2d373b767
6
.github/workflows/haskell-ci.yml
vendored
6
.github/workflows/haskell-ci.yml
vendored
@ -248,11 +248,11 @@ jobs:
|
|||||||
- name: doctest
|
- name: doctest
|
||||||
run: |
|
run: |
|
||||||
cd ${PKGDIR_effectful_core} || false
|
cd ${PKGDIR_effectful_core} || false
|
||||||
doctest -XHaskell2010 -XBangPatterns -XConstraintKinds -XDataKinds -XDeriveFunctor -XDeriveGeneric -XFlexibleContexts -XFlexibleInstances -XGADTs -XGeneralizedNewtypeDeriving -XImportQualifiedPost -XLambdaCase -XMultiParamTypeClasses -XNoStarIsType -XPolyKinds -XRankNTypes -XRoleAnnotations -XScopedTypeVariables -XStandaloneDeriving -XTupleSections -XTypeApplications -XTypeFamilies -XTypeOperators src
|
doctest -XHaskell2010 -XBangPatterns -XConstraintKinds -XDataKinds -XDeriveFunctor -XDeriveGeneric -XDerivingStrategies -XFlexibleContexts -XFlexibleInstances -XGADTs -XGeneralizedNewtypeDeriving -XImportQualifiedPost -XLambdaCase -XMultiParamTypeClasses -XNoStarIsType -XPolyKinds -XRankNTypes -XRoleAnnotations -XScopedTypeVariables -XStandaloneDeriving -XTupleSections -XTypeApplications -XTypeFamilies -XTypeOperators src
|
||||||
cd ${PKGDIR_effectful_th} || false
|
cd ${PKGDIR_effectful_th} || false
|
||||||
doctest -XHaskell2010 -XBangPatterns -XConstraintKinds -XDataKinds -XDeriveFunctor -XDeriveGeneric -XFlexibleContexts -XFlexibleInstances -XGADTs -XGeneralizedNewtypeDeriving -XImportQualifiedPost -XLambdaCase -XMultiParamTypeClasses -XNoStarIsType -XPolyKinds -XRankNTypes -XRecordWildCards -XRoleAnnotations -XScopedTypeVariables -XStandaloneDeriving -XTupleSections -XTypeApplications -XTypeFamilies -XTypeOperators src
|
doctest -XHaskell2010 -XBangPatterns -XConstraintKinds -XDataKinds -XDeriveFunctor -XDeriveGeneric -XDerivingStrategies -XFlexibleContexts -XFlexibleInstances -XGADTs -XGeneralizedNewtypeDeriving -XImportQualifiedPost -XLambdaCase -XMultiParamTypeClasses -XNoStarIsType -XPolyKinds -XRankNTypes -XRecordWildCards -XRoleAnnotations -XScopedTypeVariables -XStandaloneDeriving -XTupleSections -XTypeApplications -XTypeFamilies -XTypeOperators src
|
||||||
cd ${PKGDIR_effectful} || false
|
cd ${PKGDIR_effectful} || false
|
||||||
doctest -XHaskell2010 -XBangPatterns -XConstraintKinds -XDataKinds -XDeriveFunctor -XDeriveGeneric -XFlexibleContexts -XFlexibleInstances -XGADTs -XGeneralizedNewtypeDeriving -XImportQualifiedPost -XLambdaCase -XMultiParamTypeClasses -XNoStarIsType -XPolyKinds -XRankNTypes -XRecordWildCards -XRoleAnnotations -XScopedTypeVariables -XStandaloneDeriving -XTupleSections -XTypeApplications -XTypeFamilies -XTypeOperators src
|
doctest -XHaskell2010 -XBangPatterns -XConstraintKinds -XDataKinds -XDeriveFunctor -XDeriveGeneric -XDerivingStrategies -XFlexibleContexts -XFlexibleInstances -XGADTs -XGeneralizedNewtypeDeriving -XImportQualifiedPost -XLambdaCase -XMultiParamTypeClasses -XNoStarIsType -XPolyKinds -XRankNTypes -XRecordWildCards -XRoleAnnotations -XScopedTypeVariables -XStandaloneDeriving -XTupleSections -XTypeApplications -XTypeFamilies -XTypeOperators src
|
||||||
- name: cabal check
|
- name: cabal check
|
||||||
run: |
|
run: |
|
||||||
cd ${PKGDIR_effectful_core} || false
|
cd ${PKGDIR_effectful_core} || false
|
||||||
|
@ -19,6 +19,7 @@ run_doctest() {
|
|||||||
-XDataKinds \
|
-XDataKinds \
|
||||||
-XDeriveFunctor \
|
-XDeriveFunctor \
|
||||||
-XDeriveGeneric \
|
-XDeriveGeneric \
|
||||||
|
-XDerivingStrategies \
|
||||||
-XFlexibleContexts \
|
-XFlexibleContexts \
|
||||||
-XFlexibleInstances \
|
-XFlexibleInstances \
|
||||||
-XGADTs \
|
-XGADTs \
|
||||||
|
@ -39,6 +39,7 @@ common language
|
|||||||
DataKinds
|
DataKinds
|
||||||
DeriveFunctor
|
DeriveFunctor
|
||||||
DeriveGeneric
|
DeriveGeneric
|
||||||
|
DerivingStrategies
|
||||||
FlexibleContexts
|
FlexibleContexts
|
||||||
FlexibleInstances
|
FlexibleInstances
|
||||||
GADTs
|
GADTs
|
||||||
|
@ -1096,16 +1096,14 @@ copyRefs src@(Env soffset srefs _) dest@(Env doffset drefs storage) = do
|
|||||||
requireMatchingStorages src dest
|
requireMatchingStorages src dest
|
||||||
let size = sizeofPrimArray drefs - doffset
|
let size = sizeofPrimArray drefs - doffset
|
||||||
es = reifyIndices @es @srcEs
|
es = reifyIndices @es @srcEs
|
||||||
esSize = 2 * length es
|
esSize = length es
|
||||||
mrefs <- newPrimArray (esSize + size)
|
mrefs <- newPrimArray (esSize + size)
|
||||||
copyPrimArray mrefs esSize drefs doffset size
|
copyPrimArray mrefs esSize drefs doffset size
|
||||||
let writeRefs i = \case
|
let writeRefs i = \case
|
||||||
[] -> pure ()
|
[] -> pure ()
|
||||||
(x : xs) -> do
|
(x : xs) -> do
|
||||||
let ix = soffset + 2 * x
|
writePrimArray mrefs i $ indexPrimArray srefs (soffset + x)
|
||||||
writePrimArray mrefs i $ indexPrimArray srefs ix
|
writeRefs (i + 1) xs
|
||||||
writePrimArray mrefs (i + 1) $ indexPrimArray srefs (ix + 1)
|
|
||||||
writeRefs (i + 2) xs
|
|
||||||
writeRefs 0 es
|
writeRefs 0 es
|
||||||
refs <- unsafeFreezePrimArray mrefs
|
refs <- unsafeFreezePrimArray mrefs
|
||||||
pure $ Env 0 refs storage
|
pure $ Env 0 refs storage
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE MagicHash #-}
|
||||||
|
{-# LANGUAGE UnboxedTuples #-}
|
||||||
{-# OPTIONS_HADDOCK not-home #-}
|
{-# OPTIONS_HADDOCK not-home #-}
|
||||||
module Effectful.Internal.Env
|
module Effectful.Internal.Env
|
||||||
( -- * The environment
|
( -- * The environment
|
||||||
Env(..)
|
Env(..)
|
||||||
|
, Ref(..)
|
||||||
|
, Version
|
||||||
, Storage(..)
|
, Storage(..)
|
||||||
, AnyEffect
|
, AnyEffect
|
||||||
, toAnyEffect
|
, toAnyEffect
|
||||||
@ -49,6 +53,8 @@ import Control.Monad.Primitive
|
|||||||
import Data.IORef.Strict
|
import Data.IORef.Strict
|
||||||
import Data.Primitive.PrimArray
|
import Data.Primitive.PrimArray
|
||||||
import Data.Primitive.SmallArray
|
import Data.Primitive.SmallArray
|
||||||
|
import Data.Primitive.Types
|
||||||
|
import GHC.Exts ((*#), (+#))
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
|
|
||||||
import Effectful.Internal.Effect
|
import Effectful.Internal.Effect
|
||||||
@ -81,15 +87,50 @@ type role Env nominal
|
|||||||
--
|
--
|
||||||
data Env (es :: [Effect]) = Env
|
data Env (es :: [Effect]) = Env
|
||||||
{ envOffset :: !Int
|
{ envOffset :: !Int
|
||||||
, envRefs :: !(PrimArray Int)
|
, envRefs :: !(PrimArray Ref)
|
||||||
, envStorage :: !(IORef' Storage)
|
, envStorage :: !(IORef' Storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Reference to the effect in 'Storage'.
|
||||||
|
data Ref = Ref !Int !Version
|
||||||
|
|
||||||
|
instance Prim Ref where
|
||||||
|
sizeOf# _ = 2# *# sizeOf# (undefined :: Int)
|
||||||
|
alignment# _ = alignment# (undefined :: Int)
|
||||||
|
indexByteArray# arr# i# =
|
||||||
|
let ref = indexByteArray# arr# (2# *# i#)
|
||||||
|
version = indexByteArray# arr# (2# *# i# +# 1#)
|
||||||
|
in Ref ref version
|
||||||
|
readByteArray# arr# i# =
|
||||||
|
\s0 -> case readByteArray# arr# (2# *# i#) s0 of
|
||||||
|
(# s1#, ref #) -> case readByteArray# arr# (2# *# i# +# 1#) s1# of
|
||||||
|
(# s2#, version #) -> (# s2#, Ref ref version #)
|
||||||
|
writeByteArray# arr# i# (Ref ref version) =
|
||||||
|
\s0 -> case writeByteArray# arr# (2# *# i#) ref s0 of
|
||||||
|
s1 -> case writeByteArray# arr# (2# *# i# +# 1#) version s1 of
|
||||||
|
s2 -> s2
|
||||||
|
indexOffAddr# addr# i# =
|
||||||
|
let ref = indexOffAddr# addr# (2# *# i#)
|
||||||
|
version = indexOffAddr# addr# (2# *# i# +# 1#)
|
||||||
|
in Ref ref version
|
||||||
|
readOffAddr# addr# i# =
|
||||||
|
\s0 -> case readOffAddr# addr# (2# *# i#) s0 of
|
||||||
|
(# s1, ref #) -> case readOffAddr# addr# (2# *# i# +# 1#) s1 of
|
||||||
|
(# s2, version #) -> (# s2, Ref ref version #)
|
||||||
|
writeOffAddr# addr# i# (Ref ref version) =
|
||||||
|
\s0 -> case writeOffAddr# addr# (2# *# i#) ref s0 of
|
||||||
|
s1 -> case writeOffAddr# addr# (2# *# i# +# 1#) version s1 of
|
||||||
|
s2 -> s2
|
||||||
|
|
||||||
|
-- | Version of the effect.
|
||||||
|
newtype Version = Version Int
|
||||||
|
deriving newtype (Eq, Ord, Prim, Show)
|
||||||
|
|
||||||
-- | A storage of effects.
|
-- | A storage of effects.
|
||||||
data Storage = Storage
|
data Storage = Storage
|
||||||
{ stSize :: !Int
|
{ stSize :: !Int
|
||||||
, stVersion :: !Int
|
, stVersion :: !Version
|
||||||
, stVersions :: !(MutablePrimArray RealWorld Int)
|
, stVersions :: !(MutablePrimArray RealWorld Version)
|
||||||
, stEffects :: !(SmallMutableArray RealWorld AnyEffect)
|
, stEffects :: !(SmallMutableArray RealWorld AnyEffect)
|
||||||
, stRelinkers :: !(SmallMutableArray RealWorld AnyRelinker)
|
, stRelinkers :: !(SmallMutableArray RealWorld AnyRelinker)
|
||||||
}
|
}
|
||||||
@ -209,12 +250,12 @@ restoreEnv dest src = do
|
|||||||
-- | Get the current size of the environment.
|
-- | Get the current size of the environment.
|
||||||
sizeEnv :: Env es -> IO Int
|
sizeEnv :: Env es -> IO Int
|
||||||
sizeEnv (Env offset refs _) = do
|
sizeEnv (Env offset refs _) = do
|
||||||
pure $ (sizeofPrimArray refs - offset) `div` 2
|
pure $ sizeofPrimArray refs - offset
|
||||||
|
|
||||||
-- | Access the tail of the environment.
|
-- | Access the tail of the environment.
|
||||||
tailEnv :: Env (e : es) -> IO (Env es)
|
tailEnv :: Env (e : es) -> IO (Env es)
|
||||||
tailEnv (Env offset refs storage) = do
|
tailEnv (Env offset refs storage) = do
|
||||||
pure $ Env (offset + 2) refs storage
|
pure $ Env (offset + 1) refs storage
|
||||||
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
-- Extending and shrinking
|
-- Extending and shrinking
|
||||||
@ -229,11 +270,10 @@ consEnv
|
|||||||
-> IO (Env (e : es))
|
-> IO (Env (e : es))
|
||||||
consEnv e f (Env offset refs0 storage) = do
|
consEnv e f (Env offset refs0 storage) = do
|
||||||
let size = sizeofPrimArray refs0 - offset
|
let size = sizeofPrimArray refs0 - offset
|
||||||
mrefs <- newPrimArray (size + 2)
|
mrefs <- newPrimArray (size + 1)
|
||||||
copyPrimArray mrefs 2 refs0 offset size
|
copyPrimArray mrefs 1 refs0 offset size
|
||||||
(ref, version) <- insertEffect storage e f
|
ref <- insertEffect storage e f
|
||||||
writePrimArray mrefs 0 ref
|
writePrimArray mrefs 0 ref
|
||||||
writePrimArray mrefs 1 version
|
|
||||||
refs <- unsafeFreezePrimArray mrefs
|
refs <- unsafeFreezePrimArray mrefs
|
||||||
pure $ Env 0 refs storage
|
pure $ Env 0 refs storage
|
||||||
{-# NOINLINE consEnv #-}
|
{-# NOINLINE consEnv #-}
|
||||||
@ -264,10 +304,8 @@ replaceEnv e f (Env offset refs0 storage) = do
|
|||||||
let size = sizeofPrimArray refs0 - offset
|
let size = sizeofPrimArray refs0 - offset
|
||||||
mrefs <- newPrimArray size
|
mrefs <- newPrimArray size
|
||||||
copyPrimArray mrefs 0 refs0 offset size
|
copyPrimArray mrefs 0 refs0 offset size
|
||||||
(ref, version) <- insertEffect storage e f
|
ref <- insertEffect storage e f
|
||||||
let i = 2 * reifyIndex @e @es
|
writePrimArray mrefs (reifyIndex @e @es) ref
|
||||||
writePrimArray mrefs i ref
|
|
||||||
writePrimArray mrefs (i + 1) version
|
|
||||||
refs <- unsafeFreezePrimArray mrefs
|
refs <- unsafeFreezePrimArray mrefs
|
||||||
pure $ Env 0 refs storage
|
pure $ Env 0 refs storage
|
||||||
{-# NOINLINE replaceEnv #-}
|
{-# NOINLINE replaceEnv #-}
|
||||||
@ -278,7 +316,7 @@ replaceEnv e f (Env offset refs0 storage) = do
|
|||||||
-- usable.
|
-- usable.
|
||||||
unreplaceEnv :: forall e es. (HasCallStack, e :> es) => Env es -> IO ()
|
unreplaceEnv :: forall e es. (HasCallStack, e :> es) => Env es -> IO ()
|
||||||
unreplaceEnv (Env offset refs storage) = do
|
unreplaceEnv (Env offset refs storage) = do
|
||||||
deleteEffect storage $ indexPrimArray refs (offset + 2 * reifyIndex @e @es)
|
deleteEffect storage $ indexPrimArray refs (offset + reifyIndex @e @es)
|
||||||
{-# NOINLINE unreplaceEnv #-}
|
{-# NOINLINE unreplaceEnv #-}
|
||||||
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
@ -287,11 +325,9 @@ unreplaceEnv (Env offset refs storage) = do
|
|||||||
subsumeEnv :: forall e es. e :> es => Env es -> IO (Env (e : es))
|
subsumeEnv :: forall e es. e :> es => Env es -> IO (Env (e : es))
|
||||||
subsumeEnv (Env offset refs0 storage) = do
|
subsumeEnv (Env offset refs0 storage) = do
|
||||||
let size = sizeofPrimArray refs0 - offset
|
let size = sizeofPrimArray refs0 - offset
|
||||||
mrefs <- newPrimArray (size + 2)
|
mrefs <- newPrimArray (size + 1)
|
||||||
copyPrimArray mrefs 2 refs0 offset size
|
copyPrimArray mrefs 1 refs0 offset size
|
||||||
let ix = offset + 2 * reifyIndex @e @es
|
writePrimArray mrefs 0 $ indexPrimArray refs0 (offset + reifyIndex @e @es)
|
||||||
writePrimArray mrefs 0 $ indexPrimArray refs0 ix
|
|
||||||
writePrimArray mrefs 1 $ indexPrimArray refs0 (ix + 1)
|
|
||||||
refs <- unsafeFreezePrimArray mrefs
|
refs <- unsafeFreezePrimArray mrefs
|
||||||
pure $ Env 0 refs storage
|
pure $ Env 0 refs storage
|
||||||
{-# NOINLINE subsumeEnv #-}
|
{-# NOINLINE subsumeEnv #-}
|
||||||
@ -303,8 +339,8 @@ subsumeEnv (Env offset refs0 storage) = do
|
|||||||
injectEnv :: forall xs es. Subset xs es => Env es -> IO (Env xs)
|
injectEnv :: forall xs es. Subset xs es => Env es -> IO (Env xs)
|
||||||
injectEnv (Env offset refs0 storage) = do
|
injectEnv (Env offset refs0 storage) = do
|
||||||
let xs = reifyIndices @xs @es
|
let xs = reifyIndices @xs @es
|
||||||
permSize = 2 * length xs
|
permSize = length xs
|
||||||
prefixSize = 2 * prefixLength @es
|
prefixSize = prefixLength @es
|
||||||
suffixSize = if subsetFullyKnown @xs @es
|
suffixSize = if subsetFullyKnown @xs @es
|
||||||
then 0
|
then 0
|
||||||
else sizeofPrimArray refs0 - offset - prefixSize
|
else sizeofPrimArray refs0 - offset - prefixSize
|
||||||
@ -313,10 +349,8 @@ injectEnv (Env offset refs0 storage) = do
|
|||||||
let writePermRefs i = \case
|
let writePermRefs i = \case
|
||||||
[] -> pure ()
|
[] -> pure ()
|
||||||
(e : es) -> do
|
(e : es) -> do
|
||||||
let ix = offset + 2 * e
|
writePrimArray mrefs i $ indexPrimArray refs0 (offset + e)
|
||||||
writePrimArray mrefs i $ indexPrimArray refs0 ix
|
writePermRefs (i + 1) es
|
||||||
writePrimArray mrefs (i + 1) $ indexPrimArray refs0 (ix + 1)
|
|
||||||
writePermRefs (i + 2) es
|
|
||||||
writePermRefs 0 xs
|
writePermRefs 0 xs
|
||||||
refs <- unsafeFreezePrimArray mrefs
|
refs <- unsafeFreezePrimArray mrefs
|
||||||
pure $ Env 0 refs storage
|
pure $ Env 0 refs storage
|
||||||
@ -373,9 +407,6 @@ getLocation
|
|||||||
=> Env es
|
=> Env es
|
||||||
-> IO (Int, SmallMutableArray RealWorld AnyEffect)
|
-> IO (Int, SmallMutableArray RealWorld AnyEffect)
|
||||||
getLocation (Env offset refs storage) = do
|
getLocation (Env offset refs storage) = do
|
||||||
let i = offset + 2 * reifyIndex @e @es
|
|
||||||
ref = indexPrimArray refs i
|
|
||||||
version = indexPrimArray refs (i + 1)
|
|
||||||
Storage _ _ vs es _ <- readIORef' storage
|
Storage _ _ vs es _ <- readIORef' storage
|
||||||
storageVersion <- readPrimArray vs ref
|
storageVersion <- readPrimArray vs ref
|
||||||
-- If version of the reference is different than version in the storage, it
|
-- If version of the reference is different than version in the storage, it
|
||||||
@ -388,13 +419,15 @@ getLocation (Env offset refs storage) = do
|
|||||||
++ "of the scope of effects it captures, have a look at "
|
++ "of the scope of effects it captures, have a look at "
|
||||||
++ "UnliftingStrategy (SeqForkUnlift)."
|
++ "UnliftingStrategy (SeqForkUnlift)."
|
||||||
pure (ref, es)
|
pure (ref, es)
|
||||||
|
where
|
||||||
|
Ref ref version = indexPrimArray refs (offset + reifyIndex @e @es)
|
||||||
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
-- Internal helpers
|
-- Internal helpers
|
||||||
|
|
||||||
-- | Create an empty storage.
|
-- | Create an empty storage.
|
||||||
emptyStorage :: HasCallStack => IO Storage
|
emptyStorage :: HasCallStack => IO Storage
|
||||||
emptyStorage = Storage 0 (noVersion + 1)
|
emptyStorage = Storage 0 initialVersion
|
||||||
<$> newPrimArray 0
|
<$> newPrimArray 0
|
||||||
<*> newSmallArray 0 undefinedEffect
|
<*> newSmallArray 0 undefinedEffect
|
||||||
<*> newSmallArray 0 undefinedRelinker
|
<*> newSmallArray 0 undefinedRelinker
|
||||||
@ -406,7 +439,7 @@ insertEffect
|
|||||||
-> EffectRep (DispatchOf e) e
|
-> EffectRep (DispatchOf e) e
|
||||||
-- ^ The representation of the effect.
|
-- ^ The representation of the effect.
|
||||||
-> Relinker (EffectRep (DispatchOf e)) e
|
-> Relinker (EffectRep (DispatchOf e)) e
|
||||||
-> IO (Int, Int)
|
-> IO Ref
|
||||||
insertEffect storage e f = do
|
insertEffect storage e f = do
|
||||||
Storage size version vs0 es0 fs0 <- readIORef' storage
|
Storage size version vs0 es0 fs0 <- readIORef' storage
|
||||||
len0 <- getSizeofSmallMutableArray es0
|
len0 <- getSizeofSmallMutableArray es0
|
||||||
@ -416,8 +449,8 @@ insertEffect storage e f = do
|
|||||||
writePrimArray vs0 size version
|
writePrimArray vs0 size version
|
||||||
writeSmallArray' es0 size (toAnyEffect e)
|
writeSmallArray' es0 size (toAnyEffect e)
|
||||||
writeSmallArray' fs0 size (toAnyRelinker f)
|
writeSmallArray' fs0 size (toAnyRelinker f)
|
||||||
writeIORef' storage $ Storage (size + 1) (version + 1) vs0 es0 fs0
|
writeIORef' storage $ Storage (size + 1) (bumpVersion version) vs0 es0 fs0
|
||||||
pure (size, version)
|
pure $ Ref size version
|
||||||
EQ -> do
|
EQ -> do
|
||||||
let len = doubleCapacity len0
|
let len = doubleCapacity len0
|
||||||
vs <- newPrimArray len
|
vs <- newPrimArray len
|
||||||
@ -429,20 +462,24 @@ insertEffect storage e f = do
|
|||||||
writePrimArray vs size version
|
writePrimArray vs size version
|
||||||
writeSmallArray' es size (toAnyEffect e)
|
writeSmallArray' es size (toAnyEffect e)
|
||||||
writeSmallArray' fs size (toAnyRelinker f)
|
writeSmallArray' fs size (toAnyRelinker f)
|
||||||
writeIORef' storage $ Storage (size + 1) (version + 1) vs es fs
|
writeIORef' storage $ Storage (size + 1) (bumpVersion version) vs es fs
|
||||||
pure (size, version)
|
pure $ Ref size version
|
||||||
|
|
||||||
-- | Given a reference to an effect from the top of the stack, delete it from
|
-- | Given a reference to an effect from the top of the stack, delete it from
|
||||||
-- the storage.
|
-- the storage.
|
||||||
deleteEffect :: HasCallStack => IORef' Storage -> Int -> IO ()
|
deleteEffect :: HasCallStack => IORef' Storage -> Ref -> IO ()
|
||||||
deleteEffect storage ref = do
|
deleteEffect storage (Ref ref version) = do
|
||||||
Storage size version vs es fs <- readIORef' storage
|
Storage size currentVersion vs es fs <- readIORef' storage
|
||||||
when (ref /= size - 1) $ do
|
when (ref /= size - 1) $ do
|
||||||
error $ "ref (" ++ show ref ++ ") /= size - 1 (" ++ show (size - 1) ++ ")"
|
error $ "ref (" ++ show ref ++ ") /= size - 1 (" ++ show (size - 1) ++ ")"
|
||||||
writePrimArray vs ref noVersion
|
storageVersion <- readPrimArray vs ref
|
||||||
|
when (version /= storageVersion) $ do
|
||||||
|
error $ "version (" ++ show version ++ ") /= storageVersion ("
|
||||||
|
++ show storageVersion ++ ")\n"
|
||||||
|
writePrimArray vs ref undefinedVersion
|
||||||
writeSmallArray es ref undefinedEffect
|
writeSmallArray es ref undefinedEffect
|
||||||
writeSmallArray fs ref undefinedRelinker
|
writeSmallArray fs ref undefinedRelinker
|
||||||
writeIORef' storage $ Storage (size - 1) version vs es fs
|
writeIORef' storage $ Storage (size - 1) currentVersion vs es fs
|
||||||
|
|
||||||
-- | Relink the environment to use the new storage.
|
-- | Relink the environment to use the new storage.
|
||||||
relinkEnv :: IORef' Storage -> Env es -> IO (Env es)
|
relinkEnv :: IORef' Storage -> Env es -> IO (Env es)
|
||||||
@ -452,8 +489,14 @@ relinkEnv storage (Env offset refs _) = pure $ Env offset refs storage
|
|||||||
doubleCapacity :: Int -> Int
|
doubleCapacity :: Int -> Int
|
||||||
doubleCapacity n = max 1 n * 2
|
doubleCapacity n = max 1 n * 2
|
||||||
|
|
||||||
noVersion :: Int
|
undefinedVersion :: Version
|
||||||
noVersion = 0
|
undefinedVersion = Version 0
|
||||||
|
|
||||||
|
initialVersion :: Version
|
||||||
|
initialVersion = Version 1
|
||||||
|
|
||||||
|
bumpVersion :: Version -> Version
|
||||||
|
bumpVersion (Version n) = Version (n + 1)
|
||||||
|
|
||||||
undefinedEffect :: HasCallStack => AnyEffect
|
undefinedEffect :: HasCallStack => AnyEffect
|
||||||
undefinedEffect = toAnyEffect . errorWithoutStackTrace $ unlines
|
undefinedEffect = toAnyEffect . errorWithoutStackTrace $ unlines
|
||||||
|
@ -204,8 +204,8 @@ copyRef (Env hoffset hrefs hstorage) (Env offset refs0 storage) = do
|
|||||||
when (hstorage /= storage) $ do
|
when (hstorage /= storage) $ do
|
||||||
error "storages do not match"
|
error "storages do not match"
|
||||||
let size = sizeofPrimArray refs0 - offset
|
let size = sizeofPrimArray refs0 - offset
|
||||||
mrefs <- newPrimArray (size + 2)
|
mrefs <- newPrimArray (size + 1)
|
||||||
copyPrimArray mrefs 0 hrefs hoffset 2
|
copyPrimArray mrefs 0 hrefs hoffset 1
|
||||||
copyPrimArray mrefs 2 refs0 offset size
|
copyPrimArray mrefs 1 refs0 offset size
|
||||||
refs <- unsafeFreezePrimArray mrefs
|
refs <- unsafeFreezePrimArray mrefs
|
||||||
pure $ Env 0 refs storage
|
pure $ Env 0 refs storage
|
||||||
|
@ -148,7 +148,7 @@ copyRefs (Env hoffset hrefs hstorage) (Env offset refs0 storage) = do
|
|||||||
when (hstorage /= storage) $ do
|
when (hstorage /= storage) $ do
|
||||||
error "storages do not match"
|
error "storages do not match"
|
||||||
let size = sizeofPrimArray refs0 - offset
|
let size = sizeofPrimArray refs0 - offset
|
||||||
listSize = 2 * knownEffectsLength @list
|
listSize = knownEffectsLength @list
|
||||||
mrefs <- newPrimArray (size + listSize)
|
mrefs <- newPrimArray (size + listSize)
|
||||||
copyPrimArray mrefs 0 hrefs hoffset listSize
|
copyPrimArray mrefs 0 hrefs hoffset listSize
|
||||||
copyPrimArray mrefs listSize refs0 offset size
|
copyPrimArray mrefs listSize refs0 offset size
|
||||||
|
@ -35,6 +35,7 @@ common language
|
|||||||
DataKinds
|
DataKinds
|
||||||
DeriveFunctor
|
DeriveFunctor
|
||||||
DeriveGeneric
|
DeriveGeneric
|
||||||
|
DerivingStrategies
|
||||||
FlexibleContexts
|
FlexibleContexts
|
||||||
FlexibleInstances
|
FlexibleInstances
|
||||||
GADTs
|
GADTs
|
||||||
|
@ -35,6 +35,7 @@ common language
|
|||||||
DataKinds
|
DataKinds
|
||||||
DeriveFunctor
|
DeriveFunctor
|
||||||
DeriveGeneric
|
DeriveGeneric
|
||||||
|
DerivingStrategies
|
||||||
FlexibleContexts
|
FlexibleContexts
|
||||||
FlexibleInstances
|
FlexibleInstances
|
||||||
GADTs
|
GADTs
|
||||||
|
@ -44,6 +44,7 @@ common language
|
|||||||
DataKinds
|
DataKinds
|
||||||
DeriveFunctor
|
DeriveFunctor
|
||||||
DeriveGeneric
|
DeriveGeneric
|
||||||
|
DerivingStrategies
|
||||||
FlexibleContexts
|
FlexibleContexts
|
||||||
FlexibleInstances
|
FlexibleInstances
|
||||||
GADTs
|
GADTs
|
||||||
|
Loading…
Reference in New Issue
Block a user