module Unison.Runtime.ANF.Serialize.ValueV5
  ( getValueWithHeader,
    putValueWithHeader,
    putVersionedValue,
    versionedValueBytes,
  )
where

import Control.Monad (replicateM)
import Data.Binary.Get qualified as BGet
import Data.ByteString.Builder (Builder)
import Data.ByteString.Builder qualified as BU
import Data.ByteString.Lazy qualified as L
import Data.Bytes.Get hiding (getBytes)
import Data.Serialize.Get qualified as SGet
import GHC.IsList qualified (fromList)
import Unison.Reference (Reference)
import Unison.Runtime.ANF as ANF hiding (Tag)
import Unison.Runtime.ANF.Serialize.CodeV4
import Unison.Runtime.ANF.Serialize.Tags
import Unison.Runtime.Referenced
import Unison.Runtime.Serialize hiding
  ( getConstructorReference,
    getReference,
    getReferent,
    putConstructorReference,
    putReference,
    putReferent,
  )
import Unison.Runtime.Serialize qualified as SER
import Unison.Util.Text qualified as Util.Text
import Prelude hiding (getChar, putChar)

putGroupRef :: GroupRef RefNum -> Builder
putGroupRef :: GroupRef RefNum -> Builder
putGroupRef (GR RefNum
r Word64
i) = RefNum -> Builder
putRefNum RefNum
r Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall a.
(Integral a, Integral (Unsigned a), Bits (Unsigned a)) =>
a -> Builder
putVarInt Word64
i
{-# INLINE putGroupRef #-}

getGroupRef :: (MonadGet m) => m (GroupRef RefNum)
getGroupRef :: forall (m :: * -> *). MonadGet m => m (GroupRef RefNum)
getGroupRef = RefNum -> Word64 -> GroupRef RefNum
forall ref. ref -> Word64 -> GroupRef ref
GR (RefNum -> Word64 -> GroupRef RefNum)
-> m RefNum -> m (Word64 -> GroupRef RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m RefNum
forall (m :: * -> *). MonadGet m => m RefNum
getRefNum m (Word64 -> GroupRef RefNum) -> m Word64 -> m (GroupRef RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m Word64
forall (m :: * -> *) b. (MonadGet m, Num b, Bits b) => m b
getVarInt

-- Notes
--
-- Starting with version 4 of the value format, it is expected that
-- unboxed data does not actually occur in the values being sent. For
-- most values this was not a problem:
--
--   - Partial applications had no way of directly including unboxed
--     values, because they all result from surface level unison
--     applications
--   - Unboxed values in Data only occurred to represent certain
--     builtin types. Those have been replaced by BLits.
--
-- However, some work was required to make sure no unboxed data ended
-- up in Cont. The runtime has been modified to avoid using the
-- unboxed stack in generated code, so now only builtins use it,
-- effectively. Since continuations are never captured inside builtins
-- (and even if we wanted to do that, we could arrange for a clean
-- unboxed stack), this is no longer a problem, either.
--
-- So, unboxed data is completely absent from the format. We are now
-- exchanging unison surface values, effectively.
--
-- -----------------
--
-- Version 5 departs significantly from previous versions to try to
-- optimize the format. The two major changes are:
--
--   1. Using variable width integers everywhere to avoid
--      unnecessarily padded values for tags and such
--   2. Pulling references out into a header section so that each is
--      only serialized once, and most reference occurrences are just
--      numbers.
--
-- this second change reduces the size of the format considerably, as
-- most of the serialized representation previously was repeated
-- occurrences of the 64 byte hashes.
--
-- At the moment, the reference change is implemented by using stable
-- names, and expecting canonically constructed values. This was done
-- to avoid a significant refactoring effort, but should be able to be
-- reworked in the future.
putValue :: Value RefNum -> Builder
putValue :: Value RefNum -> Builder
putValue = \case
  Partial GroupRef RefNum
gr ValList RefNum
vs ->
    VaTag -> Builder
forall t. Tag t => t -> Builder
putTag VaTag
PartialT
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> GroupRef RefNum -> Builder
putGroupRef GroupRef RefNum
gr
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Value RefNum -> Builder) -> ValList RefNum -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Value RefNum -> Builder
putValue ValList RefNum
vs
  Data RefNum
r Word64
t ValList RefNum
vs ->
    VaTag -> Builder
forall t. Tag t => t -> Builder
putTag VaTag
DataT
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> RefNum -> Builder
putRefNum RefNum
r
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall a.
(Integral a, Integral (Unsigned a), Bits (Unsigned a)) =>
a -> Builder
putVarInt Word64
t
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Value RefNum -> Builder) -> ValList RefNum -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Value RefNum -> Builder
putValue ValList RefNum
vs
  Cont ValList RefNum
bs Cont RefNum
k ->
    VaTag -> Builder
forall t. Tag t => t -> Builder
putTag VaTag
ContT
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Value RefNum -> Builder) -> ValList RefNum -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Value RefNum -> Builder
putValue ValList RefNum
bs
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Cont RefNum -> Builder
putCont Cont RefNum
k
  BLit BLit RefNum
l -> VaTag -> Builder
forall t. Tag t => t -> Builder
putTag VaTag
BLitT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> BLit RefNum -> Builder
putBLit BLit RefNum
l

getValue :: (MonadGet m) => m (Value RefNum)
getValue :: forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue =
  m VaTag
forall (m :: * -> *) t. (MonadGet m, Tag t) => m t
getTag m VaTag -> (VaTag -> m (Value RefNum)) -> m (Value RefNum)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    VaTag
PartialT -> do
      GroupRef RefNum
gr <- m (GroupRef RefNum)
forall (m :: * -> *). MonadGet m => m (GroupRef RefNum)
getGroupRef
      ValList RefNum
vs <- m (Value RefNum) -> m (ValList RefNum)
forall (m :: * -> *) a. MonadGet m => m a -> m [a]
getList m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
      pure $ GroupRef RefNum -> ValList RefNum -> Value RefNum
forall ref. GroupRef ref -> ValList ref -> Value ref
Partial GroupRef RefNum
gr ValList RefNum
vs
    VaTag
DataT -> do
      RefNum
r <- m RefNum
forall (m :: * -> *). MonadGet m => m RefNum
getRefNum
      Word64
w <- m Word64
forall (m :: * -> *) b. (MonadGet m, Num b, Bits b) => m b
getVarInt
      ValList RefNum
vs <- m (Value RefNum) -> m (ValList RefNum)
forall (m :: * -> *) a. MonadGet m => m a -> m [a]
getList m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
      pure $ RefNum -> Word64 -> ValList RefNum -> Value RefNum
forall ref. ref -> Word64 -> ValList ref -> Value ref
Data RefNum
r Word64
w ValList RefNum
vs
    VaTag
ContT -> do
      ValList RefNum
bs <- m (Value RefNum) -> m (ValList RefNum)
forall (m :: * -> *) a. MonadGet m => m a -> m [a]
getList m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
      Cont RefNum
k <- m (Cont RefNum)
forall (m :: * -> *). MonadGet m => m (Cont RefNum)
getCont
      pure $ ValList RefNum -> Cont RefNum -> Value RefNum
forall ref. ValList ref -> Cont ref -> Value ref
Cont ValList RefNum
bs Cont RefNum
k
    VaTag
BLitT -> BLit RefNum -> Value RefNum
forall ref. BLit ref -> Value ref
BLit (BLit RefNum -> Value RefNum)
-> m (BLit RefNum) -> m (Value RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (BLit RefNum)
forall (m :: * -> *). MonadGet m => m (BLit RefNum)
getBLit
{-# SPECIALIZE getValue :: BGet.Get (Value RefNum) #-}
{-# SPECIALIZE getValue :: SGet.Get (Value RefNum) #-}

putCont :: Cont RefNum -> Builder
putCont :: Cont RefNum -> Builder
putCont = \case
  Cont RefNum
KE -> CoTag -> Builder
forall t. Tag t => t -> Builder
putTag CoTag
KET
  Mark Word64
a [RefNum]
rs [(RefNum, Value RefNum)]
ds Cont RefNum
k ->
    CoTag -> Builder
forall t. Tag t => t -> Builder
putTag CoTag
MarkT
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall a.
(Integral a, Integral (Unsigned a), Bits (Unsigned a)) =>
a -> Builder
putVarInt Word64
a
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (RefNum -> Builder) -> [RefNum] -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable RefNum -> Builder
putRefNum [RefNum]
rs
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (RefNum -> Builder)
-> (Value RefNum -> Builder) -> [(RefNum, Value RefNum)] -> Builder
forall a b. (a -> Builder) -> (b -> Builder) -> [(a, b)] -> Builder
putMapping RefNum -> Builder
putRefNum Value RefNum -> Builder
putValue [(RefNum, Value RefNum)]
ds
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Cont RefNum -> Builder
putCont Cont RefNum
k
  Push Word64
f Word64
n GroupRef RefNum
gr Cont RefNum
k ->
    CoTag -> Builder
forall t. Tag t => t -> Builder
putTag CoTag
PushT
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall a.
(Integral a, Integral (Unsigned a), Bits (Unsigned a)) =>
a -> Builder
putVarInt Word64
f
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall a.
(Integral a, Integral (Unsigned a), Bits (Unsigned a)) =>
a -> Builder
putVarInt Word64
n
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> GroupRef RefNum -> Builder
putGroupRef GroupRef RefNum
gr
      Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Cont RefNum -> Builder
putCont Cont RefNum
k

getCont :: (MonadGet m) => m (Cont RefNum)
getCont :: forall (m :: * -> *). MonadGet m => m (Cont RefNum)
getCont =
  m CoTag
forall (m :: * -> *) t. (MonadGet m, Tag t) => m t
getTag m CoTag -> (CoTag -> m (Cont RefNum)) -> m (Cont RefNum)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    CoTag
KET -> Cont RefNum -> m (Cont RefNum)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Cont RefNum
forall ref. Cont ref
KE
    CoTag
MarkT ->
      Word64
-> [RefNum]
-> [(RefNum, Value RefNum)]
-> Cont RefNum
-> Cont RefNum
forall ref.
Word64 -> [ref] -> [(ref, Value ref)] -> Cont ref -> Cont ref
Mark
        (Word64
 -> [RefNum]
 -> [(RefNum, Value RefNum)]
 -> Cont RefNum
 -> Cont RefNum)
-> m Word64
-> m ([RefNum]
      -> [(RefNum, Value RefNum)] -> Cont RefNum -> Cont RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Word64
forall (m :: * -> *) b. (MonadGet m, Num b, Bits b) => m b
getVarInt
        m ([RefNum]
   -> [(RefNum, Value RefNum)] -> Cont RefNum -> Cont RefNum)
-> m [RefNum]
-> m ([(RefNum, Value RefNum)] -> Cont RefNum -> Cont RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m RefNum -> m [RefNum]
forall (m :: * -> *) a. MonadGet m => m a -> m [a]
getList m RefNum
forall (m :: * -> *). MonadGet m => m RefNum
getRefNum
        m ([(RefNum, Value RefNum)] -> Cont RefNum -> Cont RefNum)
-> m [(RefNum, Value RefNum)] -> m (Cont RefNum -> Cont RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m RefNum -> m (Value RefNum) -> m [(RefNum, Value RefNum)]
forall (m :: * -> *) a b. MonadGet m => m a -> m b -> m [(a, b)]
getMapping m RefNum
forall (m :: * -> *). MonadGet m => m RefNum
getRefNum m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
        m (Cont RefNum -> Cont RefNum)
-> m (Cont RefNum) -> m (Cont RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m (Cont RefNum)
forall (m :: * -> *). MonadGet m => m (Cont RefNum)
getCont
    CoTag
PushT ->
      Word64 -> Word64 -> GroupRef RefNum -> Cont RefNum -> Cont RefNum
forall ref.
Word64 -> Word64 -> GroupRef ref -> Cont ref -> Cont ref
Push
        (Word64 -> Word64 -> GroupRef RefNum -> Cont RefNum -> Cont RefNum)
-> m Word64
-> m (Word64 -> GroupRef RefNum -> Cont RefNum -> Cont RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Word64
forall (m :: * -> *) b. (MonadGet m, Num b, Bits b) => m b
getVarInt
        m (Word64 -> GroupRef RefNum -> Cont RefNum -> Cont RefNum)
-> m Word64 -> m (GroupRef RefNum -> Cont RefNum -> Cont RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m Word64
forall (m :: * -> *) b. (MonadGet m, Num b, Bits b) => m b
getVarInt
        m (GroupRef RefNum -> Cont RefNum -> Cont RefNum)
-> m (GroupRef RefNum) -> m (Cont RefNum -> Cont RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m (GroupRef RefNum)
forall (m :: * -> *). MonadGet m => m (GroupRef RefNum)
getGroupRef
        m (Cont RefNum -> Cont RefNum)
-> m (Cont RefNum) -> m (Cont RefNum)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m (Cont RefNum)
forall (m :: * -> *). MonadGet m => m (Cont RefNum)
getCont
{-# SPECIALIZE getCont :: BGet.Get (Cont RefNum) #-}
{-# SPECIALIZE getCont :: SGet.Get (Cont RefNum) #-}

putBLit :: BLit RefNum -> Builder
putBLit :: BLit RefNum -> Builder
putBLit = \case
  Text Text
t -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
TextT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
putText (Text -> Text
Util.Text.toText Text
t)
  List Seq (Value RefNum)
s -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
ListT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Value RefNum -> Builder) -> Seq (Value RefNum) -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Value RefNum -> Builder
putValue Seq (Value RefNum)
s
  TmLink Referent' RefNum
r -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
TmLinkT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Referent' RefNum -> Builder
putNumberedReferent Referent' RefNum
r
  TyLink RefNum
r -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
TyLinkT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> RefNum -> Builder
putRefNum RefNum
r
  Bytes Bytes
b -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
BytesT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Bytes -> Builder
putBytes Bytes
b
  Quote Value RefNum
vl -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
QuoteT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Value RefNum -> Builder
putValue Value RefNum
vl
  Code (CodeRep SuperGroup RefNum Symbol
sg Cacheability
ch) ->
    BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
tag Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Bool -> SuperGroup RefNum Symbol -> Builder
forall v. Var v => Bool -> SuperGroup RefNum v -> Builder
putGroup Bool
False SuperGroup RefNum Symbol
sg
    where
      tag :: BLTag
tag
        | Cacheability
Cacheable <- Cacheability
ch = BLTag
CachedCodeT
        | Bool
otherwise = BLTag
CodeT
  BArr ByteArray
a -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
BArrT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteArray -> Builder
putByteArray ByteArray
a
  Pos Word64
n -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
PosT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall n.
(Bits n, Bits (Unsigned n), Integral n, Integral (Unsigned n)) =>
n -> Builder
putPositive Word64
n
  Neg Word64
n -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
NegT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
forall n.
(Bits n, Bits (Unsigned n), Integral n, Integral (Unsigned n)) =>
n -> Builder
putPositive Word64
n
  Char Char
c -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
CharT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
putChar Char
c
  Float Double
d -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
FloatT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Double -> Builder
putFloat Double
d
  Arr Array (Value RefNum)
a -> BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
ArrT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Value RefNum -> Builder) -> Array (Value RefNum) -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Value RefNum -> Builder
putValue Array (Value RefNum)
a
  Map [(Value RefNum, Value RefNum)]
m ->
    BLTag -> Builder
forall t. Tag t => t -> Builder
putTag BLTag
MapT Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Value RefNum -> Builder)
-> (Value RefNum -> Builder)
-> [(Value RefNum, Value RefNum)]
-> Builder
forall a b. (a -> Builder) -> (b -> Builder) -> [(a, b)] -> Builder
putMapping Value RefNum -> Builder
putValue Value RefNum -> Builder
putValue [(Value RefNum, Value RefNum)]
m

getBLit :: (MonadGet m) => m (BLit RefNum)
getBLit :: forall (m :: * -> *). MonadGet m => m (BLit RefNum)
getBLit =
  m BLTag
forall (m :: * -> *) t. (MonadGet m, Tag t) => m t
getTag m BLTag -> (BLTag -> m (BLit RefNum)) -> m (BLit RefNum)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    BLTag
TextT -> Text -> BLit RefNum
forall ref. Text -> BLit ref
Text (Text -> BLit RefNum) -> (Text -> Text) -> Text -> BLit RefNum
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
Util.Text.fromText (Text -> BLit RefNum) -> m Text -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Text
forall (m :: * -> *). MonadGet m => m Text
getText
    BLTag
ListT -> Seq (Value RefNum) -> BLit RefNum
forall ref. Seq (Value ref) -> BLit ref
List (Seq (Value RefNum) -> BLit RefNum)
-> m (Seq (Value RefNum)) -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Value RefNum) -> m (Seq (Value RefNum))
forall (m :: * -> *) a. MonadGet m => m a -> m (Seq a)
getSeq m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
    BLTag
TmLinkT -> Referent' RefNum -> BLit RefNum
forall ref. Referent' ref -> BLit ref
TmLink (Referent' RefNum -> BLit RefNum)
-> m (Referent' RefNum) -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Referent' RefNum)
forall (m :: * -> *). MonadGet m => m (Referent' RefNum)
getNumberedReferent
    BLTag
TyLinkT -> RefNum -> BLit RefNum
forall ref. ref -> BLit ref
TyLink (RefNum -> BLit RefNum) -> m RefNum -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m RefNum
forall (m :: * -> *). MonadGet m => m RefNum
getRefNum
    BLTag
BytesT -> Bytes -> BLit RefNum
forall ref. Bytes -> BLit ref
Bytes (Bytes -> BLit RefNum) -> m Bytes -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Bytes
forall (m :: * -> *). MonadGet m => m Bytes
getBytes
    BLTag
QuoteT -> Value RefNum -> BLit RefNum
forall ref. Value ref -> BLit ref
Quote (Value RefNum -> BLit RefNum)
-> m (Value RefNum) -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
    BLTag
CodeT ->
      Code RefNum -> BLit RefNum
forall ref. Code ref -> BLit ref
Code (Code RefNum -> BLit RefNum)
-> (SuperGroup RefNum Symbol -> Code RefNum)
-> SuperGroup RefNum Symbol
-> BLit RefNum
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SuperGroup RefNum Symbol -> Cacheability -> Code RefNum)
-> Cacheability -> SuperGroup RefNum Symbol -> Code RefNum
forall a b c. (a -> b -> c) -> b -> a -> c
flip SuperGroup RefNum Symbol -> Cacheability -> Code RefNum
forall ref. SuperGroup ref Symbol -> Cacheability -> Code ref
CodeRep Cacheability
Uncacheable (SuperGroup RefNum Symbol -> BLit RefNum)
-> m (SuperGroup RefNum Symbol) -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (SuperGroup RefNum Symbol)
forall (m :: * -> *) v.
(MonadGet m, Var v) =>
m (SuperGroup RefNum v)
getGroup
    BLTag
BArrT -> ByteArray -> BLit RefNum
forall ref. ByteArray -> BLit ref
BArr (ByteArray -> BLit RefNum) -> m ByteArray -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m ByteArray
forall (m :: * -> *). MonadGet m => m ByteArray
getByteArray
    BLTag
PosT -> Word64 -> BLit RefNum
forall ref. Word64 -> BLit ref
Pos (Word64 -> BLit RefNum) -> m Word64 -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Word64
forall (m :: * -> *) n. (Bounded n, Integral n, MonadGet m) => m n
getPositive
    BLTag
NegT -> Word64 -> BLit RefNum
forall ref. Word64 -> BLit ref
Neg (Word64 -> BLit RefNum) -> m Word64 -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Word64
forall (m :: * -> *) n. (Bounded n, Integral n, MonadGet m) => m n
getPositive
    BLTag
CharT -> Char -> BLit RefNum
forall ref. Char -> BLit ref
Char (Char -> BLit RefNum) -> m Char -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Char
forall (m :: * -> *). MonadGet m => m Char
getChar
    BLTag
FloatT -> Double -> BLit RefNum
forall ref. Double -> BLit ref
Float (Double -> BLit RefNum) -> m Double -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Double
forall (m :: * -> *). MonadGet m => m Double
getFloat
    BLTag
ArrT -> Array (Value RefNum) -> BLit RefNum
forall ref. Array (Value ref) -> BLit ref
Arr (Array (Value RefNum) -> BLit RefNum)
-> (ValList RefNum -> Array (Value RefNum))
-> ValList RefNum
-> BLit RefNum
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Item (Array (Value RefNum))] -> Array (Value RefNum)
ValList RefNum -> Array (Value RefNum)
forall l. IsList l => [Item l] -> l
GHC.IsList.fromList (ValList RefNum -> BLit RefNum)
-> m (ValList RefNum) -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Value RefNum) -> m (ValList RefNum)
forall (m :: * -> *) a. MonadGet m => m a -> m [a]
getList m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
    BLTag
CachedCodeT -> Code RefNum -> BLit RefNum
forall ref. Code ref -> BLit ref
Code (Code RefNum -> BLit RefNum)
-> (SuperGroup RefNum Symbol -> Code RefNum)
-> SuperGroup RefNum Symbol
-> BLit RefNum
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SuperGroup RefNum Symbol -> Cacheability -> Code RefNum)
-> Cacheability -> SuperGroup RefNum Symbol -> Code RefNum
forall a b c. (a -> b -> c) -> b -> a -> c
flip SuperGroup RefNum Symbol -> Cacheability -> Code RefNum
forall ref. SuperGroup ref Symbol -> Cacheability -> Code ref
CodeRep Cacheability
Cacheable (SuperGroup RefNum Symbol -> BLit RefNum)
-> m (SuperGroup RefNum Symbol) -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (SuperGroup RefNum Symbol)
forall (m :: * -> *) v.
(MonadGet m, Var v) =>
m (SuperGroup RefNum v)
getGroup
    BLTag
MapT -> [(Value RefNum, Value RefNum)] -> BLit RefNum
forall ref. [(Value ref, Value ref)] -> BLit ref
Map ([(Value RefNum, Value RefNum)] -> BLit RefNum)
-> m [(Value RefNum, Value RefNum)] -> m (BLit RefNum)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Value RefNum)
-> m (Value RefNum) -> m [(Value RefNum, Value RefNum)]
forall (m :: * -> *) a b. MonadGet m => m a -> m b -> m [(a, b)]
getMapping m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
{-# SPECIALIZE getBLit :: BGet.Get (BLit RefNum) #-}
{-# SPECIALIZE getBLit :: SGet.Get (BLit RefNum) #-}

putValueWithHeader ::
  [Reference] -> [Reference] -> Value RefNum -> Builder
putValueWithHeader :: [Reference] -> [Reference] -> Value RefNum -> Builder
putValueWithHeader [Reference]
tyrs [Reference]
tmrs Value RefNum
v =
  (Reference -> Builder) -> [Reference] -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Reference -> Builder
SER.putReference [Reference]
tyrs
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Reference -> Builder) -> [Reference] -> Builder
forall (f :: * -> *) a.
Foldable f =>
(a -> Builder) -> f a -> Builder
putFoldable Reference -> Builder
SER.putReference [Reference]
tmrs
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Value RefNum -> Builder
putValue Value RefNum
v

putVersionedValue ::
  [Reference] -> [Reference] -> Value RefNum -> Builder
putVersionedValue :: [Reference] -> [Reference] -> Value RefNum -> Builder
putVersionedValue [Reference]
tyrs [Reference]
tmrs Value RefNum
v =
  Word32 -> Builder
BU.word32BE Word32
5 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [Reference] -> [Reference] -> Value RefNum -> Builder
putValueWithHeader [Reference]
tyrs [Reference]
tmrs Value RefNum
v

versionedValueBytes ::
  [Reference] -> [Reference] -> Value RefNum -> L.ByteString
versionedValueBytes :: [Reference] -> [Reference] -> Value RefNum -> ByteString
versionedValueBytes [Reference]
tyrs [Reference]
tmrs Value RefNum
v =
  Builder -> ByteString
BU.toLazyByteString (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ [Reference] -> [Reference] -> Value RefNum -> Builder
putVersionedValue [Reference]
tyrs [Reference]
tmrs Value RefNum
v

getValueWithHeader :: (MonadGet m) => m (Referenced Value)
getValueWithHeader :: forall (m :: * -> *). MonadGet m => m (Referenced Value)
getValueWithHeader = do
  Int
tyl <- m Int
forall (m :: * -> *) n.
(MonadGet m, Integral n, Integral (Unsigned n), Bits n,
 Bits (Unsigned n)) =>
m n
getLength
  [Reference]
tys <- Int -> m Reference -> m [Reference]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
tyl m Reference
forall (m :: * -> *). MonadGet m => m Reference
SER.getReference
  Int
tml <- m Int
forall (m :: * -> *) n.
(MonadGet m, Integral n, Integral (Unsigned n), Bits n,
 Bits (Unsigned n)) =>
m n
getLength
  [Reference]
tms <- Int -> m Reference -> m [Reference]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
tml m Reference
forall (m :: * -> *). MonadGet m => m Reference
SER.getReference
  Value RefNum
v <- m (Value RefNum)
forall (m :: * -> *). MonadGet m => m (Value RefNum)
getValue
  pure ([Reference] -> [Reference] -> Value RefNum -> Referenced Value
forall (t :: * -> *).
[Reference] -> [Reference] -> t RefNum -> Referenced t
WithRefs [Reference]
tys [Reference]
tms Value RefNum
v)
{-# SPECIALIZE getValueWithHeader :: BGet.Get (Referenced Value) #-}
{-# SPECIALIZE getValueWithHeader :: SGet.Get (Referenced Value) #-}