diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2016-09-30 20:15:25 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-09-30 23:23:44 -0400 |
commit | 9e862765ffe161da8a4fd9cd67b0a600874feaa9 (patch) | |
tree | 235c1ba702b0101e1fa6a8fe7f8146e2c7ec9c69 /compiler/parser | |
parent | b3d55e20d20344bfc09f4ca4a554a819c4ecbfa8 (diff) | |
download | haskell-9e862765ffe161da8a4fd9cd67b0a600874feaa9.tar.gz |
Implement deriving strategies
Allows users to explicitly request which approach to `deriving` to use
via keywords, e.g.,
```
newtype Foo = Foo Bar
deriving Eq
deriving stock Ord
deriving newtype Show
```
Fixes #10598. Updates haddock submodule.
Test Plan: ./validate
Reviewers: hvr, kosmikus, goldfire, alanz, bgamari, simonpj, austin,
erikd, simonmar
Reviewed By: alanz, bgamari, simonpj
Subscribers: thomie, mpickering, oerjan
Differential Revision: https://phabricator.haskell.org/D2280
GHC Trac Issues: #10598
Diffstat (limited to 'compiler/parser')
-rw-r--r-- | compiler/parser/ApiAnnotation.hs | 4 | ||||
-rw-r--r-- | compiler/parser/Lexer.x | 4 | ||||
-rw-r--r-- | compiler/parser/Parser.y | 126 |
3 files changed, 84 insertions, 50 deletions
diff --git a/compiler/parser/ApiAnnotation.hs b/compiler/parser/ApiAnnotation.hs index eebec547cc..ac784bcea4 100644 --- a/compiler/parser/ApiAnnotation.hs +++ b/compiler/parser/ApiAnnotation.hs @@ -186,7 +186,8 @@ getAndRemoveAnnotationComments (anns,canns) span = -- corresponding token, unless otherwise noted -- See note [Api annotations] above for details of the usage data AnnKeywordId - = AnnAs + = AnnAnyclass + | AnnAs | AnnAt | AnnBang -- ^ '!' | AnnBackquote -- ^ '`' @@ -256,6 +257,7 @@ data AnnKeywordId | AnnSemi -- ^ ';' | AnnSimpleQuote -- ^ ''' | AnnStatic -- ^ 'static' + | AnnStock | AnnThen | AnnThIdSplice -- ^ '$' | AnnThIdTySplice -- ^ '$$' diff --git a/compiler/parser/Lexer.x b/compiler/parser/Lexer.x index 410d150f45..361fa0be6a 100644 --- a/compiler/parser/Lexer.x +++ b/compiler/parser/Lexer.x @@ -612,6 +612,8 @@ data Token | ITusing | ITpattern | ITstatic + | ITstock + | ITanyclass -- Pragmas, see note [Pragma source text] in BasicTypes | ITinline_prag SourceText InlineSpec RuleMatchInfo @@ -803,6 +805,8 @@ reservedWordsFM = listToUFM $ ( "role", ITrole, 0 ), ( "pattern", ITpattern, xbit PatternSynonymsBit), ( "static", ITstatic, 0 ), + ( "stock", ITstock, 0 ), + ( "anyclass", ITanyclass, 0 ), ( "group", ITgroup, xbit TransformComprehensionsBit), ( "by", ITby, xbit TransformComprehensionsBit), ( "using", ITusing, xbit TransformComprehensionsBit), diff --git a/compiler/parser/Parser.y b/compiler/parser/Parser.y index 5db535f20e..4cab083484 100644 --- a/compiler/parser/Parser.y +++ b/compiler/parser/Parser.y @@ -88,7 +88,7 @@ import qualified GHC.LanguageExtensions as LangExt %expect 36 -- shift/reduce conflicts -{- Last updated: 9 Jan 2016 +{- Last updated: 3 Aug 2016 If you modify this parser and add a conflict, please update this comment. You can learn more about the conflicts by passing 'happy' the -i flag: @@ -119,7 +119,7 @@ follows. Shift parses as if the 'module' keyword follows. ------------------------------------------------------------------------------- -state 46 contains 2 shift/reduce conflicts. +state 48 contains 2 shift/reduce conflicts. *** strict_mark -> unpackedness . strict_mark -> unpackedness . strictness @@ -128,7 +128,7 @@ state 46 contains 2 shift/reduce conflicts. ------------------------------------------------------------------------------- -state 50 contains 1 shift/reduce conflict. +state 52 contains 1 shift/reduce conflict. context -> btype . *** type -> btype . @@ -138,7 +138,7 @@ state 50 contains 1 shift/reduce conflict. ------------------------------------------------------------------------------- -state 51 contains 9 shift/reduce conflicts. +state 53 contains 9 shift/reduce conflicts. *** btype -> tyapps . tyapps -> tyapps . tyapp @@ -147,7 +147,7 @@ state 51 contains 9 shift/reduce conflicts. ------------------------------------------------------------------------------- -state 132 contains 14 shift/reduce conflicts. +state 134 contains 14 shift/reduce conflicts. exp -> infixexp . '::' sigtype exp -> infixexp . '-<' exp @@ -172,7 +172,7 @@ Shift parses as (per longest-parse rule): ------------------------------------------------------------------------------- -state 295 contains 1 shift/reduce conflicts. +state 299 contains 1 shift/reduce conflicts. rule -> STRING . rule_activation rule_forall infixexp '=' exp @@ -190,7 +190,7 @@ a rule instructing how to rewrite the expression '[0] f'. ------------------------------------------------------------------------------- -state 304 contains 1 shift/reduce conflict. +state 309 contains 1 shift/reduce conflict. *** type -> btype . type -> btype . '->' ctype @@ -201,7 +201,7 @@ Same as state 50 but without contexts. ------------------------------------------------------------------------------- -state 340 contains 1 shift/reduce conflicts. +state 348 contains 1 shift/reduce conflicts. tup_exprs -> commas . tup_tail sysdcon_nolist -> '(' commas . ')' @@ -216,7 +216,7 @@ if -XTupleSections is not specified. ------------------------------------------------------------------------------- -state 391 contains 1 shift/reduce conflicts. +state 402 contains 1 shift/reduce conflicts. tup_exprs -> commas . tup_tail sysdcon_nolist -> '(#' commas . '#)' @@ -228,7 +228,7 @@ Same as State 324 for unboxed tuples. ------------------------------------------------------------------------------- -state 465 contains 1 shift/reduce conflict. +state 477 contains 1 shift/reduce conflict. oqtycon -> '(' qtyconsym . ')' *** qtyconop -> qtyconsym . @@ -239,7 +239,7 @@ TODO: Why? ------------------------------------------------------------------------------- -state 639 contains 1 shift/reduce conflicts. +state 658 contains 1 shift/reduce conflicts. *** aexp2 -> ipvar . dbind -> ipvar . '=' exp @@ -254,7 +254,7 @@ sensible meaning, namely the lhs of an implicit binding. ------------------------------------------------------------------------------- -state 707 contains 1 shift/reduce conflicts. +state 731 contains 1 shift/reduce conflicts. rule -> STRING rule_activation . rule_forall infixexp '=' exp @@ -271,7 +271,7 @@ doesn't include 'forall'. ------------------------------------------------------------------------------- -state 933 contains 1 shift/reduce conflicts. +state 963 contains 1 shift/reduce conflicts. transformqual -> 'then' 'group' . 'using' exp transformqual -> 'then' 'group' . 'by' exp 'using' exp @@ -281,7 +281,7 @@ state 933 contains 1 shift/reduce conflicts. ------------------------------------------------------------------------------- -state 1269 contains 1 shift/reduce conflict. +state 1303 contains 1 shift/reduce conflict. *** atype -> tyvar . tv_bndr -> '(' tyvar . '::' kind ')' @@ -368,6 +368,8 @@ output it generates. 'using' { L _ ITusing } -- for list transform extension 'pattern' { L _ ITpattern } -- for pattern synonyms 'static' { L _ ITstatic } -- for static pointers extension + 'stock' { L _ ITstock } -- for DerivingStrategies extension + 'anyclass' { L _ ITanyclass } -- for DerivingStrategies extension '{-# INLINE' { L _ (ITinline_prag _ _ _) } -- INLINE or INLINABLE '{-# SPECIALISE' { L _ (ITspec_prag _) } @@ -870,10 +872,10 @@ ty_decl :: { LTyClDecl RdrName } ++ (fst $ unLoc $5) ++ (fst $ unLoc $6)) } -- ordinary data type or newtype declaration - | data_or_newtype capi_ctype tycl_hdr constrs deriving + | data_or_newtype capi_ctype tycl_hdr constrs maybe_derivings {% amms (mkTyData (comb4 $1 $3 $4 $5) (snd $ unLoc $1) $2 $3 Nothing (reverse (snd $ unLoc $4)) - (unLoc $5)) + (fmap reverse $5)) -- We need the location on tycl_hdr in case -- constrs and deriving are both empty ((fst $ unLoc $1):(fst $ unLoc $4)) } @@ -881,9 +883,10 @@ ty_decl :: { LTyClDecl RdrName } -- ordinary GADT declaration | data_or_newtype capi_ctype tycl_hdr opt_kind_sig gadt_constrlist - deriving + maybe_derivings {% amms (mkTyData (comb4 $1 $3 $5 $6) (snd $ unLoc $1) $2 $3 - (snd $ unLoc $4) (snd $ unLoc $5) (unLoc $6) ) + (snd $ unLoc $4) (snd $ unLoc $5) + (fmap reverse $6) ) -- We need the location on tycl_hdr in case -- constrs and deriving are both empty ((fst $ unLoc $1):(fst $ unLoc $4)++(fst $ unLoc $5)) } @@ -912,18 +915,20 @@ inst_decl :: { LInstDecl RdrName } (mj AnnType $1:mj AnnInstance $2:(fst $ unLoc $3)) } -- data/newtype instance declaration - | data_or_newtype 'instance' capi_ctype tycl_hdr constrs deriving + | data_or_newtype 'instance' capi_ctype tycl_hdr constrs + maybe_derivings {% amms (mkDataFamInst (comb4 $1 $4 $5 $6) (snd $ unLoc $1) $3 $4 Nothing (reverse (snd $ unLoc $5)) - (unLoc $6)) + (fmap reverse $6)) ((fst $ unLoc $1):mj AnnInstance $2:(fst $ unLoc $5)) } -- GADT instance declaration | data_or_newtype 'instance' capi_ctype tycl_hdr opt_kind_sig gadt_constrlist - deriving + maybe_derivings {% amms (mkDataFamInst (comb4 $1 $4 $6 $7) (snd $ unLoc $1) $3 $4 - (snd $ unLoc $5) (snd $ unLoc $6) (unLoc $7)) + (snd $ unLoc $5) (snd $ unLoc $6) + (fmap reverse $7)) ((fst $ unLoc $1):mj AnnInstance $2 :(fst $ unLoc $5)++(fst $ unLoc $6)) } @@ -938,6 +943,14 @@ overlap_pragma :: { Maybe (Located OverlapMode) } [mo $1,mc $2] } | {- empty -} { Nothing } +deriv_strategy :: { Maybe (Located DerivStrategy) } + : 'stock' {% ajs (Just (sL1 $1 DerivStock)) + [mj AnnStock $1] } + | 'anyclass' {% ajs (Just (sL1 $1 DerivAnyclass)) + [mj AnnAnyclass $1] } + | 'newtype' {% ajs (Just (sL1 $1 DerivNewtype)) + [mj AnnNewtype $1] } + | {- empty -} { Nothing } -- Injective type families @@ -1048,18 +1061,19 @@ at_decl_inst :: { LInstDecl RdrName } (mj AnnType $1:(fst $ unLoc $2)) } -- data/newtype instance declaration - | data_or_newtype capi_ctype tycl_hdr constrs deriving + | data_or_newtype capi_ctype tycl_hdr constrs maybe_derivings {% amms (mkDataFamInst (comb4 $1 $3 $4 $5) (snd $ unLoc $1) $2 $3 Nothing (reverse (snd $ unLoc $4)) - (unLoc $5)) + (fmap reverse $5)) ((fst $ unLoc $1):(fst $ unLoc $4)) } -- GADT instance declaration | data_or_newtype capi_ctype tycl_hdr opt_kind_sig gadt_constrlist - deriving + maybe_derivings {% amms (mkDataFamInst (comb4 $1 $3 $5 $6) (snd $ unLoc $1) $2 - $3 (snd $ unLoc $4) (snd $ unLoc $5) (unLoc $6)) + $3 (snd $ unLoc $4) (snd $ unLoc $5) + (fmap reverse $6)) ((fst $ unLoc $1):(fst $ unLoc $4)++(fst $ unLoc $5)) } data_or_newtype :: { Located (AddAnn, NewOrData) } @@ -1120,11 +1134,11 @@ capi_ctype : '{-# CTYPE' STRING STRING '#-}' -- Glasgow extension: stand-alone deriving declarations stand_alone_deriving :: { LDerivDecl RdrName } - : 'deriving' 'instance' overlap_pragma inst_type - {% do { let { err = text "in the stand-alone deriving instance" - <> colon <+> quotes (ppr $4) } - ; ams (sLL $1 (hsSigType $>) (DerivDecl $4 $3)) - [mj AnnDeriving $1, mj AnnInstance $2] } } + : 'deriving' deriv_strategy 'instance' overlap_pragma inst_type + {% do { let { err = text "in the stand-alone deriving instance" + <> colon <+> quotes (ppr $5) } + ; ams (sLL $1 (hsSigType $>) (DerivDecl $5 $2 $4)) + [mj AnnDeriving $1, mj AnnInstance $3] } } ----------------------------------------------------------------------------- -- Role annotations @@ -1929,22 +1943,34 @@ fielddecl :: { LConDeclField RdrName } (ConDeclField (reverse (map (\ln@(L l n) -> L l $ FieldOcc ln PlaceHolder) (unLoc $2))) $4 ($1 `mplus` $5))) [mu AnnDcolon $3] } +-- Reversed! +maybe_derivings :: { HsDeriving RdrName } + : {- empty -} { noLoc [] } + | derivings { $1 } + +-- A list of one or more deriving clauses at the end of a datatype +derivings :: { HsDeriving RdrName } + : derivings deriving { sLL $1 $> $ $2 : unLoc $1 } + | deriving { sLL $1 $> [$1] } + -- The outer Located is just to allow the caller to -- know the rightmost extremity of the 'deriving' clause -deriving :: { Located (HsDeriving RdrName) } - : {- empty -} { noLoc Nothing } - | 'deriving' qtycondoc {% let { full_loc = comb2 $1 $> } - in ams (L full_loc $ Just $ L full_loc $ - [mkLHsSigType $2]) - [mj AnnDeriving $1] } - - | 'deriving' '(' ')' {% let { full_loc = comb2 $1 $> } - in ams (L full_loc $ Just $ L full_loc []) - [mj AnnDeriving $1,mop $2,mcp $3] } - - | 'deriving' '(' deriv_types ')' {% let { full_loc = comb2 $1 $> } - in ams (L full_loc $ Just $ L full_loc $3) - [mj AnnDeriving $1,mop $2,mcp $4] } +deriving :: { LHsDerivingClause RdrName } + : 'deriving' deriv_strategy qtycondoc + {% let { full_loc = comb2 $1 $> } + in ams (L full_loc $ HsDerivingClause $2 $ L full_loc + [mkLHsSigType $3]) + [mj AnnDeriving $1] } + + | 'deriving' deriv_strategy '(' ')' + {% let { full_loc = comb2 $1 $> } + in ams (L full_loc $ HsDerivingClause $2 $ L full_loc []) + [mj AnnDeriving $1,mop $3,mcp $4] } + + | 'deriving' deriv_strategy '(' deriv_types ')' + {% let { full_loc = comb2 $1 $> } + in ams (L full_loc $ HsDerivingClause $2 $ L full_loc $4) + [mj AnnDeriving $1,mop $3,mcp $5] } -- Glasgow extension: allow partial -- applications in derivings @@ -3014,8 +3040,8 @@ qvarid :: { Located RdrName } | QVARID { sL1 $1 $! mkQual varName (getQVARID $1) } -- Note that 'role' and 'family' get lexed separately regardless of --- the use of extensions. However, because they are listed here, this --- is OK and they can be used as normal varids. +-- the use of extensions. However, because they are listed here, +-- this is OK and they can be used as normal varids. -- See Note [Lexing type pseudo-keywords] in Lexer.x varid :: { Located RdrName } : VARID { sL1 $1 $! mkUnqual varName (getVARID $1) } @@ -3049,8 +3075,8 @@ varsym_no_minus :: { Located RdrName } -- varsym not including '-' -- These special_ids are treated as keywords in various places, -- but as ordinary ids elsewhere. 'special_id' collects all these --- except 'unsafe', 'interruptible', 'forall', 'family', and 'role', --- whose treatment differs depending on context +-- except 'unsafe', 'interruptible', 'forall', 'family', 'role', 'stock', and +-- 'anyclass', whose treatment differs depending on context special_id :: { Located FastString } special_id : 'as' { sL1 $1 (fsLit "as") } @@ -3065,6 +3091,8 @@ special_id | 'prim' { sL1 $1 (fsLit "prim") } | 'javascript' { sL1 $1 (fsLit "javascript") } | 'group' { sL1 $1 (fsLit "group") } + | 'stock' { sL1 $1 (fsLit "stock") } + | 'anyclass' { sL1 $1 (fsLit "anyclass") } special_sym :: { Located FastString } special_sym : '!' {% ams (sL1 $1 (fsLit "!")) [mj AnnBang $1] } |