diff options
| author | Adam Sandberg Eriksson <adam@sandbergericsson.se> | 2015-07-27 13:18:36 +0200 |
|---|---|---|
| committer | Ben Gamari <ben@smart-cactus.org> | 2015-07-27 13:49:55 +0200 |
| commit | f842ad6c751c14ec331ca1709538c2f3e9a30ae7 (patch) | |
| tree | 5517e0a9d3cf5b896bcdd6d6eb986613b295eaf2 /compiler/parser | |
| parent | 474d4ccc6e4a3bea93be16cb7daef6ffcdf9b663 (diff) | |
| download | haskell-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.y | 82 | ||||
| -rw-r--r-- | compiler/parser/RdrHsSyn.hs | 16 |
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 -- |
