{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

-- |
-- Module      : Aztecs.ECS.Query
-- Copyright   : (c) Matt Hunzinger, 2025
-- License     : BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  : matt@hunzinger.me
-- Stability   : provisional
-- Portability : non-portable (GHC extensions)
module Aztecs.ECS.Query
  ( -- * Queries
    Query,
    QueryT (..),

    -- ** Operations
    entity,
    fetch,
    fetchMap,
    fetchMapM,
    zipFetchMap,
    zipFetchMapAccum,
    zipFetchMapM,
    zipFetchMapAccumM,

    -- ** Filters
    with,
    without,

    -- ** Running
    query,
    readSingle,
    readSingle',
    readSingleMaybe,
    readSingleMaybe',
    querySingle,
    querySingleMaybe,
    queryEntities,
    readQueryEntities,

    -- ** Conversion
    fromDyn,
  )
where

import Aztecs.ECS.Component
import Aztecs.ECS.Entity
import Aztecs.ECS.Query.Dynamic
import Aztecs.ECS.World.Components (Components)
import qualified Aztecs.ECS.World.Components as CS
import Aztecs.ECS.World.Entities (Entities (..))
import Control.Monad.Identity
import GHC.Stack

-- | @since 0.11
type Query = QueryT Identity

-- | Query for matching entities.
--
-- @since 0.11
newtype QueryT f a = Query
  { -- | Run a query, producing a `DynamicQueryT`.
    --
    -- @since 0.11
    forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery :: Components -> (Components, DynamicQueryT f a)
  }
  deriving ((forall a b. (a -> b) -> QueryT f a -> QueryT f b)
-> (forall a b. a -> QueryT f b -> QueryT f a)
-> Functor (QueryT f)
forall a b. a -> QueryT f b -> QueryT f a
forall a b. (a -> b) -> QueryT f a -> QueryT f b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
forall (f :: * -> *) a b. a -> QueryT f b -> QueryT f a
forall (f :: * -> *) a b. (a -> b) -> QueryT f a -> QueryT f b
$cfmap :: forall (f :: * -> *) a b. (a -> b) -> QueryT f a -> QueryT f b
fmap :: forall a b. (a -> b) -> QueryT f a -> QueryT f b
$c<$ :: forall (f :: * -> *) a b. a -> QueryT f b -> QueryT f a
<$ :: forall a b. a -> QueryT f b -> QueryT f a
Functor)

-- | @since 0.11
instance (Applicative f) => Applicative (QueryT f) where
  {-# INLINE pure #-}
  pure :: forall a. a -> QueryT f a
pure a
a = (Components -> (Components, DynamicQueryT f a)) -> QueryT f a
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query (,a -> DynamicQueryT f a
forall a. a -> DynamicQueryT f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a)

  {-# INLINE (<*>) #-}
  (Query Components -> (Components, DynamicQueryT f (a -> b))
f) <*> :: forall a b. QueryT f (a -> b) -> QueryT f a -> QueryT f b
<*> (Query Components -> (Components, DynamicQueryT f a)
g) = (Components -> (Components, DynamicQueryT f b)) -> QueryT f b
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query ((Components -> (Components, DynamicQueryT f b)) -> QueryT f b)
-> (Components -> (Components, DynamicQueryT f b)) -> QueryT f b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
    let !(Components
cs', DynamicQueryT f a
aQS) = Components -> (Components, DynamicQueryT f a)
g Components
cs
        !(Components
cs'', DynamicQueryT f (a -> b)
bQS) = Components -> (Components, DynamicQueryT f (a -> b))
f Components
cs'
     in (Components
cs'', DynamicQueryT f (a -> b)
bQS DynamicQueryT f (a -> b) -> DynamicQueryT f a -> DynamicQueryT f b
forall a b.
DynamicQueryT f (a -> b) -> DynamicQueryT f a -> DynamicQueryT f b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> DynamicQueryT f a
aQS)

-- | Fetch the current `EntityID`.
--
-- @since 0.11
{-# INLINE entity #-}
entity :: QueryT f EntityID
entity :: forall (f :: * -> *). QueryT f EntityID
entity = (Components -> (Components, DynamicQueryT f EntityID))
-> QueryT f EntityID
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query (,DynamicQueryT f EntityID
forall (f :: * -> *). DynamicQueryT f EntityID
entityDyn)

-- | Fetch a component.
--
-- @since 0.11
{-# INLINE fetch #-}
fetch :: forall f a. (Component a) => QueryT f a
fetch :: forall (f :: * -> *) a. Component a => QueryT f a
fetch = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @f @a ((ComponentID -> DynamicQueryT f a) -> QueryT f a)
-> (ComponentID -> DynamicQueryT f a) -> QueryT f a
forall a b. (a -> b) -> a -> b
$ ComponentID -> DynamicQueryT f a
forall a (f :: * -> *).
Component a =>
ComponentID -> DynamicQueryT f a
fetchDyn

-- | Fetch a component and map it, storing the result.
--
-- @since 0.11
{-# INLINE fetchMap #-}
fetchMap :: forall m a. (Component a) => (a -> a) -> QueryT m a
fetchMap :: forall (m :: * -> *) a. Component a => (a -> a) -> QueryT m a
fetchMap a -> a
f = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @_ @a ((ComponentID -> DynamicQueryT m a) -> QueryT m a)
-> (ComponentID -> DynamicQueryT m a) -> QueryT m a
forall a b. (a -> b) -> a -> b
$ (a -> a) -> ComponentID -> DynamicQueryT m a
forall a (f :: * -> *).
Component a =>
(a -> a) -> ComponentID -> DynamicQueryT f a
fetchMapDyn a -> a
f

-- | Fetch a component and map it with a monadic function, storing the result.
--
-- @since 0.11
{-# INLINE fetchMapM #-}
fetchMapM :: forall m a. (Monad m, Component a) => (a -> m a) -> QueryT m a
fetchMapM :: forall (m :: * -> *) a.
(Monad m, Component a) =>
(a -> m a) -> QueryT m a
fetchMapM a -> m a
f = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @_ @a ((ComponentID -> DynamicQueryT m a) -> QueryT m a)
-> (ComponentID -> DynamicQueryT m a) -> QueryT m a
forall a b. (a -> b) -> a -> b
$ (a -> m a) -> ComponentID -> DynamicQueryT m a
forall (f :: * -> *) a.
(Monad f, Component a) =>
(a -> f a) -> ComponentID -> DynamicQueryT f a
fetchMapDynM a -> m a
f

-- | Fetch a component and map it with some input, storing the result.
--
-- @since 0.11
{-# INLINE zipFetchMap #-}
zipFetchMap :: forall m a b. (Component a) => (b -> a -> a) -> QueryT m b -> QueryT m a
zipFetchMap :: forall (m :: * -> *) a b.
Component a =>
(b -> a -> a) -> QueryT m b -> QueryT m a
zipFetchMap b -> a -> a
f = forall c (f :: * -> *) a b.
Component c =>
(ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b -> QueryT f a
fromWriterInternal @a ((ComponentID -> DynamicQueryT m b -> DynamicQueryT m a)
 -> QueryT m b -> QueryT m a)
-> (ComponentID -> DynamicQueryT m b -> DynamicQueryT m a)
-> QueryT m b
-> QueryT m a
forall a b. (a -> b) -> a -> b
$ (b -> a -> a)
-> ComponentID -> DynamicQueryT m b -> DynamicQueryT m a
forall a b (f :: * -> *).
Component a =>
(b -> a -> a)
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f a
zipFetchMapDyn b -> a -> a
f

-- | Fetch a component and map it with some input, storing the result and returning some output.
--
-- @since 0.11
{-# INLINE zipFetchMapAccum #-}
zipFetchMapAccum ::
  forall m a b c. (Component a) => (b -> a -> (c, a)) -> QueryT m b -> QueryT m (c, a)
zipFetchMapAccum :: forall (m :: * -> *) a b c.
Component a =>
(b -> a -> (c, a)) -> QueryT m b -> QueryT m (c, a)
zipFetchMapAccum b -> a -> (c, a)
f = forall c (f :: * -> *) a b.
Component c =>
(ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b -> QueryT f a
fromWriterInternal @a ((ComponentID -> DynamicQueryT m b -> DynamicQueryT m (c, a))
 -> QueryT m b -> QueryT m (c, a))
-> (ComponentID -> DynamicQueryT m b -> DynamicQueryT m (c, a))
-> QueryT m b
-> QueryT m (c, a)
forall a b. (a -> b) -> a -> b
$ (b -> a -> (c, a))
-> ComponentID -> DynamicQueryT m b -> DynamicQueryT m (c, a)
forall a b c (f :: * -> *).
Component a =>
(b -> a -> (c, a))
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f (c, a)
zipFetchMapAccumDyn b -> a -> (c, a)
f

-- | Fetch a component and map it with some input and a monadic function, storing the result.
--
-- @since 0.11
{-# INLINE zipFetchMapM #-}
zipFetchMapM :: forall m a b. (Monad m, Component a) => (b -> a -> m a) -> QueryT m b -> QueryT m a
zipFetchMapM :: forall (m :: * -> *) a b.
(Monad m, Component a) =>
(b -> a -> m a) -> QueryT m b -> QueryT m a
zipFetchMapM b -> a -> m a
f = forall c (f :: * -> *) a b.
Component c =>
(ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b -> QueryT f a
fromWriterInternal @a ((ComponentID -> DynamicQueryT m b -> DynamicQueryT m a)
 -> QueryT m b -> QueryT m a)
-> (ComponentID -> DynamicQueryT m b -> DynamicQueryT m a)
-> QueryT m b
-> QueryT m a
forall a b. (a -> b) -> a -> b
$ (b -> a -> m a)
-> ComponentID -> DynamicQueryT m b -> DynamicQueryT m a
forall (f :: * -> *) a b.
(Monad f, Component a) =>
(b -> a -> f a)
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f a
zipFetchMapDynM b -> a -> m a
f

-- | Fetch a component and map it with some input and a monadic function,
-- storing the result and returning some output.
--
-- @since 0.11
{-# INLINE zipFetchMapAccumM #-}
zipFetchMapAccumM ::
  forall m a b c. (Monad m, Component a) => (b -> a -> m (c, a)) -> QueryT m b -> QueryT m (c, a)
zipFetchMapAccumM :: forall (m :: * -> *) a b c.
(Monad m, Component a) =>
(b -> a -> m (c, a)) -> QueryT m b -> QueryT m (c, a)
zipFetchMapAccumM b -> a -> m (c, a)
f = forall c (f :: * -> *) a b.
Component c =>
(ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b -> QueryT f a
fromWriterInternal @a ((ComponentID -> DynamicQueryT m b -> DynamicQueryT m (c, a))
 -> QueryT m b -> QueryT m (c, a))
-> (ComponentID -> DynamicQueryT m b -> DynamicQueryT m (c, a))
-> QueryT m b
-> QueryT m (c, a)
forall a b. (a -> b) -> a -> b
$ (b -> a -> m (c, a))
-> ComponentID -> DynamicQueryT m b -> DynamicQueryT m (c, a)
forall (f :: * -> *) a b c.
(Monad f, Component a) =>
(b -> a -> f (c, a))
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f (c, a)
zipFetchMapAccumDynM b -> a -> m (c, a)
f

-- | Filter for entities with a component.
--
-- @since 0.11
{-# INLINE with #-}
with :: forall f a. (Component a) => QueryT f ()
with :: forall (f :: * -> *) a. Component a => QueryT f ()
with = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @f @a ((ComponentID -> DynamicQueryT f ()) -> QueryT f ())
-> (ComponentID -> DynamicQueryT f ()) -> QueryT f ()
forall a b. (a -> b) -> a -> b
$ ComponentID -> DynamicQueryT f ()
forall (f :: * -> *). ComponentID -> DynamicQueryT f ()
withDyn

-- | Filter for entities without a component.
--
-- @since 0.11
{-# INLINE without #-}
without :: forall f a. (Component a) => QueryT f ()
without :: forall (f :: * -> *) a. Component a => QueryT f ()
without = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @f @a ((ComponentID -> DynamicQueryT f ()) -> QueryT f ())
-> (ComponentID -> DynamicQueryT f ()) -> QueryT f ()
forall a b. (a -> b) -> a -> b
$ ComponentID -> DynamicQueryT f ()
forall (f :: * -> *). ComponentID -> DynamicQueryT f ()
withDyn

-- | Convert a `DynamicQueryT` to a `QueryT`.
--
-- @since 0.11
{-# INLINE fromDyn #-}
fromDyn :: DynamicQueryT f a -> QueryT f a
fromDyn :: forall (f :: * -> *) a. DynamicQueryT f a -> QueryT f a
fromDyn DynamicQueryT f a
q = (Components -> (Components, DynamicQueryT f a)) -> QueryT f a
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query (,DynamicQueryT f a
q)

{-# INLINE fromDynInternal #-}
fromDynInternal ::
  forall f a b.
  (Component a) =>
  (ComponentID -> DynamicQueryT f b) ->
  QueryT f b
fromDynInternal :: forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal ComponentID -> DynamicQueryT f b
f = (Components -> (Components, DynamicQueryT f b)) -> QueryT f b
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query ((Components -> (Components, DynamicQueryT f b)) -> QueryT f b)
-> (Components -> (Components, DynamicQueryT f b)) -> QueryT f b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ComponentID
cId, Components
cs') = forall a. Component a => Components -> (ComponentID, Components)
CS.insert @a Components
cs in (Components
cs', ComponentID -> DynamicQueryT f b
f ComponentID
cId)

{-# INLINE fromWriterInternal #-}
fromWriterInternal ::
  forall c f a b.
  (Component c) =>
  (ComponentID -> DynamicQueryT f b -> DynamicQueryT f a) ->
  QueryT f b ->
  QueryT f a
fromWriterInternal :: forall c (f :: * -> *) a b.
Component c =>
(ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b -> QueryT f a
fromWriterInternal ComponentID -> DynamicQueryT f b -> DynamicQueryT f a
f QueryT f b
q = (Components -> (Components, DynamicQueryT f a)) -> QueryT f a
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query ((Components -> (Components, DynamicQueryT f a)) -> QueryT f a)
-> (Components -> (Components, DynamicQueryT f a)) -> QueryT f a
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ComponentID
cId, Components
cs') = forall a. Component a => Components -> (ComponentID, Components)
CS.insert @c Components
cs
      !(Components
cs'', DynamicQueryT f b
dynQ) = QueryT f b -> Components -> (Components, DynamicQueryT f b)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT f b
q Components
cs'
   in (Components
cs'', ComponentID -> DynamicQueryT f b -> DynamicQueryT f a
f ComponentID
cId DynamicQueryT f b
dynQ)

-- | Match and update all entities.
--
-- @since 0.11
{-# INLINE query #-}
query :: (Monad m) => QueryT m a -> Entities -> m ([a], Entities)
query :: forall (m :: * -> *) a.
Monad m =>
QueryT m a -> Entities -> m ([a], Entities)
query QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  ([a]
as, Entities
es') <- DynamicQueryT m a -> Entities -> m ([a], Entities)
forall (m :: * -> *) a.
Monad m =>
DynamicQueryT m a -> Entities -> m ([a], Entities)
queryDyn DynamicQueryT m a
dynQ Entities
es
  ([a], Entities) -> m ([a], Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a]
as, Entities
es' {components = cs'})

-- | Match and update a single matched entity.
--
-- @since 0.11
{-# INLINE querySingle #-}
querySingle :: (HasCallStack, Monad m) => QueryT m a -> Entities -> m (a, Entities)
querySingle :: forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
QueryT m a -> Entities -> m (a, Entities)
querySingle QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  (a
as, Entities
es') <- DynamicQueryT m a -> Entities -> m (a, Entities)
forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
DynamicQueryT m a -> Entities -> m (a, Entities)
mapSingleDyn DynamicQueryT m a
dynQ Entities
es
  (a, Entities) -> m (a, Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
as, Entities
es' {components = cs'})

-- | Match and update a single matched entity, or `Nothing`.
--
-- @since 0.11
{-# INLINE querySingleMaybe #-}
querySingleMaybe :: (Monad m) => QueryT m a -> Entities -> m (Maybe a, Entities)
querySingleMaybe :: forall (m :: * -> *) a.
Monad m =>
QueryT m a -> Entities -> m (Maybe a, Entities)
querySingleMaybe QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  (Maybe a
as, Entities
es') <- DynamicQueryT m a -> Entities -> m (Maybe a, Entities)
forall (m :: * -> *) a.
Monad m =>
DynamicQueryT m a -> Entities -> m (Maybe a, Entities)
mapSingleMaybeDyn DynamicQueryT m a
dynQ Entities
es
  (Maybe a, Entities) -> m (Maybe a, Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a
as, Entities
es' {components = cs'})

-- | Match and update the specified entities.
--
-- @since 0.11
queryEntities :: (Monad m) => [EntityID] -> QueryT m a -> Entities -> m ([a], Entities)
queryEntities :: forall (m :: * -> *) a.
Monad m =>
[EntityID] -> QueryT m a -> Entities -> m ([a], Entities)
queryEntities [EntityID]
eIds QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  ([a]
as, Entities
es') <- [EntityID] -> DynamicQueryT m a -> Entities -> m ([a], Entities)
forall (m :: * -> *) a.
Monad m =>
[EntityID] -> DynamicQueryT m a -> Entities -> m ([a], Entities)
queryEntitiesDyn [EntityID]
eIds DynamicQueryT m a
dynQ Entities
es
  ([a], Entities) -> m ([a], Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a]
as, Entities
es' {components = cs'})

-- | Match a single entity.
--
-- @since 0.11
{-# INLINE readSingle #-}
readSingle :: (HasCallStack, Monad m) => QueryT m a -> Entities -> m (a, Entities)
readSingle :: forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
QueryT m a -> Entities -> m (a, Entities)
readSingle QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  a
as <- DynamicQueryT m a -> Entities -> m a
forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
DynamicQueryT m a -> Entities -> m a
singleDyn DynamicQueryT m a
dynQ Entities
es
  (a, Entities) -> m (a, Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
as, Entities
es {components = cs'})

-- | Match a single entity.
--
-- @since 0.11
{-# INLINE readSingle' #-}
readSingle' :: (HasCallStack, Monad m) => QueryT m a -> Entities -> m (a, Components)
readSingle' :: forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
QueryT m a -> Entities -> m (a, Components)
readSingle' QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  a
as <- DynamicQueryT m a -> Entities -> m a
forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
DynamicQueryT m a -> Entities -> m a
singleDyn DynamicQueryT m a
dynQ Entities
es
  (a, Components) -> m (a, Components)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
as, Components
cs')

-- | Match a single entity, or `Nothing`.
--
-- @since 0.11
{-# INLINE readSingleMaybe #-}
readSingleMaybe :: (Monad m) => QueryT m a -> Entities -> m (Maybe a, Entities)
readSingleMaybe :: forall (m :: * -> *) a.
Monad m =>
QueryT m a -> Entities -> m (Maybe a, Entities)
readSingleMaybe QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  Maybe a
as <- DynamicQueryT m a -> Entities -> m (Maybe a)
forall (m :: * -> *) a.
Monad m =>
DynamicQueryT m a -> Entities -> m (Maybe a)
singleMaybeDyn DynamicQueryT m a
dynQ Entities
es
  (Maybe a, Entities) -> m (Maybe a, Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a
as, Entities
es {components = cs'})

-- | Match a single entity, or `Nothing`.
--
-- @since 0.11
{-# INLINE readSingleMaybe' #-}
readSingleMaybe' :: (Monad m) => QueryT m a -> Entities -> m (Maybe a, Components)
readSingleMaybe' :: forall (m :: * -> *) a.
Monad m =>
QueryT m a -> Entities -> m (Maybe a, Components)
readSingleMaybe' QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  Maybe a
as <- DynamicQueryT m a -> Entities -> m (Maybe a)
forall (m :: * -> *) a.
Monad m =>
DynamicQueryT m a -> Entities -> m (Maybe a)
singleMaybeDyn DynamicQueryT m a
dynQ Entities
es
  (Maybe a, Components) -> m (Maybe a, Components)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a
as, Components
cs')

-- | Match the specified entities.
--
-- @since 0.11
readQueryEntities :: (Monad m) => [EntityID] -> QueryT m a -> Entities -> m ([a], Entities)
readQueryEntities :: forall (m :: * -> *) a.
Monad m =>
[EntityID] -> QueryT m a -> Entities -> m ([a], Entities)
readQueryEntities [EntityID]
eIds QueryT m a
q Entities
es = do
  let !(Components
cs', DynamicQueryT m a
dynQ) = QueryT m a -> Components -> (Components, DynamicQueryT m a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT m a
q (Components -> (Components, DynamicQueryT m a))
-> Components -> (Components, DynamicQueryT m a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es
  [a]
as <- [EntityID] -> DynamicQueryT m a -> Entities -> m [a]
forall (m :: * -> *) a.
Monad m =>
[EntityID] -> DynamicQueryT m a -> Entities -> m [a]
readQueryEntitiesDyn [EntityID]
eIds DynamicQueryT m a
dynQ Entities
es
  ([a], Entities) -> m ([a], Entities)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a]
as, Entities
es {components = cs'})