summaryrefslogtreecommitdiff
path: root/libraries/template-haskell
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2016-08-23 14:20:36 -0400
committerBen Gamari <ben@smart-cactus.org>2016-08-23 15:35:18 -0400
commit613d745523f181991f6f916bbe58082b7970f7e6 (patch)
treeb93c010d19b953271a828eb97fa8fcdb05c2a8c7 /libraries/template-haskell
parent1766bb3cfd1460796c78bd5651f89d53603586f9 (diff)
downloadhaskell-613d745523f181991f6f916bbe58082b7970f7e6.tar.gz
Template Haskell support for unboxed sums
This adds new constructors `UnboxedSumE`, `UnboxedSumT`, and `UnboxedSumP` to represent unboxed sums in Template Haskell. One thing you can't currently do is, e.g., `reify ''(#||#)`, since I don't believe unboxed sum type/data constructors can be written in prefix form. I will look at fixing that as part of #12514. Fixes #12478. Test Plan: make test TEST=T12478_{1,2,3} Reviewers: osa1, goldfire, austin, bgamari Reviewed By: goldfire, bgamari Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2448 GHC Trac Issues: #12478
Diffstat (limited to 'libraries/template-haskell')
-rw-r--r--libraries/template-haskell/Language/Haskell/TH.hs11
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Lib.hs13
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Ppr.hs29
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs58
-rw-r--r--libraries/template-haskell/changelog.md2
5 files changed, 79 insertions, 34 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH.hs b/libraries/template-haskell/Language/Haskell/TH.hs
index 5bd610cd76..984bbc6b4f 100644
--- a/libraries/template-haskell/Language/Haskell/TH.hs
+++ b/libraries/template-haskell/Language/Haskell/TH.hs
@@ -24,6 +24,7 @@ module Language.Haskell.TH(
Info(..), ModuleInfo(..),
InstanceDec,
ParentName,
+ SumAlt, SumArity,
Arity,
Unlifted,
-- *** Language extension lookup
@@ -95,7 +96,7 @@ module Language.Haskell.TH(
intPrimL, wordPrimL, floatPrimL, doublePrimL, integerL, rationalL,
charL, stringL, stringPrimL, charPrimL,
-- *** Patterns
- litP, varP, tupP, conP, uInfixP, parensP, infixP,
+ litP, varP, tupP, unboxedSumP, conP, uInfixP, parensP, infixP,
tildeP, bangP, asP, wildP, recP,
listP, sigP, viewP,
fieldPat,
@@ -106,8 +107,8 @@ module Language.Haskell.TH(
-- *** Expressions
dyn, varE, conE, litE, appE, uInfixE, parensE, staticE,
infixE, infixApp, sectionL, sectionR,
- lamE, lam1E, lamCaseE, tupE, condE, multiIfE, letE, caseE, appsE,
- listE, sigE, recConE, recUpdE, stringE, fieldExp,
+ lamE, lam1E, lamCaseE, tupE, unboxedSumE, condE, multiIfE, letE, caseE,
+ appsE, listE, sigE, recConE, recUpdE, stringE, fieldExp,
-- **** Ranges
fromE, fromThenE, fromToE, fromThenToE,
@@ -120,8 +121,8 @@ module Language.Haskell.TH(
-- *** Types
forallT, varT, conT, appT, arrowT, infixT, uInfixT, parensT, equalityT,
- listT, tupleT, sigT, litT, promotedT, promotedTupleT, promotedNilT,
- promotedConsT,
+ listT, tupleT, unboxedSumT, sigT, litT, promotedT, promotedTupleT,
+ promotedNilT, promotedConsT,
-- **** Type literals
numTyLit, strTyLit,
-- **** Strictness
diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib.hs b/libraries/template-haskell/Language/Haskell/TH/Lib.hs
index d4529e1915..503f6ea84f 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Lib.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Lib.hs
@@ -80,12 +80,19 @@ rationalL = RationalL
litP :: Lit -> PatQ
litP l = return (LitP l)
+
varP :: Name -> PatQ
varP v = return (VarP v)
+
tupP :: [PatQ] -> PatQ
tupP ps = do { ps1 <- sequence ps; return (TupP ps1)}
+
unboxedTupP :: [PatQ] -> PatQ
unboxedTupP ps = do { ps1 <- sequence ps; return (UnboxedTupP ps1)}
+
+unboxedSumP :: PatQ -> SumAlt -> SumArity -> PatQ
+unboxedSumP p alt arity = do { p1 <- p; return (UnboxedSumP p1 alt arity) }
+
conP :: Name -> [PatQ] -> PatQ
conP n ps = do ps' <- sequence ps
return (ConP n ps')
@@ -266,6 +273,9 @@ tupE es = do { es1 <- sequence es; return (TupE es1)}
unboxedTupE :: [ExpQ] -> ExpQ
unboxedTupE es = do { es1 <- sequence es; return (UnboxedTupE es1)}
+unboxedSumE :: ExpQ -> SumAlt -> SumArity -> ExpQ
+unboxedSumE e alt arity = do { e1 <- e; return (UnboxedSumE e1 alt arity) }
+
condE :: ExpQ -> ExpQ -> ExpQ -> ExpQ
condE x y z = do { a <- x; b <- y; c <- z; return (CondE a b c)}
@@ -627,6 +637,9 @@ tupleT i = return (TupleT i)
unboxedTupleT :: Int -> TypeQ
unboxedTupleT i = return (UnboxedTupleT i)
+unboxedSumT :: SumArity -> TypeQ
+unboxedSumT arity = return (UnboxedSumT arity)
+
sigT :: TypeQ -> Kind -> TypeQ
sigT t k
= do
diff --git a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
index ca74db7e45..49d0e7b0d8 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
@@ -149,6 +149,7 @@ pprExp i (LamCaseE ms) = parensIf (i > noPrec)
$ text "\\case" $$ nest nestDepth (ppr ms)
pprExp _ (TupE es) = parens (commaSep es)
pprExp _ (UnboxedTupE es) = hashParens (commaSep es)
+pprExp _ (UnboxedSumE e alt arity) = unboxedSumBars (ppr e) alt arity
-- Nesting in Cond is to avoid potential problems in do statments
pprExp i (CondE guard true false)
= parensIf (i > noPrec) $ sep [text "if" <+> ppr guard,
@@ -179,7 +180,7 @@ pprExp i (DoE ss_) = parensIf (i > noPrec) $ text "do" <+> pprStms ss_
pprExp _ (CompE []) = text "<<Empty CompExp>>"
-- This will probably break with fixity declarations - would need a ';'
pprExp _ (CompE ss) = text "[" <> ppr s
- <+> text "|"
+ <+> bar
<+> commaSep ss'
<> text "]"
where s = last ss
@@ -205,7 +206,7 @@ instance Ppr Stmt where
ppr (BindS p e) = ppr p <+> text "<-" <+> ppr e
ppr (LetS ds) = text "let" <+> (braces (semiSep ds))
ppr (NoBindS e) = ppr e
- ppr (ParS sss) = sep $ punctuate (text "|")
+ ppr (ParS sss) = sep $ punctuate bar
$ map commaSep sss
------------------------------
@@ -216,8 +217,8 @@ instance Ppr Match where
------------------------------
pprGuarded :: Doc -> (Guard, Exp) -> Doc
pprGuarded eqDoc (guard, expr) = case guard of
- NormalG guardExpr -> char '|' <+> ppr guardExpr <+> eqDoc <+> ppr expr
- PatG stmts -> char '|' <+> vcat (punctuate comma $ map ppr stmts) $$
+ NormalG guardExpr -> bar <+> ppr guardExpr <+> eqDoc <+> ppr expr
+ PatG stmts -> bar <+> vcat (punctuate comma $ map ppr stmts) $$
nest nestDepth (eqDoc <+> ppr expr)
------------------------------
@@ -266,6 +267,7 @@ pprPat i (LitP l) = pprLit i l
pprPat _ (VarP v) = pprName' Applied v
pprPat _ (TupP ps) = parens (commaSep ps)
pprPat _ (UnboxedTupP ps) = hashParens (commaSep ps)
+pprPat _ (UnboxedSumP p alt arity) = unboxedSumBars (ppr p) alt arity
pprPat i (ConP s ps) = parensIf (i >= appPrec) $ pprName' Applied s
<+> sep (map (pprPat appPrec) ps)
pprPat _ (ParensP p) = parens $ pprPat noPrec p
@@ -389,7 +391,7 @@ ppr_data maybeInst ctxt t argsDoc ksig cs decs
pref :: [Doc] -> [Doc]
pref xs | isGadtDecl = xs
pref [] = [] -- No constructors; can't happen in H98
- pref (d:ds) = (char '=' <+> d):map (char '|' <+>) ds
+ pref (d:ds) = (char '=' <+> d):map (bar <+>) ds
maybeWhere :: Doc
maybeWhere | isGadtDecl = text "where"
@@ -436,7 +438,7 @@ ppr_tf_head (TypeFamilyHead tc tvs res inj)
instance Ppr FunDep where
ppr (FunDep xs ys) = hsep (map ppr xs) <+> text "->" <+> hsep (map ppr ys)
ppr_list [] = empty
- ppr_list xs = char '|' <+> commaSep xs
+ ppr_list xs = bar <+> commaSep xs
------------------------------
instance Ppr FamFlavour where
@@ -452,7 +454,7 @@ instance Ppr FamilyResultSig where
------------------------------
instance Ppr InjectivityAnn where
ppr (InjectivityAnn lhs rhs) =
- char '|' <+> ppr lhs <+> text "->" <+> hsep (map ppr rhs)
+ bar <+> ppr lhs <+> text "->" <+> hsep (map ppr rhs)
------------------------------
instance Ppr Foreign where
@@ -655,6 +657,7 @@ pprParendType (ConT c) = ppr c
pprParendType (TupleT 0) = text "()"
pprParendType (TupleT n) = parens (hcat (replicate (n-1) comma))
pprParendType (UnboxedTupleT n) = hashParens $ hcat $ replicate (n-1) comma
+pprParendType (UnboxedSumT arity) = hashParens $ hcat $ replicate (arity-1) bar
pprParendType ArrowT = parens (text "->")
pprParendType ListT = text "[]"
pprParendType (LitT l) = pprTyLit l
@@ -795,3 +798,15 @@ commaSepWith pprFun = sep . punctuate comma . map pprFun
-- followed by space.
semiSep :: Ppr a => [a] -> Doc
semiSep = sep . punctuate semi . map ppr
+
+-- Prints out the series of vertical bars that wraps an expression or pattern
+-- used in an unboxed sum.
+unboxedSumBars :: Doc -> SumAlt -> SumArity -> Doc
+unboxedSumBars d alt arity = hashParens $
+ bars (alt-1) <> d <> bars (arity - alt)
+ where
+ bars i = hsep (replicate i bar)
+
+-- Text containing the vertical bar character.
+bar :: Doc
+bar = char '|'
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index 62bdd10aac..8539e79bd2 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -1176,8 +1176,6 @@ mk_unboxed_tup_name n_commas space
occ = mkOccName ("(#" ++ replicate n_commas ',' ++ "#)")
tup_mod = mkModName "GHC.Tuple"
-
-
-----------------------------------------------------
-- Locations
-----------------------------------------------------
@@ -1278,6 +1276,19 @@ In 'ClassOpI' and 'DataConI', name of the parent class or type
-}
type ParentName = Name
+-- | In 'UnboxedSumE' and 'UnboxedSumP', the number associated with a
+-- particular data constructor. 'SumAlt's are one-indexed and should never
+-- exceed the value of its corresponding 'SumArity'. For example:
+--
+-- * @(\#_|\#)@ has 'SumAlt' 1 (out of a total 'SumArity' of 2)
+--
+-- * @(\#|_\#)@ has 'SumAlt' 2 (out of a total 'SumArity' of 2)
+type SumAlt = Int
+
+-- | In 'UnboxedSumE', 'UnboxedSumT', and 'UnboxedSumP', the total number of
+-- 'SumAlt's. For example, @(\#|\#)@ has a 'SumArity' of 2.
+type SumArity = Int
+
-- | In 'PrimTyConI', arity of the type constructor
type Arity = Int
@@ -1398,26 +1409,27 @@ data Lit = CharL Char
-- | Pattern in Haskell given in @{}@
data Pat
- = LitP Lit -- ^ @{ 5 or \'c\' }@
- | VarP Name -- ^ @{ x }@
- | TupP [Pat] -- ^ @{ (p1,p2) }@
- | UnboxedTupP [Pat] -- ^ @{ (\# p1,p2 \#) }@
- | ConP Name [Pat] -- ^ @data T1 = C1 t1 t2; {C1 p1 p1} = e@
- | InfixP Pat Name Pat -- ^ @foo ({x :+ y}) = e@
- | UInfixP Pat Name Pat -- ^ @foo ({x :+ y}) = e@
- --
- -- See "Language.Haskell.TH.Syntax#infix"
- | ParensP Pat -- ^ @{(p)}@
- --
- -- See "Language.Haskell.TH.Syntax#infix"
- | TildeP Pat -- ^ @{ ~p }@
- | BangP Pat -- ^ @{ !p }@
- | AsP Name Pat -- ^ @{ x \@ p }@
- | WildP -- ^ @{ _ }@
- | RecP Name [FieldPat] -- ^ @f (Pt { pointx = x }) = g x@
- | ListP [ Pat ] -- ^ @{ [1,2,3] }@
- | SigP Pat Type -- ^ @{ p :: t }@
- | ViewP Exp Pat -- ^ @{ e -> p }@
+ = LitP Lit -- ^ @{ 5 or \'c\' }@
+ | VarP Name -- ^ @{ x }@
+ | TupP [Pat] -- ^ @{ (p1,p2) }@
+ | UnboxedTupP [Pat] -- ^ @{ (\# p1,p2 \#) }@
+ | UnboxedSumP Pat SumAlt SumArity -- ^ @{ (\#|p|\#) }@
+ | ConP Name [Pat] -- ^ @data T1 = C1 t1 t2; {C1 p1 p1} = e@
+ | InfixP Pat Name Pat -- ^ @foo ({x :+ y}) = e@
+ | UInfixP Pat Name Pat -- ^ @foo ({x :+ y}) = e@
+ --
+ -- See "Language.Haskell.TH.Syntax#infix"
+ | ParensP Pat -- ^ @{(p)}@
+ --
+ -- See "Language.Haskell.TH.Syntax#infix"
+ | TildeP Pat -- ^ @{ ~p }@
+ | BangP Pat -- ^ @{ !p }@
+ | AsP Name Pat -- ^ @{ x \@ p }@
+ | WildP -- ^ @{ _ }@
+ | RecP Name [FieldPat] -- ^ @f (Pt { pointx = x }) = g x@
+ | ListP [ Pat ] -- ^ @{ [1,2,3] }@
+ | SigP Pat Type -- ^ @{ p :: t }@
+ | ViewP Exp Pat -- ^ @{ e -> p }@
deriving( Show, Eq, Ord, Data, Generic )
type FieldPat = (Name,Pat)
@@ -1452,6 +1464,7 @@ data Exp
| LamCaseE [Match] -- ^ @{ \\case m1; m2 }@
| TupE [Exp] -- ^ @{ (e1,e2) } @
| UnboxedTupE [Exp] -- ^ @{ (\# e1,e2 \#) } @
+ | UnboxedSumE Exp SumAlt SumArity -- ^ @{ (\#|e|\#) }@
| CondE Exp Exp Exp -- ^ @{ if e1 then e2 else e3 }@
| MultiIfE [(Guard, Exp)] -- ^ @{ if | g1 -> e1 | g2 -> e2 }@
| LetE [Dec] Exp -- ^ @{ let x=e1; y=e2 in e3 }@
@@ -1804,6 +1817,7 @@ data Type = ForallT [TyVarBndr] Cxt Type -- ^ @forall \<vars\>. \<ctxt\> -> \<t
-- See Note [Representing concrete syntax in types]
| TupleT Int -- ^ @(,), (,,), etc.@
| UnboxedTupleT Int -- ^ @(\#,\#), (\#,,\#), etc.@
+ | UnboxedSumT SumArity -- ^ @(\#|\#), (\#||\#), etc.@
| ArrowT -- ^ @->@
| EqualityT -- ^ @~@
| ListT -- ^ @[]@
diff --git a/libraries/template-haskell/changelog.md b/libraries/template-haskell/changelog.md
index e9084e27f9..d6f0d46c02 100644
--- a/libraries/template-haskell/changelog.md
+++ b/libraries/template-haskell/changelog.md
@@ -8,6 +8,8 @@
`PatSynSigD`), and two new data types (`PatSynDir` and `PatSynArgs`),
among other changes. (#8761)
+ * Add support for unboxed sums. (#12478)
+
## 2.11.0.0 *May 2016*
* Bundled with GHC 8.0.1