packages feed

large-records-0.4.2: src/Data/Record/Plugin/Runtime.hs

{-# LANGUAGE ConstraintKinds          #-}
{-# LANGUAGE DataKinds                #-}
{-# LANGUAGE DisambiguateRecordFields #-}
{-# LANGUAGE KindSignatures           #-}
{-# LANGUAGE PolyKinds                #-}
{-# LANGUAGE ScopedTypeVariables      #-}
{-# LANGUAGE TypeApplications         #-}

-- | Re-exports of types and functions used by generated code
--
-- This exports all functionality required by the generated code, with the
-- exception of GHC generics (name clash with @large-records@ generics).
module Data.Record.Plugin.Runtime (
    -- * Prelude
    Int
  , error
    -- * Other base
  , Constraint
  , Proxy
  , Type
  , proxy
    -- * AnyArray
  , AnyArray
  , anyArrayFromList
  , anyArrayToList
  , anyArrayIndex
  , anyArrayUpdate
    -- * large-generics
  , Rep
  , Dict
  , anyArrayToRep
  , anyArrayFromRep
  , mkDicts
  , mkDict
  , mkStrictField
  , mkLazyField
  , mkMetadata
    -- ** wrappers
  , gcompare
  , geq
  , gshowsPrec
  , noInlineUnsafeCo
    -- ** ThroughLRGenerics
  , ThroughLRGenerics
  , wrapThroughLRGenerics
  , unwrapThroughLRGenerics
  ) where

import Prelude hiding (Int, error)
import qualified Prelude as Prelude

import Control.Monad (forM_)
import Data.Coerce (coerce)
import Data.Primitive.SmallArray
import GHC.Exts (Any)
import GHC.Stack (HasCallStack)
import GHC.TypeLits

import qualified Data.Foldable                    as Foldable
import qualified Data.Kind                        as Base
import qualified Data.Proxy                       as Base
import qualified Data.Record.Generic              as LR
import qualified Data.Record.Generic.Eq           as LR
import qualified Data.Record.Generic.GHC          as LR
import qualified Data.Record.Generic.Rep.Internal as LR
import qualified Data.Record.Generic.Show         as LR

{-------------------------------------------------------------------------------
  Prelude
-------------------------------------------------------------------------------}

type Int = Prelude.Int

error :: HasCallStack => String -> a
error = Prelude.error

{-------------------------------------------------------------------------------
  base
-------------------------------------------------------------------------------}

type Constraint = Base.Constraint
type Proxy      = Base.Proxy
type Type       = Base.Type

proxy :: forall k (a :: k). Proxy a
proxy = Base.Proxy

{-------------------------------------------------------------------------------
  AnyArray
-------------------------------------------------------------------------------}

type AnyArray = SmallArray Any

anyArrayFromList :: [Any] -> AnyArray
anyArrayFromList = smallArrayFromList

anyArrayToList :: AnyArray -> [Any]
anyArrayToList = Foldable.toList

anyArrayIndex :: AnyArray -> Int -> Any
anyArrayIndex = indexSmallArray

anyArrayUpdate :: AnyArray -> [(Int, Any)] -> AnyArray
anyArrayUpdate v updates = runSmallArray (do
    v' <- thawSmallArray v 0 (sizeofSmallArray v)
    forM_ updates (\(i, a) -> writeSmallArray v' i a)
    return v'
  )

{-------------------------------------------------------------------------------
  large-generics: utilities
-------------------------------------------------------------------------------}

anyArrayToRep :: AnyArray -> Rep LR.I a
anyArrayToRep = coerce

anyArrayFromRep :: Rep LR.I a -> AnyArray
anyArrayFromRep = coerce

mkDicts :: [Dict c Any] -> Rep (Dict c) a
mkDicts ds = LR.Rep (smallArrayFromList ds)

mkDict :: c x => Proxy c -> Proxy x -> Dict c x
mkDict _ _ = LR.Dict

mkStrictField :: forall name a.
     KnownSymbol name
  => Proxy name -> LR.FieldMetadata a
mkStrictField _ = LR.FieldMetadata (Base.Proxy @name) LR.FieldStrict

mkLazyField :: forall name a.
     KnownSymbol name
  => Proxy name -> LR.FieldMetadata a
mkLazyField _ = LR.FieldMetadata (Base.Proxy @name) LR.FieldLazy

mkMetadata ::
     String  -- ^ Record name
  -> String  -- ^ Constructor name
  -> [LR.FieldMetadata Any]
  -> LR.Metadata a
mkMetadata name constr fields = LR.Metadata {
      recordName          = name
    , recordConstructor   = constr
    , recordSize          = length fields
    , recordFieldMetadata = LR.Rep (smallArrayFromList fields)
    }

{-------------------------------------------------------------------------------
  large-generics: wrappers
-------------------------------------------------------------------------------}

type Rep  = LR.Rep
type Dict = LR.Dict

gcompare :: (LR.Generic a, LR.Constraints a Ord) => a -> a -> Ordering
gcompare = LR.gcompare

geq :: (LR.Generic a, LR.Constraints a Eq) => a -> a -> Bool
geq = LR.geq

gshowsPrec :: (LR.Generic a, LR.Constraints a Show) => Int -> a -> ShowS
gshowsPrec = LR.gshowsPrec

noInlineUnsafeCo :: a -> b
noInlineUnsafeCo = LR.noInlineUnsafeCo

{-------------------------------------------------------------------------------
  large-generics: ThroughLRGenerics
-------------------------------------------------------------------------------}

type ThroughLRGenerics = LR.ThroughLRGenerics

wrapThroughLRGenerics :: a -> ThroughLRGenerics a p
wrapThroughLRGenerics = LR.WrapThroughLRGenerics

unwrapThroughLRGenerics :: ThroughLRGenerics a p -> a
unwrapThroughLRGenerics = LR.unwrapThroughLRGenerics