1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import Language.Haskell.Meta.Parse -- from haskell-src-meta import Language.Haskell.TH.Quote -- from template-haskell obviously myedsl :: QuasiQuoter myedsl = QuasiQuoter { quoteExp = myedslExpr } myedslExpr :: String -> Q Exp myedslExpr = return . transform . either error id . parseExp -- TODO The above code calls `error` on failure; it might be better to do -- something else -- Do the actual code transformation here transform :: Exp -> Exp -- Transform any variable that starts and ends with '.' into the variable -- without the '.'s transform (VarE name) | let base = nameBase name in (not . null . tail $ base) -- Name is longer than 1 char && head base == '.' -- Name starts with '.' && last base == '.' -- Name ends with '.' = VarE . mkName -- Create a new variable . maybe id -- in the same module as the old variable sepPeriod (nameModule name) . tail . init -- with the first and last characters removed . nameBase $ name -- from the base name of the old variable -- TODO The above code will fail if the variable has a qualified -- module (e.g. `EDSL..%.`) where sepPeriod a b = a ++ "." ++ b -- If the expression isn't a variable, you have to visits any child -- expressions that might exist. Here I show the example for AppE, but -- there are many more transform (AppE e1 e2) = AppE (transform e1) (transform e2) -- ... TODOother constructors such as InfixE, UInfixE, ParensE, LamE, ... -- There are some expressions that don't need rewriting transform expr = expr |