{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# 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)

--

-- Query for matching entities.

module Aztecs.ECS.Query
  ( -- * Queries

    Query (..),
    DynamicQueryF (..),

    -- ** Operations

    query,
    queryMaybe,
    queryMap,
    queryMap_,
    queryMapM,
    queryMapWith,
    queryMapWith_,
    queryMapWithM,
    queryMapWithAccum,
    queryMapWithAccumM,

    -- ** Running

    readQuery,
    readQuery',
    readQuerySingle,
    readQuerySingle',
    readQuerySingleMaybe,
    readQuerySingleMaybe',
    runQuery,
    runQuerySingle,
    runQuerySingleMaybe,

    -- * Filters

    QueryFilter (..),
    with,
    without,

    -- * Reads and writes

    ReadsWrites (..),
    disjoint,
  )
where

import Aztecs.ECS.Access.Internal (Access)
import Aztecs.ECS.Component
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 qualified Aztecs.ECS.World.Entities as E
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Vector (Vector)
import GHC.Stack
import Prelude hiding (reads)

-- | Query for matching entities.

newtype Query m a = Query
  { -- | Run a query, producing a `DynamicQuery`.

    --

    -- @since 0.10

    forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' :: Components -> (ReadsWrites, Components, DynamicQuery m a)
  }
  deriving ((forall a b. (a -> b) -> Query m a -> Query m b)
-> (forall a b. a -> Query m b -> Query m a) -> Functor (Query m)
forall a b. a -> Query m b -> Query m a
forall a b. (a -> b) -> Query m a -> Query m b
forall (m :: * -> *) a b. Functor m => a -> Query m b -> Query m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Query m a -> Query m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Query m a -> Query m b
fmap :: forall a b. (a -> b) -> Query m a -> Query m b
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> Query m b -> Query m a
<$ :: forall a b. a -> Query m b -> Query m a
Functor)

instance (Monad m) => Applicative (Query m) where
  pure :: forall a. a -> Query m a
pure a
a = (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query (ReadsWrites
forall a. Monoid a => a
mempty,,a -> DynamicQuery m a
forall a. a -> DynamicQuery m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a)
  {-# INLINE pure #-}

  (Query Components -> (ReadsWrites, Components, DynamicQuery m (a -> b))
f) <*> :: forall a b. Query m (a -> b) -> Query m a -> Query m b
<*> (Query Components -> (ReadsWrites, Components, DynamicQuery m a)
g) = (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m b))
 -> Query m b)
-> (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
    let !(ReadsWrites
cIdsG, Components
cs', DynamicQuery m a
aQS) = Components -> (ReadsWrites, Components, DynamicQuery m a)
g Components
cs
        !(ReadsWrites
cIdsF, Components
cs'', DynamicQuery m (a -> b)
bQS) = Components -> (ReadsWrites, Components, DynamicQuery m (a -> b))
f Components
cs'
     in (ReadsWrites
cIdsG ReadsWrites -> ReadsWrites -> ReadsWrites
forall a. Semigroup a => a -> a -> a
<> ReadsWrites
cIdsF, Components
cs'', DynamicQuery m (a -> b)
bQS DynamicQuery m (a -> b) -> DynamicQuery m a -> DynamicQuery m b
forall a b.
DynamicQuery m (a -> b) -> DynamicQuery m a -> DynamicQuery m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> DynamicQuery m a
aQS)
  {-# INLINE (<*>) #-}

instance (Monad m) => DynamicQueryF m (Query m) where
  entity :: Query m EntityID
entity = (Components -> (ReadsWrites, Components, DynamicQuery m EntityID))
-> Query m EntityID
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query (ReadsWrites
forall a. Monoid a => a
mempty,,DynamicQuery m EntityID
forall (m :: * -> *) (f :: * -> *). DynamicQueryF m f => f EntityID
entity)
  {-# INLINE entity #-}

  queryDyn :: forall a. Component m a => ComponentID -> Query m a
queryDyn = (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryReader ComponentID -> DynamicQuery m a
forall a. Component m a => ComponentID -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
ComponentID -> f a
queryDyn
  {-# INLINE queryDyn #-}

  queryMaybeDyn :: forall a. Component m a => ComponentID -> Query m (Maybe a)
queryMaybeDyn = (ComponentID -> DynamicQuery m (Maybe a))
-> ComponentID -> Query m (Maybe a)
forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryReader ComponentID -> DynamicQuery m (Maybe a)
forall a. Component m a => ComponentID -> DynamicQuery m (Maybe a)
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
ComponentID -> f (Maybe a)
queryMaybeDyn
  {-# INLINE queryMaybeDyn #-}

  queryMapDyn :: forall a. Component m a => (a -> a) -> ComponentID -> Query m a
queryMapDyn a -> a
f = (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryWriter' ((ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a)
-> (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
forall a b. (a -> b) -> a -> b
$ (a -> a) -> ComponentID -> DynamicQuery m a
forall a.
Component m a =>
(a -> a) -> ComponentID -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
(a -> a) -> ComponentID -> f a
queryMapDyn a -> a
f
  {-# INLINE queryMapDyn #-}

  queryMapDyn_ :: forall a. Component m a => (a -> a) -> ComponentID -> Query m ()
queryMapDyn_ a -> a
f = (ComponentID -> DynamicQuery m ()) -> ComponentID -> Query m ()
forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryWriter' ((ComponentID -> DynamicQuery m ()) -> ComponentID -> Query m ())
-> (ComponentID -> DynamicQuery m ()) -> ComponentID -> Query m ()
forall a b. (a -> b) -> a -> b
$ (a -> a) -> ComponentID -> DynamicQuery m ()
forall a.
Component m a =>
(a -> a) -> ComponentID -> DynamicQuery m ()
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
(a -> a) -> ComponentID -> f ()
queryMapDyn_ a -> a
f
  {-# INLINE queryMapDyn_ #-}

  queryMapDynM :: forall a.
(Monad m, Component m a) =>
(a -> m a) -> ComponentID -> Query m a
queryMapDynM a -> m a
f = (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryWriter' ((ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a)
-> (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
forall a b. (a -> b) -> a -> b
$ (a -> m a) -> ComponentID -> DynamicQuery m a
forall a.
(Monad m, Component m a) =>
(a -> m a) -> ComponentID -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Monad m, Component m a) =>
(a -> m a) -> ComponentID -> f a
queryMapDynM a -> m a
f
  {-# INLINE queryMapDynM #-}

  queryMapDynWith :: forall b a.
Component m b =>
(a -> b -> b) -> ComponentID -> Query m a -> Query m b
queryMapDynWith a -> b -> b
f = (ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
forall (m :: * -> *) a b.
(ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
dynQueryWriter ((ComponentID -> DynamicQuery m a -> DynamicQuery m b)
 -> ComponentID -> Query m a -> Query m b)
-> (ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID
-> Query m a
-> Query m b
forall a b. (a -> b) -> a -> b
$ (a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall b a.
Component m b =>
(a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall (m :: * -> *) (f :: * -> *) b a.
(DynamicQueryF m f, Component m b) =>
(a -> b -> b) -> ComponentID -> f a -> f b
queryMapDynWith a -> b -> b
f
  {-# INLINE queryMapDynWith #-}

  queryMapDynWith_ :: forall b a.
Component m b =>
(a -> b -> b) -> ComponentID -> Query m a -> Query m ()
queryMapDynWith_ a -> b -> b
f = (ComponentID -> DynamicQuery m a -> DynamicQuery m ())
-> ComponentID -> Query m a -> Query m ()
forall (m :: * -> *) a b.
(ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
dynQueryWriter ((ComponentID -> DynamicQuery m a -> DynamicQuery m ())
 -> ComponentID -> Query m a -> Query m ())
-> (ComponentID -> DynamicQuery m a -> DynamicQuery m ())
-> ComponentID
-> Query m a
-> Query m ()
forall a b. (a -> b) -> a -> b
$ (a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m ()
forall b a.
Component m b =>
(a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m ()
forall (m :: * -> *) (f :: * -> *) b a.
(DynamicQueryF m f, Component m b) =>
(a -> b -> b) -> ComponentID -> f a -> f ()
queryMapDynWith_ a -> b -> b
f
  {-# INLINE queryMapDynWith_ #-}

  queryMapDynWithM :: forall b a.
(Monad m, Component m b) =>
(a -> b -> m b) -> ComponentID -> Query m a -> Query m b
queryMapDynWithM a -> b -> m b
f = (ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
forall (m :: * -> *) a b.
(ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
dynQueryWriter ((ComponentID -> DynamicQuery m a -> DynamicQuery m b)
 -> ComponentID -> Query m a -> Query m b)
-> (ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID
-> Query m a
-> Query m b
forall a b. (a -> b) -> a -> b
$ (a -> b -> m b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall b a.
(Monad m, Component m b) =>
(a -> b -> m b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall (m :: * -> *) (f :: * -> *) b a.
(DynamicQueryF m f, Monad m, Component m b) =>
(a -> b -> m b) -> ComponentID -> f a -> f b
queryMapDynWithM a -> b -> m b
f
  {-# INLINE queryMapDynWithM #-}

  queryMapDynWithAccum :: forall c b a.
Component m c =>
(b -> c -> (a, c)) -> ComponentID -> Query m b -> Query m (a, c)
queryMapDynWithAccum b -> c -> (a, c)
f = (ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
-> ComponentID -> Query m b -> Query m (a, c)
forall (m :: * -> *) a b.
(ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
dynQueryWriter ((ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
 -> ComponentID -> Query m b -> Query m (a, c))
-> (ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
-> ComponentID
-> Query m b
-> Query m (a, c)
forall a b. (a -> b) -> a -> b
$ (b -> c -> (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall c b a.
Component m c =>
(b -> c -> (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall (m :: * -> *) (f :: * -> *) c b a.
(DynamicQueryF m f, Component m c) =>
(b -> c -> (a, c)) -> ComponentID -> f b -> f (a, c)
queryMapDynWithAccum b -> c -> (a, c)
f
  {-# INLINE queryMapDynWithAccum #-}

  queryUntracked :: forall a. Query m a -> Query m a
queryUntracked (Query Components -> (ReadsWrites, Components, DynamicQuery m a)
q) = (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m a))
 -> Query m a)
-> (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
    let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Components -> (ReadsWrites, Components, DynamicQuery m a)
q Components
cs
     in (ReadsWrites
rws, Components
cs', DynamicQuery m a -> DynamicQuery m a
forall a. DynamicQuery m a -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
DynamicQueryF m f =>
f a -> f a
queryUntracked DynamicQuery m a
dynQ)
  {-# INLINE queryUntracked #-}

  queryMapDynWithAccumM :: forall c b a.
(Monad m, Component m c) =>
(b -> c -> m (a, c)) -> ComponentID -> Query m b -> Query m (a, c)
queryMapDynWithAccumM b -> c -> m (a, c)
f = (ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
-> ComponentID -> Query m b -> Query m (a, c)
forall (m :: * -> *) a b.
(ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
dynQueryWriter ((ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
 -> ComponentID -> Query m b -> Query m (a, c))
-> (ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
-> ComponentID
-> Query m b
-> Query m (a, c)
forall a b. (a -> b) -> a -> b
$ (b -> c -> m (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall c b a.
(Monad m, Component m c) =>
(b -> c -> m (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall (m :: * -> *) (f :: * -> *) c b a.
(DynamicQueryF m f, Monad m, Component m c) =>
(b -> c -> m (a, c)) -> ComponentID -> f b -> f (a, c)
queryMapDynWithAccumM b -> c -> m (a, c)
f
  {-# INLINE queryMapDynWithAccumM #-}

  queryFilterMap :: forall a b. (a -> Maybe b) -> Query m a -> Query m b
queryFilterMap a -> Maybe b
p (Query Components -> (ReadsWrites, Components, DynamicQuery m a)
q) = (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m b))
 -> Query m b)
-> (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
    let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Components -> (ReadsWrites, Components, DynamicQuery m a)
q Components
cs
     in (ReadsWrites
rws, Components
cs', (a -> Maybe b) -> DynamicQuery m a -> DynamicQuery m b
forall a b. (a -> Maybe b) -> DynamicQuery m a -> DynamicQuery m b
forall (m :: * -> *) (f :: * -> *) a b.
DynamicQueryF m f =>
(a -> Maybe b) -> f a -> f b
queryFilterMap a -> Maybe b
p DynamicQuery m a
dynQ)
  {-# INLINE queryFilterMap #-}

-- | Query a component.

query :: forall m a. (Monad m, Component m a) => Query m a
query :: forall (m :: * -> *) a. (Monad m, Component m a) => Query m a
query = forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryReader @m @a ComponentID -> DynamicQuery m a
forall a. Component m a => ComponentID -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
ComponentID -> f a
queryDyn
{-# INLINE query #-}

-- | Optionally query a component, returning @Nothing@ if it does not exist.

queryMaybe :: forall m a. (Monad m, Component m a) => Query m (Maybe a)
queryMaybe :: forall (m :: * -> *) a.
(Monad m, Component m a) =>
Query m (Maybe a)
queryMaybe = forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryReader @m @a ComponentID -> DynamicQuery m (Maybe a)
forall a. Component m a => ComponentID -> DynamicQuery m (Maybe a)
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
ComponentID -> f (Maybe a)
queryMaybeDyn
{-# INLINE queryMaybe #-}

-- | Query a component and update it.

queryMap :: forall m a. (Monad m, Component m a) => (a -> a) -> Query m a
queryMap :: forall (m :: * -> *) a.
(Monad m, Component m a) =>
(a -> a) -> Query m a
queryMap a -> a
f = forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryWriter' @m @a ((ComponentID -> DynamicQuery m a) -> Query m a)
-> (ComponentID -> DynamicQuery m a) -> Query m a
forall a b. (a -> b) -> a -> b
$ (a -> a) -> ComponentID -> DynamicQuery m a
forall a.
Component m a =>
(a -> a) -> ComponentID -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
(a -> a) -> ComponentID -> f a
queryMapDyn a -> a
f
{-# INLINE queryMap #-}

-- | Query a component and update it, ignoring any output.

queryMap_ :: forall m a. (Monad m, Component m a) => (a -> a) -> Query m ()
queryMap_ :: forall (m :: * -> *) a.
(Monad m, Component m a) =>
(a -> a) -> Query m ()
queryMap_ a -> a
f = forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryWriter' @m @a ((ComponentID -> DynamicQuery m ()) -> Query m ())
-> (ComponentID -> DynamicQuery m ()) -> Query m ()
forall a b. (a -> b) -> a -> b
$ (a -> a) -> ComponentID -> DynamicQuery m ()
forall a.
Component m a =>
(a -> a) -> ComponentID -> DynamicQuery m ()
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Component m a) =>
(a -> a) -> ComponentID -> f ()
queryMapDyn_ a -> a
f
{-# INLINE queryMap_ #-}

-- | Query a component and update it with a monadic action.

queryMapM :: forall m a. (Monad m, Component m a) => (a -> m a) -> Query m a
queryMapM :: forall (m :: * -> *) a.
(Monad m, Component m a) =>
(a -> m a) -> Query m a
queryMapM a -> m a
f = forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryWriter' @m @a ((ComponentID -> DynamicQuery m a) -> Query m a)
-> (ComponentID -> DynamicQuery m a) -> Query m a
forall a b. (a -> b) -> a -> b
$ (a -> m a) -> ComponentID -> DynamicQuery m a
forall a.
(Monad m, Component m a) =>
(a -> m a) -> ComponentID -> DynamicQuery m a
forall (m :: * -> *) (f :: * -> *) a.
(DynamicQueryF m f, Monad m, Component m a) =>
(a -> m a) -> ComponentID -> f a
queryMapDynM a -> m a
f
{-# INLINE queryMapM #-}

-- | Query a component with input and update it.

queryMapWith :: forall m a b. (Monad m, Component m b) => (a -> b -> b) -> Query m a -> Query m b
queryMapWith :: forall (m :: * -> *) a b.
(Monad m, Component m b) =>
(a -> b -> b) -> Query m a -> Query m b
queryMapWith a -> b -> b
f = forall (m :: * -> *) a b c.
Component m a =>
(ComponentID -> DynamicQuery m b -> DynamicQuery m c)
-> Query m b -> Query m c
queryWriter @m @b ((ComponentID -> DynamicQuery m a -> DynamicQuery m b)
 -> Query m a -> Query m b)
-> (ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> Query m a
-> Query m b
forall a b. (a -> b) -> a -> b
$ (a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall b a.
Component m b =>
(a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall (m :: * -> *) (f :: * -> *) b a.
(DynamicQueryF m f, Component m b) =>
(a -> b -> b) -> ComponentID -> f a -> f b
queryMapDynWith a -> b -> b
f
{-# INLINE queryMapWith #-}

-- | Query a component with input and update it, ignoring any output.

queryMapWith_ :: forall m a b. (Monad m, Component m b) => (a -> b -> b) -> Query m a -> Query m ()
queryMapWith_ :: forall (m :: * -> *) a b.
(Monad m, Component m b) =>
(a -> b -> b) -> Query m a -> Query m ()
queryMapWith_ a -> b -> b
f = forall (m :: * -> *) a b c.
Component m a =>
(ComponentID -> DynamicQuery m b -> DynamicQuery m c)
-> Query m b -> Query m c
queryWriter @m @b ((ComponentID -> DynamicQuery m a -> DynamicQuery m ())
 -> Query m a -> Query m ())
-> (ComponentID -> DynamicQuery m a -> DynamicQuery m ())
-> Query m a
-> Query m ()
forall a b. (a -> b) -> a -> b
$ (a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m ()
forall b a.
Component m b =>
(a -> b -> b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m ()
forall (m :: * -> *) (f :: * -> *) b a.
(DynamicQueryF m f, Component m b) =>
(a -> b -> b) -> ComponentID -> f a -> f ()
queryMapDynWith_ a -> b -> b
f
{-# INLINE queryMapWith_ #-}

-- | Query a component with input and update it with a monadic action.

queryMapWithM ::
  forall m a b.
  (Monad m, Component m b) =>
  (a -> b -> m b) ->
  Query m a ->
  Query m b
queryMapWithM :: forall (m :: * -> *) a b.
(Monad m, Component m b) =>
(a -> b -> m b) -> Query m a -> Query m b
queryMapWithM a -> b -> m b
f = forall (m :: * -> *) a b c.
Component m a =>
(ComponentID -> DynamicQuery m b -> DynamicQuery m c)
-> Query m b -> Query m c
queryWriter @m @b ((ComponentID -> DynamicQuery m a -> DynamicQuery m b)
 -> Query m a -> Query m b)
-> (ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> Query m a
-> Query m b
forall a b. (a -> b) -> a -> b
$ (a -> b -> m b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall b a.
(Monad m, Component m b) =>
(a -> b -> m b)
-> ComponentID -> DynamicQuery m a -> DynamicQuery m b
forall (m :: * -> *) (f :: * -> *) b a.
(DynamicQueryF m f, Monad m, Component m b) =>
(a -> b -> m b) -> ComponentID -> f a -> f b
queryMapDynWithM a -> b -> m b
f
{-# INLINE queryMapWithM #-}

-- | Query a component with input, returning a tuple of the result and the updated component.

queryMapWithAccum ::
  forall m a b c.
  (Monad m, Component m c) =>
  (b -> c -> (a, c)) ->
  Query m b ->
  Query m (a, c)
queryMapWithAccum :: forall (m :: * -> *) a b c.
(Monad m, Component m c) =>
(b -> c -> (a, c)) -> Query m b -> Query m (a, c)
queryMapWithAccum b -> c -> (a, c)
f = forall (m :: * -> *) a b c.
Component m a =>
(ComponentID -> DynamicQuery m b -> DynamicQuery m c)
-> Query m b -> Query m c
queryWriter @m @c ((ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
 -> Query m b -> Query m (a, c))
-> (ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
-> Query m b
-> Query m (a, c)
forall a b. (a -> b) -> a -> b
$ (b -> c -> (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall c b a.
Component m c =>
(b -> c -> (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall (m :: * -> *) (f :: * -> *) c b a.
(DynamicQueryF m f, Component m c) =>
(b -> c -> (a, c)) -> ComponentID -> f b -> f (a, c)
queryMapDynWithAccum b -> c -> (a, c)
f
{-# INLINE queryMapWithAccum #-}

-- | Query a component with input and update it with a monadic action, returning a tuple.

queryMapWithAccumM ::
  forall m a b c.
  (Monad m, Component m c) =>
  (b -> c -> m (a, c)) ->
  Query m b ->
  Query m (a, c)
queryMapWithAccumM :: forall (m :: * -> *) a b c.
(Monad m, Component m c) =>
(b -> c -> m (a, c)) -> Query m b -> Query m (a, c)
queryMapWithAccumM b -> c -> m (a, c)
f = forall (m :: * -> *) a b c.
Component m a =>
(ComponentID -> DynamicQuery m b -> DynamicQuery m c)
-> Query m b -> Query m c
queryWriter @m @c ((ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
 -> Query m b -> Query m (a, c))
-> (ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c))
-> Query m b
-> Query m (a, c)
forall a b. (a -> b) -> a -> b
$ (b -> c -> m (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall c b a.
(Monad m, Component m c) =>
(b -> c -> m (a, c))
-> ComponentID -> DynamicQuery m b -> DynamicQuery m (a, c)
forall (m :: * -> *) (f :: * -> *) c b a.
(DynamicQueryF m f, Monad m, Component m c) =>
(b -> c -> m (a, c)) -> ComponentID -> f b -> f (a, c)
queryMapDynWithAccumM b -> c -> m (a, c)
f
{-# INLINE queryMapWithAccumM #-}

dynQueryReader :: (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryReader :: forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryReader ComponentID -> DynamicQuery m a
f ComponentID
cId = (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query (ReadsWrites {reads :: Set ComponentID
reads = ComponentID -> Set ComponentID
forall a. a -> Set a
Set.singleton ComponentID
cId, writes :: Set ComponentID
writes = Set ComponentID
forall a. Set a
Set.empty},,ComponentID -> DynamicQuery m a
f ComponentID
cId)
{-# INLINE dynQueryReader #-}

dynQueryWriter ::
  ( ComponentID ->
    DynamicQuery m a ->
    DynamicQuery m b
  ) ->
  ComponentID ->
  Query m a ->
  Query m b
dynQueryWriter :: forall (m :: * -> *) a b.
(ComponentID -> DynamicQuery m a -> DynamicQuery m b)
-> ComponentID -> Query m a -> Query m b
dynQueryWriter ComponentID -> DynamicQuery m a -> DynamicQuery m b
f ComponentID
cId Query m a
q = (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m b))
 -> Query m b)
-> (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m a
q Components
cs
   in (ReadsWrites
rws ReadsWrites -> ReadsWrites -> ReadsWrites
forall a. Semigroup a => a -> a -> a
<> Set ComponentID -> Set ComponentID -> ReadsWrites
ReadsWrites Set ComponentID
forall a. Set a
Set.empty (ComponentID -> Set ComponentID
forall a. a -> Set a
Set.singleton ComponentID
cId), Components
cs', ComponentID -> DynamicQuery m a -> DynamicQuery m b
f ComponentID
cId DynamicQuery m a
dynQ)
{-# INLINE dynQueryWriter #-}

dynQueryWriter' :: (ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryWriter' :: forall (m :: * -> *) a.
(ComponentID -> DynamicQuery m a) -> ComponentID -> Query m a
dynQueryWriter' ComponentID -> DynamicQuery m a
f ComponentID
cId = (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query (ReadsWrites {reads :: Set ComponentID
reads = Set ComponentID
forall a. Set a
Set.empty, writes :: Set ComponentID
writes = ComponentID -> Set ComponentID
forall a. a -> Set a
Set.singleton ComponentID
cId},,ComponentID -> DynamicQuery m a
f ComponentID
cId)
{-# INLINE dynQueryWriter' #-}

queryReader :: forall m a b. (Component m a) => (ComponentID -> DynamicQuery m b) -> Query m b
queryReader :: forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryReader ComponentID -> DynamicQuery m b
f = (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m b))
 -> Query m b)
-> (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ComponentID
cId, Components
cs') = forall a (m :: * -> *).
Component m a =>
Components -> (ComponentID, Components)
CS.insert @a @m Components
cs
   in (ReadsWrites {reads :: Set ComponentID
reads = ComponentID -> Set ComponentID
forall a. a -> Set a
Set.singleton ComponentID
cId, writes :: Set ComponentID
writes = Set ComponentID
forall a. Set a
Set.empty}, Components
cs', ComponentID -> DynamicQuery m b
f ComponentID
cId)
{-# INLINE queryReader #-}

queryWriter ::
  forall m a b c.
  (Component m a) =>
  ( ComponentID ->
    DynamicQuery m b ->
    DynamicQuery m c
  ) ->
  Query m b ->
  Query m c
queryWriter :: forall (m :: * -> *) a b c.
Component m a =>
(ComponentID -> DynamicQuery m b -> DynamicQuery m c)
-> Query m b -> Query m c
queryWriter ComponentID -> DynamicQuery m b -> DynamicQuery m c
f (Query Components -> (ReadsWrites, Components, DynamicQuery m b)
g) = (Components -> (ReadsWrites, Components, DynamicQuery m c))
-> Query m c
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m c))
 -> Query m c)
-> (Components -> (ReadsWrites, Components, DynamicQuery m c))
-> Query m c
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m b
dynQ) = Components -> (ReadsWrites, Components, DynamicQuery m b)
g Components
cs
      !(ComponentID
cId, Components
cs'') = forall a (m :: * -> *).
Component m a =>
Components -> (ComponentID, Components)
CS.insert @a @m Components
cs'
   in (ReadsWrites
rws ReadsWrites -> ReadsWrites -> ReadsWrites
forall a. Semigroup a => a -> a -> a
<> Set ComponentID -> Set ComponentID -> ReadsWrites
ReadsWrites Set ComponentID
forall a. Set a
Set.empty (ComponentID -> Set ComponentID
forall a. a -> Set a
Set.singleton ComponentID
cId), Components
cs'', ComponentID -> DynamicQuery m b -> DynamicQuery m c
f ComponentID
cId DynamicQuery m b
dynQ)
{-# INLINE queryWriter #-}

queryWriter' :: forall m a b. (Component m a) => (ComponentID -> DynamicQuery m b) -> Query m b
queryWriter' :: forall (m :: * -> *) a b.
Component m a =>
(ComponentID -> DynamicQuery m b) -> Query m b
queryWriter' ComponentID -> DynamicQuery m b
f = (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall (m :: * -> *) a.
(Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Query m a
Query ((Components -> (ReadsWrites, Components, DynamicQuery m b))
 -> Query m b)
-> (Components -> (ReadsWrites, Components, DynamicQuery m b))
-> Query m b
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ComponentID
cId, Components
cs') = forall a (m :: * -> *).
Component m a =>
Components -> (ComponentID, Components)
CS.insert @a @m Components
cs
   in (ReadsWrites {reads :: Set ComponentID
reads = Set ComponentID
forall a. Set a
Set.empty, writes :: Set ComponentID
writes = ComponentID -> Set ComponentID
forall a. a -> Set a
Set.singleton ComponentID
cId}, Components
cs', ComponentID -> DynamicQuery m b
f ComponentID
cId)
{-# INLINE queryWriter' #-}

-- | Reads and writes of a `Query`.

data ReadsWrites = ReadsWrites
  { -- | Component IDs being read.

    ReadsWrites -> Set ComponentID
reads :: !(Set ComponentID),
    -- | Component IDs being written.

    ReadsWrites -> Set ComponentID
writes :: !(Set ComponentID)
  }
  deriving (Int -> ReadsWrites -> ShowS
[ReadsWrites] -> ShowS
ReadsWrites -> String
(Int -> ReadsWrites -> ShowS)
-> (ReadsWrites -> String)
-> ([ReadsWrites] -> ShowS)
-> Show ReadsWrites
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReadsWrites -> ShowS
showsPrec :: Int -> ReadsWrites -> ShowS
$cshow :: ReadsWrites -> String
show :: ReadsWrites -> String
$cshowList :: [ReadsWrites] -> ShowS
showList :: [ReadsWrites] -> ShowS
Show)

instance Semigroup ReadsWrites where
  ReadsWrites Set ComponentID
r1 Set ComponentID
w1 <> :: ReadsWrites -> ReadsWrites -> ReadsWrites
<> ReadsWrites Set ComponentID
r2 Set ComponentID
w2 = Set ComponentID -> Set ComponentID -> ReadsWrites
ReadsWrites (Set ComponentID
r1 Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> Set ComponentID
r2) (Set ComponentID
w1 Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> Set ComponentID
w2)
  {-# INLINE (<>) #-}

instance Monoid ReadsWrites where
  mempty :: ReadsWrites
mempty = Set ComponentID -> Set ComponentID -> ReadsWrites
ReadsWrites Set ComponentID
forall a. Monoid a => a
mempty Set ComponentID
forall a. Monoid a => a
mempty
  {-# INLINE mempty #-}

-- | `True` if the reads and writes of two `Query`s overlap.

disjoint :: ReadsWrites -> ReadsWrites -> Bool
disjoint :: ReadsWrites -> ReadsWrites -> Bool
disjoint ReadsWrites
a ReadsWrites
b =
  Set ComponentID -> Set ComponentID -> Bool
forall a. Ord a => Set a -> Set a -> Bool
Set.disjoint (ReadsWrites -> Set ComponentID
reads ReadsWrites
a) (ReadsWrites -> Set ComponentID
writes ReadsWrites
b)
    Bool -> Bool -> Bool
|| Set ComponentID -> Set ComponentID -> Bool
forall a. Ord a => Set a -> Set a -> Bool
Set.disjoint (ReadsWrites -> Set ComponentID
reads ReadsWrites
b) (ReadsWrites -> Set ComponentID
writes ReadsWrites
a)
    Bool -> Bool -> Bool
|| Set ComponentID -> Set ComponentID -> Bool
forall a. Ord a => Set a -> Set a -> Bool
Set.disjoint (ReadsWrites -> Set ComponentID
writes ReadsWrites
b) (ReadsWrites -> Set ComponentID
writes ReadsWrites
a)

-- | Match all entities.

readQuery :: (Monad m) => Query m a -> Entities m -> m (Vector a, Entities m)
readQuery :: forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Vector a, Entities m)
readQuery Query m a
q Entities m
es = do
  (Vector a
as, Components
cs) <- Query m a -> Entities m -> m (Vector a, Components)
forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Vector a, Components)
readQuery' Query m a
q Entities m
es
  (Vector a, Entities m) -> m (Vector a, Entities m)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector a
as, Entities m
es {E.components = cs})
{-# INLINE readQuery #-}

-- | Match all entities.

readQuery' :: (Monad m) => Query m a -> Entities m -> m (Vector a, Components)
readQuery' :: forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Vector a, Components)
readQuery' Query m a
q Entities m
es = do
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m a
q (Entities m -> Components
forall (m :: * -> *). Entities m -> Components
E.components Entities m
es)
      !cIds :: Set ComponentID
cIds = ReadsWrites -> Set ComponentID
reads ReadsWrites
rws Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> ReadsWrites -> Set ComponentID
writes ReadsWrites
rws
  Vector a
as <- Set ComponentID -> DynamicQuery m a -> Entities m -> m (Vector a)
forall (m :: * -> *) a.
Monad m =>
Set ComponentID -> DynamicQuery m a -> Entities m -> m (Vector a)
readQueryDyn Set ComponentID
cIds DynamicQuery m a
dynQ Entities m
es
  (Vector a, Components) -> m (Vector a, Components)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector a
as, Components
cs')
{-# INLINE readQuery' #-}

-- | Match a single entity.

readQuerySingle :: (HasCallStack, Monad m) => Query m a -> Entities m -> m (a, Entities m)
readQuerySingle :: forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
Query m a -> Entities m -> m (a, Entities m)
readQuerySingle Query m a
q Entities m
es = do
  (a
a, Components
cs) <- Query m a -> Entities m -> m (a, Components)
forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
Query m a -> Entities m -> m (a, Components)
readQuerySingle' Query m a
q Entities m
es
  (a, Entities m) -> m (a, Entities m)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, Entities m
es {E.components = cs})
{-# INLINE readQuerySingle #-}

-- | Match a single entity.

readQuerySingle' :: (HasCallStack, Monad m) => Query m a -> Entities m -> m (a, Components)
readQuerySingle' :: forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
Query m a -> Entities m -> m (a, Components)
readQuerySingle' Query m a
q Entities m
es = do
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m a
q (Entities m -> Components
forall (m :: * -> *). Entities m -> Components
E.components Entities m
es)
      !cIds :: Set ComponentID
cIds = ReadsWrites -> Set ComponentID
reads ReadsWrites
rws Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> ReadsWrites -> Set ComponentID
writes ReadsWrites
rws
  a
a <- Set ComponentID -> DynamicQuery m a -> Entities m -> m a
forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
Set ComponentID -> DynamicQuery m a -> Entities m -> m a
readQuerySingleDyn Set ComponentID
cIds DynamicQuery m a
dynQ Entities m
es
  (a, Components) -> m (a, Components)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, Components
cs')
{-# INLINE readQuerySingle' #-}

-- | Match a single entity.

readQuerySingleMaybe :: (Monad m) => Query m a -> Entities m -> m (Maybe a, Entities m)
readQuerySingleMaybe :: forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Maybe a, Entities m)
readQuerySingleMaybe Query m a
q Entities m
es = do
  (Maybe a
a, Components
cs) <- Query m a -> Entities m -> m (Maybe a, Components)
forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Maybe a, Components)
readQuerySingleMaybe' Query m a
q Entities m
es
  (Maybe a, Entities m) -> m (Maybe a, Entities m)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a
a, Entities m
es {E.components = cs})
{-# INLINE readQuerySingleMaybe #-}

-- | Match a single entity.

readQuerySingleMaybe' :: (Monad m) => Query m a -> Entities m -> m (Maybe a, Components)
readQuerySingleMaybe' :: forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Maybe a, Components)
readQuerySingleMaybe' Query m a
q Entities m
es = do
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m a
q (Entities m -> Components
forall (m :: * -> *). Entities m -> Components
E.components Entities m
es)
      !cIds :: Set ComponentID
cIds = ReadsWrites -> Set ComponentID
reads ReadsWrites
rws Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> ReadsWrites -> Set ComponentID
writes ReadsWrites
rws
  Maybe a
a <- Set ComponentID -> DynamicQuery m a -> Entities m -> m (Maybe a)
forall (m :: * -> *) a.
Monad m =>
Set ComponentID -> DynamicQuery m a -> Entities m -> m (Maybe a)
readQuerySingleMaybeDyn Set ComponentID
cIds DynamicQuery m a
dynQ Entities m
es
  (Maybe a, Components) -> m (Maybe a, Components)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a
a, Components
cs')
{-# INLINE readQuerySingleMaybe' #-}

-- | Map all matched entities.

runQuery :: (Monad m) => Query m o -> Entities m -> m (Vector o, Entities m, Access m ())
runQuery :: forall (m :: * -> *) o.
Monad m =>
Query m o -> Entities m -> m (Vector o, Entities m, Access m ())
runQuery Query m o
q Entities m
es = do
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m o
dynQ) = Query m o
-> Components -> (ReadsWrites, Components, DynamicQuery m o)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m o
q (Components -> (ReadsWrites, Components, DynamicQuery m o))
-> Components -> (ReadsWrites, Components, DynamicQuery m o)
forall a b. (a -> b) -> a -> b
$ Entities m -> Components
forall (m :: * -> *). Entities m -> Components
components Entities m
es
      !cIds :: Set ComponentID
cIds = ReadsWrites -> Set ComponentID
reads ReadsWrites
rws Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> ReadsWrites -> Set ComponentID
writes ReadsWrites
rws
  (Vector o
as, Entities m
es', Access m ()
hook) <- Set ComponentID
-> DynamicQuery m o
-> Entities m
-> m (Vector o, Entities m, Access m ())
forall (m :: * -> *) a.
Monad m =>
Set ComponentID
-> DynamicQuery m a
-> Entities m
-> m (Vector a, Entities m, Access m ())
runQueryDyn Set ComponentID
cIds DynamicQuery m o
dynQ Entities m
es
  (Vector o, Entities m, Access m ())
-> m (Vector o, Entities m, Access m ())
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Vector o
as, Entities m
es' {components = cs'}, Access m ()
hook)
{-# INLINE runQuery #-}

-- | Map a single matched entity.

runQuerySingle ::
  (HasCallStack, Monad m) =>
  Query m a ->
  Entities m ->
  m (a, Entities m, Access m ())
runQuerySingle :: forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
Query m a -> Entities m -> m (a, Entities m, Access m ())
runQuerySingle Query m a
q Entities m
es = do
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m a
q (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall a b. (a -> b) -> a -> b
$ Entities m -> Components
forall (m :: * -> *). Entities m -> Components
components Entities m
es
      !cIds :: Set ComponentID
cIds = ReadsWrites -> Set ComponentID
reads ReadsWrites
rws Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> ReadsWrites -> Set ComponentID
writes ReadsWrites
rws
  (a
as, Entities m
es', Access m ()
hook) <- Set ComponentID
-> DynamicQuery m a -> Entities m -> m (a, Entities m, Access m ())
forall (m :: * -> *) a.
(HasCallStack, Monad m) =>
Set ComponentID
-> DynamicQuery m a -> Entities m -> m (a, Entities m, Access m ())
runQuerySingleDyn Set ComponentID
cIds DynamicQuery m a
dynQ Entities m
es
  (a, Entities m, Access m ()) -> m (a, Entities m, Access m ())
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
as, Entities m
es' {components = cs'}, Access m ()
hook)
{-# INLINE runQuerySingle #-}

-- | Map a single matched entity, or `Nothing`.

runQuerySingleMaybe ::
  (Monad m) =>
  Query m a ->
  Entities m ->
  m (Maybe a, Entities m, Access m ())
runQuerySingleMaybe :: forall (m :: * -> *) a.
Monad m =>
Query m a -> Entities m -> m (Maybe a, Entities m, Access m ())
runQuerySingleMaybe Query m a
q Entities m
es = do
  let !(ReadsWrites
rws, Components
cs', DynamicQuery m a
dynQ) = Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall (m :: * -> *) a.
Query m a
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
runQuery' Query m a
q (Components -> (ReadsWrites, Components, DynamicQuery m a))
-> Components -> (ReadsWrites, Components, DynamicQuery m a)
forall a b. (a -> b) -> a -> b
$ Entities m -> Components
forall (m :: * -> *). Entities m -> Components
components Entities m
es
      !cIds :: Set ComponentID
cIds = ReadsWrites -> Set ComponentID
reads ReadsWrites
rws Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> ReadsWrites -> Set ComponentID
writes ReadsWrites
rws
  (Maybe a
as, Entities m
es', Access m ()
hook) <- Set ComponentID
-> DynamicQuery m a
-> Entities m
-> m (Maybe a, Entities m, Access m ())
forall (m :: * -> *) a.
Monad m =>
Set ComponentID
-> DynamicQuery m a
-> Entities m
-> m (Maybe a, Entities m, Access m ())
runQuerySingleMaybeDyn Set ComponentID
cIds DynamicQuery m a
dynQ Entities m
es
  (Maybe a, Entities m, Access m ())
-> m (Maybe a, Entities m, Access m ())
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a
as, Entities m
es' {components = cs'}, Access m ()
hook)
{-# INLINE runQuerySingleMaybe #-}

-- | Filter for a `Query`.

newtype QueryFilter = QueryFilter
  { -- | Run a query filter.

    QueryFilter -> Components -> (DynamicQueryFilter, Components)
runQueryFilter :: Components -> (DynamicQueryFilter, Components)
  }

instance Semigroup QueryFilter where
  QueryFilter
a <> :: QueryFilter -> QueryFilter -> QueryFilter
<> QueryFilter
b =
    (Components -> (DynamicQueryFilter, Components)) -> QueryFilter
QueryFilter
      ( \Components
cs ->
          let !(DynamicQueryFilter
withA', Components
cs') = QueryFilter -> Components -> (DynamicQueryFilter, Components)
runQueryFilter QueryFilter
a Components
cs
              !(DynamicQueryFilter
withB', Components
cs'') = QueryFilter -> Components -> (DynamicQueryFilter, Components)
runQueryFilter QueryFilter
b Components
cs'
           in (DynamicQueryFilter
withA' DynamicQueryFilter -> DynamicQueryFilter -> DynamicQueryFilter
forall a. Semigroup a => a -> a -> a
<> DynamicQueryFilter
withB', Components
cs'')
      )

instance Monoid QueryFilter where
  mempty :: QueryFilter
mempty = (Components -> (DynamicQueryFilter, Components)) -> QueryFilter
QueryFilter (DynamicQueryFilter
forall a. Monoid a => a
mempty,)

-- | Filter for entities containing this component.

with :: forall m a. (Component m a) => QueryFilter
with :: forall (m :: * -> *) a. Component m a => QueryFilter
with = (Components -> (DynamicQueryFilter, Components)) -> QueryFilter
QueryFilter ((Components -> (DynamicQueryFilter, Components)) -> QueryFilter)
-> (Components -> (DynamicQueryFilter, Components)) -> QueryFilter
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ComponentID
cId, Components
cs') = forall a (m :: * -> *).
Component m a =>
Components -> (ComponentID, Components)
CS.insert @a @m Components
cs in (DynamicQueryFilter
forall a. Monoid a => a
mempty {filterWith = Set.singleton cId}, Components
cs')

-- | Filter out entities containing this component.

without :: forall m a. (Component m a) => QueryFilter
without :: forall (m :: * -> *) a. Component m a => QueryFilter
without = (Components -> (DynamicQueryFilter, Components)) -> QueryFilter
QueryFilter ((Components -> (DynamicQueryFilter, Components)) -> QueryFilter)
-> (Components -> (DynamicQueryFilter, Components)) -> QueryFilter
forall a b. (a -> b) -> a -> b
$ \Components
cs ->
  let !(ComponentID
cId, Components
cs') = forall a (m :: * -> *).
Component m a =>
Components -> (ComponentID, Components)
CS.insert @a @m Components
cs in (DynamicQueryFilter
forall a. Monoid a => a
mempty {filterWithout = Set.singleton cId}, Components
cs')