summaryrefslogtreecommitdiff
path: root/compiler/parser
diff options
context:
space:
mode:
authorAdam Sandberg Eriksson <adam@sandbergericsson.se>2015-07-27 13:18:36 +0200
committerBen Gamari <ben@smart-cactus.org>2015-07-27 13:49:55 +0200
commitf842ad6c751c14ec331ca1709538c2f3e9a30ae7 (patch)
tree5517e0a9d3cf5b896bcdd6d6eb986613b295eaf2 /compiler/parser
parent474d4ccc6e4a3bea93be16cb7daef6ffcdf9b663 (diff)
downloadhaskell-f842ad6c751c14ec331ca1709538c2f3e9a30ae7.tar.gz
Implementation of StrictData language extension
This implements the `StrictData` language extension, which lets the programmer default to strict data fields in datatype declarations on a per-module basis. Specification and motivation can be found at https://ghc.haskell.org/trac/ghc/wiki/StrictPragma This includes a tricky parser change due to conflicts regarding `~` in the type level syntax: all ~'s are parsed as strictness annotations (see `strict_mark` in Parser.y) and then turned into equality constraints at the appropriate places using `RdrHsSyn.splitTilde`. Updates haddock submodule. Test Plan: Validate through Harbormaster. Reviewers: goldfire, austin, hvr, simonpj, tibbe, bgamari Reviewed By: simonpj, tibbe, bgamari Subscribers: lelf, simonpj, alanz, goldfire, thomie, bgamari, mpickering Differential Revision: https://phabricator.haskell.org/D1033 GHC Trac Issues: #8347
Diffstat (limited to 'compiler/parser')
-rw-r--r--compiler/parser/Parser.y82
-rw-r--r--compiler/parser/RdrHsSyn.hs16
2 files changed, 63 insertions, 35 deletions
diff --git a/compiler/parser/Parser.y b/compiler/parser/Parser.y
index 99abf162d1..815c8cb798 100644
--- a/compiler/parser/Parser.y
+++ b/compiler/parser/Parser.y
@@ -1566,18 +1566,21 @@ sigtypes1 :: { (OrdList (LHsType RdrName)) } -- Always HsForAllTys
-- Types
strict_mark :: { Located ([AddAnn],HsBang) }
- : '!' { sL1 $1 ([mj AnnBang $1]
- ,HsSrcBang Nothing Nothing True) }
- | '{-# UNPACK' '#-}' { sLL $1 $> ([mo $1,mc $2]
- ,HsSrcBang (Just $ getUNPACK_PRAGs $1) (Just True) False) }
- | '{-# NOUNPACK' '#-}' { sLL $1 $> ([mo $1,mc $2]
- ,HsSrcBang (Just $ getNOUNPACK_PRAGs $1) (Just False) False) }
- | '{-# UNPACK' '#-}' '!' { sLL $1 $> ([mo $1,mc $2,mj AnnBang $3]
- ,HsSrcBang (Just $ getUNPACK_PRAGs $1) (Just True) True) }
- | '{-# NOUNPACK' '#-}' '!' { sLL $1 $> ([mo $1,mc $2,mj AnnBang $3]
- ,HsSrcBang (Just $ getNOUNPACK_PRAGs $1) (Just False) True) }
- -- Although UNPACK with no '!' is illegal, we get a
- -- better error message if we parse it here
+ : strictness { sL1 $1 (let (a, str) = unLoc $1 in (a, HsSrcBang Nothing NoSrcUnpack str)) }
+ | unpackedness { sL1 $1 (let (a, prag, unpk) = unLoc $1 in (a, HsSrcBang prag unpk NoSrcStrictness)) }
+ | unpackedness strictness { sLL $1 $> (let { (a, prag, unpk) = unLoc $1
+ ; (a', str) = unLoc $2 }
+ in (a ++ a', HsSrcBang prag unpk str)) }
+ -- Although UNPACK with no '!' without StrictData and UNPACK with '~' are illegal,
+ -- we get a better error message if we parse them here
+
+strictness :: { Located ([AddAnn], SrcStrictness) }
+ : '!' { sL1 $1 ([mj AnnBang $1], SrcStrict) }
+ | '~' { sL1 $1 ([mj AnnTilde $1], SrcLazy) }
+
+unpackedness :: { Located ([AddAnn], Maybe SourceText, SrcUnpackedness) }
+ : '{-# UNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], Just $ getUNPACK_PRAGs $1, SrcUnpack) }
+ | '{-# NOUNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], Just $ getNOUNPACK_PRAGs $1, SrcNoUnpack) }
-- A ctype is a for-all type
ctype :: { LHsType RdrName }
@@ -1626,47 +1629,39 @@ ctypedoc :: { LHsType RdrName }
-- to permit an individual equational constraint without parenthesis.
-- Thus for some reason we allow f :: a~b => blah
-- but not f :: ?x::Int => blah
+-- See Note [Parsing ~]
context :: { LHsContext RdrName }
- : btype '~' btype {% do { (anns,ctx) <- checkContext
- (sLL $1 $> $ HsEqTy $1 $3)
- ; ams ctx (mj AnnTilde $2:anns) } }
- | btype {% do { (anns,ctx) <- checkContext $1
- ; if null (unLoc ctx)
- then addAnnotation (gl $1) AnnUnit (gl $1)
- else return ()
- ; ams ctx anns
- } }
-
+ : btype {% do { (anns,ctx) <- checkContext (splitTilde $1)
+ ; if null (unLoc ctx)
+ then addAnnotation (gl $1) AnnUnit (gl $1)
+ else return ()
+ ; ams ctx anns
+ } }
+-- See Note [Parsing ~]
type :: { LHsType RdrName }
- : btype { $1 }
+ : btype { splitTilde $1 }
| btype qtyconop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype tyvarop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype '->' ctype {% ams $1 [mj AnnRarrow $2]
- >> ams (sLL $1 $> $ HsFunTy $1 $3)
+ >> ams (sLL $1 $> $ HsFunTy (splitTilde $1) $3)
[mj AnnRarrow $2] }
- | btype '~' btype {% ams (sLL $1 $> $ HsEqTy $1 $3)
- [mj AnnTilde $2] }
- -- see Note [Promotion]
| btype SIMPLEQUOTE qconop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
[mj AnnSimpleQuote $2] }
| btype SIMPLEQUOTE varop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
[mj AnnSimpleQuote $2] }
-
+-- See Note [Parsing ~]
typedoc :: { LHsType RdrName }
- : btype { $1 }
- | btype docprev { sLL $1 $> $ HsDocTy $1 $2 }
+ : btype { splitTilde $1 }
+ | btype docprev { sLL $1 $> $ HsDocTy (splitTilde $1) $2 }
| btype qtyconop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype qtyconop type docprev { sLL $1 $> $ HsDocTy (L (comb3 $1 $2 $3) (mkHsOpTy $1 $2 $3)) $4 }
| btype tyvarop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype tyvarop type docprev { sLL $1 $> $ HsDocTy (L (comb3 $1 $2 $3) (mkHsOpTy $1 $2 $3)) $4 }
- | btype '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy $1 $3)
+ | btype '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy (splitTilde $1) $3)
[mj AnnRarrow $2] }
- | btype docprev '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy (L (comb2 $1 $2)
+ | btype docprev '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy (L (comb2 (splitTilde $1) $2)
(HsDocTy $1 $2)) $4)
[mj AnnRarrow $3] }
- | btype '~' btype {% ams (sLL $1 $> $ HsEqTy $1 $3)
- [mj AnnTilde $2] }
- -- see Note [Promotion]
| btype SIMPLEQUOTE qconop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
[mj AnnSimpleQuote $2] }
| btype SIMPLEQUOTE varop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
@@ -1791,6 +1786,23 @@ varids0 :: { Located [Located RdrName] }
: {- empty -} { noLoc [] }
| varids0 tyvar { sLL $1 $> ($2 : unLoc $1) }
+{-
+Note [Parsing ~]
+~~~~~~~~~~~~~~~~
+
+Due to parsing conflicts between lazyness annotations in data type
+declarations (see strict_mark) and equality types ~'s are always
+parsed as lazyness annotations, and turned into HsEqTy's in the
+correct places using RdrHsSyn.splitTilde.
+
+Since strict_mark is parsed as part of atype which is part of type,
+typedoc and context (where HsEqTy previously appeared) it made most
+sense and was simplest to parse ~ as part of strict_mark and later
+turn them into HsEqTy's.
+
+-}
+
+
-----------------------------------------------------------------------------
-- Kinds
diff --git a/compiler/parser/RdrHsSyn.hs b/compiler/parser/RdrHsSyn.hs
index aa0b8cf16f..357512be33 100644
--- a/compiler/parser/RdrHsSyn.hs
+++ b/compiler/parser/RdrHsSyn.hs
@@ -52,6 +52,7 @@ module RdrHsSyn (
checkDoAndIfThenElse,
checkRecordSyntax,
parseErrorSDoc,
+ splitTilde,
-- Help with processing exports
ImpExpSubSpec(..),
@@ -1059,6 +1060,21 @@ isFunLhs e = go e [] []
go _ _ _ = return Nothing
+-- | Transform btype with strict_mark's into HsEqTy's
+-- (((~a) ~b) c) ~d ==> ((~a) ~ (b c)) ~ d
+splitTilde :: LHsType RdrName -> LHsType RdrName
+splitTilde t = go t
+ where go (L loc (HsAppTy t1 t2))
+ | L _ (HsBangTy (HsSrcBang Nothing NoSrcUnpack SrcLazy) t2') <- t2
+ = L loc (HsEqTy (go t1) t2')
+ | otherwise
+ = case go t1 of
+ (L _ (HsEqTy tl tr)) ->
+ L loc (HsEqTy tl (L (combineLocs tr t2) (HsAppTy tr t2)))
+ t -> L loc (HsAppTy t t2)
+
+ go t = t
+
---------------------------------------------------------------------------
-- Check for monad comprehensions
--