+cvtTop :: TH.Dec -> CvtM (LHsDecl RdrName)
+cvtTop d@(TH.ValD _ _ _) = do { L loc d' <- cvtBind d; return (L loc $ Hs.ValD d') }
+cvtTop d@(TH.FunD _ _) = do { L loc d' <- cvtBind d; return (L loc $ Hs.ValD d') }
+cvtTop (TH.SigD nm typ) = do { nm' <- vNameL nm
+ ; ty' <- cvtType typ
+ ; returnL $ Hs.SigD (TypeSig nm' ty') }
+
+cvtTop (TySynD tc tvs rhs)
+ = do { tc' <- tconNameL tc
+ ; tvs' <- cvtTvs tvs
+ ; rhs' <- cvtType rhs
+ ; returnL $ TyClD (TySynonym tc' tvs' rhs') }
+
+cvtTop (DataD ctxt tc tvs constrs derivs)
+ = do { stuff <- cvt_tycl_hdr ctxt tc tvs
+ ; cons' <- mapM cvtConstr constrs
+ ; derivs' <- cvtDerivs derivs
+ ; returnL $ TyClD (mkTyData DataType stuff Nothing cons' derivs') }
+
+
+cvtTop (NewtypeD ctxt tc tvs constr derivs)
+ = do { stuff <- cvt_tycl_hdr ctxt tc tvs
+ ; con' <- cvtConstr constr
+ ; derivs' <- cvtDerivs derivs
+ ; returnL $ TyClD (mkTyData NewType stuff Nothing [con'] derivs') }
+
+cvtTop (ClassD ctxt cl tvs fds decs)
+ = do { stuff <- cvt_tycl_hdr ctxt cl tvs
+ ; fds' <- mapM cvt_fundep fds
+ ; (binds', sigs') <- cvtBindsAndSigs decs
+ ; returnL $ TyClD $ mkClassDecl stuff fds' sigs' binds' }
+
+cvtTop (InstanceD tys ty decs)
+ = do { (binds', sigs') <- cvtBindsAndSigs decs
+ ; ctxt' <- cvtContext tys
+ ; L loc pred' <- cvtPred ty
+ ; inst_ty' <- returnL $ mkImplicitHsForAllTy ctxt' (L loc (HsPredTy pred'))
+ ; returnL $ InstD (InstDecl inst_ty' binds' sigs') }
+
+cvtTop (ForeignD ford) = do { ford' <- cvtForD ford; returnL $ ForD ford' }
+
+cvt_tycl_hdr cxt tc tvs
+ = do { cxt' <- cvtContext cxt
+ ; tc' <- tconNameL tc
+ ; tvs' <- cvtTvs tvs
+ ; return (cxt', tc', tvs') }
+
+---------------------------------------------------
+-- Data types
+-- Can't handle GADTs yet
+---------------------------------------------------
+
+cvtConstr (NormalC c strtys)
+ = do { c' <- cNameL c
+ ; cxt' <- returnL []
+ ; tys' <- mapM cvt_arg strtys
+ ; returnL $ ConDecl c' Explicit noExistentials cxt' (PrefixCon tys') ResTyH98 }
+
+cvtConstr (RecC c varstrtys)
+ = do { c' <- cNameL c
+ ; cxt' <- returnL []
+ ; args' <- mapM cvt_id_arg varstrtys
+ ; returnL $ ConDecl c' Explicit noExistentials cxt' (RecCon args') ResTyH98 }
+
+cvtConstr (InfixC st1 c st2)
+ = do { c' <- cNameL c
+ ; cxt' <- returnL []
+ ; st1' <- cvt_arg st1
+ ; st2' <- cvt_arg st2
+ ; returnL $ ConDecl c' Explicit noExistentials cxt' (InfixCon st1' st2') ResTyH98 }
+
+cvtConstr (ForallC tvs ctxt (ForallC tvs' ctxt' con'))
+ = cvtConstr (ForallC (tvs ++ tvs') (ctxt ++ ctxt') con')
+
+cvtConstr (ForallC tvs ctxt con)
+ = do { L _ con' <- cvtConstr con
+ ; tvs' <- cvtTvs tvs
+ ; ctxt' <- cvtContext ctxt
+ ; case con' of
+ ConDecl l _ [] (L _ []) x ResTyH98
+ -> returnL $ ConDecl l Explicit tvs' ctxt' x ResTyH98
+ c -> panic "ForallC: Can't happen" }
+
+cvt_arg (IsStrict, ty) = do { ty' <- cvtType ty; returnL $ HsBangTy HsStrict ty' }
+cvt_arg (NotStrict, ty) = cvtType ty
+
+cvt_id_arg (i, str, ty) = do { i' <- vNameL i
+ ; ty' <- cvt_arg (str,ty)
+ ; return (i', ty') }
+
+cvtDerivs [] = return Nothing
+cvtDerivs cs = do { cs' <- mapM cvt_one cs
+ ; return (Just cs') }
+ where
+ cvt_one c = do { c' <- tconName c
+ ; returnL $ HsPredTy $ HsClassP c' [] }
+
+cvt_fundep :: FunDep -> CvtM (Located (Class.FunDep RdrName))
+cvt_fundep (FunDep xs ys) = do { xs' <- mapM tName xs; ys' <- mapM tName ys; returnL (xs', ys') }
+
+noExistentials = []
+
+------------------------------------------
+-- Foreign declarations
+------------------------------------------
+
+cvtForD :: Foreign -> CvtM (ForeignDecl RdrName)
+cvtForD (ImportF callconv safety from nm ty)
+ | Just (c_header, cis) <- parse_ccall_impent (TH.nameBase nm) from
+ = do { nm' <- vNameL nm
+ ; ty' <- cvtType ty
+ ; let i = CImport (cvt_conv callconv) safety' c_header nilFS cis
+ ; return $ ForeignImport nm' ty' i False }
+
+ | otherwise
+ = failWith $ text (show from)<+> ptext SLIT("is not a valid ccall impent")
+ where
+ safety' = case safety of
+ Unsafe -> PlayRisky
+ Safe -> PlaySafe False
+ Threadsafe -> PlaySafe True
+
+cvtForD (ExportF callconv as nm ty)
+ = do { nm' <- vNameL nm
+ ; ty' <- cvtType ty
+ ; let e = CExport (CExportStatic (mkFastString as) (cvt_conv callconv))
+ ; return $ ForeignExport nm' ty' e False }
+
+cvt_conv CCall = CCallConv
+cvt_conv StdCall = StdCallConv
+
+parse_ccall_impent :: String -> String -> Maybe (FastString, CImportSpec)
+parse_ccall_impent nm s
+ = case lex_ccall_impent s of
+ Just ["dynamic"] -> Just (nilFS, CFunction DynamicTarget)
+ Just ["wrapper"] -> Just (nilFS, CWrapper)
+ Just ("static":ts) -> parse_ccall_impent_static nm ts
+ Just ts -> parse_ccall_impent_static nm ts
+ Nothing -> Nothing
+
+parse_ccall_impent_static :: String
+ -> [String]
+ -> Maybe (FastString, CImportSpec)
+parse_ccall_impent_static nm ts
+ = let ts' = case ts of
+ [ "&", cid] -> [ cid]
+ [fname, "&" ] -> [fname ]
+ [fname, "&", cid] -> [fname, cid]
+ _ -> ts
+ in case ts' of
+ [ cid] | is_cid cid -> Just (nilFS, mk_cid cid)
+ [fname, cid] | is_cid cid -> Just (mkFastString fname, mk_cid cid)
+ [ ] -> Just (nilFS, mk_cid nm)
+ [fname ] -> Just (mkFastString fname, mk_cid nm)
+ _ -> Nothing
+ where is_cid :: String -> Bool
+ is_cid x = all (/= '.') x && (isAlpha (head x) || head x == '_')
+ mk_cid :: String -> CImportSpec
+ mk_cid = CFunction . StaticTarget . mkFastString
+
+lex_ccall_impent :: String -> Maybe [String]
+lex_ccall_impent "" = Just []
+lex_ccall_impent ('&':xs) = fmap ("&":) $ lex_ccall_impent xs
+lex_ccall_impent (' ':xs) = lex_ccall_impent xs
+lex_ccall_impent ('\t':xs) = lex_ccall_impent xs
+lex_ccall_impent xs = case span is_valid xs of
+ ("", _) -> Nothing
+ (t, xs') -> fmap (t:) $ lex_ccall_impent xs'
+ where is_valid :: Char -> Bool
+ is_valid c = isAscii c && (isAlphaNum c || c `elem` "._")
+
+
+---------------------------------------------------
+-- Declarations
+---------------------------------------------------
+
+cvtDecs :: [TH.Dec] -> CvtM (HsLocalBinds RdrName)
+cvtDecs [] = return EmptyLocalBinds
+cvtDecs ds = do { (binds,sigs) <- cvtBindsAndSigs ds
+ ; return (HsValBinds (ValBindsIn binds sigs)) }