1515{-# LANGUAGE UndecidableInstances #-}
1616{-# LANGUAGE ViewPatterns #-}
1717{-# OPTIONS_GHC -Wno-name-shadowing #-}
18+ {-# LANGUAGE LambdaCase #-}
1819
1920-- | This module uses the python mini language detailed in
2021-- 'PyF.Internal.PythonSyntax' to build an template haskell expression
2122-- representing a formatted string.
2223module PyF.Internal.QQ
23- ( toExp ,
24- toExpPlain ,
25- Config (.. ),
26- wrapFromString ,
27- expQQ ,
28- )
24+ -- ( toExp,
25+ -- toExpPlain,
26+ -- toExpPlain',
27+ -- toFormatPlain,
28+ -- ItemPlain(..),
29+ -- Config (..),
30+ -- wrapFromString,
31+ -- expQQ,
32+ -- )
2933where
3034
3135import Control.Monad.Reader
@@ -107,6 +111,9 @@ import Text.Parsec.Error
107111import Text.Parsec.Pos (initialPos )
108112import Text.ParserCombinators.Parsec.Error (Message (.. ))
109113import Unsafe.Coerce (unsafeCoerce )
114+ import qualified Data.Text as Text
115+ import Data.List.NonEmpty (NonEmpty ((:|) ), nonEmpty )
116+ import Data.Semigroup (Semigroup (sconcat ))
110117
111118-- | Configuration for the quasiquoter
112119data Config = Config
@@ -168,28 +175,31 @@ toExp Config {delimiters = expressionDelimiters, postProcess} s = do
168175
169176-- | Parse a string and return a formatter for it
170177toExpPlain :: Config -> String -> Q Exp
171- toExpPlain Config {delimiters = expressionDelimiters, postProcess} s = do
178+ toExpPlain config s = do
172179 loc <- location
173180 exts <- extsEnabled
174- let context = ParsingContext expressionDelimiters exts
181+ toExpPlain' loc s exts config
175182
183+ toExpPlain' :: Loc -> String -> [Extension ] -> Config -> Q Exp
184+ toExpPlain' loc s exts Config {delimiters = expressionDelimiters, postProcess} = do
176185 -- Setup the parser so it matchs the real original position in the source
177186 -- code.
178187 let filename = loc_filename loc
179188 let initPos = setSourceColumn (setSourceLine (initialPos filename) (fst $ loc_start loc)) (snd $ loc_start loc)
189+ let context = ParsingContext expressionDelimiters exts
180190 case runReader (runParserT (setPosition initPos >> parseGenericFormatStringPlain) () filename s) context of
181191 Left err -> do
182192 reportParserErrorAt err
183193 -- returns a dummy exp, so TH continues its life. This TH code won't be
184194 -- executed anyway, there is an error
185- [| () | ]
195+ [| interpolateInto Text. empty | ]
186196 Right items -> do
187197 checkResult <- checkVariablesPlain items
188198 case checkResult of
189- Nothing -> postProcess ( goFormatPlain items)
199+ Nothing -> goFormatPlain items
190200 Just (srcSpan, msg) -> do
191201 reportErrorAt srcSpan msg
192- [| () | ]
202+ [| interpolateInto Text. empty | ]
193203
194204
195205findFreeVariablesInFormatMode :: Maybe FormatMode -> [(SrcSpan , RdrName )]
@@ -377,9 +387,14 @@ goFormat items = foldl1 sappendQ <$> mapM toFormat items
377387
378388goFormatPlain :: [ItemPlain ] -> Q Exp
379389-- We special case on empty list in order to generate an empty string
380- goFormatPlain [] = pure $ LitE (StringL " " ) -- see [Empty String Lifting]
381- goFormatPlain items = [| mconcat $ (ListE <$> mapM toFormatPlain items)| ]
390+ goFormatPlain items = case nonEmpty items of
391+ Nothing -> [| interpolateInto Text. empty| ] -- see [Empty String Lifting]
392+ Just items -> do
393+ let items' = fmap toFormatPlain items
394+ [|$ (nonEmptyE items')| ]
382395
396+ nonEmptyE :: NonEmpty (Q Exp ) -> Q Exp
397+ nonEmptyE (x :| xs) = [| sconcat ($ (x) :| $ (listE xs))| ]
383398
384399-- | call `<>` between two 'Exp'
385400sappendQ :: Exp -> Exp -> Exp
@@ -395,11 +410,13 @@ toFormat (Replacement (_, expr) y) = do
395410
396411
397412toFormatPlain :: ItemPlain -> Q Exp
398- toFormatPlain (RawPlain x) = pure $ LitE (StringL x) -- see [Empty String Lifting]
399- toFormatPlain (ReplacementPlain (_, expr)) = do
400- f <- [| pyfToString| ]
401- pure $ f `AppE ` expr
402-
413+ toFormatPlain item = do
414+ let tyProxy = SigE (ConE 'Proxy) (AppT (ConT ''Proxy) (ConT ''Text. Text ))
415+ case item of
416+ (RawPlain x) -> [| interpolateInto $ [| Text. pack x| ]| ]
417+ (ReplacementPlain (_, expr)) -> do
418+ exprTyped <- [|$ (pure expr)| ]
419+ [| interpolateInto $ (pure exprTyped)| ]
403420
404421-- | Default precision for floating point
405422defaultFloatPrecision :: Maybe Int
0 commit comments