packages feed

mischief-ecs-0.1.0.0: src/Mischief/ECS/World/Query/TH.hs

{-# OPTIONS_GHC -Wno-overlapping-patterns #-}

module Mischief.ECS.World.Query.TH (q, s, g) where

import Control.Monad
import Control.Monad.IO.Class
import Data.Maybe
import Data.Text (Text)
import Data.Text qualified as T
import Data.Void
import Language.Haskell.TH
import Language.Haskell.TH qualified
import Language.Haskell.TH.Quote
import Language.Haskell.TH.Syntax
import Mischief.ECS.Collectable
import Mischief.ECS.Components
import Mischief.ECS.Components.Common hiding (Name)
import Mischief.ECS.Entities
import Mischief.ECS.Hidden
import Mischief.ECS.Log
import Mischief.ECS.Utils
import Mischief.ECS.World.Query
import Mischief.ECS.World.Query.QueryFilter
import Mischief.ECS.World.Query.Queryable hiding (Q)
import Mischief.ECS.World.Query.TH.Common
import Mischief.ECS.World.Query.TH.QD
import Mischief.ECS.World.Query.TH.QF (Qf, pCheck, pQf, quoteQf)
import Text.Megaparsec (MonadParsec (eof), Parsec, choice, optional, parse, parseTest, runParserT, some, (<|>))
import Text.Megaparsec.Char
import Text.Megaparsec.Char.Lexer qualified as L

q :: QuasiQuoter
q =
  QuasiQuoter
    { quoteExp = \str -> do
        let x = parse (whitespace *> pQuery <* eof) "inline_input" (T.pack str)
        case x of
          Left f -> error (show f)
          Right x -> quoteQuery x,
      quotePat = undefined,
      quoteType = undefined,
      quoteDec = undefined
    }

data Query = Query Qd (Maybe Qf) deriving (Show)

pQuery :: Parser Query
pQuery = do
  qd <- pQd
  whitespace

  qf <- optional $ do
    void $ char '/'
    whitespace
    pQf

  pure $ Query qd qf

quoteQuery :: Query -> Q Exp
quoteQuery (Query qd Nothing) = AppE (VarE 'query) <$> quoteQd qd
quoteQuery (Query qd (Just qf)) = do
  qd <- quoteQd qd
  qf <- quoteQf qf
  return $ AppE (AppE (VarE 'query') qd) qf

s :: QuasiQuoter
s =
  QuasiQuoter
    { quoteExp = \str -> do
        let x = parse (whitespace *> pQuery <* eof) "inline_input" (T.pack str)
        case x of
          Left f -> error (show f)
          Right x -> quoteSingle x,
      quotePat = undefined,
      quoteType = undefined,
      quoteDec = undefined
    }

quoteSingle :: Query -> Q Exp
quoteSingle (Query qd Nothing) = AppE (VarE 'single) <$> quoteQd qd
quoteSingle (Query qd (Just qf)) = do
  qd <- quoteQd qd
  qf <- quoteQf qf
  return $ AppE (AppE (VarE 'single') qd) qf

g :: QuasiQuoter
g =
  QuasiQuoter
    { quoteExp = \str -> do
        let x = parse (whitespace *> pQuery <* eof) "inline_input" (T.pack str)
        case x of
          Left f -> error (show f)
          Right x -> quoteGet x,
      quotePat = undefined,
      quoteType = undefined,
      quoteDec = undefined
    }

quoteGet :: Query -> Q Exp
quoteGet (Query qd Nothing) = AppE (VarE 'get) <$> quoteQd qd
quoteGet (Query qd (Just qf)) = do
  qd <- quoteQd qd
  qf <- quoteQf qf
  return $ AppE (AppE (VarE 'get') qd) qf