From d8453ba7a64dbc41dc8784078895170746b455a9 Mon Sep 17 00:00:00 2001 From: "simonpj@microsoft.com" Date: Wed, 10 Feb 2010 11:42:13 +0000 Subject: [PATCH] Documentation for changes to Template Haskell and quasi-quotation --- docs/users_guide/glasgow_exts.xml | 104 ++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index 603c6c6..f794c4d 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -6249,25 +6249,29 @@ Wiki page. a list of top-level declarations; the spliced expression must have type Q [Dec] + Note that pattern splices are not supported. Inside a splice you can can only call functions defined in imported modules, - not functions defined elsewhere in the same module. + not functions defined elsewhere in the same module. A expression quotation is written in Oxford brackets, thus: - [| ... |], where the "..." is an expression; + [| ... |], or [e| ... |], + where the "..." is an expression; the quotation has type Q Exp. [d| ... |], where the "..." is a list of top-level declarations; the quotation has type Q [Dec]. [t| ... |], where the "..." is a type; - the quotation has type Q Typ. + the quotation has type Q Type. + [p| ... |], where the "..." is a pattern; + the quotation has type Q Pat. A quasi-quotation can appear in either a pattern context or an expression context and is also written in Oxford brackets: - [$varid| ... |], + [varid| ... |], where the "..." is an arbitrary string; a full description of the quasi-quotation facility is given in . @@ -6473,19 +6477,67 @@ several examples are documented in Nice to be Quoted: Quasiquoting for Haskell" (Proc Haskell Workshop 2007). The example below shows how to write a quasiquoter for a simple expression language. - -In the example, the quasiquoter expr is bound to a value of -type Language.Haskell.TH.Quote.QuasiQuoter which contains two -functions for quoting expressions and patterns, respectively. The first argument -to each quoter is the (arbitrary) string enclosed in the Oxford brackets. The -context of the quasi-quotation statement determines which of the two parsers is -called: if the quasi-quotation occurs in an expression context, the expression -parser is called, and if it occurs in a pattern context, the pattern parser is -called. +Here are the salient features + + +A quasi-quote has the form +[quoter| string |]. + + +The quoter must be the (unqualified) name of an imported +quoter; it cannot be an arbitrary expression. + + +The quoter cannot be "e", +"t", "d", or "p", since +those overlap with Template Haskell quotations. + + +There must be no spaces in the token +[quoter|. + + +The quoted string +can be arbitrary, and may contain newlines. + + + + +A quasiquote may appear in place of + +An expression +A pattern +A type +A top-level declaration + +(Only the first two are described in the paper.) + + + +A quoter is a value of type Language.Haskell.TH.Quote.QuasiQuoter, +which is defined thus: + +data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp, + quotePat :: String -> Q Pat, + quoteType :: String -> Q Type, + quoteDec :: String -> Q [Dec] } + +That is, a quoter is a tuple of four parsers, one for each of the contexts +in which a quasi-quote can occur. + + +A quasi-quote is expanded by applying the appropriate parser to the string +enclosed by the Oxford brackets. The context of the quasi-quote (expression, pattern, +type, declaration) determines which of the parsers is called. + + + -Note that in the example we make use of an antiquoted +The example below shows quasi-quotation in action. The quoter expr +is bound to a value of type QuasiQuoter defined in module Expr. +The example makes use of an antiquoted variable n, indicated by the syntax 'int:n (this syntax for anti-quotation was defined by the parser's author, not by GHC). This binds n to the @@ -6497,12 +6549,6 @@ an expression parser that returns a value of type Q Exp and a pattern parser that returns a value of type Q Pat. -In general, a quasi-quote has the form -[$quoter| string |]. -The quoter must be the name of an imported quoter; it -cannot be an arbitrary expression. The quoted string -can be arbitrary, and may contain newlines. - Quasiquoters must obey the same stage restrictions as Template Haskell, e.g., in the example, expr cannot be defined @@ -6510,22 +6556,21 @@ in Main.hs where it is used, but must be imported. - -{- Main.hs -} +{- ------------- file Main.hs --------------- -} module Main where import Expr main :: IO () -main = do { print $ eval [$expr|1 + 2|] +main = do { print $ eval [expr|1 + 2|] ; case IntExpr 1 of - { [$expr|'int:n|] -> print n + { [expr|'int:n|] -> print n ; _ -> return () } } -{- Expr.hs -} +{- ------------- file Expr.hs --------------- -} module Expr where import qualified Language.Haskell.TH as TH @@ -6552,7 +6597,7 @@ eval (BinopExpr op x y) = (opToFun op) (eval x) (eval y) opToFun MulOp = (*) opToFun DivOp = div -expr = QuasiQuoter parseExprExp parseExprPat +expr = QuasiQuoter { quoteExp = parseExprExp, quotePat = parseExprPat } -- Parse an Expr, returning its representation as -- either a Q Exp or a Q Pat. See the referenced paper @@ -6568,19 +6613,18 @@ parseExprPat ... Now run the compiler: - $ ghc --make -XQuasiQuotes Main.hs -o main + -Run "main" and here is your output: - +Run "main" and here is your output: $ ./main 3 1 - + -- 1.7.10.4