{-# 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,
    fetchMaybe,
    fetchMap,
    fetchMapM,
    zipFetchMap,
    zipFetchMapAccum,
    zipFetchMapM,
    zipFetchMapAccumM,

    -- ** Filters

    with,
    without,

    -- ** Conversion

    fromDyn,
    liftQuery,

    -- ** Running


    -- *** Writing

    query,
    querySingle,
    querySingleMaybe,
    queryEntities,

    -- *** Reading

    readQueryEntities,
    readQuery,
    readQuerySingle,
    readQuerySingleMaybe,
  )
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 Control.Monad.Trans
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, or `Nothing`.

--

-- @since 0.12

{-# INLINE fetchMaybe #-}
fetchMaybe :: forall f a. (Component a) => QueryT f (Maybe a)
fetchMaybe :: forall (f :: * -> *) a. Component a => QueryT f (Maybe a)
fetchMaybe = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @f @a ((ComponentID -> DynamicQueryT f (Maybe a)) -> QueryT f (Maybe a))
-> (ComponentID -> DynamicQueryT f (Maybe a)) -> QueryT f (Maybe a)
forall a b. (a -> b) -> a -> b
$ ComponentID -> DynamicQueryT f (Maybe a)
forall a (f :: * -> *).
Component a =>
ComponentID -> DynamicQueryT f (Maybe a)
fetchMaybeDyn

-- | Fetch a component and map it, storing the result.

--

-- @since 0.11

{-# INLINE fetchMap #-}
fetchMap :: forall f a. (Component a) => (a -> a) -> QueryT f a
fetchMap :: forall (f :: * -> *) a. Component a => (a -> a) -> QueryT f a
fetchMap a -> a
f = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @_ @a ((ComponentID -> DynamicQueryT f a) -> QueryT f a)
-> (ComponentID -> DynamicQueryT f a) -> QueryT f a
forall a b. (a -> b) -> a -> b
$ (a -> a) -> ComponentID -> DynamicQueryT f 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 f a. (Monad f, Component a) => (a -> f a) -> QueryT f a
fetchMapM :: forall (f :: * -> *) a.
(Monad f, Component a) =>
(a -> f a) -> QueryT f a
fetchMapM a -> f a
f = forall (f :: * -> *) a b.
Component a =>
(ComponentID -> DynamicQueryT f b) -> QueryT f b
fromDynInternal @_ @a ((ComponentID -> DynamicQueryT f a) -> QueryT f a)
-> (ComponentID -> DynamicQueryT f a) -> QueryT f a
forall a b. (a -> b) -> a -> b
$ (a -> f a) -> ComponentID -> DynamicQueryT f a
forall (f :: * -> *) a.
(Monad f, Component a) =>
(a -> f a) -> ComponentID -> DynamicQueryT f a
fetchMapDynM a -> f a
f

-- | Fetch a component and map it with some input, storing the result.

--

-- @since 0.11

{-# INLINE zipFetchMap #-}
zipFetchMap :: forall f a b. (Component a) => (b -> a -> a) -> QueryT f b -> QueryT f a
zipFetchMap :: forall (f :: * -> *) a b.
Component a =>
(b -> a -> a) -> QueryT f b -> QueryT f 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 f b -> DynamicQueryT f a)
 -> QueryT f b -> QueryT f a)
-> (ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b
-> QueryT f a
forall a b. (a -> b) -> a -> b
$ (b -> a -> a)
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f 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 f a b c. (Component a) => (b -> a -> (c, a)) -> QueryT f b -> QueryT f (c, a)
zipFetchMapAccum :: forall (f :: * -> *) a b c.
Component a =>
(b -> a -> (c, a)) -> QueryT f b -> QueryT f (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 f b -> DynamicQueryT f (c, a))
 -> QueryT f b -> QueryT f (c, a))
-> (ComponentID -> DynamicQueryT f b -> DynamicQueryT f (c, a))
-> QueryT f b
-> QueryT f (c, a)
forall a b. (a -> b) -> a -> b
$ (b -> a -> (c, a))
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f (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 f a b. (Monad f, Component a) => (b -> a -> f a) -> QueryT f b -> QueryT f a
zipFetchMapM :: forall (f :: * -> *) a b.
(Monad f, Component a) =>
(b -> a -> f a) -> QueryT f b -> QueryT f a
zipFetchMapM b -> a -> f 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 f b -> DynamicQueryT f a)
 -> QueryT f b -> QueryT f a)
-> (ComponentID -> DynamicQueryT f b -> DynamicQueryT f a)
-> QueryT f b
-> QueryT f a
forall a b. (a -> b) -> a -> b
$ (b -> a -> f a)
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f a
forall (f :: * -> *) a b.
(Monad f, Component a) =>
(b -> a -> f a)
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f a
zipFetchMapDynM b -> a -> f 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 f a b c. (Monad f, Component a) => (b -> a -> f (c, a)) -> QueryT f b -> QueryT f (c, a)
zipFetchMapAccumM :: forall (f :: * -> *) a b c.
(Monad f, Component a) =>
(b -> a -> f (c, a)) -> QueryT f b -> QueryT f (c, a)
zipFetchMapAccumM b -> a -> f (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 f b -> DynamicQueryT f (c, a))
 -> QueryT f b -> QueryT f (c, a))
-> (ComponentID -> DynamicQueryT f b -> DynamicQueryT f (c, a))
-> QueryT f b
-> QueryT f (c, a)
forall a b. (a -> b) -> a -> b
$ (b -> a -> f (c, a))
-> ComponentID -> DynamicQueryT f b -> DynamicQueryT f (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 -> f (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)

liftQuery :: (MonadTrans g, Monad (g f), Monad f) => QueryT f a -> QueryT (g f) a
liftQuery :: forall (g :: (* -> *) -> * -> *) (f :: * -> *) a.
(MonadTrans g, Monad (g f), Monad f) =>
QueryT f a -> QueryT (g f) a
liftQuery QueryT f a
q = (Components -> (Components, DynamicQueryT (g f) a))
-> QueryT (g f) a
forall (f :: * -> *) a.
(Components -> (Components, DynamicQueryT f a)) -> QueryT f a
Query ((Components -> (Components, DynamicQueryT (g f) a))
 -> QueryT (g f) a)
-> (Components -> (Components, DynamicQueryT (g f) a))
-> QueryT (g f) a
forall a b. (a -> b) -> a -> b
$ \Components
cs -> let !(Components
cs', DynamicQueryT f a
dynQ) = QueryT f a -> Components -> (Components, DynamicQueryT f a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT f a
q Components
cs in (Components
cs', DynamicQueryT f a -> DynamicQueryT (g f) a
forall (g :: (* -> *) -> * -> *) (f :: * -> *) a.
(MonadTrans g, Monad (g f), Monad f) =>
DynamicQueryT f a -> DynamicQueryT (g f) a
liftQueryDyn DynamicQueryT f a
dynQ)

-- | Match and update all entities.

--

-- @since 0.11

{-# INLINE query #-}
query :: (Applicative f) => QueryT f a -> Entities -> f ([a], Entities)
query :: forall (f :: * -> *) a.
Applicative f =>
QueryT f a -> Entities -> f ([a], Entities)
query = (DynamicQueryT f a -> Entities -> f ([a], Entities))
-> QueryT f a -> Entities -> f ([a], Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn DynamicQueryT f a -> Entities -> f ([a], Entities)
forall (f :: * -> *) a.
Applicative f =>
DynamicQueryT f a -> Entities -> f ([a], Entities)
queryDyn

-- | Match and update a single matched entity.

--

-- @since 0.12

{-# INLINE querySingle #-}
querySingle :: (HasCallStack, Applicative f) => QueryT f a -> Entities -> f (a, Entities)
querySingle :: forall (f :: * -> *) a.
(HasCallStack, Applicative f) =>
QueryT f a -> Entities -> f (a, Entities)
querySingle = (DynamicQueryT f a -> Entities -> f (a, Entities))
-> QueryT f a -> Entities -> f (a, Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn DynamicQueryT f a -> Entities -> f (a, Entities)
forall (m :: * -> *) a.
(HasCallStack, Applicative m) =>
DynamicQueryT m a -> Entities -> m (a, Entities)
querySingleDyn

-- | Match and update a single matched entity, or `Nothing`.

--

-- @since 0.12

{-# INLINE querySingleMaybe #-}
querySingleMaybe :: (Applicative m) => QueryT m a -> Entities -> m (Maybe a, Entities)
querySingleMaybe :: forall (m :: * -> *) a.
Applicative m =>
QueryT m a -> Entities -> m (Maybe a, Entities)
querySingleMaybe = (DynamicQueryT m a -> Entities -> m (Maybe a, Entities))
-> QueryT m a -> Entities -> m (Maybe a, Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn DynamicQueryT m a -> Entities -> m (Maybe a, Entities)
forall (f :: * -> *) a.
Applicative f =>
DynamicQueryT f a -> Entities -> f (Maybe a, Entities)
querySingleMaybeDyn

-- | Match and update the specified entities.

--

-- @since 0.12

{-# INLINE queryEntities #-}
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 = (DynamicQueryT m a -> Entities -> m ([a], Entities))
-> QueryT m a -> Entities -> m ([a], Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn ((DynamicQueryT m a -> Entities -> m ([a], Entities))
 -> QueryT m a -> Entities -> m ([a], Entities))
-> (DynamicQueryT m a -> Entities -> m ([a], Entities))
-> QueryT m a
-> Entities
-> m ([a], Entities)
forall a b. (a -> b) -> a -> b
$ [EntityID] -> DynamicQueryT m a -> Entities -> m ([a], Entities)
forall (m :: * -> *) a.
Monad m =>
[EntityID] -> DynamicQueryT m a -> Entities -> m ([a], Entities)
queryEntitiesDyn [EntityID]
eIds

-- | Match and update all entities.

--

-- @since 0.12

{-# INLINE readQuery #-}
readQuery :: (Applicative f) => QueryT f a -> Entities -> f ([a], Entities)
readQuery :: forall (f :: * -> *) a.
Applicative f =>
QueryT f a -> Entities -> f ([a], Entities)
readQuery = (DynamicQueryT f a -> Entities -> f ([a], Entities))
-> QueryT f a -> Entities -> f ([a], Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn ((DynamicQueryT f a -> Entities -> f ([a], Entities))
 -> QueryT f a -> Entities -> f ([a], Entities))
-> (DynamicQueryT f a -> Entities -> f ([a], Entities))
-> QueryT f a
-> Entities
-> f ([a], Entities)
forall a b. (a -> b) -> a -> b
$ \DynamicQueryT f a
q Entities
es -> (,Entities
es) ([a] -> ([a], Entities)) -> f [a] -> f ([a], Entities)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicQueryT f a -> Entities -> f [a]
forall (f :: * -> *) a.
Applicative f =>
DynamicQueryT f a -> Entities -> f [a]
readQueryDyn DynamicQueryT f a
q Entities
es

-- | Match a single entity.

--

-- @since 0.12

{-# INLINE readQuerySingle #-}
readQuerySingle :: (HasCallStack, Applicative f) => QueryT f a -> Entities -> f (a, Entities)
readQuerySingle :: forall (f :: * -> *) a.
(HasCallStack, Applicative f) =>
QueryT f a -> Entities -> f (a, Entities)
readQuerySingle = (DynamicQueryT f a -> Entities -> f (a, Entities))
-> QueryT f a -> Entities -> f (a, Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn ((DynamicQueryT f a -> Entities -> f (a, Entities))
 -> QueryT f a -> Entities -> f (a, Entities))
-> (DynamicQueryT f a -> Entities -> f (a, Entities))
-> QueryT f a
-> Entities
-> f (a, Entities)
forall a b. (a -> b) -> a -> b
$ \DynamicQueryT f a
q Entities
es -> (,Entities
es) (a -> (a, Entities)) -> f a -> f (a, Entities)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicQueryT f a -> Entities -> f a
forall (f :: * -> *) a.
(HasCallStack, Applicative f) =>
DynamicQueryT f a -> Entities -> f a
readQuerySingleDyn DynamicQueryT f a
q Entities
es

-- | Match a single entity, or `Nothing`.

--

-- @since 0.12

{-# INLINE readQuerySingleMaybe #-}
readQuerySingleMaybe :: (Applicative f) => QueryT f a -> Entities -> f (Maybe a, Entities)
readQuerySingleMaybe :: forall (m :: * -> *) a.
Applicative m =>
QueryT m a -> Entities -> m (Maybe a, Entities)
readQuerySingleMaybe = (DynamicQueryT f a -> Entities -> f (Maybe a, Entities))
-> QueryT f a -> Entities -> f (Maybe a, Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn ((DynamicQueryT f a -> Entities -> f (Maybe a, Entities))
 -> QueryT f a -> Entities -> f (Maybe a, Entities))
-> (DynamicQueryT f a -> Entities -> f (Maybe a, Entities))
-> QueryT f a
-> Entities
-> f (Maybe a, Entities)
forall a b. (a -> b) -> a -> b
$ \DynamicQueryT f a
q Entities
es -> (,Entities
es) (Maybe a -> (Maybe a, Entities))
-> f (Maybe a) -> f (Maybe a, Entities)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicQueryT f a -> Entities -> f (Maybe a)
forall (f :: * -> *) a.
Applicative f =>
DynamicQueryT f a -> Entities -> f (Maybe a)
readQuerySingleMaybeDyn DynamicQueryT f a
q Entities
es

-- | Match the specified entities.

--

-- @since 0.12

{-# INLINE readQueryEntities #-}
readQueryEntities :: (Applicative f) => [EntityID] -> QueryT f a -> Entities -> f ([a], Entities)
readQueryEntities :: forall (f :: * -> *) a.
Applicative f =>
[EntityID] -> QueryT f a -> Entities -> f ([a], Entities)
readQueryEntities [EntityID]
eIds = (DynamicQueryT f a -> Entities -> f ([a], Entities))
-> QueryT f a -> Entities -> f ([a], Entities)
forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn ((DynamicQueryT f a -> Entities -> f ([a], Entities))
 -> QueryT f a -> Entities -> f ([a], Entities))
-> (DynamicQueryT f a -> Entities -> f ([a], Entities))
-> QueryT f a
-> Entities
-> f ([a], Entities)
forall a b. (a -> b) -> a -> b
$ \DynamicQueryT f a
q Entities
es -> (,Entities
es) ([a] -> ([a], Entities)) -> f [a] -> f ([a], Entities)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [EntityID] -> DynamicQueryT f a -> Entities -> f [a]
forall (f :: * -> *) a.
Applicative f =>
[EntityID] -> DynamicQueryT f a -> Entities -> f [a]
readQueryEntitiesDyn [EntityID]
eIds DynamicQueryT f a
q Entities
es

{-# INLINE runQueryWithDyn #-}
runQueryWithDyn ::
  (Applicative f) =>
  (DynamicQueryT f a -> Entities -> b) ->
  QueryT f a ->
  Entities ->
  b
runQueryWithDyn :: forall (f :: * -> *) a b.
Applicative f =>
(DynamicQueryT f a -> Entities -> b) -> QueryT f a -> Entities -> b
runQueryWithDyn DynamicQueryT f a -> Entities -> b
f QueryT f a
q Entities
es =
  let !(Components
cs', DynamicQueryT f a
dynQ) = QueryT f a -> Components -> (Components, DynamicQueryT f a)
forall (f :: * -> *) a.
QueryT f a -> Components -> (Components, DynamicQueryT f a)
runQuery QueryT f a
q (Components -> (Components, DynamicQueryT f a))
-> Components -> (Components, DynamicQueryT f a)
forall a b. (a -> b) -> a -> b
$ Entities -> Components
components Entities
es in DynamicQueryT f a -> Entities -> b
f DynamicQueryT f a
dynQ Entities
es {components = cs'}