{-# LANGUAGE UnboxedTuples #-}
module Cleff.Internal.Data.Mem (Mem, MemPtr, empty, adjust, alloca, read, write, replace, append, update) where
import Cleff.Internal.Data.Any (Any, fromAny, toAny)
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as Map
import Data.Kind (Type)
import Data.Rec.SmallArray (Rec, pattern (:~:))
import qualified Data.Rec.SmallArray as Rec
import Prelude hiding (read)
type role MemPtr representational nominal
newtype MemPtr (f :: k -> Type) (a :: k) = MemPtr { MemPtr f a -> Int
unMemPtr :: Int }
deriving newtype
( Eq
, Ord
)
type role Mem representational nominal
data Mem (f :: k -> Type) (es :: [k]) = Mem
{-# UNPACK #-} !(Rec (MemPtr f) es)
{-# UNPACK #-} !Int
!(IntMap Any)
empty :: Mem f '[]
empty :: Mem f '[]
empty = Rec (MemPtr f) '[] -> Int -> IntMap Any -> Mem f '[]
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem Rec (MemPtr f) '[]
forall k (f :: k -> Type). Rec f '[]
Rec.empty Int
0 IntMap Any
forall a. IntMap a
Map.empty
{-# INLINE empty #-}
adjust :: ∀ es' es f. (Rec (MemPtr f) es -> Rec (MemPtr f) es') -> Mem f es -> Mem f es'
adjust :: (Rec (MemPtr f) es -> Rec (MemPtr f) es') -> Mem f es -> Mem f es'
adjust Rec (MemPtr f) es -> Rec (MemPtr f) es'
f (Mem Rec (MemPtr f) es
re Int
n IntMap Any
mem) = Rec (MemPtr f) es' -> Int -> IntMap Any -> Mem f es'
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem (Rec (MemPtr f) es -> Rec (MemPtr f) es'
f Rec (MemPtr f) es
re) Int
n IntMap Any
mem
{-# INLINE adjust #-}
alloca :: ∀ e es f. Mem f es -> (# MemPtr f e, Mem f es #)
alloca :: Mem f es -> (# MemPtr f e, Mem f es #)
alloca (Mem Rec (MemPtr f) es
re Int
n IntMap Any
mem) = (# Int -> MemPtr f e
forall k (f :: k -> Type) (a :: k). Int -> MemPtr f a
MemPtr Int
n, Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem Rec (MemPtr f) es
re (Int -> Int
forall a. Enum a => a -> a
succ Int
n) IntMap Any
mem #)
{-# INLINE alloca #-}
read :: ∀ e es f. Rec.Elem e es => Mem f es -> f e
read :: Mem f es -> f e
read (Mem Rec (MemPtr f) es
re Int
_ IntMap Any
mem) = Any -> f e
forall a. Any -> a
fromAny (Any -> f e) -> Any -> f e
forall a b. (a -> b) -> a -> b
$ IntMap Any
mem IntMap Any -> Int -> Any
forall a. IntMap a -> Int -> a
Map.! MemPtr f e -> Int
forall k (f :: k -> Type) (a :: k). MemPtr f a -> Int
unMemPtr (Rec (MemPtr f) es -> MemPtr f e
forall k (e :: k) (es :: [k]) (f :: k -> Type).
Elem e es =>
Rec f es -> f e
Rec.index @e Rec (MemPtr f) es
re)
{-# INLINE read #-}
write :: ∀ e es f. MemPtr f e -> f e -> Mem f es -> Mem f es
write :: MemPtr f e -> f e -> Mem f es -> Mem f es
write (MemPtr Int
m) f e
x (Mem Rec (MemPtr f) es
re Int
n IntMap Any
mem) = Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem Rec (MemPtr f) es
re Int
n (Int -> Any -> IntMap Any -> IntMap Any
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
m (f e -> Any
forall a. a -> Any
toAny f e
x) IntMap Any
mem)
{-# INLINE write #-}
replace :: ∀ e es f. Rec.Elem e es => MemPtr f e -> f e -> Mem f es -> Mem f es
replace :: MemPtr f e -> f e -> Mem f es -> Mem f es
replace (MemPtr Int
m) f e
x (Mem Rec (MemPtr f) es
re Int
n IntMap Any
mem) = Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem (MemPtr f e -> Rec (MemPtr f) es -> Rec (MemPtr f) es
forall k (e :: k) (es :: [k]) (f :: k -> Type).
Elem e es =>
f e -> Rec f es -> Rec f es
Rec.update @e (Int -> MemPtr f e
forall k (f :: k -> Type) (a :: k). Int -> MemPtr f a
MemPtr Int
m) Rec (MemPtr f) es
re) Int
n (Int -> Any -> IntMap Any -> IntMap Any
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
m (f e -> Any
forall a. a -> Any
toAny f e
x) IntMap Any
mem)
{-# INLINE replace #-}
append :: ∀ e es f. MemPtr f e -> f e -> Mem f es -> Mem f (e ': es)
append :: MemPtr f e -> f e -> Mem f es -> Mem f (e : es)
append (MemPtr Int
m) f e
x (Mem Rec (MemPtr f) es
re Int
n IntMap Any
mem) = Rec (MemPtr f) (e : es) -> Int -> IntMap Any -> Mem f (e : es)
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem (Int -> MemPtr f e
forall k (f :: k -> Type) (a :: k). Int -> MemPtr f a
MemPtr Int
m MemPtr f e -> Rec (MemPtr f) es -> Rec (MemPtr f) (e : es)
forall a (f :: a -> Type) (e :: a) (es :: [a]).
f e -> Rec f es -> Rec f (e : es)
:~: Rec (MemPtr f) es
re) Int
n (Int -> Any -> IntMap Any -> IntMap Any
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
m (f e -> Any
forall a. a -> Any
toAny f e
x) IntMap Any
mem)
{-# INLINE append #-}
update :: ∀ es es' f. Mem f es' -> Mem f es -> Mem f es
update :: Mem f es' -> Mem f es -> Mem f es
update (Mem Rec (MemPtr f) es'
_ Int
n IntMap Any
mem) (Mem Rec (MemPtr f) es
re' Int
_ IntMap Any
_) = Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
forall k (f :: k -> Type) (es :: [k]).
Rec (MemPtr f) es -> Int -> IntMap Any -> Mem f es
Mem Rec (MemPtr f) es
re' Int
n IntMap Any
mem
{-# INLINE update #-}