diff options
author | Michael Smith <michael@diglumi.com> | 2015-09-02 13:57:44 +0200 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2015-09-02 13:58:59 +0200 |
commit | c8f623e305ec0a51ac2406a1f754d244e05b96f5 (patch) | |
tree | 5486d652fa38985657e8916ba176149644ed74a9 | |
parent | ba5554ec2753cc41f5e087a91f23e1f612a9eb29 (diff) | |
download | haskell-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.hs | 9 | ||||
-rw-r--r-- | compiler/rename/RnSplice.hs-boot | 2 | ||||
-rw-r--r-- | docs/users_guide/7.12.1-notes.xml | 47 | ||||
-rw-r--r-- | docs/users_guide/glasgow_exts.xml | 39 | ||||
-rw-r--r-- | testsuite/tests/quasiquotation/qq007/test.T | 1 | ||||
-rw-r--r-- | testsuite/tests/quasiquotation/qq008/test.T | 1 | ||||
-rw-r--r-- | testsuite/tests/quasiquotation/qq009/Makefile | 11 | ||||
-rw-r--r-- | testsuite/tests/quasiquotation/qq009/QQ.hs | 14 | ||||
-rw-r--r-- | testsuite/tests/quasiquotation/qq009/Test.hs | 9 | ||||
-rw-r--r-- | testsuite/tests/quasiquotation/qq009/test.T | 7 |
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']) |