[project @ 2003-09-24 13:04:45 by simonmar]
[ghc-hetmet.git] / ghc / compiler / parser / RdrHsSyn.lhs
index 1ed2429..652a3e6 100644 (file)
@@ -20,6 +20,8 @@ module RdrHsSyn (
        RdrNameGRHS,
        RdrNameGRHSs,
        RdrNameHsBinds,
+       RdrNameHsCmd,
+       RdrNameHsCmdTop,
        RdrNameHsDecl,
        RdrNameHsExpr,
        RdrNameHsModule,
@@ -43,10 +45,12 @@ module RdrHsSyn (
        RdrBinding(..),
        RdrMatch(..),
 
+       main_RDR_Unqual,
+
        extractHsTyRdrNames,  extractHsTyRdrTyVars, 
        extractHsCtxtRdrTyVars, extractGenericPatTyVars,
  
-       mkHsOpApp, mkClassDecl, mkClassOpSigDM, 
+       mkHsOpApp, mkClassDecl, 
        mkHsNegApp, mkNPlusKPat, mkHsIntegral, mkHsFractional,
        mkHsDo, mkHsSplice, mkSigDecls,
         mkTyData, mkPrefixCon, mkRecCon,
@@ -56,7 +60,6 @@ module RdrHsSyn (
        cvBinds,
        cvMonoBindsAndSigs,
        cvTopDecls,
-       cvClassOpSig, 
        findSplice, addImpDecls, emptyGroup, mkGroup,
 
        -- Stuff to do with Foreign declarations
@@ -92,16 +95,16 @@ module RdrHsSyn (
 
 import HsSyn           -- Lots of it
 import RdrName         ( RdrName, isRdrTyVar, mkRdrUnqual, mkUnqual, rdrNameOcc, 
-                         isRdrTyVar, isRdrDataCon, isUnqual, getRdrName,
+                         isRdrTyVar, isRdrDataCon, isUnqual, getRdrName, isQual,
                          setRdrNameSpace )
 import BasicTypes      ( RecFlag(..), FixitySig(..), maxPrecedence )
 import Class            ( DefMeth (..) )
-import Lex             ( P, mapP, setSrcLocP, thenP, returnP, getSrcLocP, failMsgP )
+import Lexer           ( P, setSrcLocFor, getSrcLoc, failLocMsgP )
 import HscTypes                ( RdrAvailInfo, GenAvailInfo(..) )
 import TysWiredIn      ( unitTyCon )
 import ForeignCall     ( CCallConv, Safety, CCallTarget(..), CExportSpec(..),
-                         DNCallSpec(..))
-import OccName         ( dataName, varName, isDataOcc, isTcOcc, occNameUserString,
+                         DNCallSpec(..), DNKind(..))
+import OccName         ( srcDataName, varName, isDataOcc, isTcOcc, occNameUserString,
                          mkDefaultMethodOcc, mkVarOcc )
 import SrcLoc
 import CStrings                ( CLabelString )
@@ -133,6 +136,8 @@ type RdrNameGRHS            = GRHS                  RdrName
 type RdrNameGRHSs              = GRHSs                 RdrName
 type RdrNameHsBinds            = HsBinds               RdrName
 type RdrNameHsExpr             = HsExpr                RdrName
+type RdrNameHsCmd              = HsCmd                 RdrName
+type RdrNameHsCmdTop           = HsCmdTop              RdrName
 type RdrNameHsModule           = HsModule              RdrName
 type RdrNameIE                 = IE                    RdrName
 type RdrNameImportDecl                 = ImportDecl            RdrName
@@ -154,6 +159,12 @@ type RdrNameFixitySig              = FixitySig             RdrName
 type RdrNameHsRecordBinds      = HsRecordBinds         RdrName
 \end{code}
 
+\begin{code}
+main_RDR_Unqual :: RdrName
+main_RDR_Unqual = mkUnqual varName FSLIT("main")
+       -- We definitely don't want an Orig RdrName, because
+       -- main might, in principle, be imported into module Main
+\end{code}
 
 %************************************************************************
 %*                                                                     *
@@ -237,7 +248,9 @@ Similarly for mkConDecl, mkClassOpSig and default-method names.
 \begin{code}
 mkClassDecl (cxt, cname, tyvars) fds sigs mbinds loc
   = ClassDecl { tcdCtxt = cxt, tcdName = cname, tcdTyVars = tyvars,
-               tcdFDs = fds,  tcdSigs = sigs,  tcdMeths = mbinds,
+               tcdFDs = fds,  
+               tcdSigs = map cvClassOpSig sigs,        -- Convert to class-op sigs
+               tcdMeths = mbinds,
                tcdLoc = loc }
 
 mkTyData new_or_data (context, tname, tyvars) data_cons maybe src
@@ -245,10 +258,13 @@ mkTyData new_or_data (context, tname, tyvars) data_cons maybe src
             tcdTyVars = tyvars,  tcdCons = data_cons, 
             tcdDerivs = maybe,   tcdLoc = src, tcdGeneric = Nothing }
 
-mkClassOpSigDM op ty loc
-  = ClassOpSig op (DefMeth dm_rn) ty loc
+cvClassOpSig :: RdrNameSig -> RdrNameSig
+cvClassOpSig (Sig var poly_ty src_loc) 
+  = ClassOpSig var (DefMeth dm_rn) poly_ty src_loc
   where
-    dm_rn = mkRdrUnqual (mkDefaultMethodOcc (rdrNameOcc op))
+    dm_rn = mkRdrUnqual (mkDefaultMethodOcc (rdrNameOcc var))
+cvClassOpSig sig 
+  = sig
 \end{code}
 
 \begin{code}
@@ -281,7 +297,7 @@ mkHsDo ctxt stmts loc = HsDo ctxt stmts [] placeHolderType loc
 \end{code}
 
 \begin{code}
-mkHsSplice e = HsSplice unqualSplice e
+mkHsSplice e loc = HsSplice unqualSplice e loc
 
 unqualSplice = mkRdrUnqual (mkVarOcc FSLIT("splice"))
                -- A name (uniquified later) to
@@ -316,22 +332,6 @@ data RdrMatch
 
 %************************************************************************
 %*                                                                     *
-\subsection[cvDecls]{Convert various top-level declarations}
-%*                                                                     *
-%************************************************************************
-
-We make a point not to throw any user-pragma ``sigs'' at
-these conversion functions:
-
-\begin{code}
-cvClassOpSig :: RdrNameSig -> RdrNameSig
-cvClassOpSig (Sig var poly_ty src_loc) = mkClassOpSigDM var poly_ty src_loc
-cvClassOpSig sig                      = sig
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
 \subsection[cvBinds-etc]{Converting to @HsBinds@, @MonoBinds@, etc.}
 %*                                                                     *
 %************************************************************************
@@ -391,15 +391,17 @@ getMonoBind :: RdrNameMonoBinds -> [RdrBinding] -> (RdrNameMonoBinds, [RdrBindin
 --
 -- No AndMonoBinds or EmptyMonoBinds here; just single equations
 
-getMonoBind (FunMonoBind f1 inf1 mtchs1 loc1) binds
-  | has_args mtchs1
-  = go mtchs1 loc1 binds
+getMonoBind (FunMonoBind f inf mtchs loc) binds
+  | has_args mtchs
+  = go mtchs loc binds
   where
-    go mtchs loc (RdrValBinding (FunMonoBind f2 inf2 mtchs2 loc2) : binds)
-       | f1 == f2 = go (mtchs2 ++ mtchs1) loc2 binds
+    go mtchs1 loc1 (RdrValBinding (FunMonoBind f2 inf2 mtchs2 loc2) : binds)
+       | f == f2 = go (mtchs2 ++ mtchs1) loc2 binds
        -- Remember binds is reversed, so glue mtchs2 on the front
        -- and use loc2 as the final location
-    go mtchs loc binds = (FunMonoBind f1 inf1 mtchs loc, binds)
+    go mtchs1 loc1 binds = (FunMonoBind f inf mtchs1 loc1, binds)
+
+getMonoBind bind binds = (bind, binds)
 
 has_args ((Match args _ _) : _) = not (null args)
        -- Don't group together FunMonoBinds if they have
@@ -416,7 +418,7 @@ emptyGroup = HsGroup { hs_valds = MonoBind EmptyMonoBinds [] Recursive,
                       hs_fixds = [], hs_defds = [], hs_fords = [], 
                       hs_depds = [] ,hs_ruleds = [], hs_coreds = [] }
 
-findSplice :: [HsDecl a] -> (HsGroup a, Maybe (HsExpr a, [HsDecl a]))
+findSplice :: [HsDecl a] -> (HsGroup a, Maybe (SpliceDecl a, [HsDecl a]))
 findSplice ds = add emptyGroup ds
 
 mkGroup :: [HsDecl a] -> HsGroup a
@@ -428,7 +430,7 @@ addImpDecls group decls = case add group decls of
                                (group', Nothing) -> group'
                                other             -> panic "addImpDecls"
 
-add :: HsGroup a -> [HsDecl a] -> (HsGroup a, Maybe (HsExpr a, [HsDecl a]))
+add :: HsGroup a -> [HsDecl a] -> (HsGroup a, Maybe (SpliceDecl a, [HsDecl a]))
        -- This stuff reverses the declarations (again) but it doesn't matter
 
 -- Base cases
@@ -438,7 +440,7 @@ add gp (SpliceD e : ds) = (gp, Just (e, ds))
 -- Class declarations: pull out the fixity signatures to the top
 add gp@(HsGroup {hs_tyclds = ts, hs_fixds = fs}) (TyClD d : ds)   
        | isClassDecl d = add (gp { hs_tyclds = d : ts, 
-                                   hs_fixds  = [f | FixSig f <- tcdSigs d] }) ds
+                                   hs_fixds  = [f | FixSig f <- tcdSigs d] ++ fs }) ds
        | otherwise     = add (gp { hs_tyclds = d : ts }) ds
 
 -- Signatures: fixity sigs go a different place than all others
@@ -482,19 +484,19 @@ mkPrefixCon ty tys
  = split ty tys
  where
    split (HsAppTy t u)  ts = split t (unbangedType u : ts)
-   split (HsTyVar tc)   ts = tyConToDataCon tc `thenP` \ data_con ->
-                            returnP (data_con, PrefixCon ts)
+   split (HsTyVar tc)   ts = tyConToDataCon tc >>= \ data_con ->
+                            return (data_con, PrefixCon ts)
    split _              _ = parseError "Illegal data/newtype declaration"
 
 mkRecCon :: RdrName -> [([RdrName],RdrNameBangType)] -> P (RdrName, RdrNameConDetails)
 mkRecCon con fields
-  = tyConToDataCon con `thenP` \ data_con ->
-    returnP (data_con, RecCon [ (l,t) | (ls,t) <- fields, l <- ls ])
+  = tyConToDataCon con >>= \ data_con ->
+    return (data_con, RecCon [ (l,t) | (ls,t) <- fields, l <- ls ])
 
 tyConToDataCon :: RdrName -> P RdrName
 tyConToDataCon tc
   | isTcOcc (rdrNameOcc tc)
-  = returnP (setRdrNameSpace tc dataName)
+  = return (setRdrNameSpace tc srcDataName)
   | otherwise
   = parseError (showSDoc (text "Not a constructor:" <+> quotes (ppr tc)))
 
@@ -505,20 +507,22 @@ checkInstType :: RdrNameHsType -> P RdrNameHsType
 checkInstType t 
   = case t of
        HsForAllTy tvs ctxt ty ->
-               checkDictTy ty [] `thenP` \ dict_ty ->
-               returnP (HsForAllTy tvs ctxt dict_ty)
+               checkDictTy ty [] >>= \ dict_ty ->
+               return (HsForAllTy tvs ctxt dict_ty)
 
         HsParTy ty -> checkInstType ty
 
-       ty ->   checkDictTy ty [] `thenP` \ dict_ty->
-               returnP (HsForAllTy Nothing [] dict_ty)
+       ty ->   checkDictTy ty [] >>= \ dict_ty->
+               return (HsForAllTy Nothing [] dict_ty)
 
 checkTyVars :: [RdrNameHsType] -> P [RdrNameHsTyVar]
-checkTyVars tvs = mapP chk tvs
-               where
-                 chk (HsKindSig (HsTyVar tv) k) = returnP (IfaceTyVar tv k)
-                 chk (HsTyVar tv)               = returnP (UserTyVar tv)
-                 chk other                      = parseError "Type found where type variable expected"
+checkTyVars tvs 
+  = mapM chk tvs
+  where
+       --  Check that the name space is correct!
+    chk (HsKindSig (HsTyVar tv) k) | isRdrTyVar tv = return (IfaceTyVar tv k)
+    chk (HsTyVar tv)              | isRdrTyVar tv = return (UserTyVar tv)
+    chk other                     = parseError "Type found where type variable expected"
 
 checkTyClHdr :: RdrNameHsType -> P (RdrName, [RdrNameHsTyVar])
 -- The header of a type or class decl should look like
@@ -530,46 +534,46 @@ checkTyClHdr ty
   = go ty []
   where
     go (HsTyVar tc)    acc 
-       | not (isRdrTyVar tc) = checkTyVars acc         `thenP` \ tvs ->
-                               returnP (tc, tvs)
+       | not (isRdrTyVar tc) = checkTyVars acc         >>= \ tvs ->
+                               return (tc, tvs)
     go (HsOpTy t1 (HsTyOp tc) t2) acc  
-                             = checkTyVars (t1:t2:acc) `thenP` \ tvs ->
-                               returnP (tc, tvs)
+                             = checkTyVars (t1:t2:acc) >>= \ tvs ->
+                               return (tc, tvs)
     go (HsParTy ty)    acc    = go ty acc
     go (HsAppTy t1 t2) acc    = go t1 (t2:acc)
     go other          acc    = parseError "Malformed LHS to type of class declaration"
 
 checkContext :: RdrNameHsType -> P RdrNameContext
 checkContext (HsTupleTy _ ts)  -- (Eq a, Ord b) shows up as a tuple type
-  = mapP checkPred ts
+  = mapM checkPred ts
 
 checkContext (HsParTy ty)      -- to be sure HsParTy doesn't get into the way
   = checkContext ty
 
 checkContext (HsTyVar t)       -- Empty context shows up as a unit type ()
-  | t == getRdrName unitTyCon = returnP []
+  | t == getRdrName unitTyCon = return []
 
 checkContext t 
-  = checkPred t `thenP` \p ->
-    returnP [p]
+  = checkPred t >>= \p ->
+    return [p]
 
 checkPred :: RdrNameHsType -> P (HsPred RdrName)
 -- Watch out.. in ...deriving( Show )... we use checkPred on 
 -- the list of partially applied predicates in the deriving,
 -- so there can be zero args.
-checkPred (HsPredTy (HsIParam n ty)) = returnP (HsIParam n ty)
+checkPred (HsPredTy (HsIParam n ty)) = return (HsIParam n ty)
 checkPred ty
   = go ty []
   where
     go (HsTyVar t) args   | not (isRdrTyVar t) 
-                         = returnP (HsClassP t args)
+                         = return (HsClassP t args)
     go (HsAppTy l r) args = go l (r:args)
     go (HsParTy t)   args = go t args
     go _            _    = parseError "Illegal class assertion"
 
 checkDictTy :: RdrNameHsType -> [RdrNameHsType] -> P RdrNameHsType
 checkDictTy (HsTyVar t) args@(_:_) | not (isRdrTyVar t) 
-       = returnP (mkHsDictTy t args)
+       = return (mkHsDictTy t args)
 checkDictTy (HsAppTy l r) args = checkDictTy l (r:args)
 checkDictTy (HsParTy t)   args = checkDictTy t args
 checkDictTy _ _ = parseError "Malformed context in instance header"
@@ -587,36 +591,37 @@ checkDo    = checkDoMDo "a " "'do'"
 checkMDo = checkDoMDo "an " "'mdo'"
 
 checkDoMDo _   nm []              = parseError $ "Empty " ++ nm ++ " construct"
-checkDoMDo _   _  [ExprStmt e _ l] = returnP [ResultStmt e l]
+checkDoMDo _   _  [ExprStmt e _ l] = return [ResultStmt e l]
 checkDoMDo pre nm [s]             = parseError $ "The last statement in " ++ pre ++ nm ++ " construct must be an expression"
-checkDoMDo pre nm (s:ss)          = checkDoMDo pre nm ss       `thenP` \ ss' ->
-                                    returnP (s:ss')
+checkDoMDo pre nm (s:ss)          = checkDoMDo pre nm ss       >>= \ ss' ->
+                                    return (s:ss')
 
----------------------------------------------------------------------------
+-- -------------------------------------------------------------------------
 -- Checking Patterns.
 
 -- We parse patterns as expressions and check for valid patterns below,
 -- converting the expression into a pattern at the same time.
 
 checkPattern :: SrcLoc -> RdrNameHsExpr -> P RdrNamePat
-checkPattern loc e = setSrcLocP loc (checkPat e [])
+checkPattern loc e = setSrcLocFor loc (checkPat e [])
 
 checkPatterns :: SrcLoc -> [RdrNameHsExpr] -> P [RdrNamePat]
-checkPatterns loc es = mapP (checkPattern loc) es
+checkPatterns loc es = mapM (checkPattern loc) es
 
 checkPat :: RdrNameHsExpr -> [RdrNamePat] -> P RdrNamePat
-checkPat (HsVar c) args | isRdrDataCon c = returnP (ConPatIn c (PrefixCon args))
+checkPat (HsVar c) args | isRdrDataCon c = return (ConPatIn c (PrefixCon args))
 checkPat (HsApp f x) args = 
-       checkPat x [] `thenP` \x ->
+       checkPat x [] >>= \x ->
        checkPat f (x:args)
 checkPat e [] = case e of
-       EWildPat           -> returnP (WildPat placeHolderType)
-       HsVar x            -> returnP (VarPat x)
-       HsLit l            -> returnP (LitPat l)
-       HsOverLit l        -> returnP (NPatIn l Nothing)
-       ELazyPat e         -> checkPat e [] `thenP` (returnP . LazyPat)
-       EAsPat n e         -> checkPat e [] `thenP` (returnP . AsPat n)
-        ExprWithTySig e t  -> checkPat e [] `thenP` \e ->
+       EWildPat            -> return (WildPat placeHolderType)
+       HsVar x | isQual x  -> parseError ("Qualified variable in pattern: " ++ showRdrName x)
+               | otherwise -> return (VarPat x)
+       HsLit l            -> return (LitPat l)
+       HsOverLit l        -> return (NPatIn l Nothing)
+       ELazyPat e         -> checkPat e [] >>= (return . LazyPat)
+       EAsPat n e         -> checkPat e [] >>= (return . AsPat n)
+        ExprWithTySig e t  -> checkPat e [] >>= \e ->
                              -- Pattern signatures are parsed as sigtypes,
                              -- but they aren't explicit forall points.  Hence
                              -- we have to remove the implicit forall here.
@@ -624,48 +629,48 @@ checkPat e [] = case e of
                                          HsForAllTy Nothing [] ty -> ty
                                          other -> other
                              in
-                             returnP (SigPatIn e t')
+                             return (SigPatIn e t')
 
        -- Translate out NegApps of literals in patterns. We negate
        -- the Integer here, and add back the call to 'negate' when
        -- we typecheck the pattern.
        -- NB. Negative *primitive* literals are already handled by
        --     RdrHsSyn.mkHsNegApp
-       NegApp (HsOverLit lit) neg -> returnP (NPatIn lit (Just neg))
+       NegApp (HsOverLit lit) neg -> return (NPatIn lit (Just neg))
 
        OpApp (HsVar n) (HsVar plus) _ (HsOverLit lit@(HsIntegral _ _)) 
                           | plus == plus_RDR
-                          -> returnP (mkNPlusKPat n lit)
+                          -> return (mkNPlusKPat n lit)
                           where
                              plus_RDR = mkUnqual varName FSLIT("+")    -- Hack
 
-       OpApp l op fix r   -> checkPat l [] `thenP` \l ->
-                             checkPat r [] `thenP` \r ->
+       OpApp l op fix r   -> checkPat l [] >>= \l ->
+                             checkPat r [] >>= \r ->
                              case op of
                                 HsVar c | isDataOcc (rdrNameOcc c)
-                                       -> returnP (ConPatIn c (InfixCon l r))
+                                       -> return (ConPatIn c (InfixCon l r))
                                 _ -> patFail
 
-       HsPar e            -> checkPat e [] `thenP` (returnP . ParPat)
-       ExplicitList _ es  -> mapP (\e -> checkPat e []) es `thenP` \ps ->
-                             returnP (ListPat ps placeHolderType)
-       ExplicitPArr _ es  -> mapP (\e -> checkPat e []) es `thenP` \ps ->
-                             returnP (PArrPat ps placeHolderType)
+       HsPar e            -> checkPat e [] >>= (return . ParPat)
+       ExplicitList _ es  -> mapM (\e -> checkPat e []) es >>= \ps ->
+                             return (ListPat ps placeHolderType)
+       ExplicitPArr _ es  -> mapM (\e -> checkPat e []) es >>= \ps ->
+                             return (PArrPat ps placeHolderType)
 
-       ExplicitTuple es b -> mapP (\e -> checkPat e []) es `thenP` \ps ->
-                             returnP (TuplePat ps b)
+       ExplicitTuple es b -> mapM (\e -> checkPat e []) es >>= \ps ->
+                             return (TuplePat ps b)
 
-       RecordCon c fs     -> mapP checkPatField fs `thenP` \fs ->
-                             returnP (ConPatIn c (RecCon fs))
+       RecordCon c fs     -> mapM checkPatField fs >>= \fs ->
+                             return (ConPatIn c (RecCon fs))
 -- Generics 
-       HsType ty          -> returnP (TypePat ty) 
+       HsType ty          -> return (TypePat ty) 
        _                  -> patFail
 
 checkPat _ _ = patFail
 
 checkPatField :: (RdrName, RdrNameHsExpr) -> P (RdrName, RdrNamePat)
-checkPatField (n,e) = checkPat e [] `thenP` \p ->
-                     returnP (n,p)
+checkPatField (n,e) = checkPat e [] >>= \p ->
+                     return (n,p)
 
 patFail = parseError "Parse error in pattern"
 
@@ -682,20 +687,23 @@ checkValDef
 
 checkValDef lhs opt_sig grhss loc
  = case isFunLhs lhs [] of
-          Just (f,inf,es) -> 
-               checkPatterns loc es `thenP` \ps ->
-               returnP (RdrValBinding (FunMonoBind f inf [Match ps opt_sig grhss] loc))
+          Just (f,inf,es) 
+            | isQual f
+            -> parseError ("Qualified name in function definition: "  ++ showRdrName f)
+            | otherwise
+            -> checkPatterns loc es >>= \ps ->
+               return (RdrValBinding (FunMonoBind f inf [Match ps opt_sig grhss] loc))
 
            Nothing ->
-               checkPattern loc lhs `thenP` \lhs ->
-               returnP (RdrValBinding (PatMonoBind lhs grhss loc))
+               checkPattern loc lhs >>= \lhs ->
+               return (RdrValBinding (PatMonoBind lhs grhss loc))
 
 checkValSig
        :: RdrNameHsExpr
        -> RdrNameHsType
        -> SrcLoc
        -> P RdrBinding
-checkValSig (HsVar v) ty loc | isUnqual v = returnP (RdrHsDecl (SigD (Sig v ty loc)))
+checkValSig (HsVar v) ty loc | isUnqual v = return (RdrHsDecl (SigD (Sig v ty loc)))
 checkValSig other     ty loc = parseError "Type signature given for an expression"
 
 mkSigDecls :: [Sig RdrName] -> RdrBinding
@@ -723,7 +731,7 @@ isFunLhs _ _                        = Nothing
 -- Miscellaneous utilities
 
 checkPrecP :: Int -> P Int
-checkPrecP i | 0 <= i && i <= maxPrecedence = returnP i
+checkPrecP i | 0 <= i && i <= maxPrecedence = return i
             | otherwise                    = parseError "Precedence out of range"
 
 mkRecConstrOrUpdate 
@@ -732,9 +740,9 @@ mkRecConstrOrUpdate
        -> P RdrNameHsExpr
 
 mkRecConstrOrUpdate (HsVar c) fs | isRdrDataCon c
-  = returnP (RecordCon c fs)
+  = return (RecordCon c fs)
 mkRecConstrOrUpdate exp fs@(_:_) 
-  = returnP (RecordUpd exp fs)
+  = return (RecordUpd exp fs)
 mkRecConstrOrUpdate _ _
   = parseError "Empty record update"
 
@@ -754,10 +762,11 @@ mkImport :: CallConv
         -> SrcLoc 
         -> P RdrNameHsDecl
 mkImport (CCall  cconv) safety (entity, v, ty) loc =
-  parseCImport entity cconv safety v                    `thenP` \importSpec ->
-  returnP $ ForD (ForeignImport v ty importSpec                     False loc)
+  parseCImport entity cconv safety v                    >>= \importSpec ->
+  return $ ForD (ForeignImport v ty importSpec                     False loc)
 mkImport (DNCall      ) _      (entity, v, ty) loc =
-  returnP $ ForD (ForeignImport v ty (DNImport (DNCallSpec entity)) False loc)
+  parseDImport entity                                   >>= \ spec ->
+  return $ ForD (ForeignImport v ty (DNImport spec) False loc)
 
 -- parse the entity string of a foreign import declaration for the `ccall' or
 -- `stdcall' calling convention'
@@ -770,9 +779,9 @@ parseCImport :: FastString
 parseCImport entity cconv safety v
   -- FIXME: we should allow white space around `dynamic' and `wrapper' -=chak
   | entity == FSLIT ("dynamic") = 
-    returnP $ CImport cconv safety nilFS nilFS (CFunction DynamicTarget)
+    return $ CImport cconv safety nilFS nilFS (CFunction DynamicTarget)
   | entity == FSLIT ("wrapper") =
-    returnP $ CImport cconv safety nilFS nilFS CWrapper
+    return $ CImport cconv safety nilFS nilFS CWrapper
   | otherwise                 = parse0 (unpackFS entity)
     where
       -- using the static keyword?
@@ -811,18 +820,54 @@ parseCImport entity cconv safety v
         where
          (first, rest) = break (== ' ') str
       --
-      build cid header False lib = returnP $
+      build cid header False lib = return $
         CImport cconv safety header lib (CFunction (StaticTarget cid))
-      build cid header True  lib = returnP $
+      build cid header True  lib = return $
         CImport cconv safety header lib (CLabel                  cid )
 
+--
+-- Unravel a dotnet spec string.
+--
+parseDImport :: FastString -> P DNCallSpec
+parseDImport entity = parse0 comps
+ 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
+  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 "Malformed entity string"
+  
 -- construct a foreign export declaration
 --
 mkExport :: CallConv
          -> (FastString, RdrName, RdrNameHsType) 
         -> SrcLoc 
         -> P RdrNameHsDecl
-mkExport (CCall  cconv) (entity, v, ty) loc = returnP $ 
+mkExport (CCall  cconv) (entity, v, ty) loc = return $ 
   ForD (ForeignExport v ty (CExport (CExportStatic entity' cconv)) False loc)
   where
     entity' | nullFastString entity = mkExtName v
@@ -860,9 +905,11 @@ mkIfaceExports decls = map getExport decls
 -- Misc utils
 
 \begin{code}
+showRdrName :: RdrName -> String
+showRdrName r = showSDoc (ppr r)
+
 parseError :: String -> P a
 parseError s = 
-  getSrcLocP `thenP` \ loc ->
-  failMsgP (hcat [ppr loc, text ": ", text s])
+  getSrcLoc >>= \ loc ->
+  failLocMsgP loc loc s
 \end{code}
-