X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fparser%2FRdrHsSyn.lhs;h=9af7e2fafa3edff842acb396e7a3fc00081a2b23;hp=a914bbaa59eab04d76027b8b1dd3251be4bdb6d1;hb=d8b99b7e9b2ce9fd8ba97fa10657082ceac09c59;hpb=58521c72cec262496dabf5fffb057d25ab17a0f7 diff --git a/compiler/parser/RdrHsSyn.lhs b/compiler/parser/RdrHsSyn.lhs index a914bba..9af7e2f 100644 --- a/compiler/parser/RdrHsSyn.lhs +++ b/compiler/parser/RdrHsSyn.lhs @@ -10,29 +10,26 @@ module RdrHsSyn ( mkHsOpApp, mkHsIntegral, mkHsFractional, mkHsIsString, - mkHsDo, mkHsSplice, + mkHsDo, mkHsSplice, mkTopSpliceDecl, mkClassDecl, mkTyData, mkTyFamily, mkTySynonym, - splitCon, mkInlineSpec, + splitCon, mkInlinePragma, mkRecConstrOrUpdate, -- HsExp -> [HsFieldUpdate] -> P HsExp cvBindGroup, cvBindsAndSigs, cvTopDecls, findSplice, checkDecBrGroup, + placeHolderPunRhs, -- Stuff to do with Foreign declarations - CallConv(..), - mkImport, -- CallConv -> Safety - -- -> (FastString, RdrName, RdrNameHsType) - -- -> P RdrNameHsDecl - mkExport, -- CallConv - -- -> (FastString, RdrName, RdrNameHsType) - -- -> P RdrNameHsDecl + mkImport, + parseCImport, + mkExport, mkExtName, -- RdrName -> CLabelString mkGadtDecl, -- [Located RdrName] -> LHsType RdrName -> ConDecl RdrName mkSimpleConDecl, mkDeprecatedGadtRecordDecl, - + -- Bunch of functions in the parser monad for -- checking and constructing values checkPrecP, -- Int -> P Int @@ -41,7 +38,6 @@ module RdrHsSyn ( checkTyVars, -- [LHsType RdrName] -> P () checkKindSigs, -- [LTyClDecl RdrName] -> P () checkInstType, -- HsType -> P HsType - checkDerivDecl, -- LDerivDecl RdrName -> P (LDerivDecl RdrName) checkPattern, -- HsExp -> P HsPat bang_RDR, checkPatterns, -- SrcLoc -> [HsExp] -> P [HsPat] @@ -57,25 +53,27 @@ import HsSyn -- Lots of it import Class ( FunDep ) import TypeRep ( Kind ) import RdrName ( RdrName, isRdrTyVar, isRdrTc, mkUnqual, rdrNameOcc, - isRdrDataCon, isUnqual, getRdrName, isQual, - setRdrNameSpace, showRdrName ) -import BasicTypes ( maxPrecedence, Activation, RuleMatchInfo, - InlinePragma(..), InlineSpec(..), - alwaysInlineSpec, neverInlineSpec ) -import Lexer ( P, failSpanMsgP, extension, standaloneDerivingEnabled, bangPatEnabled ) + isRdrDataCon, isUnqual, getRdrName, setRdrNameSpace ) +import BasicTypes ( maxPrecedence, Activation(..), RuleMatchInfo, + InlinePragma(..) ) +import Lexer import TysWiredIn ( unitTyCon ) -import ForeignCall ( CCallConv(..), Safety, CCallTarget(..), CExportSpec(..), - DNCallSpec(..), DNKind(..), CLabelString ) +import ForeignCall import OccName ( srcDataName, varName, isDataOcc, isTcOcc, occNameString ) import PrelNames ( forall_tv_RDR ) +import DynFlags import SrcLoc import OrdList ( OrdList, fromOL ) import Bag ( Bag, emptyBag, snocBag, consBag, foldrBag ) import Outputable import FastString +import Maybes -import List ( isSuffixOf, nubBy ) +import Control.Applicative ((<$>)) +import Text.ParserCombinators.ReadP as ReadP +import Data.List ( nubBy ) +import Data.Char #include "HsVersions.h" \end{code} @@ -129,7 +127,8 @@ extract_lty (L loc ty) 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 - HsSpliceTy _ -> acc -- Type splices mention no type variables + HsSpliceTy {} -> acc -- Type splices mention no type variables + HsSpliceTyOut {} -> acc -- Type splices mention no type variables HsKindSig ty _ -> extract_lty ty acc HsForAllTy _ [] cx ty -> extract_lctxt cx (extract_lty ty acc) HsForAllTy _ tvs cx ty -> acc ++ (filter ((`notElem` locals) . unLoc) $ @@ -224,6 +223,20 @@ mkTyFamily loc flavour lhs ksig = do { (tc, tparams) <- checkTyClHdr lhs ; tyvars <- checkTyVars tparams ; return (L loc (TyFamily flavour tc tyvars ksig)) } + +mkTopSpliceDecl :: LHsExpr RdrName -> HsDecl RdrName +-- If the user wrote +-- $(e) +-- then that's the splice, but if she wrote, say, +-- f x +-- then behave as if she'd written +-- $(f x) +mkTopSpliceDecl expr + = SpliceD (SpliceDecl expr') + where + expr' = case expr of + (L _ (HsSpliceE (HsSplice _ expr))) -> expr + _other -> expr \end{code} %************************************************************************ @@ -256,7 +269,7 @@ cvBindGroup binding ValBindsIn mbs sigs cvBindsAndSigs :: OrdList (LHsDecl RdrName) - -> (Bag (LHsBind RdrName), [LSig RdrName], [LTyClDecl RdrName], [LDocDecl RdrName]) + -> (Bag (LHsBind RdrName), [LSig RdrName], [LTyClDecl RdrName], [LDocDecl]) -- Input decls contain just value bindings and signatures -- and in case of class or instance declarations also -- associated type declarations. They might also contain Haddock comments. @@ -659,15 +672,6 @@ checkPred (L spn ty) "malformed class assertion" --------------------------------------------------------------------------- --- Checking stand-alone deriving declarations - -checkDerivDecl :: LDerivDecl RdrName -> P (LDerivDecl RdrName) -checkDerivDecl d@(L loc _) = - do stDerivOn <- extension standaloneDerivingEnabled - if stDerivOn then return d - else parseError loc "Illegal stand-alone deriving declaration (use -XStandaloneDeriving)" - ---------------------------------------------------------------------------- -- Checking statements in a do-expression -- We parse do { e1 ; e2 ; } -- as [ExprStmt e1, ExprStmt e2] @@ -720,17 +724,17 @@ checkPat loc e args -- OK to let this happen even if bang-patterns checkPat loc (L _ (HsApp f x)) args = do { x <- checkLPat x; checkPat loc f (x:args) } checkPat loc (L _ e) [] - = do { p <- checkAPat loc e; return (L loc p) } + = do { pState <- getPState + ; p <- checkAPat (dflags pState) loc e + ; return (L loc p) } checkPat loc _ _ = patFail loc -checkAPat :: SrcSpan -> HsExpr RdrName -> P (Pat RdrName) -checkAPat loc e = case e of - EWildPat -> return (WildPat placeHolderType) - HsVar x | isQual x -> parseError loc ("Qualified variable in pattern: " - ++ showRdrName x) - | otherwise -> return (VarPat x) - HsLit l -> return (LitPat l) +checkAPat :: DynFlags -> SrcSpan -> HsExpr RdrName -> P (Pat RdrName) +checkAPat dynflags loc e = case e of + EWildPat -> return (WildPat placeHolderType) + HsVar x -> return (VarPat x) + HsLit l -> return (LitPat l) -- Overloaded numeric patterns (e.g. f 0 x = x) -- Negation is recorded separately, so that the literal is zero or +ve @@ -761,7 +765,7 @@ checkAPat loc e = case e of -- n+k patterns OpApp (L nloc (HsVar n)) (L _ (HsVar plus)) _ (L _ (HsOverLit lit@(OverLit {ol_val = HsIntegral {}}))) - | plus == plus_RDR + | dopt Opt_NPlusKPatterns dynflags && (plus == plus_RDR) -> return (mkNPlusKPat (L nloc n) lit) OpApp l op _fix r -> do l <- checkLPat l @@ -790,9 +794,15 @@ checkAPat loc e = case e of HsType ty -> return (TypePat ty) _ -> patFail loc -plus_RDR, bang_RDR :: RdrName +placeHolderPunRhs :: HsExpr RdrName +-- The RHS of a punned record field will be filled in by the renamer +-- It's better not to make it an error, in case we want to print it when debugging +placeHolderPunRhs = HsVar pun_RDR + +plus_RDR, bang_RDR, pun_RDR :: RdrName plus_RDR = mkUnqual varName (fsLit "+") -- Hack bang_RDR = mkUnqual varName (fsLit "!") -- Hack +pun_RDR = mkUnqual varName (fsLit "pun-right-hand-side") checkPatField :: HsRecField RdrName (LHsExpr RdrName) -> P (HsRecField RdrName (LPat RdrName)) checkPatField fld = do { p <- checkLPat (hsRecFieldArg fld) @@ -829,10 +839,6 @@ checkFunBind :: SrcSpan -> Located (GRHSs RdrName) -> P (HsBind RdrName) checkFunBind lhs_loc fun is_infix pats opt_sig (L rhs_span grhss) - | isQual (unLoc fun) - = parseErrorSDoc (getLoc fun) - (ptext (sLit "Qualified name in function definition:") <+> ppr (unLoc fun)) - | otherwise = do ps <- checkPatterns pats let match_span = combineSrcSpans lhs_loc rhs_span return (makeFunBind fun is_infix [L match_span (Match ps opt_sig grhss)]) @@ -953,141 +959,83 @@ 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) } -mkInlineSpec :: Maybe Activation -> RuleMatchInfo -> Bool -> InlineSpec --- The Maybe is becuase the user can omit the activation spec (and usually does) -mkInlineSpec Nothing match_info True = alwaysInlineSpec match_info - -- INLINE -mkInlineSpec Nothing match_info False = neverInlineSpec match_info - -- NOINLINE -mkInlineSpec (Just act) match_info inl = Inline (InlinePragma act match_info) inl +mkInlinePragma :: Maybe Activation -> RuleMatchInfo -> Bool -> InlinePragma +-- The Maybe is because the user can omit the activation spec (and usually does) +mkInlinePragma mb_act match_info inl + = InlinePragma { inl_inline = inl + , inl_act = act + , inl_rule = match_info } + 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 ----------------------------------------------------------------------------- -- utilities for foreign declarations --- supported calling conventions --- -data CallConv = CCall CCallConv -- ccall or stdcall - | DNCall -- .NET - -- construct a foreign import declaration -- -mkImport :: CallConv +mkImport :: CCallConv -> Safety -> (Located FastString, Located RdrName, LHsType RdrName) -> P (HsDecl RdrName) -mkImport (CCall cconv) safety (entity, v, ty) +mkImport cconv safety (L loc entity, v, ty) | cconv == PrimCallConv = do - let funcTarget = CFunction (StaticTarget (unLoc entity)) + let funcTarget = CFunction (StaticTarget entity) importSpec = CImport PrimCallConv safety nilFS funcTarget return (ForD (ForeignImport v ty importSpec)) | otherwise = do - importSpec <- parseCImport entity cconv safety v - return (ForD (ForeignImport v ty importSpec)) -mkImport (DNCall ) _ (entity, v, ty) = do - spec <- parseDImport entity - return $ ForD (ForeignImport v ty (DNImport spec)) - --- parse the entity string of a foreign import declaration for the `ccall' or --- `stdcall' calling convention' --- -parseCImport :: Located FastString - -> CCallConv - -> Safety - -> Located RdrName - -> P ForeignImport -parseCImport (L loc entity) cconv safety v - -- FIXME: we should allow white space around `dynamic' and `wrapper' -=chak - | entity == fsLit "dynamic" = - return $ CImport cconv safety nilFS (CFunction DynamicTarget) - | entity == fsLit "wrapper" = - return $ CImport cconv safety nilFS CWrapper - | otherwise = parse0 (unpackFS entity) - where - -- using the static keyword? - parse0 (' ': rest) = parse0 rest - parse0 ('s':'t':'a':'t':'i':'c':rest) = parse1 rest - parse0 rest = parse1 rest - -- check for header file name - parse1 "" = parse4 "" nilFS False - parse1 (' ':rest) = parse1 rest - parse1 str@('&':_ ) = parse2 str nilFS - parse1 str - | ".h" `isSuffixOf` first = parse2 rest (mkFastString first) - | otherwise = parse4 str nilFS False - where - (first, rest) = break (\c -> c == ' ' || c == '&') str - -- check for address operator (indicating a label import) - parse2 "" header = parse4 "" header False - parse2 (' ':rest) header = parse2 rest header - parse2 ('&':rest) header = parse3 rest header - parse2 str header = parse4 str header False - -- eat spaces after '&' - parse3 (' ':rest) header = parse3 rest header - parse3 str header = parse4 str header True - -- check for name of C function - parse4 "" header isLbl = build (mkExtName (unLoc v)) header isLbl - parse4 (' ':rest) header isLbl = parse4 rest header isLbl - parse4 str header isLbl - | all (== ' ') rest = build (mkFastString first) header isLbl - | otherwise = parseError loc "Malformed entity string" - where - (first, rest) = break (== ' ') str - -- - build cid header False = return $ - CImport cconv safety header (CFunction (StaticTarget cid)) - build cid header True = return $ - CImport cconv safety header (CLabel cid ) - --- --- Unravel a dotnet spec string. --- -parseDImport :: Located FastString -> P DNCallSpec -parseDImport (L loc entity) = parse0 comps + case parseCImport cconv safety (mkExtName (unLoc v)) (unpackFS entity) of + Nothing -> parseError loc "Malformed entity string" + Just importSpec -> return (ForD (ForeignImport v ty importSpec)) + +-- the string "foo" is ambigous: either a header or a C identifier. The +-- C identifier case comes first in the alternatives below, so we pick +-- that one. +parseCImport :: CCallConv -> Safety -> FastString -> String + -> Maybe ForeignImport +parseCImport cconv safety nm str = + listToMaybe $ map fst $ filter (null.snd) $ + readP_to_S parse str where - comps = words (unpackFS entity) - - parse0 [] = d'oh - parse0 (x : xs) - | x == "static" = parse1 True xs - | otherwise = parse1 False (x:xs) - - parse1 _ [] = d'oh - parse1 isStatic (x:xs) - | x == "method" = parse2 isStatic DNMethod xs - | x == "field" = parse2 isStatic DNField xs - | x == "ctor" = parse2 isStatic DNConstructor xs - parse1 isStatic xs = parse2 isStatic DNMethod xs - - parse2 _ _ [] = d'oh - parse2 isStatic kind (('[':x):xs) = - case x of - [] -> d'oh - vs | last vs == ']' -> parse3 isStatic kind (init vs) xs - _ -> d'oh - parse2 isStatic kind xs = parse3 isStatic kind "" xs - - parse3 isStatic kind assem [x] = - return (DNCallSpec isStatic kind assem x - -- these will be filled in once known. - (error "FFI-dotnet-args") - (error "FFI-dotnet-result")) - parse3 _ _ _ _ = d'oh - - d'oh = parseError loc "Malformed entity string" - + parse = choice [ + string "dynamic" >> return (mk nilFS (CFunction DynamicTarget)), + string "wrapper" >> return (mk nilFS CWrapper), + optional (string "static" >> skipSpaces) >> + (mk nilFS <$> cimp nm) +++ + (do h <- munch1 hdr_char; skipSpaces; mk (mkFastString h) <$> cimp nm) + ] + + mk = CImport cconv safety + + hdr_char c = not (isSpace c) -- header files are filenames, which can contain + -- pretty much any char (depending on the platform), + -- so just accept any non-space character + id_char c = isAlphaNum c || c == '_' + + cimp nm = (ReadP.char '&' >> skipSpaces >> CLabel <$> cid) + +++ ((CFunction . StaticTarget) <$> cid) + where + cid = return nm +++ + (do c <- satisfy (\c -> isAlpha c || c == '_') + cs <- many (satisfy id_char) + return (mkFastString (c:cs))) + + -- construct a foreign export declaration -- -mkExport :: CallConv +mkExport :: CCallConv -> (Located FastString, Located RdrName, LHsType RdrName) -> P (HsDecl RdrName) -mkExport (CCall cconv) (L _ entity, v, ty) = return $ +mkExport cconv (L _ entity, v, ty) = return $ ForD (ForeignExport v ty (CExport (CExportStatic entity' cconv))) where entity' | nullFS entity = mkExtName (unLoc v) | otherwise = entity -mkExport DNCall (L _ _, v, _) = - parseError (getLoc v){-TODO: not quite right-} - "Foreign export is not yet supported for .NET" -- Supplying the ext_name in a foreign decl is optional; if it -- isn't there, the Haskell name is assumed. Note that no transformation