X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fparser%2FRdrHsSyn.lhs;h=a9433441e81ed4c7f0c8e53758efb6ca765a8ff1;hp=ae4a15a2a1c29eafc0f0940978ba0c2e3d77546a;hb=2d4d636af091b8da27466b5cf90011395a9c2f66;hpb=0a5613f40b0e32cf59966e6b56b807cdbe80aa7b diff --git a/compiler/parser/RdrHsSyn.lhs b/compiler/parser/RdrHsSyn.lhs index ae4a15a..a943344 100644 --- a/compiler/parser/RdrHsSyn.lhs +++ b/compiler/parser/RdrHsSyn.lhs @@ -40,10 +40,10 @@ module RdrHsSyn ( checkPattern, -- HsExp -> P HsPat bang_RDR, checkPatterns, -- SrcLoc -> [HsExp] -> P [HsPat] - checkDo, -- [Stmt] -> P [Stmt] - checkMDo, -- [Stmt] -> P [Stmt] + checkMonadComp, -- P (HsStmtContext RdrName) checkValDef, -- (SrcLoc, HsExp, HsRhs, [HsDecl]) -> P HsDecl checkValSig, -- (SrcLoc, HsExp, HsRhs, [HsDecl]) -> P HsDecl + checkDoAndIfThenElse, parseError, parseErrorSDoc, ) where @@ -53,8 +53,9 @@ import Class ( FunDep ) import TypeRep ( Kind ) import RdrName ( RdrName, isRdrTyVar, isRdrTc, mkUnqual, rdrNameOcc, isRdrDataCon, isUnqual, getRdrName, setRdrNameSpace ) +import Name ( Name ) import BasicTypes ( maxPrecedence, Activation(..), RuleMatchInfo, - InlinePragma(..) ) + InlinePragma(..), InlineSpec(..) ) import Lexer import TysWiredIn ( unitTyCon ) import ForeignCall @@ -70,6 +71,7 @@ import FastString import Maybes import Control.Applicative ((<$>)) +import Control.Monad import Text.ParserCombinators.ReadP as ReadP import Data.List ( nubBy ) import Data.Char @@ -125,7 +127,7 @@ extract_lty (L loc ty) acc HsPredTy p -> extract_pred p acc HsOpTy ty1 (L loc tv) ty2 -> extract_tv loc tv (extract_lty ty1 (extract_lty ty2 acc)) HsParTy ty -> extract_lty ty acc - HsNumTy _ -> acc + HsCoreTy {} -> acc -- The type is closed HsQuasiQuoteTy {} -> acc -- Quasi quotes mention no type variables HsSpliceTy {} -> acc -- Type splices mention no type variables HsKindSig ty _ -> extract_lty ty acc @@ -149,8 +151,7 @@ extractGenericPatTyVars binds get (L _ (FunBind { fun_matches = MatchGroup ms _ })) acc = foldr (get_m.unLoc) acc ms get _ acc = acc - get_m (Match (L _ (TypePat ty) : _) _ _) acc = extract_lty ty acc - get_m _ acc = acc + get_m _ acc = acc \end{code} @@ -172,13 +173,14 @@ Similarly for mkConDecl, mkClassOpSig and default-method names. \begin{code} mkClassDecl :: SrcSpan - -> Located (LHsContext RdrName, LHsType RdrName) + -> Located (Maybe (LHsContext RdrName), LHsType RdrName) -> Located [Located (FunDep RdrName)] -> Located (OrdList (LHsDecl RdrName)) -> P (LTyClDecl RdrName) -mkClassDecl loc (L _ (cxt, tycl_hdr)) fds where_cls +mkClassDecl loc (L _ (mcxt, tycl_hdr)) fds where_cls = do { let (binds, sigs, ats, docs) = cvBindsAndSigs (unLoc where_cls) + ; let cxt = fromMaybe (noLoc []) mcxt ; (cls, tparams) <- checkTyClHdr tycl_hdr ; tyvars <- checkTyVars tparams -- Only type vars allowed ; checkKindSigs ats @@ -189,14 +191,16 @@ mkClassDecl loc (L _ (cxt, tycl_hdr)) fds where_cls mkTyData :: SrcSpan -> NewOrData -> Bool -- True <=> data family instance - -> Located (LHsContext RdrName, LHsType RdrName) + -> Located (Maybe (LHsContext RdrName), LHsType RdrName) -> Maybe Kind -> [LConDecl RdrName] -> Maybe [LHsType RdrName] -> P (LTyClDecl RdrName) -mkTyData loc new_or_data is_family (L _ (cxt, tycl_hdr)) ksig data_cons maybe_deriv +mkTyData loc new_or_data is_family (L _ (mcxt, tycl_hdr)) ksig data_cons maybe_deriv = do { (tc, tparams) <- checkTyClHdr tycl_hdr + ; checkDatatypeContext mcxt + ; let cxt = fromMaybe (noLoc []) mcxt ; (tyvars, typats) <- checkTParams is_family tparams ; return (L loc (TyData { tcdND = new_or_data, tcdCtxt = cxt, tcdLName = tc, tcdTyVars = tyvars, tcdTyPats = typats, @@ -231,8 +235,8 @@ mkTopSpliceDecl :: LHsExpr RdrName -> HsDecl RdrName -- f x then behave as if she'd written $(f x) -- ie a SpliceD mkTopSpliceDecl (L _ (HsQuasiQuoteE qq)) = QuasiQuoteD qq -mkTopSpliceDecl (L _ (HsSpliceE (HsSplice _ expr))) = SpliceD (SpliceDecl expr) -mkTopSpliceDecl other_expr = SpliceD (SpliceDecl other_expr) +mkTopSpliceDecl (L _ (HsSpliceE (HsSplice _ expr))) = SpliceD (SpliceDecl expr Explicit) +mkTopSpliceDecl other_expr = SpliceD (SpliceDecl other_expr Implicit) \end{code} %************************************************************************ @@ -358,7 +362,7 @@ splitCon ty split (L _ (HsAppTy t u)) ts = split t (u : ts) split (L l (HsTyVar tc)) ts = do data_con <- tyConToDataCon l tc return (data_con, mk_rest ts) - split (L l _) _ = parseError l "parse error in data/newtype declaration" + split (L l _) _ = parseErrorSDoc l (text "parse error in constructor in data/newtype declaration:" <+> ppr ty) mk_rest [L _ (HsRecTy flds)] = RecCon flds mk_rest ts = PrefixCon ts @@ -475,7 +479,7 @@ checkDictTy (L spn ty) = check ty [] check (HsOpTy t1 (L _ tc) t2) args | isRdrTc tc = done tc (t1:t2:args) check (HsAppTy l r) args = check (unLoc l) (r:args) check (HsParTy t) args = check (unLoc t) args - check _ _ = parseError spn "Malformed instance header" + check _ _ = parseErrorSDoc spn (text "Malformed instance header:" <+> ppr ty) done tc args = return (L spn (HsPredTy (HsClassP tc args))) @@ -518,8 +522,19 @@ checkTyVars tparms = mapM chk tparms | isRdrTyVar tv = return (L l (KindedTyVar tv k)) chk (L l (HsTyVar tv)) | isRdrTyVar tv = return (L l (UserTyVar tv placeHolderKind)) - chk (L l _) = - parseError l "Type found where type variable expected" + chk t@(L l _) = + parseErrorSDoc l (text "Type found:" <+> ppr t + $$ text "where type variable expected, in:" <+> + sep (map (pprParendHsType . unLoc) tparms)) + +checkDatatypeContext :: Maybe (LHsContext RdrName) -> P () +checkDatatypeContext Nothing = return () +checkDatatypeContext (Just (L loc c)) + = do allowed <- extension datatypeContextsEnabled + unless allowed $ + parseErrorSDoc loc + (text "Illegal datatype context (use -XDatatypeContexts):" <+> + pprHsContext c) checkTyClHdr :: LHsType RdrName -> P (Located RdrName, -- the head symbol (type or class name) @@ -540,7 +555,7 @@ checkTyClHdr ty | isRdrTc tc = return (ltc, t1:t2:acc) go _ (HsParTy ty) acc = goL ty acc go _ (HsAppTy t1 t2) acc = goL t1 (t2:acc) - go l _ _ = parseError l "Malformed head of type or class declaration" + go l _ _ = parseErrorSDoc l (text "Malformed head of type or class declaration:" <+> ppr ty) -- Check that associated type declarations of a class are all kind signatures. -- @@ -551,7 +566,7 @@ checkKindSigs = mapM_ check | isFamilyDecl tydecl || isSynDecl tydecl = return () | otherwise = - parseError l "Type declaration in a class must be a kind signature or synonym default" + parseErrorSDoc l (text "Type declaration in a class must be a kind signature or synonym default:" $$ ppr tydecl) checkContext :: LHsType RdrName -> P (LHsContext RdrName) checkContext (L l t) @@ -591,34 +606,8 @@ checkPred (L spn ty) check _loc (HsAppTy l r) args = checkl l (r:args) check _loc (HsOpTy l (L loc tc) r) args = check loc (HsTyVar tc) (l:r:args) check _loc (HsParTy t) args = checkl t args - check loc _ _ = parseError loc - "malformed class assertion" - ---------------------------------------------------------------------------- --- Checking statements in a do-expression --- We parse do { e1 ; e2 ; } --- as [ExprStmt e1, ExprStmt e2] --- checkDo (a) checks that the last thing is an ExprStmt --- (b) returns it separately --- same comments apply for mdo as well - -checkDo, checkMDo :: SrcSpan -> [LStmt RdrName] -> P ([LStmt RdrName], LHsExpr RdrName) - -checkDo = checkDoMDo "a " "'do'" -checkMDo = checkDoMDo "an " "'mdo'" - -checkDoMDo :: String -> String -> SrcSpan -> [LStmt RdrName] -> P ([LStmt RdrName], LHsExpr RdrName) -checkDoMDo _ nm loc [] = parseError loc ("Empty " ++ nm ++ " construct") -checkDoMDo pre nm _ ss = do - check ss - where - check [] = panic "RdrHsSyn:checkDoMDo" - check [L _ (ExprStmt e _ _)] = return ([], e) - check [L l _] = parseError l ("The last statement in " ++ pre ++ nm ++ - " construct must be an expression") - check (s:ss) = do - (ss',e') <- check ss - return ((s:ss'),e') + check loc _ _ = parseErrorSDoc loc + (text "malformed class assertion:" <+> ppr ty) -- ------------------------------------------------------------------------- -- Checking Patterns. @@ -650,11 +639,11 @@ checkPat loc (L _ e) [] = do { pState <- getPState ; p <- checkAPat (dflags pState) loc e ; return (L loc p) } -checkPat loc _ _ - = patFail loc +checkPat loc e _ + = patFail loc (unLoc e) checkAPat :: DynFlags -> SrcSpan -> HsExpr RdrName -> P (Pat RdrName) -checkAPat dynflags loc e = case e of +checkAPat dynflags loc e0 = case e0 of EWildPat -> return (WildPat placeHolderType) HsVar x -> return (VarPat x) HsLit l -> return (LitPat l) @@ -670,7 +659,7 @@ checkAPat dynflags loc e = case e of | bang == bang_RDR -> do { bang_on <- extension bangPatEnabled ; if bang_on then checkLPat e >>= (return . BangPat) - else parseError loc "Illegal bang-pattern (use -XBangPatterns)" } + else parseErrorSDoc loc (text "Illegal bang-pattern (use -XBangPatterns):" $$ ppr e0) } ELazyPat e -> checkLPat e >>= (return . LazyPat) EAsPat n e -> checkLPat e >>= (return . AsPat n) @@ -688,7 +677,7 @@ checkAPat dynflags loc e = case e of -- n+k patterns OpApp (L nloc (HsVar n)) (L _ (HsVar plus)) _ (L _ (HsOverLit lit@(OverLit {ol_val = HsIntegral {}}))) - | dopt Opt_NPlusKPatterns dynflags && (plus == plus_RDR) + | xopt Opt_NPlusKPatterns dynflags && (plus == plus_RDR) -> return (mkNPlusKPat (L nloc n) lit) OpApp l op _fix r -> do l <- checkLPat l @@ -696,7 +685,7 @@ checkAPat dynflags loc e = case e of case op of L cl (HsVar c) | isDataOcc (rdrNameOcc c) -> return (ConPatIn (L cl c) (InfixCon l r)) - _ -> patFail loc + _ -> patFail loc e0 HsPar e -> checkLPat e >>= (return . ParPat) ExplicitList _ es -> do ps <- mapM checkLPat es @@ -707,15 +696,13 @@ checkAPat dynflags loc e = case e of ExplicitTuple es b | all tupArgPresent es -> do ps <- mapM checkLPat [e | Present e <- es] return (TuplePat ps b placeHolderType) - | otherwise -> parseError loc "Illegal tuple section in pattern" + | otherwise -> parseErrorSDoc loc (text "Illegal tuple section in pattern:" $$ ppr e0) RecordCon c _ (HsRecFields fs dd) -> do fs <- mapM checkPatField fs return (ConPatIn c (RecCon (HsRecFields fs dd))) HsQuasiQuoteE q -> return (QuasiQuotePat q) --- Generics - HsType ty -> return (TypePat ty) - _ -> patFail loc + _ -> patFail loc e0 placeHolderPunRhs :: LHsExpr RdrName -- The RHS of a punned record field will be filled in by the renamer @@ -731,8 +718,8 @@ checkPatField :: HsRecField RdrName (LHsExpr RdrName) -> P (HsRecField RdrName ( checkPatField fld = do { p <- checkLPat (hsRecFieldArg fld) ; return (fld { hsRecFieldArg = p }) } -patFail :: SrcSpan -> P a -patFail loc = parseError loc "Parse error in pattern" +patFail :: SrcSpan -> HsExpr RdrName -> P a +patFail loc e = parseErrorSDoc loc (text "Parse error in pattern:" <+> ppr e) --------------------------------------------------------------------------- @@ -788,20 +775,46 @@ checkValSig checkValSig (L l (HsVar v)) ty | isUnqual v && not (isDataOcc (rdrNameOcc v)) = return (TypeSig (L l v) ty) -checkValSig lhs@(L l _) _ - | looks_like_foreign lhs - = parseError l "Invalid type signature; perhaps you meant to use -XForeignFunctionInterface?" - | otherwise - = parseError l "Invalid type signature: should be of form :: " +checkValSig lhs@(L l _) ty + = parseErrorSDoc l ((text "Invalid type signature:" <+> + ppr lhs <+> text "::" <+> ppr ty) + $$ text hint) where + hint = if foreign_RDR `looks_like` lhs + then "Perhaps you meant to use -XForeignFunctionInterface?" + else if default_RDR `looks_like` lhs + then "Perhaps you meant to use -XDefaultSignatures?" + else "Should be of form :: " -- A common error is to forget the ForeignFunctionInterface flag -- so check for that, and suggest. cf Trac #3805 -- Sadly 'foreign import' still barfs 'parse error' because 'import' is a keyword - looks_like_foreign (L _ (HsVar v)) = v == foreign_RDR - looks_like_foreign (L _ (HsApp lhs _)) = looks_like_foreign lhs - looks_like_foreign _ = False + looks_like s (L _ (HsVar v)) = v == s + looks_like s (L _ (HsApp lhs _)) = looks_like s lhs + looks_like _ _ = False foreign_RDR = mkUnqual varName (fsLit "foreign") + default_RDR = mkUnqual varName (fsLit "default") + +checkDoAndIfThenElse :: LHsExpr RdrName + -> Bool + -> LHsExpr RdrName + -> Bool + -> LHsExpr RdrName + -> P () +checkDoAndIfThenElse guardExpr semiThen thenExpr semiElse elseExpr + | semiThen || semiElse + = do pState <- getPState + unless (xopt Opt_DoAndIfThenElse (dflags pState)) $ do + parseErrorSDoc (combineLocs guardExpr elseExpr) + (text "Unexpected semi-colons in conditional:" + $$ nest 4 expr + $$ text "Perhaps you meant to use -XDoAndIfThenElse?") + | otherwise = return () + where pprOptSemi True = semi + pprOptSemi False = empty + expr = text "if" <+> ppr guardExpr <> pprOptSemi semiThen <+> + text "then" <+> ppr thenExpr <> pprOptSemi semiElse <+> + text "else" <+> ppr elseExpr \end{code} @@ -870,13 +883,28 @@ isFunLhs e = go e [] _ -> return Nothing } go _ _ = return Nothing + +--------------------------------------------------------------------------- +-- Check for monad comprehensions +-- +-- If the flag MonadComprehensions is set, return a `MonadComp' context, +-- otherwise use the usual `ListComp' context + +checkMonadComp :: P (HsStmtContext Name) +checkMonadComp = do + pState <- getPState + return $ if xopt Opt_MonadComprehensions (dflags pState) + then MonadComp + else ListComp + --------------------------------------------------------------------------- -- Miscellaneous utilities checkPrecP :: Located Int -> P Int checkPrecP (L l i) | 0 <= i && i <= maxPrecedence = return i - | otherwise = parseError l "Precedence out of range" + | otherwise + = parseErrorSDoc l (text ("Precedence out of range: " ++ show i)) mkRecConstrOrUpdate :: LHsExpr RdrName @@ -887,16 +915,16 @@ mkRecConstrOrUpdate mkRecConstrOrUpdate (L l (HsVar c)) _ (fs,dd) | isRdrDataCon c = return (RecordCon (L l c) noPostTcExpr (mk_rec_fields fs dd)) mkRecConstrOrUpdate exp loc (fs,dd) - | null fs = parseError loc "Empty record update" + | null fs = parseErrorSDoc loc (text "Empty record update of:" <+> ppr exp) | otherwise = return (RecordUpd exp (mk_rec_fields fs dd) [] [] []) mk_rec_fields :: [HsRecField id arg] -> Bool -> HsRecFields id arg mk_rec_fields fs False = HsRecFields { rec_flds = fs, rec_dotdot = Nothing } mk_rec_fields fs True = HsRecFields { rec_flds = fs, rec_dotdot = Just (length fs) } -mkInlinePragma :: Maybe Activation -> RuleMatchInfo -> Bool -> InlinePragma +mkInlinePragma :: (InlineSpec, RuleMatchInfo) -> Maybe Activation -> InlinePragma -- The Maybe is because the user can omit the activation spec (and usually does) -mkInlinePragma mb_act match_info inl +mkInlinePragma (inl, match_info) mb_act = InlinePragma { inl_inline = inl , inl_sat = Nothing , inl_act = act @@ -904,11 +932,10 @@ mkInlinePragma mb_act match_info inl where act = case mb_act of Just act -> act - Nothing | inl -> AlwaysActive - | otherwise -> NeverActive - -- If no specific phase is given then: - -- NOINLINE => NeverActive - -- INLINE => Active + Nothing -> -- No phase specified + case inl of + NoInline -> NeverActive + _other -> AlwaysActive ----------------------------------------------------------------------------- -- utilities for foreign declarations @@ -927,7 +954,7 @@ mkImport cconv safety (L loc entity, v, ty) | otherwise = do case parseCImport cconv safety (mkExtName (unLoc v)) (unpackFS entity) of - Nothing -> parseError loc "Malformed entity string" + Nothing -> parseErrorSDoc loc (text "Malformed entity string") Just importSpec -> return (ForD (ForeignImport v ty importSpec)) -- the string "foo" is ambigous: either a header or a C identifier. The