{-# LANGUAGE TemplateHaskell #-} module Data.String.Interpolate ( i ) where import Data.Proxy import Language.Haskell.Meta.Parse ( parseExp ) import Language.Haskell.TH import Language.Haskell.TH.Quote ( QuasiQuoter(..) ) import Language.Haskell.TH.Syntax ( returnQ ) import Data.String.Interpolate.Conversion ( Builder, InterpSink, Interpolatable, build, finalize, interpolate, ofString ) import Data.String.Interpolate.Parse ( InterpSegment(..), dosToUnix, parseInterpSegments ) i :: QuasiQuoter i = QuasiQuoter { quoteExp = toExp . parseInterpSegments . dosToUnix , quotePat = err "pattern" , quoteType = err "type" , quoteDec = err "declaration" } where err name = error ("Data.String.Interpolate.i: This QuasiQuoter cannot be used as a " ++ name) toExp :: Either String [InterpSegment] -> Q Exp toExp parseResult = case parseResult of Left msg -> fail $ "Data.String.Interpolate.i: " ++ msg Right segs -> emitBuildExp segs emitBuildExp :: [InterpSegment] -> Q Exp emitBuildExp segs = [|finalize Proxy $(go segs)|] where go [] = [|ofString Proxy ""|] go (Verbatim str : rest) = [|build Proxy (ofString Proxy str) $(go rest)|] go (Expression expr : rest) = [|build Proxy (interpolate Proxy $(reifyExpression expr)) $(go rest)|] reifyExpression :: String -> Q Exp reifyExpression s = case parseExp s of Left _ -> fail $ "Data.String.Interpolate.i: parse error in expression: " ++ s Right e -> pure e