More hacking on monad-comp; now works
[ghc-hetmet.git] / compiler / hsSyn / Convert.lhs
index 8b64c98..5933e9d 100644 (file)
@@ -7,7 +7,8 @@ This module converts Template Haskell syntax into HsSyn
 
 \begin{code}
 module Convert( convertToHsExpr, convertToPat, convertToHsDecls,
-                convertToHsType, thRdrNameGuesses ) where
+                convertToHsType, convertToHsPred,
+                thRdrNameGuesses ) where
 
 import HsSyn as Hs
 import qualified Class
@@ -19,18 +20,20 @@ import qualified OccName
 import OccName
 import SrcLoc
 import Type
+import Coercion
 import TysWiredIn
 import BasicTypes as Hs
 import ForeignCall
-import Char
-import List
 import Unique
 import MonadUtils
 import ErrUtils
 import Bag
+import Util
 import FastString
 import Outputable
 
+import Control.Monad( unless )
+
 import Language.Haskell.TH as TH hiding (sigP)
 import Language.Haskell.TH.Syntax as TH
 
@@ -40,25 +43,25 @@ import GHC.Exts
 --             The external interface
 
 convertToHsDecls :: SrcSpan -> [TH.Dec] -> Either Message [LHsDecl RdrName]
-convertToHsDecls loc ds = initCvt loc (mapM cvtTop ds)
+convertToHsDecls loc ds = initCvt loc (mapM cvt_dec ds)
+  where
+    cvt_dec d = wrapMsg "declaration" d (cvtDec d)
 
 convertToHsExpr :: SrcSpan -> TH.Exp -> Either Message (LHsExpr RdrName)
 convertToHsExpr loc e 
-  = case initCvt loc (cvtl e) of
-       Left msg  -> Left (msg $$ (ptext (sLit "When splicing TH expression:")
-                                   <+> text (show e)))
-       Right res -> Right res
+  = initCvt loc $ wrapMsg "expression" e $ cvtl e
 
 convertToPat :: SrcSpan -> TH.Pat -> Either Message (LPat RdrName)
-convertToPat loc e
-  = case initCvt loc (cvtPat e) of
-        Left msg  -> Left (msg $$ (ptext (sLit "When splicing TH pattern:")
-                                    <+> text (show e)))
-        Right res -> Right res
+convertToPat loc p
+  = initCvt loc $ wrapMsg "pattern" p $ cvtPat p
 
 convertToHsType :: SrcSpan -> TH.Type -> Either Message (LHsType RdrName)
-convertToHsType loc t = initCvt loc (cvtType t)
+convertToHsType loc t
+  = initCvt loc $ wrapMsg "type" t $ cvtType t
 
+convertToHsPred :: SrcSpan -> TH.Pred -> Either Message (LHsPred RdrName)
+convertToHsPred loc t
+  = initCvt loc $ wrapMsg "type" t $ cvtPred t
 
 -------------------------------------------------------------------
 newtype CvtM a = CvtM { unCvtM :: SrcSpan -> Either Message a }
@@ -87,39 +90,71 @@ force :: a -> CvtM ()
 force a = a `seq` return ()
 
 failWith :: Message -> CvtM a
-failWith m = CvtM (\_ -> Left full_msg)
-   where
-     full_msg = m $$ ptext (sLit "When splicing generated code into the program")
+failWith m = CvtM (\_ -> Left m)
 
 returnL :: a -> CvtM (Located a)
 returnL x = CvtM (\loc -> Right (L loc x))
 
+wrapMsg :: (Show a, TH.Ppr a) => String -> a -> CvtM b -> CvtM b
+-- E.g  wrapMsg "declaration" dec thing
+wrapMsg what item (CvtM m)
+  = CvtM (\loc -> case m loc of
+                     Left err -> Left (err $$ getPprStyle msg)
+                     Right v  -> Right v)
+  where
+       -- Show the item in pretty syntax normally, 
+       -- but with all its constructors if you say -dppr-debug
+    msg sty = hang (ptext (sLit "When splicing a TH") <+> text what <> colon)
+                 2 (if debugStyle sty 
+                    then text (show item)
+                    else text (pprint item))
+
 wrapL :: CvtM a -> CvtM (Located a)
 wrapL (CvtM m) = CvtM (\loc -> case m loc of
                          Left err -> Left err
                          Right v  -> Right (L loc v))
 
 -------------------------------------------------------------------
-cvtTop :: TH.Dec -> CvtM (LHsDecl RdrName)
-cvtTop d@(TH.ValD _ _ _) 
-  = do { L loc d' <- cvtBind d
-       ; return (L loc $ Hs.ValD d') }
+cvtDec :: TH.Dec -> CvtM (LHsDecl RdrName)
+cvtDec (TH.ValD pat body ds) 
+  | TH.VarP s <- pat
+  = do { s' <- vNameL s
+       ; cl' <- cvtClause (Clause [] body ds)
+       ; returnL $ Hs.ValD $ mkFunBind s' [cl'] }
 
-cvtTop d@(TH.FunD _ _)   
-  = do { L loc d' <- cvtBind d
-       ; return (L loc $ Hs.ValD d') }
+  | otherwise
+  = do { pat' <- cvtPat pat
+       ; body' <- cvtGuard body
+       ; ds' <- cvtLocalDecs (ptext (sLit "a where clause")) ds
+       ; returnL $ Hs.ValD $
+          PatBind { pat_lhs = pat', pat_rhs = GRHSs body' ds' 
+                 , pat_rhs_ty = void, bind_fvs = placeHolderNames } }
+
+cvtDec (TH.FunD nm cls)   
+  | null cls
+  = failWith (ptext (sLit "Function binding for")
+                   <+> quotes (text (TH.pprint nm))
+                   <+> ptext (sLit "has no equations"))
+  | otherwise
+  = do { nm' <- vNameL nm
+       ; cls' <- mapM cvtClause cls
+       ; returnL $ Hs.ValD $ mkFunBind nm' cls' }
 
-cvtTop (TH.SigD nm typ)  
+cvtDec (TH.SigD nm typ)  
   = do  { nm' <- vNameL nm
        ; ty' <- cvtType typ
        ; returnL $ Hs.SigD (TypeSig nm' ty') }
 
-cvtTop (TySynD tc tvs rhs)
+cvtDec (PragmaD prag)
+  = do { prag' <- cvtPragmaD prag
+       ; returnL $ Hs.SigD prag' }
+
+cvtDec (TySynD tc tvs rhs)
   = do { (_, tc', tvs') <- cvt_tycl_hdr [] tc tvs
        ; rhs' <- cvtType rhs
        ; returnL $ TyClD (TySynonym tc' tvs' Nothing rhs') }
 
-cvtTop (DataD ctxt tc tvs constrs derivs)
+cvtDec (DataD ctxt tc tvs constrs derivs)
   = do { (ctxt', tc', tvs') <- cvt_tycl_hdr ctxt tc tvs
        ; cons' <- mapM cvtConstr constrs
        ; derivs' <- cvtDerivs derivs
@@ -127,7 +162,7 @@ cvtTop (DataD ctxt tc tvs constrs derivs)
                                   , tcdTyVars = tvs', tcdTyPats = Nothing, tcdKindSig = Nothing
                                   , tcdCons = cons', tcdDerivs = derivs' }) }
 
-cvtTop (NewtypeD ctxt tc tvs constr derivs)
+cvtDec (NewtypeD ctxt tc tvs constr derivs)
   = do { (ctxt', tc', tvs') <- cvt_tycl_hdr ctxt tc tvs
        ; con' <- cvtConstr constr
        ; derivs' <- cvtDerivs derivs
@@ -135,69 +170,45 @@ cvtTop (NewtypeD ctxt tc tvs constr derivs)
                                  , tcdTyVars = tvs', tcdTyPats = Nothing, tcdKindSig = Nothing
                                   , tcdCons = [con'], tcdDerivs = derivs'}) }
 
-cvtTop (ClassD ctxt cl tvs fds decs)
+cvtDec (ClassD ctxt cl tvs fds decs)
   = do { (cxt', tc', tvs') <- cvt_tycl_hdr ctxt cl tvs
        ; fds'  <- mapM cvt_fundep fds
-        ; let (ats, bind_sig_decs) = partition isFamilyD decs
-       ; (binds', sigs') <- cvtBindsAndSigs bind_sig_decs
-        ; ats' <- mapM cvtTop ats
-        ; let ats'' = map unTyClD ats'
+        ; (binds', sigs', ats') <- cvt_ci_decs (ptext (sLit "a class declaration")) decs
        ; returnL $ 
             TyClD $ ClassDecl { tcdCtxt = cxt', tcdLName = tc', tcdTyVars = tvs'
                              , tcdFDs = fds', tcdSigs = sigs', tcdMeths = binds'
-                             , tcdATs = ats'', tcdDocs = [] }
-                                                       -- no docs in TH ^^
+                             , tcdATs = ats', tcdDocs = [] }
+                                        -- no docs in TH ^^
        }
-  where
-    isFamilyD (FamilyD _ _ _ _) = True
-    isFamilyD _                 = False
-
-cvtTop (InstanceD ctxt ty decs)
-  = do         { let (ats, bind_sig_decs) = partition isFamInstD decs
-        ; (binds', sigs') <- cvtBindsAndSigs bind_sig_decs
-        ; ats' <- mapM cvtTop ats
-        ; let ats'' = map unTyClD ats'
+       
+cvtDec (InstanceD ctxt ty decs)
+  = do         { (binds', sigs', ats') <- cvt_ci_decs (ptext (sLit "an instance declaration")) decs
        ; ctxt' <- cvtContext ctxt
        ; L loc pred' <- cvtPredTy ty
-       ; inst_ty' <- returnL $ 
-                        mkImplicitHsForAllTy ctxt' (L loc (HsPredTy pred'))
-       ; returnL $ InstD (InstDecl inst_ty' binds' sigs' ats'')
-       }
-  where
-    isFamInstD (DataInstD _ _ _ _ _)    = True
-    isFamInstD (NewtypeInstD _ _ _ _ _) = True
-    isFamInstD (TySynInstD _ _ _)       = True
-    isFamInstD _                        = False
+       ; let inst_ty' = L loc $ mkImplicitHsForAllTy ctxt' $ L loc $ HsPredTy pred'
+       ; returnL $ InstD (InstDecl inst_ty' binds' sigs' ats') }
 
-cvtTop (ForeignD ford) 
+cvtDec (ForeignD ford) 
   = do { ford' <- cvtForD ford
-       ; returnL $ ForD ford' 
-       }
+       ; returnL $ ForD ford' }
 
-cvtTop (PragmaD prag)
-  = do { prag' <- cvtPragmaD prag
-       ; returnL $ Hs.SigD prag'
-       }
-
-cvtTop (FamilyD flav tc tvs kind)
+cvtDec (FamilyD flav tc tvs kind)
   = do { (_, tc', tvs') <- cvt_tycl_hdr [] tc tvs
        ; let kind' = fmap cvtKind kind
-       ; returnL $ TyClD (TyFamily (cvtFamFlavour flav) tc' tvs' kind')
-       }
+       ; returnL $ TyClD (TyFamily (cvtFamFlavour flav) tc' tvs' kind') }
   where
     cvtFamFlavour TypeFam = TypeFamily
     cvtFamFlavour DataFam = DataFamily
 
-cvtTop (DataInstD ctxt tc tys constrs derivs)
+cvtDec (DataInstD ctxt tc tys constrs derivs)
   = do { (ctxt', tc', tvs', typats') <- cvt_tyinst_hdr ctxt tc tys
        ; cons' <- mapM cvtConstr constrs
        ; derivs' <- cvtDerivs derivs
        ; returnL $ TyClD (TyData { tcdND = DataType, tcdLName = tc', tcdCtxt = ctxt'
                                   , tcdTyVars = tvs', tcdTyPats = typats', tcdKindSig = Nothing
-                                  , tcdCons = cons', tcdDerivs = derivs' })
-       }
+                                  , tcdCons = cons', tcdDerivs = derivs' }) }
 
-cvtTop (NewtypeInstD ctxt tc tys constr derivs)
+cvtDec (NewtypeInstD ctxt tc tys constr derivs)
   = do { (ctxt', tc', tvs', typats') <- cvt_tyinst_hdr ctxt tc tys
        ; con' <- cvtConstr constr
        ; derivs' <- cvtDerivs derivs
@@ -206,17 +217,27 @@ cvtTop (NewtypeInstD ctxt tc tys constr derivs)
                                   , tcdCons = [con'], tcdDerivs = derivs' })
        }
 
-cvtTop (TySynInstD tc tys rhs)
+cvtDec (TySynInstD tc tys rhs)
   = do { (_, tc', tvs', tys') <- cvt_tyinst_hdr [] tc tys
        ; rhs' <- cvtType rhs
        ; returnL $ TyClD (TySynonym tc' tvs' tys' rhs') }
 
--- FIXME: This projection is not nice, but to remove it, cvtTop should be 
---        refactored.
-unTyClD :: LHsDecl a -> LTyClDecl a
-unTyClD (L l (TyClD d)) = L l d
-unTyClD _               = panic "Convert.unTyClD: internal error"
-
+----------------
+cvt_ci_decs :: Message -> [TH.Dec]
+            -> CvtM (LHsBinds RdrName, 
+                     [LSig RdrName], 
+                     [LTyClDecl RdrName])
+-- Convert the declarations inside a class or instance decl
+-- ie signatures, bindings, and associated types
+cvt_ci_decs doc decs
+  = do  { decs' <- mapM cvtDec decs
+        ; let (ats', bind_sig_decs') = partitionWith is_tycl decs'
+       ; let (sigs', prob_binds') = partitionWith is_sig bind_sig_decs'
+       ; let (binds', bads) = partitionWith is_bind prob_binds'
+       ; unless (null bads) (failWith (mkBadDecMsg doc bads))
+        ; return (listToBag binds', sigs', ats') }
+
+----------------
 cvt_tycl_hdr :: TH.Cxt -> TH.Name -> [TH.TyVarBndr]
              -> CvtM ( LHsContext RdrName
                      , Located RdrName
@@ -247,6 +268,7 @@ cvt_tyinst_hdr cxt tc tys
     collect (VarT tv)    = return [PlainTV tv]
     collect (ConT _)     = return []
     collect (TupleT _)   = return []
+    collect (UnboxedTupleT _) = return []
     collect ArrowT       = return []
     collect ListT        = return []
     collect (AppT t1 t2)
@@ -257,6 +279,27 @@ cvt_tyinst_hdr cxt tc tys
     collect (SigT (VarT tv) ki) = return [KindedTV tv ki]
     collect (SigT ty _)         = collect ty
 
+-------------------------------------------------------------------
+--             Partitioning declarations
+-------------------------------------------------------------------
+
+is_tycl :: LHsDecl RdrName -> Either (LTyClDecl RdrName) (LHsDecl RdrName)
+is_tycl (L loc (Hs.TyClD tcd)) = Left (L loc tcd)
+is_tycl decl                   = Right decl
+
+is_sig :: LHsDecl RdrName -> Either (LSig RdrName) (LHsDecl RdrName)
+is_sig (L loc (Hs.SigD sig)) = Left (L loc sig)
+is_sig decl                  = Right decl
+
+is_bind :: LHsDecl RdrName -> Either (LHsBind RdrName) (LHsDecl RdrName)
+is_bind (L loc (Hs.ValD bind)) = Left (L loc bind)
+is_bind decl                  = Right decl
+
+mkBadDecMsg :: Message -> [LHsDecl RdrName] -> Message
+mkBadDecMsg doc bads 
+  = sep [ ptext (sLit "Illegal declaration(s) in") <+> doc <> colon
+        , nest 2 (vcat (map Outputable.ppr bads)) ]
+
 ---------------------------------------------------
 --     Data types
 -- Can't handle GADTs yet
@@ -283,17 +326,12 @@ cvtConstr (InfixC st1 c st2)
        ; st2' <- cvt_arg st2
        ; returnL $ mkSimpleConDecl c' noExistentials cxt' (InfixCon st1' st2') }
 
-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 { con_qvars = [], con_cxt = L _ [] }
-             -> returnL $ con' { con_qvars = tvs', con_cxt = ctxt' }
-           _ -> panic "ForallC: Can't happen" }
+  = do { tvs'  <- cvtTvs tvs
+       ; L loc ctxt' <- cvtContext ctxt
+       ; L _ con' <- cvtConstr con
+       ; returnL $ con' { con_qvars = tvs' ++ con_qvars con'
+                         , con_cxt = L loc (ctxt' ++ (unLoc $ con_cxt con')) } }
 
 cvt_arg :: (TH.Strict, TH.Type) -> CvtM (LHsType RdrName)
 cvt_arg (IsStrict, ty)  = do { ty' <- cvtType ty; returnL $ HsBangTy HsStrict ty' }
@@ -325,19 +363,20 @@ noExistentials = []
 
 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 cis
-       ; return $ ForeignImport nm' ty' i }
-
+  | Just impspec <- parseCImport (cvt_conv callconv) safety' 
+                                 (mkFastString (TH.nameBase nm)) from
+  = do { nm' <- vNameL nm
+       ; ty' <- cvtType ty
+       ; return (ForeignImport nm' ty' impspec)
+       }
   | otherwise
-  = failWith $ text (show from)<+> ptext (sLit "is not a valid ccall impent")
-  where 
+  = 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
+                     Interruptible -> PlayInterruptible
 
 cvtForD (ExportF callconv as nm ty)
   = do { nm' <- vNameL nm
@@ -349,61 +388,6 @@ cvt_conv :: TH.Callconv -> CCallConv
 cvt_conv TH.CCall   = CCallConv
 cvt_conv TH.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
-
--- XXX we should be sharing code with RdrHsSyn.parseCImport
-parse_ccall_impent_static :: String
-                          -> [String]
-                          -> Maybe (FastString, CImportSpec)
-parse_ccall_impent_static nm ts
- = case ts of
-     [               ] -> mkFun nilFS                 nm
-     [       "&", cid] -> mkLbl nilFS                 cid
-     [fname, "&"     ] -> mkLbl (mkFastString fname)  nm
-     [fname, "&", cid] -> mkLbl (mkFastString fname)  cid
-     [       "&"     ] -> mkLbl nilFS                 nm
-     [fname,      cid] -> mkFun (mkFastString fname)  cid
-     [            cid]
-          | is_cid cid -> mkFun nilFS                 cid
-          | otherwise  -> mkFun (mkFastString cid)    nm
-           -- tricky case when there's a single string: "foo.h" is a header,
-           -- but "foo" is a C identifier, and we tell the difference by
-           -- checking for a valid C identifier (see is_cid below).
-     _anything_else    -> Nothing
-
-    where is_cid :: String -> Bool
-          is_cid x = all (/= '.') x && (isAlpha (head x) || head x == '_')
-
-          mkLbl :: FastString -> String -> Maybe (FastString, CImportSpec)
-          mkLbl fname lbl  = Just (fname, CLabel (mkFastString lbl))
-
-          mkFun :: FastString -> String -> Maybe (FastString, CImportSpec)
-          mkFun fname lbl  = Just (fname, CFunction (StaticTarget (mkFastString lbl)))
-
--- This code is tokenising something like "foo.h &bar", eg.
---   ""           -> Just []
---   "foo.h"      -> Just ["foo.h"]
---   "foo.h &bar" -> Just ["foo.h","&","bar"]
---   "&"          -> Just ["&"]
--- Nothing is returned for a parse error.
-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` "._")
-
 ------------------------------------------
 --              Pragmas
 ------------------------------------------
@@ -411,96 +395,55 @@ lex_ccall_impent xs = case span is_valid xs of
 cvtPragmaD :: Pragma -> CvtM (Sig RdrName)
 cvtPragmaD (InlineP nm ispec)
   = do { nm'    <- vNameL nm
-       ; return $ InlineSig nm' (cvtInlineSpec (Just ispec))
-       }
+       ; return $ InlineSig nm' (cvtInlineSpec (Just ispec)) }
+
 cvtPragmaD (SpecialiseP nm ty opt_ispec)
-  = do { nm'    <- vNameL nm
-       ; ty'    <- cvtType ty
-       ; return $ SpecSig nm' ty' (cvtInlineSpec opt_ispec)
-       }
+  = do { nm' <- vNameL nm
+       ; ty' <- cvtType ty
+       ; return $ SpecSig nm' ty' (cvtInlineSpec opt_ispec) }
 
-cvtInlineSpec :: Maybe TH.InlineSpec -> Hs.InlineSpec
+cvtInlineSpec :: Maybe TH.InlineSpec -> Hs.InlinePragma
 cvtInlineSpec Nothing 
-  = defaultInlineSpec
+  = defaultInlinePragma
 cvtInlineSpec (Just (TH.InlineSpec inline conlike opt_activation)) 
-  = mkInlineSpec opt_activation' matchinfo inline
+  = InlinePragma { inl_act = opt_activation', inl_rule = matchinfo
+                 , inl_inline = inl_spec, inl_sat = Nothing }
   where
     matchinfo       = cvtRuleMatchInfo conlike
-    opt_activation' = fmap cvtActivation opt_activation
+    opt_activation' = cvtActivation opt_activation
 
     cvtRuleMatchInfo False = FunLike
     cvtRuleMatchInfo True  = ConLike
 
-    cvtActivation (False, phase) = ActiveBefore phase
-    cvtActivation (True , phase) = ActiveAfter  phase
+    inl_spec | inline    = Inline
+             | otherwise = NoInline
+            -- Currently we have no way to say Inlinable
+
+    cvtActivation Nothing | inline      = AlwaysActive
+                          | otherwise   = NeverActive
+    cvtActivation (Just (False, phase)) = ActiveBefore phase
+    cvtActivation (Just (True , phase)) = ActiveAfter  phase
 
 ---------------------------------------------------
 --             Declarations
 ---------------------------------------------------
 
-cvtDecs :: [TH.Dec] -> CvtM (HsLocalBinds RdrName)
-cvtDecs [] = return EmptyLocalBinds
-cvtDecs ds = do { (binds, sigs) <- cvtBindsAndSigs ds
-               ; return (HsValBinds (ValBindsIn binds sigs)) }
-
-cvtBindsAndSigs :: [TH.Dec] -> CvtM (Bag (LHsBind RdrName), [LSig RdrName])
-cvtBindsAndSigs ds 
-  = do { binds' <- mapM cvtBind binds
-       ; sigs' <- mapM cvtSig sigs
-       ; return (listToBag binds', sigs') }
-  where 
-    (sigs, binds) = partition is_sig ds
-
-    is_sig (TH.SigD _ _)  = True
-    is_sig (TH.PragmaD _) = True
-    is_sig _              = False
-
-cvtSig :: TH.Dec -> CvtM (LSig RdrName)
-cvtSig (TH.SigD nm ty)
-  = do { nm' <- vNameL nm
-       ; ty' <- cvtType ty
-       ; returnL (Hs.TypeSig nm' ty') 
-       }
-cvtSig (TH.PragmaD prag)
-  = do { prag' <- cvtPragmaD prag
-       ; returnL prag'
-       }
-cvtSig _ = panic "Convert.cvtSig: Signature expected"
-
-cvtBind :: TH.Dec -> CvtM (LHsBind RdrName)
--- Used only for declarations in a 'let/where' clause,
--- not for top level decls
-cvtBind (TH.ValD (TH.VarP s) body ds) 
-  = do { s' <- vNameL s
-       ; cl' <- cvtClause (Clause [] body ds)
-       ; returnL $ mkFunBind s' [cl'] }
-
-cvtBind (TH.FunD nm cls)
-  | null cls
-  = failWith (ptext (sLit "Function binding for")
-                   <+> quotes (text (TH.pprint nm))
-                   <+> ptext (sLit "has no equations"))
+cvtLocalDecs :: Message -> [TH.Dec] -> CvtM (HsLocalBinds RdrName)
+cvtLocalDecs doc ds 
+  | null ds
+  = return EmptyLocalBinds
   | otherwise
-  = do { nm' <- vNameL nm
-       ; cls' <- mapM cvtClause cls
-       ; returnL $ mkFunBind nm' cls' }
-
-cvtBind (TH.ValD p body ds)
-  = do { p' <- cvtPat p
-       ; g' <- cvtGuard body
-       ; ds' <- cvtDecs ds
-       ; returnL $ PatBind { pat_lhs = p', pat_rhs = GRHSs g' ds', 
-                             pat_rhs_ty = void, bind_fvs = placeHolderNames } }
-
-cvtBind d 
-  = failWith (sep [ptext (sLit "Illegal kind of declaration in where clause"),
-                  nest 2 (text (TH.pprint d))])
+  = do { ds' <- mapM cvtDec ds
+       ; let (binds, prob_sigs) = partitionWith is_bind ds'
+       ; let (sigs, bads) = partitionWith is_sig prob_sigs
+       ; unless (null bads) (failWith (mkBadDecMsg doc bads))
+       ; return (HsValBinds (ValBindsIn (listToBag binds) sigs)) }
 
 cvtClause :: TH.Clause -> CvtM (Hs.LMatch RdrName)
 cvtClause (Clause ps body wheres)
   = do { ps' <- cvtPats ps
        ; g'  <- cvtGuard body
-       ; ds' <- cvtDecs wheres
+       ; ds' <- cvtLocalDecs (ptext (sLit "a where clause")) wheres
        ; returnL $ Hs.Match ps' Nothing (GRHSs g' ds') }
 
 
@@ -521,10 +464,13 @@ cvtl e = wrapL (cvt e)
     cvt (LamE ps e)    = do { ps' <- cvtPats ps; e' <- cvtl e 
                            ; return $ HsLam (mkMatchGroup [mkSimpleMatch ps' e']) }
     cvt (TupE [e])     = cvt e -- Singleton tuples treated like nothing (just parens)
-    cvt (TupE es)      = do { es' <- mapM cvtl es; return $ ExplicitTuple es' Boxed }
-    cvt (CondE x y z)  = do { x' <- cvtl x; y' <- cvtl y; z' <- cvtl z
-                           ; return $ HsIf x' y' z' }
-    cvt (LetE ds e)    = do { ds' <- cvtDecs ds; e' <- cvtl e; return $ HsLet ds' e' }
+    cvt (TupE es)      = do { es' <- mapM cvtl es; return $ ExplicitTuple (map Present es') Boxed }
+    cvt (UnboxedTupE [e])     = cvt e  -- Singleton tuples treated like nothing (just parens)
+    cvt (UnboxedTupE es)      = do { es' <- mapM cvtl es; return $ ExplicitTuple (map Present es') Unboxed }
+    cvt (CondE x y z)  = do { x' <- cvtl x; y' <- cvtl y; z' <- cvtl z;
+                           ; return $ HsIf (Just noSyntaxExpr) x' y' z' }
+    cvt (LetE ds e)    = do { ds' <- cvtLocalDecs (ptext (sLit "a let expression")) ds
+                            ; e' <- cvtl e; return $ HsLet ds' e' }
     cvt (CaseE e ms)   
        | null ms       = failWith (ptext (sLit "Case expression with no alternatives"))
        | otherwise     = do { e' <- cvtl e; ms' <- mapM cvtMatch ms
@@ -576,19 +522,27 @@ cvtHsDo do_or_lc stmts
   | null stmts = failWith (ptext (sLit "Empty stmt list in do-block"))
   | otherwise
   = do { stmts' <- cvtStmts stmts
-       ; let body = case last stmts' of
-                       L _ (ExprStmt body _ _) -> body
-                        _                       -> panic "Malformed body"
-       ; return $ HsDo do_or_lc (init stmts') body void }
+        ; let Just (stmts'', last') = snocView stmts'
+        
+       ; last'' <- case last' of
+                     L loc (ExprStmt body _ _ _) -> return (L loc (mkLastStmt body))
+                      _ -> failWith (bad_last last')
 
+       ; return $ HsDo do_or_lc (stmts'' ++ [last'']) void }
+  where
+    bad_last stmt = vcat [ ptext (sLit "Illegal last statement of") <+> pprAStmtContext do_or_lc <> colon
+                         , nest 2 $ Outputable.ppr stmt
+                        , ptext (sLit "(It should be an expression.)") ]
+               
 cvtStmts :: [TH.Stmt] -> CvtM [Hs.LStmt RdrName]
 cvtStmts = mapM cvtStmt 
 
 cvtStmt :: TH.Stmt -> CvtM (Hs.LStmt RdrName)
 cvtStmt (NoBindS e)    = do { e' <- cvtl e; returnL $ mkExprStmt e' }
 cvtStmt (TH.BindS p e) = do { p' <- cvtPat p; e' <- cvtl e; returnL $ mkBindStmt p' e' }
-cvtStmt (TH.LetS ds)   = do { ds' <- cvtDecs ds; returnL $ LetStmt ds' }
-cvtStmt (TH.ParS dss)  = do { dss' <- mapM cvt_one dss; returnL $ ParStmt dss' }
+cvtStmt (TH.LetS ds)   = do { ds' <- cvtLocalDecs (ptext (sLit "a let binding")) ds
+                            ; returnL $ LetStmt ds' }
+cvtStmt (TH.ParS dss)  = do { dss' <- mapM cvt_one dss; returnL $ ParStmt dss' noSyntaxExpr noSyntaxExpr noSyntaxExpr }
                       where
                         cvt_one ds = do { ds' <- cvtStmts ds; return (ds', undefined) }
 
@@ -596,7 +550,7 @@ cvtMatch :: TH.Match -> CvtM (Hs.LMatch RdrName)
 cvtMatch (TH.Match p body decs)
   = do         { p' <- cvtPat p
        ; g' <- cvtGuard body
-       ; decs' <- cvtDecs decs
+       ; decs' <- cvtLocalDecs (ptext (sLit "a where clause")) decs
        ; returnL $ Hs.Match [p'] Nothing (GRHSs g' decs') }
 
 cvtGuard :: TH.Body -> CvtM [LGRHS RdrName]
@@ -634,10 +588,16 @@ if it isn't a literal string
 
 allCharLs :: [TH.Exp] -> Maybe String
 -- Note [Converting strings]
-allCharLs (LitE (CharL c) : xs) 
-  | Just cs <- allCharLs xs = Just (c:cs)
-allCharLs [] = Just []
-allCharLs _  = Nothing
+-- NB: only fire up this setup for a non-empty list, else
+--     there's a danger of returning "" for [] :: [Int]!
+allCharLs xs
+  = case xs of 
+      LitE (CharL c) : ys -> go [c] ys
+      _                   -> Nothing
+  where
+    go cs []                    = Just (reverse cs)
+    go cs (LitE (CharL c) : ys) = go (c:cs) ys
+    go _  _                     = Nothing
 
 cvtLit :: Lit -> CvtM HsLit
 cvtLit (IntPrimL i)    = do { force i; return $ HsIntPrim i }
@@ -645,12 +605,16 @@ cvtLit (WordPrimL w)   = do { force w; return $ HsWordPrim w }
 cvtLit (FloatPrimL f)  = do { force f; return $ HsFloatPrim f }
 cvtLit (DoublePrimL f) = do { force f; return $ HsDoublePrim f }
 cvtLit (CharL c)       = do { force c; return $ HsChar c }
-cvtLit (StringL s)     
-  = do { let { s' = mkFastString s }
-       ; force s'
-       ; return $ HsString s' 
-       }
+cvtLit (StringL s)     = do { let { s' = mkFastString s }
+                                   ; force s'      
+                                   ; return $ HsString s' }
+cvtLit (StringPrimL s) = do { let { s' = mkFastString s }
+                                   ; force s'           
+                                   ; return $ HsStringPrim s' }
 cvtLit _ = panic "Convert.cvtLit: Unexpected literal"
+       -- cvtLit should not be called on IntegerL, RationalL
+       -- That precondition is established right here in
+       -- Convert.lhs, hence panic
 
 cvtPats :: [TH.Pat] -> CvtM [Hs.LPat RdrName]
 cvtPats pats = mapM cvtPat pats
@@ -668,6 +632,8 @@ cvtp (TH.LitP l)
 cvtp (TH.VarP s)      = do { s' <- vName s; return $ Hs.VarPat s' }
 cvtp (TupP [p])       = cvtp p
 cvtp (TupP ps)        = do { ps' <- cvtPats ps; return $ TuplePat ps' Boxed void }
+cvtp (UnboxedTupP [p]) = cvtp p
+cvtp (UnboxedTupP ps)  = do { ps' <- cvtPats ps; return $ TuplePat ps' Unboxed void }
 cvtp (ConP s ps)      = do { s' <- cNameL s; ps' <- cvtPats ps; return $ ConPatIn s' (PrefixCon ps') }
 cvtp (InfixP p1 s p2) = do { s' <- cNameL s; p1' <- cvtPat p1; p2' <- cvtPat p2
                           ; return $ ConPatIn s' (InfixCon p1' p2') }
@@ -679,6 +645,7 @@ cvtp (RecP c fs)      = do { c' <- cNameL c; fs' <- mapM cvtPatFld fs
                           ; return $ ConPatIn c' $ Hs.RecCon (HsRecFields fs' Nothing) }
 cvtp (ListP ps)       = do { ps' <- cvtPats ps; return $ ListPat ps' void }
 cvtp (SigP p t)       = do { p' <- cvtPat p; t' <- cvtType t; return $ SigPatIn p' t' }
+cvtp (ViewP e p)      = do { e' <- cvtl e; p' <- cvtPat p; return $ ViewPat e' p' void }
 
 cvtPatFld :: (TH.Name, TH.Pat) -> CvtM (HsRecField RdrName (LPat RdrName))
 cvtPatFld (s,p)
@@ -694,7 +661,7 @@ cvtTvs tvs = mapM cvt_tv tvs
 cvt_tv :: TH.TyVarBndr -> CvtM (LHsTyVarBndr RdrName)
 cvt_tv (TH.PlainTV nm) 
   = do { nm' <- tName nm
-       ; returnL $ UserTyVar nm' 
+       ; returnL $ UserTyVar nm' placeHolderKind
        }
 cvt_tv (TH.KindedTV nm ki) 
   = do { nm' <- tName nm
@@ -738,6 +705,15 @@ cvtType ty
              -> failWith (ptext (sLit "Illegal 1-tuple type constructor"))
              | otherwise 
              -> mk_apps (HsTyVar (getRdrName (tupleTyCon Boxed n))) tys'
+           UnboxedTupleT n
+             | length tys' == n        -- Saturated
+             -> if n==1 then return (head tys')        -- Singleton tuples treated
+                                                -- like nothing (ie just parens)
+                        else returnL (HsTupleTy Unboxed tys')
+             | n == 1
+             -> failWith (ptext (sLit "Illegal 1-unboxed-tuple type constructor"))
+             | otherwise
+             -> mk_apps (HsTyVar (getRdrName (tupleTyCon Unboxed n))) tys'
            ArrowT 
              | [x',y'] <- tys' -> returnL (HsFunTy x' y')
              | otherwise       -> mk_apps (HsTyVar (getRdrName funTyCon)) tys'
@@ -897,14 +873,7 @@ isBuiltInOcc ctxt_ns occ
 mk_uniq_occ :: OccName.NameSpace -> String -> Int# -> OccName.OccName
 mk_uniq_occ ns occ uniq 
   = OccName.mkOccName ns (occ ++ '[' : shows (mk_uniq uniq) "]")
-       -- The idea here is to make a name that 
-       -- a) the user could not possibly write, and
-       -- b) cannot clash with another NameU
-       -- Previously I generated an Exact RdrName with mkInternalName.
-       -- This works fine for local binders, but does not work at all for
-       -- top-level binders, which must have External Names, since they are
-       -- rapidly baked into data constructors and the like.  Baling out
-       -- and generating an unqualified RdrName here is the simple solution
+        -- See Note [Unique OccNames from Template Haskell]
 
 -- The packing and unpacking is rather turgid :-(
 mk_occ :: OccName.NameSpace -> String -> OccName.OccName
@@ -925,3 +894,17 @@ mk_uniq :: Int# -> Unique
 mk_uniq u = mkUniqueGrimily (I# u)
 \end{code}
 
+Note [Unique OccNames from Template Haskell]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The idea here is to make a name that 
+  a) the user could not possibly write (it has a "[" 
+     and letters or digits from the unique)
+  b) cannot clash with another NameU
+Previously I generated an Exact RdrName with mkInternalName.  This
+works fine for local binders, but does not work at all for top-level
+binders, which must have External Names, since they are rapidly baked
+into data constructors and the like.  Baling out and generating an
+unqualified RdrName here is the simple solution
+
+See also Note [Suppressing uniques in OccNames] in OccName, which
+suppresses the unique when opt_SuppressUniques is on.