content: ----------------------------------------------------------------------------
  -- |
  -- Module      :  Data.Emacs.Module.Value.Internal
  -- Copyright   :  (c) Sergey Vinokurov 2018
  -- License     :  Apache-2.0 (see LICENSE)
  -- Maintainer  :  serg.foo@gmail.com
  ----------------------------------------------------------------------------
  
  {-# LANGUAGE CPP                  #-}
  {-# LANGUAGE DataKinds            #-}
  {-# LANGUAGE DerivingVia          #-}
  {-# LANGUAGE TypeFamilies         #-}
  {-# LANGUAGE UndecidableInstances #-}
  
  {-# LANGUAGE UnboxedTuples #-}
  
  module Data.Emacs.Module.Value.Internal
    ( Value(..)
    ) where
  
  import Control.DeepSeq
  import Data.Primitive.Types
  import Data.Vector.Generic qualified as G
  import Data.Vector.Generic.Mutable qualified as GM
  import Data.Vector.Primitive qualified as P
  import Data.Vector.Unboxed qualified as U
  #if !MIN_VERSION_vector(0, 13, 1)
  import Data.Vector.Unboxed.Base qualified as U
  #endif
  import GHC.Generics (Generic)
  import Prettyprinter (Pretty)
  
  import Data.Emacs.Module.Raw.Value
  
  -- | Value that is independent of environment ('Env') that produced it.
  -- Incidentally, this implies that it's "protected" against Emacs GC and
  -- thus will not unexpectedly go out of scope.
  --
  -- In order to prevent memory leaks, value is registered in the Emacs
  -- monad than produced it and will be freed when the monad finishes.
  -- To make the connection clear the value is tagged with parameter
  -- @s@, which serves the same purpose as tag of the 'ST' monad. That
  -- is, it ensures that value cannot leave the scope of the monad that
  -- produced it.
  newtype Value (s :: k) = Value
    { unValue :: RawValue 'Regular
    } deriving (Show, NFData, Generic, Prim, Pretty)
  
  newtype instance U.MVector s (Value s') = MV_Value (P.MVector s (Value s'))
  newtype instance U.Vector    (Value s') = V_Value  (P.Vector    (Value s'))
  
  deriving via (U.UnboxViaPrim (Value s')) instance GM.MVector U.MVector (Value s')
  deriving via (U.UnboxViaPrim (Value s')) instance G.Vector   U.Vector  (Value s')
  
  instance U.Unbox (Value s')
  
  