packages feed

mischief-ecs-0.2.0.0: src/Mischief/ECS/World/Query/Queryable.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}

module Mischief.ECS.World.Query.Queryable where

import Control.Applicative
import Control.Monad.IO.Class
import Data.Bifunctor qualified
import Data.Data
import Data.IORef
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Maybe
import Data.Set (Set)
import Data.Set qualified as Set
import Data.Traversable
import GHC.Base (Int (I#), eqWord#, isTrue#)
import Mischief.ECS.App.SystemDef
import Mischief.ECS.Components
import Mischief.ECS.Entities
import Mischief.ECS.Tables
import Mischief.ECS.Utils
import Mischief.ECS.Vec qualified as Vec
import Mischief.ECS.World
import Mischief.ECS.World.Query.Markers
import Mischief.ECS.World.Query.QueryFilter
import Mischief.ECS.World.Utils

data TypeQuery = CompQ | RelQ | RelQ' Entity deriving (Eq, Ord, Show)

data RelTarget = AnyTarget | RelTargets [Entities]

class Queryable qd output | qd -> output where
  runQueryEntity :: qd -> World -> Entity -> IO (Maybe output)
  runQueryInternal :: qd -> [ArchetypeId] -> World -> IO [(Entity, Bool, output)]
  queryTypes :: qd -> Set (TypeRep, TypeQuery)

data HTrue

data HFalse

type family IsComponentC c where
  IsComponentC Entity = HFalse
  IsComponentC a = HTrue

instance Queryable () () where
  runQueryEntity _ _ _ = pure $ Just ()
  runQueryInternal _ archetypes world = do
    !e <- tryGetEntities world archetypes
    pure $ map (\(!e) -> (e, True, ())) e
  queryTypes _ = Set.empty

instance {-# OVERLAPPABLE #-} (Component c) => Queryable (C c) c where
  runQueryEntity _ !world !entity = do
    !result <- tryGetEntityComponent @c world entity
    return $ case result of
      Just (Just !res) -> Just res
      _ -> Nothing

  runQueryInternal _ !archetypes !world = map (\(!a, !b) -> (a, True, b)) <$> tryGetComponents @c world archetypes

  queryTypes _ = Set.singleton (typeRep (Proxy @c), CompQ)

instance (Component c) => Queryable (c -> Res c) (Res c) where
  runQueryEntity _ !world _ = do
    !x <- getComponentId (typeRep $ Proxy @c) world.components
    case x of
      Nothing -> pure Nothing
      Just (ComponentId (# !id, _ #)) -> do
        let !entity = Entity (# id, 0## #)
        !y <- runQueryEntity (C @c) world entity
        pure $ fmap Res y

  runQueryInternal _ !archetypes !world = do
    !res <- runQueryEntity (Res @c) world (undefined :: Entity)
    !x <- tryGetEntities world archetypes

    pure $ case res of
      Nothing -> map (,False,undefined) x
      Just !res -> map (,True,res) x

  queryTypes _ = Set.empty

instance (Component c) => Queryable (MRes c) (Maybe (Res c)) where
  runQueryEntity _ !world _ = do
    !x <- getComponentId (typeRep $ Proxy @c) world.components
    case x of
      Nothing -> pure (Just Nothing)
      Just (ComponentId (# !id, _ #)) -> do
        let !entity = Entity (# id, 0## #)
        !y <- runQueryEntity (C @c) world entity
        pure $ Just $ fmap Res y

  runQueryInternal _ archetypes world = do
    !res <- runQueryEntity (MRes @c) world (undefined :: Entity)
    !x <- tryGetEntities world archetypes

    pure $ case res of
      Nothing -> map (,False,undefined) x
      Just !res -> map (,True,res) x

  queryTypes _ = Set.empty

instance (Component c) => Queryable (HasRes c) Bool where
  runQueryEntity _ !world _ = do
    !x <- getComponentId (typeRep $ Proxy @c) world.components
    case x of
      Nothing -> pure (Just False)
      Just (ComponentId (# !id, _ #)) -> do
        let !entity = Entity (# id, 0## #)
        !y <- runQueryEntity (C @c) world entity
        pure $ Just $ isJust y

  runQueryInternal _ !archetypes !world = do
    !res <- runQueryEntity (HasRes @c) world (undefined :: Entity)
    !x <- tryGetEntities world archetypes

    pure $ case res of
      Nothing -> map (,False,undefined) x
      Just !res -> map (,True,res) x

  queryTypes _ = Set.empty

instance Queryable E Entity where
  runQueryEntity _ _ entity = return $ Just entity

  runQueryInternal _ archetypes world = map (\x -> (x, True, x)) <$> tryGetEntities world archetypes

  queryTypes _ = Set.empty

class RelQuery (exclusive :: Bool) qd output | qd exclusive -> output where
  relRunQueryEntity :: qd -> World -> Entity -> IO (Maybe output)
  relRunQueryInternal :: qd -> [ArchetypeId] -> World -> IO [(Entity, Bool, output)]
  relQueryTypes :: qd -> Set (TypeRep, TypeQuery)

instance (Component c) => RelQuery False (R c Any) [Rel c] where
  relRunQueryEntity _ !world !entity = do
    !res <- tryGetEntityRelCollection @c world entity
    return $ case res of
      Just (Just !x) -> Just x
      _ -> Nothing

  relRunQueryInternal _ !archetypes !world = map (\(!a, !b) -> (a, True, b)) <$> tryGetRelCollections @c world archetypes

  relQueryTypes _ = Set.singleton (typeRep $ Proxy @c, RelQ)

instance (Component c) => RelQuery True (R c Any) (Rel c) where
  relRunQueryEntity _ !world !entity = do
    !res <- tryGetEntityRelCollection @c world entity
    return $ case res of
      Just (Just [!x]) -> Just x
      _ -> Nothing

  relRunQueryInternal _ !archetypes !world = do
    !rels <- tryGetRelCollections @c world archetypes
    return $ map (\(!e, !x : _) -> (e, True, x)) rels

  relQueryTypes _ = Set.singleton (typeRep $ Proxy @c, RelQ)

instance (Component c, Queryable q out) => RelQuery False (R c (Q q)) [From out] where
  relRunQueryEntity (R (Q !q)) !world !entity = do
    !res <- relRunQueryEntity @False (R @c Any) world entity

    case fmap (traverse $ \(!r) -> fmap (From r.target) <$> runQueryEntity q world r.target) res of
      Nothing -> pure Nothing
      Just !x -> do
        !x <- x
        pure $ case catMaybes x of
          [] -> Nothing
          !x -> Just x

  relRunQueryInternal (R (Q !q)) !archetypes !world = do
    !res <- relRunQueryInternal @False (R @c Any) archetypes world
    for res $ \(!e, !b, !rels) -> do
      !a <- catMaybes <$> (traverse $ \(!r) -> fmap (From r.target) <$> runQueryEntity q world r.target) rels

      pure $ case a of
        [] -> (e, False, undefined)
        !x -> (e, b, x)

  relQueryTypes _ = Set.singleton (typeRep $ Proxy @c, RelQ)

instance (Component c, Queryable q out) => RelQuery False (R c (Q' q QueryFilter)) [From out] where
  relRunQueryEntity (R (Q' !q !f)) !world !entity = do
    !res <- relRunQueryEntity @False (R @c Any) world entity

    case fmap
      ( traverse $ \(!r) -> do
          !t <- filterEntity f world r.target
          if t
            then
              fmap (From r.target) <$> runQueryEntity q world r.target
            else pure Nothing
      )
      res of
      Nothing -> pure Nothing
      Just !x -> do
        !x <- x
        pure $ case catMaybes x of
          [] -> Nothing
          !x -> Just x

  relRunQueryInternal (R (Q' !q !f)) !archetypes !world = do
    !res <- relRunQueryInternal @False (R @c Any) archetypes world
    for res $ \(!e, !b, !rels) -> do
      !a <-
        catMaybes
          <$> ( traverse $ \(!r) -> do
                  !t <- filterEntity f world r.target
                  if t
                    then
                      fmap (From r.target) <$> runQueryEntity q world r.target
                    else pure Nothing
              )
            rels

      pure $ case a of
        [] -> (e, False, undefined)
        !x -> (e, b, x)

  relQueryTypes _ = Set.singleton (typeRep $ Proxy @c, RelQ)

instance (Component c, Queryable q out) => RelQuery True (R c (Q q)) (From out) where
  relRunQueryEntity (R (Q !q)) !world !entity = do
    !res <- relRunQueryEntity @True (R @c Any) world entity

    case fmap (\(!r) -> (r.target, runQueryEntity q world r.target)) res of
      Nothing -> pure Nothing
      Just (!e, !x) -> fmap (From e) <$> x
  relRunQueryInternal (R (Q !q)) !archetypes !world = do
    !res <- relRunQueryInternal @True (R @c Any) archetypes world
    for res $ \(!e, !b, !rels) -> do
      !r <- (\(!r) -> (,r.target) <$> runQueryEntity q world r.target) rels

      pure $ case r of
        (Nothing, _) -> (e, False, undefined)
        (Just !x, !e') -> (e, b, From e' x)

  relQueryTypes _ = Set.singleton (typeRep $ Proxy @c, RelQ)

instance (Component c, Queryable q out) => RelQuery True (R c (Q' q QueryFilter)) (From out) where
  relRunQueryEntity (R (Q' !q !f)) !world !entity = do
    !res <- relRunQueryEntity @True (R @c Any) world entity

    case fmap
      ( \(!r) -> do
          !t <- filterEntity f world r.target
          if t
            then
              fmap (From r.target) <$> runQueryEntity q world r.target
            else pure Nothing
      )
      res of
      Nothing -> pure Nothing
      Just !x -> x
  relRunQueryInternal (R (Q' q !f)) !archetypes !world = do
    !res <- relRunQueryInternal @True (R @c Any) archetypes world
    for res $ \(!e, !b, !rels) -> do
      !r <-
        ( \(!r) -> do
            !t <- filterEntity f world r.target
            if t
              then
                fmap (From r.target) <$> runQueryEntity q world r.target
              else pure Nothing
        )
          rels
      pure $ case r of
        Nothing -> (e, False, undefined)
        Just !x -> (e, b, x)

  relQueryTypes _ = Set.singleton (typeRep $ Proxy @c, RelQ)

instance (Component c) => Queryable (R c Entity) (Rel c) where
  runQueryEntity (R !target) !world !entity = do
    !res <- tryGetEntityRel @c target world entity
    return $ case res of
      Just (Just !x) -> Just (Rel x target)
      _ -> Nothing

  runQueryInternal (R !target) archetypes world = map (\(!a, !b) -> (a, True, b)) <$> tryGetRels @c target world archetypes

  queryTypes (R target) = Set.singleton (typeRep $ Proxy @c, RelQ' target)

instance (RelQuery (IsExclusiveRel c) (R c Any) out) => Queryable (R c Any) out where
  runQueryEntity = relRunQueryEntity @(IsExclusiveRel c)

  runQueryInternal = relRunQueryInternal @(IsExclusiveRel c)

  queryTypes = relQueryTypes @(IsExclusiveRel c)

instance (RelQuery (IsExclusiveRel c) (R c (Q q)) out) => Queryable (R c (Q q)) out where
  runQueryEntity = relRunQueryEntity @(IsExclusiveRel c)

  runQueryInternal = relRunQueryInternal @(IsExclusiveRel c)

  queryTypes = relQueryTypes @(IsExclusiveRel c)

instance (RelQuery (IsExclusiveRel c) (R c (Q' q f)) out) => Queryable (R c (Q' q f)) out where
  runQueryEntity = relRunQueryEntity @(IsExclusiveRel c)

  runQueryInternal = relRunQueryInternal @(IsExclusiveRel c)

  queryTypes = relQueryTypes @(IsExclusiveRel c)

instance (RelQuery False (R c e) out) => Queryable (R' c e) out where
  runQueryEntity (R' !e) = relRunQueryEntity @False (R @c e)
  runQueryInternal (R' !e) = relRunQueryInternal @False (R @c e)
  queryTypes (R' !e) = relQueryTypes @False (R @c e)

instance (Component c) => Queryable (M c) (Maybe c) where
  runQueryEntity _ !world !entity = do
    !res <- tryGetEntityComponent @c world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just Nothing
      Just (Just !x) -> pure $ Just $ Just x

  runQueryInternal _ !archetypes !world = map (\(!a, !b) -> (a, True, b)) <$> tryGetComponentsMaybe @c world archetypes

  queryTypes _ = Set.empty

instance (Component c) => Queryable (MR c Entity) (Maybe (Rel c)) where
  runQueryEntity (MR !target) !world !entity = do
    !res <- tryGetEntityRel @c target world entity
    pure $ case res of
      Nothing -> Nothing
      Just Nothing -> Just Nothing
      Just (Just !x) -> Just $ Just (Rel x target)

  runQueryInternal (MR !target) !archetypes !world = map (\(!a, !b) -> (a, True, b)) <$> tryGetRelsMaybe @c target world archetypes
  queryTypes _ = Set.empty

instance (Component c) => RelQuery False (MR c Any) (Maybe [Rel c]) where
  relRunQueryEntity _ = tryGetEntityRelCollection @c

  relRunQueryInternal _ !archetypes !world = do
    !x <- tryGetRelCollections @c world archetypes
    pure $ flip map x $ \(!e, !x) ->
      case x of
        [] -> (e, True, Nothing)
        !x -> (e, True, Just x)
  relQueryTypes _ = Set.empty

instance (Component c) => RelQuery True (MR c Any) (Maybe (Rel c)) where
  relRunQueryEntity _ !world !entity = do
    !res <- tryGetEntityRelCollection @c world entity
    pure $ case res of
      Just (Just [!x]) -> Just (Just x)
      Just (Just _) -> undefined
      Just Nothing -> Just Nothing
      Nothing -> Nothing

  relRunQueryInternal _ !archetypes !world = do
    !x <- tryGetRelCollections @c world archetypes
    pure $ flip map x $ \(!e, !x) ->
      case x of
        [] -> (e, True, Nothing)
        [!x] -> (e, True, Just x)
        _ -> undefined
  relQueryTypes _ = Set.empty

instance (Component c, Queryable q out) => RelQuery False (MR c (Q q)) (Maybe [From out]) where
  relRunQueryEntity (MR (Q !q)) !world !entity = do
    !res <- relRunQueryEntity @False (MR @c Any) world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just Nothing
      Just (Just !r) ->
        Just <$> do
          let !targets = map (\(!x) -> x.target) r
          !results <- catMaybes <$> for targets (\(!x) -> fmap (From x) <$> runQueryEntity q world x)
          case results of
            [] -> pure Nothing
            !x -> pure $ Just x

  relRunQueryInternal (MR (Q !q)) !archetypes !world = do
    !res <- relRunQueryInternal @False (MR @c Any) archetypes world
    for res $ \(!e, !b, !r) -> do
      case r of
        Nothing -> pure (e, b, Nothing)
        Just !r -> do
          !rs <- for r (\(!x) -> fmap (From x.target) <$> runQueryEntity q world x.target)
          case catMaybes rs of
            [] -> pure (e, b, Nothing)
            !x -> pure (e, b, Just x)

  relQueryTypes _ = Set.empty

instance (Component c, Queryable q out) => RelQuery False (MR c (Q' q QueryFilter)) (Maybe [From out]) where
  relRunQueryEntity (MR (Q' !q !f)) !world !entity = do
    !res <- relRunQueryEntity @False (MR @c Any) world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just Nothing
      Just (Just !r) ->
        Just <$> do
          let !targets = map (\(!x) -> x.target) r
          !results <-
            catMaybes
              <$> for
                targets
                ( \(!t) -> do
                    !b <- filterEntity f world t
                    if b
                      then
                        fmap (From t) <$> runQueryEntity q world t
                      else
                        pure Nothing
                )
          case results of
            [] -> pure Nothing
            !x -> pure $ Just x

  relRunQueryInternal (MR (Q' !q !f)) !archetypes !world = do
    !res <- relRunQueryInternal @False (MR @c Any) archetypes world
    for res $ \(!e, !b, !r) -> do
      case r of
        Nothing -> pure (e, b, Nothing)
        Just !r -> do
          !rs <-
            for
              r
              ( \(!x) -> do
                  !t <- filterEntity f world x.target
                  if t
                    then
                      fmap (From x.target) <$> runQueryEntity q world x.target
                    else pure Nothing
              )
          case catMaybes rs of
            [] -> pure (e, b, Nothing)
            !x -> pure (e, b, Just x)

  relQueryTypes _ = Set.empty

instance (Component c, Queryable q out) => RelQuery True (MR c (Q q)) (Maybe (From out)) where
  relRunQueryEntity (MR (Q !q)) !world !entity = do
    !res <- relRunQueryEntity @True (MR @c Any) world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just Nothing
      Just (Just !x) -> Just . fmap (From x.target) <$> runQueryEntity q world x.target

  relRunQueryInternal (MR (Q !q)) !archetypes !world = do
    !res <- relRunQueryInternal @True (MR @c Any) archetypes world
    for res $ \(!e, !b, !r) -> do
      case r of
        Nothing -> pure (e, b, Nothing)
        Just !r -> do
          !res <- fmap (From r.target) <$> runQueryEntity q world r.target
          pure (e, b, res)

  relQueryTypes _ = Set.empty

instance (Component c, Queryable q out) => RelQuery True (MR c (Q' q QueryFilter)) (Maybe (From out)) where
  relRunQueryEntity (MR (Q' !q !f)) world entity = do
    !res <- relRunQueryEntity @True (MR @c Any) world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just Nothing
      Just (Just !x) -> do
        !t <- filterEntity f world x.target
        if t
          then
            Just . fmap (From x.target) <$> runQueryEntity q world x.target
          else pure (Just Nothing)

  relRunQueryInternal (MR (Q' !q !f)) !archetypes !world = do
    !res <- relRunQueryInternal @True (MR @c Any) archetypes world
    for res $ \(!e, !b, !r) -> do
      case r of
        Nothing -> pure (e, b, Nothing)
        Just !r -> do
          !res <- do
            !t <- filterEntity f world r.target
            if t
              then
                fmap (From r.target) <$> runQueryEntity q world r.target
              else pure Nothing
          pure (e, b, res)

  relQueryTypes _ = Set.empty

instance (RelQuery (IsExclusiveRel c) (MR c Any) out) => Queryable (MR c Any) out where
  runQueryEntity = relRunQueryEntity @(IsExclusiveRel c)

  runQueryInternal = relRunQueryInternal @(IsExclusiveRel c)
  queryTypes _ = Set.empty

instance (RelQuery (IsExclusiveRel c) (MR c (Q q)) out) => Queryable (MR c (Q q)) out where
  runQueryEntity = relRunQueryEntity @(IsExclusiveRel c)

  runQueryInternal = relRunQueryInternal @(IsExclusiveRel c)
  queryTypes _ = Set.empty

instance (RelQuery (IsExclusiveRel c) (MR c (Q' q f)) out) => Queryable (MR c (Q' q f)) out where
  runQueryEntity = relRunQueryEntity @(IsExclusiveRel c)

  runQueryInternal = relRunQueryInternal @(IsExclusiveRel c)
  queryTypes _ = Set.empty

instance (Component c) => Queryable (Has c) Bool where
  runQueryEntity _ !world !entity = do
    !list <- runQueryEntity (M @c) world entity
    case list of
      Nothing -> return Nothing
      Just !x -> pure $ Just (isJust x)

  runQueryInternal _ !archetypes !world = do
    !list <- runQueryInternal (M @c) archetypes world
    pure $ map (Data.Bifunctor.second isJust) list

  queryTypes _ = Set.empty

instance (Component c) => Queryable (HasR c Any) Bool where
  runQueryEntity _ !world !entity = do
    !res <- tryGetEntityRelCollection @c world entity
    pure $ case res of
      Nothing -> Nothing
      Just Nothing -> Just False
      Just (Just _) -> Just True

  runQueryInternal _ !archetypes !world = do
    !res <- tryGetRelCollections @c world archetypes
    pure $ map ((\(!a, !b) -> (a, True, b)) . Data.Bifunctor.second null) res

  queryTypes _ = Set.empty

instance (Component c) => Queryable (HasR c Entity) Bool where
  runQueryEntity (HasR !target) !world !entity = do
    !res <- tryGetEntityRel @c target world entity
    pure $ case res of
      Nothing -> Nothing
      Just Nothing -> Just False
      Just (Just _) -> Just True

  runQueryInternal (HasR !target) !archetypes !world = do
    !res <- runQueryInternal (MR @c target) archetypes world
    pure $ map (Data.Bifunctor.second isNothing) res

  queryTypes _ = Set.empty

instance (Component c, Queryable q out) => Queryable (HasR c (Q q)) Bool where
  runQueryEntity (HasR (Q !q)) !world !entity = do
    !res <- tryGetEntityRelCollection @c world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just False
      Just (Just !r) -> do
        !res <- catMaybes <$> for r (\(!r) -> runQueryEntity q world r.target)
        case res of
          [] -> pure $ Just False
          _ -> pure $ Just True

  runQueryInternal (HasR (Q !q)) !archetypes !world = do
    !res <- relRunQueryInternal @False (MR @c Any) archetypes world
    for res $ \(!e, !b, !r) -> do
      case r of
        Nothing -> pure (e, b, False)
        Just !r -> do
          !res <- catMaybes <$> for r (\(!r) -> runQueryEntity q world r.target)
          case res of
            [] -> pure (e, b, False)
            _ -> pure (e, b, True)

  queryTypes _ = Set.empty

instance (Component c, Queryable q out) => Queryable (HasR c (Q' q QueryFilter)) Bool where
  runQueryEntity (HasR (Q' !q !f)) !world !entity = do
    !res <- tryGetEntityRelCollection @c world entity
    case res of
      Nothing -> pure Nothing
      Just Nothing -> pure $ Just False
      Just (Just !r) -> do
        !res <-
          catMaybes
            <$> for
              r
              ( \(!r) -> do
                  !t <- filterEntity f world r.target
                  if t
                    then
                      runQueryEntity q world r.target
                    else pure Nothing
              )
        case res of
          [] -> pure $ Just False
          _ -> pure $ Just True

  runQueryInternal (HasR (Q' !q !f)) !archetypes !world = do
    !res <- relRunQueryInternal @False (MR @c Any) archetypes world
    for res $ \(!e, !b, !r) -> do
      case r of
        Nothing -> pure (e, b, False)
        Just !r -> do
          !res <-
            catMaybes
              <$> for
                r
                ( \(!r) -> do
                    !t <- filterEntity f world r.target
                    if t
                      then
                        runQueryEntity q world r.target
                      else pure Nothing
                )
          case res of
            [] -> pure (e, b, False)
            _ -> pure (e, b, True)

  queryTypes _ = Set.empty

filterEntity' :: FilterComponent -> Entity -> World -> IO Bool
filterEntity' (FilterComponent (!x, Nothing, Nothing)) !entity !world = do
  !comp <- getComponentId x world.components
  case comp of
    Nothing -> pure False
    Just (ComponentId (# !id, _ #)) -> do
      Just (ComponentType (_ :: Proxy a)) <- runQueryEntity (C @ComponentType) world (Entity (# id, 0## #))
      !a <- runQueryEntity (Has @a) world entity
      pure $ fromMaybe False a
filterEntity' (FilterComponent (!x, Just !e, Nothing)) !entity !world = do
  !comp <- getComponentId x world.components
  case comp of
    Nothing -> return False
    Just (ComponentId (# !id, _ #)) -> do
      Just (ComponentType (_ :: Proxy a)) <- runQueryEntity (C @ComponentType) world (Entity (# id, 0## #))
      !a <- runQueryEntity (HasR @a e) world entity
      pure $ fromMaybe False a
filterEntity' (FilterComponent (!x, _, Just _)) !entity !world = do
  !comp <- liftIO $ getComponentId x world.components
  case comp of
    Nothing -> return False
    Just (ComponentId (# !id, _ #)) -> do
      Just (ComponentType (_ :: Proxy a)) <- liftIO $ runQueryEntity (C @ComponentType) world (Entity (# id, 0## #))
      !a <- liftIO $ runQueryEntity (HasR @a Any) world entity
      pure $ fromMaybe False a

filterEntity :: QueryFilter -> World -> Entity -> IO Bool
filterEntity f world entity = do
  !pointer <- getPointer entity world.entities

  case pointer of
    Nothing -> pure False
    Just !x -> do
      (EntityPointer (# !archetypeId, _ #)) <- readIORef x
      let Tables tables = world.tables
      table <- Vec.unsafeRead tables (I# archetypeId)
      filterArchetype f world table

filterArchetype :: QueryFilter -> World -> Table -> IO Bool
filterArchetype NoFilter _ _ = pure True
filterArchetype (With !a) !b !t = filterArchetype' (toFilterComponent a) b t.components
filterArchetype (Without !a) !b !t = not <$> filterArchetype' (toFilterComponent a) b t.components
filterArchetype (Changed a f1 f2) !b !t = do
  map <- readIORef t.ticks
  runSystem (addedChanged (qfChangedF f1 f2) (toFilterComponent a) map t) b
filterArchetype (And !a0 !a1) !b !t = (&&) <$> filterArchetype a0 b t <*> filterArchetype a1 b t
filterArchetype (Or !a0 !a1) !b !t = (||) <$> filterArchetype a0 b t <*> filterArchetype a1 b t

addedChanged :: forall m w. (MonadSystem w m) => (ComponentTick -> Tick -> Tick -> Bool) -> FilterComponent -> Map ComponentId ComponentTick -> Table -> m Bool
addedChanged !f (FilterComponent (!c, Nothing, Nothing)) m _ = do
  !world <- unsafeGetWorld
  !id <- liftIO $ getComponentId c world.components
  case id of
    Nothing -> pure False
    Just !id -> do
      -- !ticks <- liftIO $ tryGetEntityTicks e id world
      let ticks = Map.lookup id m
      case ticks of
        Nothing -> pure False
        Just !ticks -> do
          (!lastSystemTick, !currentSystemTick) <- liftIO $ getSystemTicksInternal world
          pure $ f ticks lastSystemTick currentSystemTick
addedChanged !f (FilterComponent (!c, Just !entity, Nothing)) !e _ = do
  world <- unsafeGetWorld
  !id <- liftIO $ getComponentId c world.components
  case id of
    Nothing -> pure False
    Just (ComponentId (# !id, _ #)) -> do
      let ticks = Map.lookup (ComponentId (# id, Just entity #)) e
      case ticks of
        Nothing -> pure False
        Just !ticks -> do
          (!lastSystemTick, !currentSystemTick) <- liftIO $ getSystemTicksInternal world
          pure $ f ticks lastSystemTick currentSystemTick
addedChanged !f (FilterComponent (!c, _, Just _)) m t = do
  world <- unsafeGetWorld
  !id <- liftIO $ getComponentId c world.components
  case id of
    Nothing -> return False
    Just (ComponentId (# !id, _ #)) -> do
      -- Just (ComponentType (_ :: Proxy a)) <- liftIO $ runQueryEntity (C @ComponentType) world (Entity (# id, 0## #))

      -- !rels <- single $ mkGet e (R' @a Any)

      anyM
        ( \(ComponentId (# id', e #)) -> do
            if not (isTrue# (eqWord# id' id))
              then
                pure False
              else do
                let ticks = Map.lookup (ComponentId (# id', e #)) m
                case ticks of
                  Nothing -> pure False
                  Just !ticks -> do
                    (!lastSystemTick, !currentSystemTick) <- liftIO $ getSystemTicksInternal world
                    pure $ f ticks lastSystemTick currentSystemTick
        )
        t.components

-- case rels of
--   Nothing -> pure False
--   Just !rels -> do
--     and
--       <$> for
--         rels
--         ( \(Rel _ !target) -> do
--             addedChanged f (FilterComponent (c, Just target, Nothing)) e
--         )

getSystemTicksInternal :: World -> IO (Tick, Tick)
getSystemTicksInternal !world = do
  let (SystemId !sys) = world.systemId
  Just !a <- runQueryEntity (C @LastSystemTick) world sys
  Just !b <- runQueryEntity (C @SystemTick) world sys
  pure (a.inner, b.inner)

-- filterEntity NoFilter _ _ = pure True
-- filterEntity (With !x) world entity = filterEntity' (toFilterComponent x) entity world
-- filterEntity (Without !x) world entity = not <$> filterEntity' (toFilterComponent x) entity world
-- filterEntity (Not !a) world entity = not <$> filterEntity a world entity
-- filterEntity (And !a !b) world entity = (&&) <$> filterEntity a world entity <*> filterEntity b world entity
-- filterEntity (Or !a !b) world entity = (||) <$> filterEntity a world entity <*> filterEntity b world entity

findComponentsOfEntity :: World -> Entity -> IO (Maybe [ComponentId])
findComponentsOfEntity !world !entity = do
  !pointer <- getPointer entity world.entities

  case pointer of
    Nothing -> return Nothing
    Just !x -> do
      (EntityPointer (# !archetypeId, _ #)) <- readIORef x

      !x <- Vec.read world.tables.inner (I# archetypeId)

      pure $ Just x.components

-- addedChanged' :: forall m w. (MonadSystem w m) => (ComponentTicks -> Tick -> Tick -> Bool) -> ComponentId -> Entity -> m Bool
-- addedChanged' !f !id !entity = do
--   !world <- unsafeGetWorld
--   !ticks <- liftIO $ tryGetEntityTicks entity id world
--   case ticks of
--     Nothing -> pure False
--     Just !ticks -> do
--       (!lastSystemTick, !currentSystemTick) <- liftIO $ getSystemTicksInternal world
--       pure $ f ticks lastSystemTick currentSystemTick

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1) => Queryable (q0, q1) (o0, o1) where
  runQueryEntity (q0, q1) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity

    return $ (,) <$> r0 <*> r1

  runQueryInternal (q0, q1) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1)) -> (e0, b0 || b1, (r0, r1))) $ getZipList $ (,) <$> ZipList r0 <*> ZipList r1

  queryTypes (q0, q1) = Set.unions [queryTypes q0, queryTypes q1]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2) => Queryable (q0, q1, q2) (o0, o1, o2) where
  runQueryEntity (q0, q1, q2) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity

    return $ (,,) <$> r0 <*> r1 <*> r2

  runQueryInternal (q0, q1, q2) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2)) -> (e0, b0 || b1 || b2, (r0, r1, r2))) $ getZipList $ (,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2

  queryTypes (q0, q1, q2) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3) => Queryable (q0, q1, q2, q3) (o0, o1, o2, o3) where
  runQueryEntity (q0, q1, q2, q3) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity

    return $ (,,,) <$> r0 <*> r1 <*> r2 <*> r3

  runQueryInternal (q0, q1, q2, q3) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3)) -> (e0, b0 || b1 || b2 || b3, (r0, r1, r2, r3))) $ getZipList $ (,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3

  queryTypes (q0, q1, q2, q3) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4) => Queryable (q0, q1, q2, q3, q4) (o0, o1, o2, o3, o4) where
  runQueryEntity (q0, q1, q2, q3, q4) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity

    return $ (,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4

  runQueryInternal (q0, q1, q2, q3, q4) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4)) -> (e0, b0 || b1 || b2 || b3 || b4, (r0, r1, r2, r3, r4))) $ getZipList $ (,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4

  queryTypes (q0, q1, q2, q3, q4) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5) => Queryable (q0, q1, q2, q3, q4, q5) (o0, o1, o2, o3, o4, o5) where
  runQueryEntity (q0, q1, q2, q3, q4, q5) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity

    return $ (,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5

  runQueryInternal (q0, q1, q2, q3, q4, q5) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5, (r0, r1, r2, r3, r4, r5))) $ getZipList $ (,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5

  queryTypes (q0, q1, q2, q3, q4, q5) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6) => Queryable (q0, q1, q2, q3, q4, q5, q6) (o0, o1, o2, o3, o4, o5, o6) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity

    return $ (,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6, (r0, r1, r2, r3, r4, r5, r6))) $ getZipList $ (,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6

  queryTypes (q0, q1, q2, q3, q4, q5, q6) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7) (o0, o1, o2, o3, o4, o5, o6, o7) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity

    return $ (,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7, (r0, r1, r2, r3, r4, r5, r6, r7))) $ getZipList $ (,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8) (o0, o1, o2, o3, o4, o5, o6, o7, o8) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity

    return $ (,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8, (r0, r1, r2, r3, r4, r5, r6, r7, r8))) $ getZipList $ (,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8, Queryable q9 o9) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9) (o0, o1, o2, o3, o4, o5, o6, o7, o8, o9) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity
    r9 <- runQueryEntity q9 world entity

    return $ (,,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8 <*> r9

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world
    r9 <- runQueryInternal q9 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8), (_, b9, r9)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9, (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9))) $ getZipList $ (,,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8 <*> ZipList r9

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8, queryTypes q9]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8, Queryable q9 o9, Queryable q10 o10) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10) (o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity
    r9 <- runQueryEntity q9 world entity
    r10 <- runQueryEntity q10 world entity

    return $ (,,,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8 <*> r9 <*> r10

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world
    r9 <- runQueryInternal q9 archetypes world
    r10 <- runQueryInternal q10 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8), (_, b9, r9), (_, b10, r10)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9 || b10, (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10))) $ getZipList $ (,,,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8 <*> ZipList r9 <*> ZipList r10

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8, queryTypes q9, queryTypes q10]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8, Queryable q9 o9, Queryable q10 o10, Queryable q11 o11) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11) (o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity
    r9 <- runQueryEntity q9 world entity
    r10 <- runQueryEntity q10 world entity
    r11 <- runQueryEntity q11 world entity

    return $ (,,,,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8 <*> r9 <*> r10 <*> r11

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world
    r9 <- runQueryInternal q9 archetypes world
    r10 <- runQueryInternal q10 archetypes world
    r11 <- runQueryInternal q11 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8), (_, b9, r9), (_, b10, r10), (_, b11, r11)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9 || b10 || b11, (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11))) $ getZipList $ (,,,,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8 <*> ZipList r9 <*> ZipList r10 <*> ZipList r11

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8, queryTypes q9, queryTypes q10, queryTypes q11]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8, Queryable q9 o9, Queryable q10 o10, Queryable q11 o11, Queryable q12 o12) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12) (o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity
    r9 <- runQueryEntity q9 world entity
    r10 <- runQueryEntity q10 world entity
    r11 <- runQueryEntity q11 world entity
    r12 <- runQueryEntity q12 world entity

    return $ (,,,,,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8 <*> r9 <*> r10 <*> r11 <*> r12

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world
    r9 <- runQueryInternal q9 archetypes world
    r10 <- runQueryInternal q10 archetypes world
    r11 <- runQueryInternal q11 archetypes world
    r12 <- runQueryInternal q12 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8), (_, b9, r9), (_, b10, r10), (_, b11, r11), (_, b12, r12)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9 || b10 || b11 || b12, (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12))) $ getZipList $ (,,,,,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8 <*> ZipList r9 <*> ZipList r10 <*> ZipList r11 <*> ZipList r12

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8, queryTypes q9, queryTypes q10, queryTypes q11, queryTypes q12]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8, Queryable q9 o9, Queryable q10 o10, Queryable q11 o11, Queryable q12 o12, Queryable q13 o13) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13) (o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity
    r9 <- runQueryEntity q9 world entity
    r10 <- runQueryEntity q10 world entity
    r11 <- runQueryEntity q11 world entity
    r12 <- runQueryEntity q12 world entity
    r13 <- runQueryEntity q13 world entity

    return $ (,,,,,,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8 <*> r9 <*> r10 <*> r11 <*> r12 <*> r13

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world
    r9 <- runQueryInternal q9 archetypes world
    r10 <- runQueryInternal q10 archetypes world
    r11 <- runQueryInternal q11 archetypes world
    r12 <- runQueryInternal q12 archetypes world
    r13 <- runQueryInternal q13 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8), (_, b9, r9), (_, b10, r10), (_, b11, r11), (_, b12, r12), (_, b13, r13)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9 || b10 || b11 || b12 || b13, (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13))) $ getZipList $ (,,,,,,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8 <*> ZipList r9 <*> ZipList r10 <*> ZipList r11 <*> ZipList r12 <*> ZipList r13

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8, queryTypes q9, queryTypes q10, queryTypes q11, queryTypes q12, queryTypes q13]

instance {-# OVERLAPPING #-} (Queryable q0 o0, Queryable q1 o1, Queryable q2 o2, Queryable q3 o3, Queryable q4 o4, Queryable q5 o5, Queryable q6 o6, Queryable q7 o7, Queryable q8 o8, Queryable q9 o9, Queryable q10 o10, Queryable q11 o11, Queryable q12 o12, Queryable q13 o13, Queryable q14 o14) => Queryable (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14) (o0, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14) where
  runQueryEntity (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14) world entity = do
    r0 <- runQueryEntity q0 world entity
    r1 <- runQueryEntity q1 world entity
    r2 <- runQueryEntity q2 world entity
    r3 <- runQueryEntity q3 world entity
    r4 <- runQueryEntity q4 world entity
    r5 <- runQueryEntity q5 world entity
    r6 <- runQueryEntity q6 world entity
    r7 <- runQueryEntity q7 world entity
    r8 <- runQueryEntity q8 world entity
    r9 <- runQueryEntity q9 world entity
    r10 <- runQueryEntity q10 world entity
    r11 <- runQueryEntity q11 world entity
    r12 <- runQueryEntity q12 world entity
    r13 <- runQueryEntity q13 world entity
    r14 <- runQueryEntity q14 world entity

    return $ (,,,,,,,,,,,,,,) <$> r0 <*> r1 <*> r2 <*> r3 <*> r4 <*> r5 <*> r6 <*> r7 <*> r8 <*> r9 <*> r10 <*> r11 <*> r12 <*> r13 <*> r14

  runQueryInternal (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14) archetypes world = do
    r0 <- runQueryInternal q0 archetypes world
    r1 <- runQueryInternal q1 archetypes world
    r2 <- runQueryInternal q2 archetypes world
    r3 <- runQueryInternal q3 archetypes world
    r4 <- runQueryInternal q4 archetypes world
    r5 <- runQueryInternal q5 archetypes world
    r6 <- runQueryInternal q6 archetypes world
    r7 <- runQueryInternal q7 archetypes world
    r8 <- runQueryInternal q8 archetypes world
    r9 <- runQueryInternal q9 archetypes world
    r10 <- runQueryInternal q10 archetypes world
    r11 <- runQueryInternal q11 archetypes world
    r12 <- runQueryInternal q12 archetypes world
    r13 <- runQueryInternal q13 archetypes world
    r14 <- runQueryInternal q14 archetypes world

    return $ map (\((e0, b0, r0), (_, b1, r1), (_, b2, r2), (_, b3, r3), (_, b4, r4), (_, b5, r5), (_, b6, r6), (_, b7, r7), (_, b8, r8), (_, b9, r9), (_, b10, r10), (_, b11, r11), (_, b12, r12), (_, b13, r13), (_, b14, r14)) -> (e0, b0 || b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9 || b10 || b11 || b12 || b13 || b14, (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14))) $ getZipList $ (,,,,,,,,,,,,,,) <$> ZipList r0 <*> ZipList r1 <*> ZipList r2 <*> ZipList r3 <*> ZipList r4 <*> ZipList r5 <*> ZipList r6 <*> ZipList r7 <*> ZipList r8 <*> ZipList r9 <*> ZipList r10 <*> ZipList r11 <*> ZipList r12 <*> ZipList r13 <*> ZipList r14

  queryTypes (q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14) = Set.unions [queryTypes q0, queryTypes q1, queryTypes q2, queryTypes q3, queryTypes q4, queryTypes q5, queryTypes q6, queryTypes q7, queryTypes q8, queryTypes q9, queryTypes q10, queryTypes q11, queryTypes q12, queryTypes q13, queryTypes q14]