module Text.Flamethrower (flamethrower, flamef) where
import Data.Maybe (fromMaybe)
import Language.Haskell.TH
import Language.Haskell.TH.Quote
import qualified Text.Flamethrower.Lexer as L
import qualified Text.Flamethrower.Parser as P
import qualified Text.Flamethrower.Compiler as C
import Text.Flamethrower.Escape
import qualified Data.Text
codeTreeToExpression :: C.CodeTree -> Exp
codeTreeToExpression tree = case tree of
C.Text s -> ListE [LitE $ StringL s]
C.Expression escaper exp -> ListE . replicate 1 $
case escaper of
None -> exp
Content -> VarE 'escapeContent `AppE` exp
Attribute -> VarE 'escapeAttributeValue `AppE` exp
C.If condition truePart falsePart ->
let cond = CondE condition (ListE $ map codeTreeToExpression truePart) (ListE $ map codeTreeToExpression falsePart)
in VarE 'concat `AppE` cond
C.For bind loop children -> VarE 'concat `AppE` CompE [BindS (VarP bind) loop, NoBindS $ VarE 'concat `AppE` ListE (map codeTreeToExpression children)]
compileTemplate :: String -> [Exp]
compileTemplate = map codeTreeToExpression . C.compile . P.parse . L.lex
flamethrower' :: String -> Q Exp
flamethrower' template = return $ VarE 'Data.Text.concat `AppE` (VarE 'concat `AppE` ListE (compileTemplate template))
flamethrower :: QuasiQuoter
flamethrower = QuasiQuoter {
quoteExp = flamethrower',
quotePat = error "Flamethrower templates are expressions, not patterns.",
quoteDec = error "Flamethrower templates are expressions, not declarations.",
quoteType = error "Flamethrower templates are expressions, not types."
}
flamef :: QuasiQuoter
flamef = quoteFile flamethrower