summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Smith <michael@diglumi.com>2015-09-02 13:57:44 +0200
committerBen Gamari <ben@smart-cactus.org>2015-09-02 13:58:59 +0200
commitc8f623e305ec0a51ac2406a1f754d244e05b96f5 (patch)
tree5486d652fa38985657e8916ba176149644ed74a9
parentba5554ec2753cc41f5e087a91f23e1f612a9eb29 (diff)
downloadhaskell-c8f623e305ec0a51ac2406a1f754d244e05b96f5.tar.gz
Expand declaration QQs first (#10047)
Declaration QuasiQuoters do not cause a group split like $(...) splices, and are run and expanded before other declarations in the group. Resolves the lingering issue with #10047, and fixes broken tests qq007 and qq008. Test Plan: validate Reviewers: goldfire, austin, bgamari Reviewed By: bgamari Subscribers: goldfire, simonpj, thomie, spinda Differential Revision: https://phabricator.haskell.org/D1199 GHC Trac Issues: #10047
-rw-r--r--compiler/rename/RnSource.hs9
-rw-r--r--compiler/rename/RnSplice.hs-boot2
-rw-r--r--docs/users_guide/7.12.1-notes.xml47
-rw-r--r--docs/users_guide/glasgow_exts.xml39
-rw-r--r--testsuite/tests/quasiquotation/qq007/test.T1
-rw-r--r--testsuite/tests/quasiquotation/qq008/test.T1
-rw-r--r--testsuite/tests/quasiquotation/qq009/Makefile11
-rw-r--r--testsuite/tests/quasiquotation/qq009/QQ.hs14
-rw-r--r--testsuite/tests/quasiquotation/qq009/Test.hs9
-rw-r--r--testsuite/tests/quasiquotation/qq009/test.T7
10 files changed, 111 insertions, 29 deletions
diff --git a/compiler/rename/RnSource.hs b/compiler/rename/RnSource.hs
index f6a300763f..1a6fa170be 100644
--- a/compiler/rename/RnSource.hs
+++ b/compiler/rename/RnSource.hs
@@ -13,7 +13,7 @@ module RnSource (
#include "HsVersions.h"
import {-# SOURCE #-} RnExpr( rnLExpr )
-import {-# SOURCE #-} RnSplice ( rnSpliceDecl )
+import {-# SOURCE #-} RnSplice ( rnSpliceDecl, rnTopSpliceDecls )
import HsSyn
import RdrName
@@ -1510,6 +1510,13 @@ addl gp (L l d : ds) = add gp l d ds
add :: HsGroup RdrName -> SrcSpan -> HsDecl RdrName -> [LHsDecl RdrName]
-> RnM (HsGroup RdrName, Maybe (SpliceDecl RdrName, [LHsDecl RdrName]))
+-- #10047: Declaration QuasiQuoters are expanded immediately, without
+-- causing a group split
+add gp _ (SpliceD (SpliceDecl (L _ qq@HsQuasiQuote{}) _)) ds
+ = do { (ds', _) <- rnTopSpliceDecls qq
+ ; addl gp (ds' ++ ds)
+ }
+
add gp loc (SpliceD splice@(SpliceDecl _ flag)) ds
= do { -- We've found a top-level splice. If it is an *implicit* one
-- (i.e. a naked top level expression)
diff --git a/compiler/rename/RnSplice.hs-boot b/compiler/rename/RnSplice.hs-boot
index ece78f8408..b079b30bd5 100644
--- a/compiler/rename/RnSplice.hs-boot
+++ b/compiler/rename/RnSplice.hs-boot
@@ -13,3 +13,5 @@ rnSpliceType :: HsSplice RdrName -> PostTc Name Kind
rnSplicePat :: HsSplice RdrName -> RnM ( Either (Pat RdrName) (Pat Name)
, FreeVars )
rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
+
+rnTopSpliceDecls :: HsSplice RdrName -> RnM ([LHsDecl RdrName], FreeVars)
diff --git a/docs/users_guide/7.12.1-notes.xml b/docs/users_guide/7.12.1-notes.xml
index 3916e7105a..fa3ea0197d 100644
--- a/docs/users_guide/7.12.1-notes.xml
+++ b/docs/users_guide/7.12.1-notes.xml
@@ -194,6 +194,18 @@
pragmas.
</para>
</listitem>
+ <listitem>
+ <para>
+ Internally, the implementation of quasi-quotes has been
+ unified with that of normal Template Haskell splices. Under
+ the previous implementation, top-level declaration
+ quasi-quotes did not cause a break in the declaration
+ groups, unlike splices of the form
+ <literal>$(...)</literal>. This behavior has been
+ preserved under the new implementation, and is now
+ recognized and documented in <xref linked="th-syntax"/>.
+ </para>
+ </listitem>
</itemizedlist>
</sect3>
@@ -255,16 +267,19 @@
</listitem>
<listitem>
<para>
- The functions <literal>error</literal>,
- <literal>undefined</literal>, and
- <literal>assertError</literal> now take an implicit
- <literal>CallStack</literal> parameter, and will
- output a formatted call stack alongside the error
- message.
+ A new module <literal>GHC.SrcLoc</literal> was added,
+ exporting a new type <literal>SrcLoc</literal>. A
+ <literal>SrcLoc</literal> contains package, module,
+ and file names, as well as start and end positions.
</para>
+ </listitem>
+ <listitem>
<para>
- See <xref linkend="implicit-parameters-special"/> for a description of the
- implicit call stack feature.
+ A new type <literal>CallStack</literal> was added for use
+ with the new implicit callstack parameters. A
+ <literal>CallStack</literal> is a
+ <literal>[(String, SrcLoc)]</literal>, sorted by most-recent
+ call.
</para>
</listitem>
<listitem>
@@ -403,22 +418,6 @@
Version number XXXXX (was 0.3.1.0)
</para>
</listitem>
- <listitem>
- <para>
- A new type <literal>SrcLoc</literal> was added. A
- <literal>SrcLoc</literal> contains package, module,
- and file names, as well as start and end positions.
- </para>
- </listitem>
- <listitem>
- <para>
- A new type <literal>CallStack</literal> was added for use
- with the new implicit callstack parameters. A
- <literal>CallStack</literal> is a
- <literal>[(String, SrcLoc)]</literal>, sorted by most-recent
- call.
- </para>
- </listitem>
</itemizedlist>
</sect3>
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index f8fa9c34c6..1a4fbdbb81 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -9721,8 +9721,8 @@ Wiki page</ulink>.
</listitem>
<listitem><para>
- A quasi-quotation can appear in either a pattern context or an
- expression context and is also written in Oxford brackets:
+ A quasi-quotation can appear in a pattern, type, expression, or
+ declaration context and is also written in Oxford brackets:
<itemizedlist>
<listitem><para> <literal>[<replaceable>varid</replaceable>| ... |]</literal>,
where the "..." is an arbitrary string; a full description of the
@@ -9868,6 +9868,17 @@ f n = \ [haskell|y|] -> y+n
declaration group, but no more.
</para>
+ <para>
+ Unlike normal declaration splices, declaration quasiquoters
+ do not cause a break. These quasiquoters are expanded before
+ the rest of the declaration group is processed, and the
+ declarations they generate are merged into the surrounding
+ declaration group. Consequently, the type environment seen
+ by <literal>reify</literal> from a declaration quasiquoter
+ will not include anything from the quasiquoter's declaration
+ group.
+ </para>
+
<para>
Concretely, consider the following code
<programlisting>
@@ -9876,6 +9887,8 @@ module M where
f x = x
$(th1 4)
h y = k y y $(blah1)
+ [qq|blah|]
+ k x y = x + y
$(th2 10)
w z = $(blah2)
</programlisting>
@@ -9918,6 +9931,23 @@ module M where
as the splice <literal>$(th2...)</literal>.
</para>
</listitem>
+ <listitem>
+ <para>
+ The body of <literal>h</literal> <emphasis>is</emphasis>
+ able to refer to the function <literal>k</literal>
+ appearing on the other side of the declaration
+ quasiquoter, as quasiquoters never cause a declaration
+ group to be broken up.
+ </para>
+ <para>
+ A <literal>reify</literal> inside the
+ <literal>qq</literal> quasiquoter would be able to see
+ the definition of <literal>f</literal> from the
+ preceding declaration group, but not the definitions of
+ <literal>h</literal> or <literal>k</literal>, or any
+ definitions from subsequent declaration groups.
+ </para>
+ </listitem>
</orderedlist>
</para>
</listitem>
@@ -10220,6 +10250,11 @@ 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.
</para></listitem>
+<listitem><para>
+Unlike normal declaration splices of the form <literal>$(...)</literal>,
+declaration quasi-quotes do not cause a declaration group break. See
+<xref linkend="th-syntax"/> for more information.
+</para></listitem>
</itemizedlist>
</para>
<para>
diff --git a/testsuite/tests/quasiquotation/qq007/test.T b/testsuite/tests/quasiquotation/qq007/test.T
index d9a2df31d3..0b4448cdc0 100644
--- a/testsuite/tests/quasiquotation/qq007/test.T
+++ b/testsuite/tests/quasiquotation/qq007/test.T
@@ -2,7 +2,6 @@ test('qq007',
[when(fast(), skip),
extra_clean(['QQ.hi', 'QQ.o', 'Test.hi', 'Test.o']),
pre_cmd('$MAKE -s --no-print-directory TH_QQ'),
- expect_broken(10047),
],
multimod_compile,
['Test', '-v0'])
diff --git a/testsuite/tests/quasiquotation/qq008/test.T b/testsuite/tests/quasiquotation/qq008/test.T
index 5bdd2a9822..8cac1a9f0a 100644
--- a/testsuite/tests/quasiquotation/qq008/test.T
+++ b/testsuite/tests/quasiquotation/qq008/test.T
@@ -2,7 +2,6 @@ test('qq008',
[when(fast(), skip),
extra_clean(['QQ.hi', 'QQ.o', 'Test.hi', 'Test.o']),
pre_cmd('$MAKE -s --no-print-directory TH_QQ'),
- expect_broken(10047),
],
multimod_compile,
['Test', '-v0'])
diff --git a/testsuite/tests/quasiquotation/qq009/Makefile b/testsuite/tests/quasiquotation/qq009/Makefile
new file mode 100644
index 0000000000..0fa91dbf9a
--- /dev/null
+++ b/testsuite/tests/quasiquotation/qq009/Makefile
@@ -0,0 +1,11 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+.PHONY: TH_QQ
+TH_QQ:
+ifeq "$(GhcDynamic)" "YES"
+ '$(TEST_HC)' $(TEST_HC_OPTS) -c QQ.hs -dynamic -osuf dyn_o -hisuf dyn_hi
+else
+ '$(TEST_HC)' $(TEST_HC_OPTS) -c QQ.hs
+endif
diff --git a/testsuite/tests/quasiquotation/qq009/QQ.hs b/testsuite/tests/quasiquotation/qq009/QQ.hs
new file mode 100644
index 0000000000..89350bac60
--- /dev/null
+++ b/testsuite/tests/quasiquotation/qq009/QQ.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE TemplateHaskell #-}
+module QQ where
+
+import Language.Haskell.TH.Quote
+import Language.Haskell.TH.Syntax
+import Language.Haskell.TH
+
+pq = QuasiQuoter { quoteDec = \_ -> return [sig],
+ quoteType = \_ -> undefined,
+ quoteExp = \_ -> undefined,
+ quotePat = \_ -> undefined }
+
+sig = SigD (mkName "f") (ArrowT `AppT` int `AppT` int)
+int = ConT (mkName "Int")
diff --git a/testsuite/tests/quasiquotation/qq009/Test.hs b/testsuite/tests/quasiquotation/qq009/Test.hs
new file mode 100644
index 0000000000..1b43fb2acf
--- /dev/null
+++ b/testsuite/tests/quasiquotation/qq009/Test.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE QuasiQuotes #-}
+module Test where
+
+import QQ
+
+f' = f . (+ 1)
+
+[pq| foo |] -- Expands to f :: Int -> Int
+f x = x + 1
diff --git a/testsuite/tests/quasiquotation/qq009/test.T b/testsuite/tests/quasiquotation/qq009/test.T
new file mode 100644
index 0000000000..10b939a3bd
--- /dev/null
+++ b/testsuite/tests/quasiquotation/qq009/test.T
@@ -0,0 +1,7 @@
+test('qq009',
+ [when(fast(), skip),
+ extra_clean(['QQ.hi', 'QQ.o', 'Test.hi', 'Test.o']),
+ pre_cmd('$MAKE -s --no-print-directory TH_QQ'),
+ ],
+ multimod_compile,
+ ['Test', '-v0'])