diff options
author | Matthias Pall Gissurarson <mpg@mpg.is> | 2020-05-19 22:50:47 +0200 |
---|---|---|
committer | Facundo DomÃnguez <facundo.dominguez@tweag.io> | 2020-06-26 17:12:45 +0000 |
commit | 9ee58f8d900884ac8b721b6b95dbfa6500f39431 (patch) | |
tree | 2025e2f3ef4a92b252059287ea5d84745eec1118 /libraries/template-haskell/Language | |
parent | a3d69dc6c2134afe239caf4f881ba5542d2c2be0 (diff) | |
download | haskell-9ee58f8d900884ac8b721b6b95dbfa6500f39431.tar.gz |
Implement the proposed -XQualifiedDo extension
Co-authored-by: Facundo DomÃnguez <facundo.dominguez@tweag.io>
QualifiedDo is implemented using the same placeholders for operation names in
the AST that were devised for RebindableSyntax. Whenever the renamer checks
which names to use for do syntax, it first checks if the do block is qualified
(e.g. M.do { stmts }), in which case it searches for qualified names in
the module M.
This allows users to write
{-# LANGUAGE QualifiedDo #-}
import qualified SomeModule as M
f x = M.do -- desugars to:
y <- M.return x -- M.return x M.>>= \y ->
M.return y -- M.return y M.>>
M.return y -- M.return y
See Note [QualifiedDo] and the users' guide for more details.
Issue #18214
Proposal:
https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0216-qualified-do.rst
Since we change the constructors `ITdo` and `ITmdo` to carry the new module
name, we need to bump the haddock submodule to account or the new shape of
these constructors.
Diffstat (limited to 'libraries/template-haskell/Language')
4 files changed, 28 insertions, 8 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib.hs b/libraries/template-haskell/Language/Haskell/TH/Lib.hs index 4c4eaf5dbe..7aa4761321 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Lib.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Lib.hs @@ -157,12 +157,15 @@ import Language.Haskell.TH.Lib.Internal hiding , derivClause , standaloneDerivWithStrategyD + , doE + , mdoE , tupE , unboxedTupE , Role , InjectivityAnn ) +import qualified Language.Haskell.TH.Lib.Internal as Internal import Language.Haskell.TH.Syntax import Control.Applicative ( liftA2 ) @@ -337,3 +340,12 @@ tupE es = do { es1 <- sequenceA es; return (TupE $ map Just es1)} unboxedTupE :: Quote m => [m Exp] -> m Exp unboxedTupE es = do { es1 <- sequenceA es; return (UnboxedTupE $ map Just es1)} + +------------------------------------------------------------------------------- +-- * Do expressions + +doE :: Quote m => [m Stmt] -> m Exp +doE = Internal.doE Nothing + +mdoE :: Quote m => [m Stmt] -> m Exp +mdoE = Internal.mdoE Nothing diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs b/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs index ff020ee62d..c93cc6c3a8 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs @@ -312,11 +312,11 @@ letE ds e = do { ds2 <- sequenceA ds; e2 <- e; pure (LetE ds2 e2) } caseE :: Quote m => m Exp -> [m Match] -> m Exp caseE e ms = do { e1 <- e; ms1 <- sequenceA ms; pure (CaseE e1 ms1) } -doE :: Quote m => [m Stmt] -> m Exp -doE ss = do { ss1 <- sequenceA ss; pure (DoE ss1) } +doE :: Quote m => Maybe ModName -> [m Stmt] -> m Exp +doE m ss = do { ss1 <- sequenceA ss; pure (DoE m ss1) } -mdoE :: Quote m => [m Stmt] -> m Exp -mdoE ss = do { ss1 <- sequenceA ss; pure (MDoE ss1) } +mdoE :: Quote m => Maybe ModName -> [m Stmt] -> m Exp +mdoE m ss = do { ss1 <- sequenceA ss; pure (MDoE m ss1) } compE :: Quote m => [m Stmt] -> m Exp compE ss = do { ss1 <- sequenceA ss; pure (CompE ss1) } diff --git a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs index fcaaa40c3e..337017a958 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs @@ -182,13 +182,19 @@ pprExp i (LetE ds_ e) = parensIf (i > noPrec) $ text "let" <+> pprDecs ds_ pprExp i (CaseE e ms) = parensIf (i > noPrec) $ text "case" <+> ppr e <+> text "of" $$ nest nestDepth (ppr ms) -pprExp i (DoE ss_) = parensIf (i > noPrec) $ text "do" <+> pprStms ss_ +pprExp i (DoE m ss_) = parensIf (i > noPrec) $ + pprQualifier m <> text "do" <+> pprStms ss_ where + pprQualifier Nothing = empty + pprQualifier (Just modName) = text (modString modName) <> char '.' pprStms [] = empty pprStms [s] = ppr s pprStms ss = braces (semiSep ss) -pprExp i (MDoE ss_) = parensIf (i > noPrec) $ text "mdo" <+> pprStms ss_ +pprExp i (MDoE m ss_) = parensIf (i > noPrec) $ + pprQualifier m <> text "mdo" <+> pprStms ss_ where + pprQualifier Nothing = empty + pprQualifier (Just modName) = text (modString modName) <> char '.' pprStms [] = empty pprStms [s] = ppr s pprStms ss = braces (semiSep ss) diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs index 955f430d33..a894ce8378 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs @@ -2039,8 +2039,10 @@ data Exp | MultiIfE [(Guard, Exp)] -- ^ @{ if | g1 -> e1 | g2 -> e2 }@ | LetE [Dec] Exp -- ^ @{ let { x=e1; y=e2 } in e3 }@ | CaseE Exp [Match] -- ^ @{ case e of m1; m2 }@ - | DoE [Stmt] -- ^ @{ do { p <- e1; e2 } }@ - | MDoE [Stmt] -- ^ @{ mdo { x <- e1 y; y <- e2 x; } }@ + | DoE (Maybe ModName) [Stmt] -- ^ @{ do { p <- e1; e2 } }@ or a qualified do if + -- the module name is present + | MDoE (Maybe ModName) [Stmt] -- ^ @{ mdo { x <- e1 y; y <- e2 x; } }@ or a qualified + -- mdo if the module name is present | CompE [Stmt] -- ^ @{ [ (x,y) | x <- xs, y <- ys ] }@ -- -- The result expression of the comprehension is |