summaryrefslogtreecommitdiff
path: root/compiler/parser/RdrHsSyn.hs
diff options
context:
space:
mode:
authorAlan Zimmerman <alan.zimm@gmail.com>2015-11-23 22:59:27 +0200
committerAlan Zimmerman <alan.zimm@gmail.com>2015-12-01 16:09:22 +0200
commit410b6477ce9396555900b46f740515a432171524 (patch)
tree61fed4846ac197c562ca2857f34938213374850e /compiler/parser/RdrHsSyn.hs
parent744d4b0086f9aac866b98227158a41125153e1e4 (diff)
downloadhaskell-wip/T11028.tar.gz
Refactor ConDeclwip/T11028
The ConDecl type in HsDecls is an uneasy compromise. For the most part, HsSyn directly reflects the syntax written by the programmer; and that gives just the right "pegs" on which to hang Alan's API annotations. But ConDecl doesn't properly reflect the syntax of Haskell-98 and GADT-style data type declarations. To be concrete, here's a draft new data type data ConDecl name | ConDeclGADT { con_names :: [Located name] , con_type :: LHsSigType name -- The type after the ‘::’ , con_doc :: Maybe LHsDocString } | ConDeclH98 { con_name :: Located name , con_qvars :: Maybe (LHsQTyVars name) -- User-written forall (if any), and its implicit -- kind variables -- Non-Nothing needs -XExistentialQuantification , con_cxt :: Maybe (LHsContext name) -- ^ User-written context (if any) , con_details :: HsConDeclDetails name -- ^ Arguments , con_doc :: Maybe LHsDocString -- ^ A possible Haddock comment. } deriving (Typeable) Note that For GADTs, just keep a type. That's what the user writes. NB:HsType can represent records on the LHS of an arrow: { x:Int,y:Bool} -> T con_qvars and con_cxt are both Maybe because they are both optional (the forall and the context of an existential data type For ConDeclGADT the type variables of the data type do not scope over the con_type; whereas for ConDeclH98 they do scope over con_cxt and con_details. Trac issue: #11028
Diffstat (limited to 'compiler/parser/RdrHsSyn.hs')
-rw-r--r--compiler/parser/RdrHsSyn.hs72
1 files changed, 26 insertions, 46 deletions
diff --git a/compiler/parser/RdrHsSyn.hs b/compiler/parser/RdrHsSyn.hs
index 4b744fe69a..70be8e5d0e 100644
--- a/compiler/parser/RdrHsSyn.hs
+++ b/compiler/parser/RdrHsSyn.hs
@@ -35,7 +35,8 @@ module RdrHsSyn (
mkExport,
mkExtName, -- RdrName -> CLabelString
mkGadtDecl, -- [Located RdrName] -> LHsType RdrName -> ConDecl RdrName
- mkSimpleConDecl,
+ gadtDeclDetails,
+ mkConDeclH98,
mkATDefault,
-- Bunch of functions in the parser monad for
@@ -487,38 +488,30 @@ mkPatSynMatchGroup (L _ patsyn_name) (L _ decls) =
text "pattern synonym 'where' clause must bind the pattern synonym's name" <+>
quotes (ppr patsyn_name) $$ ppr decl
-mkSimpleConDecl :: Located RdrName -> Maybe [LHsTyVarBndr RdrName]
+mkConDeclH98 :: Located RdrName -> Maybe [LHsTyVarBndr RdrName]
-> LHsContext RdrName -> HsConDeclDetails RdrName
-> ConDecl RdrName
-mkSimpleConDecl name mb_forall cxt details
- = ConDecl { con_names = [name]
- , con_explicit = explicit
- , con_qvars = qvars
- , con_cxt = cxt
- , con_details = details
- , con_res = ResTyH98
- , con_doc = Nothing }
- where
- (explicit, qvars) = case mb_forall of
- Nothing -> (False, mkHsQTvs [])
- Just tvs -> (True, mkHsQTvs tvs)
+mkConDeclH98 name mb_forall cxt details
+ = ConDeclH98 { con_name = name
+ , con_qvars = fmap mkHsQTvs mb_forall
+ , con_cxt = Just cxt
+ -- AZ:TODO: when can cxt be Nothing?
+ -- remembering that () is a valid context.
+ , con_details = details
+ , con_doc = Nothing }
mkGadtDecl :: [Located RdrName]
- -> LHsType RdrName -- Always a HsForAllTy
- -> ([AddAnn], ConDecl RdrName)
-mkGadtDecl names ty = ([], mkGadtDecl' names ty)
-
-mkGadtDecl' :: [Located RdrName]
- -> LHsType RdrName
- -> ConDecl RdrName
--- We allow C,D :: ty
--- and expand it as if it had been
--- C :: ty; D :: ty
--- (Just like type signatures in general.)
-
-mkGadtDecl' names lbody_ty@(L loc body_ty)
- = mk_gadt_con names
+ -> LHsSigType RdrName -- Always a HsForAllTy
+ -> ConDecl RdrName
+mkGadtDecl names ty = ConDeclGADT { con_names = names
+ , con_type = ty
+ , con_doc = Nothing }
+
+-- AZ:TODO: this probably belongs in a different module
+gadtDeclDetails :: LHsSigType name
+ -> (HsConDeclDetails name,LHsType name,LHsContext name,[LHsTyVarBndr name])
+gadtDeclDetails (HsIB {hsib_body = lbody_ty}) = (details,res_ty,cxt,tvs)
where
(tvs, cxt, tau) = splitLHsSigmaTy lbody_ty
(details, res_ty) -- See Note [Sorting out the result type]
@@ -527,19 +520,6 @@ mkGadtDecl' names lbody_ty@(L loc body_ty)
-> (RecCon (L l flds), res_ty)
_other -> (PrefixCon [], tau)
- explicit = case body_ty of
- HsForAllTy {} -> True
- _ -> False
-
- mk_gadt_con names
- = ConDecl { con_names = names
- , con_explicit = explicit
- , con_qvars = mkHsQTvs tvs
- , con_cxt = cxt
- , con_details = details
- , con_res = ResTyGADT loc res_ty
- , con_doc = Nothing }
-
tyConToDataCon :: SrcSpan -> RdrName -> P (Located RdrName)
tyConToDataCon loc tc
| isTcOcc (rdrNameOcc tc)
@@ -639,19 +619,19 @@ really doesn't matter!
-- | Note [Sorting out the result type]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- In a GADT declaration which is not a record, we put the whole constr
--- type into the ResTyGADT for now; the renamer will unravel it once it
--- has sorted out operator fixities. Consider for example
+-- In a GADT declaration which is not a record, we put the whole constr type
+-- into the res_ty for a ConDeclGADT for now; the renamer will unravel it once
+-- it has sorted out operator fixities. Consider for example
-- C :: a :*: b -> a :*: b -> a :+: b
-- Initially this type will parse as
-- a :*: (b -> (a :*: (b -> (a :+: b))))
-
+--
-- so it's hard to split up the arguments until we've done the precedence
-- resolution (in the renamer) On the other hand, for a record
-- { x,y :: Int } -> a :*: b
-- there is no doubt. AND we need to sort records out so that
-- we can bring x,y into scope. So:
--- * For PrefixCon we keep all the args in the ResTyGADT
+-- * For PrefixCon we keep all the args in the res_ty
-- * For RecCon we do not
checkTyVarsP :: SDoc -> SDoc -> Located RdrName -> [LHsType RdrName] -> P (LHsQTyVars RdrName)