diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2016-08-23 14:20:36 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-08-23 15:35:18 -0400 |
commit | 613d745523f181991f6f916bbe58082b7970f7e6 (patch) | |
tree | b93c010d19b953271a828eb97fa8fcdb05c2a8c7 /libraries/template-haskell | |
parent | 1766bb3cfd1460796c78bd5651f89d53603586f9 (diff) | |
download | haskell-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.hs | 11 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Lib.hs | 13 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Ppr.hs | 29 | ||||
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Syntax.hs | 58 | ||||
-rw-r--r-- | libraries/template-haskell/changelog.md | 2 |
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 |