{-# LANGUAGE TemplateHaskell #-} {-# OPTIONS -fno-warn-name-shadowing #-} module Atomo.QuasiQuotes ( p , e , es ) where import "monads-fd" Control.Monad.State hiding (lift) import Data.Maybe (fromJust) import Data.Typeable import Language.Haskell.TH.Quote import Language.Haskell.TH.Syntax import System.IO.Unsafe import Text.Parsec import qualified Language.Haskell.TH as TH import Atomo.Core import Atomo.Helpers (fromHaskell') import Atomo.Parser import Atomo.Parser.Base import Atomo.Parser.Expr import Atomo.Pattern (toDefinePattern) import Atomo.Types qqEnv :: Env qqEnv = snd $ unsafePerformIO $ runVM (initCore >> return (particle "ok")) startEnv -- | Pattern quasi-quoter. p :: QuasiQuoter p = QuasiQuoter quotePatternExp undefined -- | Single expression quasi-quoter. e :: QuasiQuoter e = QuasiQuoter quoteExprExp undefined -- | Quasi-quoter for multiple expressions (a block of code). es :: QuasiQuoter es = QuasiQuoter quoteExprsExp undefined withLocation :: (String -> (String, Int, Int) -> a) -> (a -> Q Exp) -> String -> TH.ExpQ withLocation p c s = do l <- TH.location c $ p s ( TH.loc_filename l , fst $ TH.loc_start l , snd $ TH.loc_start l ) parsing :: Typeable a => Parser a -> String -> (String, Int, Int) -> a parsing p s (file, line, col) = -- here be dragons fromHaskell' "a" $ unsafePerformIO (runWith go (qqEnv)) where go = liftM haskell $ continue pp "" s pp = do pos <- getPosition setPosition $ flip setSourceName file $ flip setSourceLine line $ setSourceColumn pos col whiteSpace e <- p whiteSpace eof return e quotePatternExp :: String -> TH.ExpQ quotePatternExp = withLocation (parsing (liftM (fromJust . toDefinePattern) pExpr)) lift quoteExprExp :: String -> TH.ExpQ quoteExprExp = withLocation (parsing pExpr) lift quoteExprsExp :: String -> TH.ExpQ quoteExprsExp = withLocation (parsing (wsBlock pExpr)) (fmap ListE . mapM lift)