[project @ 2005-05-19 07:58:35 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcSplice.lhs
index b51bfdc..4b2c7e5 100644 (file)
@@ -19,10 +19,10 @@ import qualified Language.Haskell.TH.Syntax as TH
 
 import HsSyn           ( HsBracket(..), HsExpr(..), HsSplice(..), LHsExpr, LHsDecl, 
                          HsType, LHsType )
-import Convert         ( convertToHsExpr, convertToHsDecls, convertToHsType )
+import Convert         ( convertToHsExpr, convertToHsDecls, convertToHsType, thRdrName )
 import RnExpr          ( rnLExpr )
-import RnEnv           ( lookupFixityRn, lookupSrcOcc_maybe )
-import RdrName         ( RdrName, mkRdrQual, mkRdrUnqual, lookupLocalRdrEnv )
+import RnEnv           ( lookupFixityRn, lookupSrcOcc_maybe, lookupImportedName )
+import RdrName         ( RdrName, mkRdrQual, mkRdrUnqual, lookupLocalRdrEnv, isSrcRdrName )
 import RnTypes         ( rnLHsType )
 import TcExpr          ( tcCheckRho, tcMonoExpr )
 import TcHsSyn         ( mkHsLet, zonkTopLExpr )
@@ -37,7 +37,7 @@ import TypeRep                ( Type(..), PredType(..), TyThing(..) ) -- For reification
 import Name            ( Name, NamedThing(..), nameOccName, nameModule, isExternalName, 
                          mkInternalName, nameIsLocalOrFrom )
 import NameEnv         ( lookupNameEnv )
-import HscTypes                ( lookupType, ExternalPackageState(..) )
+import HscTypes                ( lookupType, ExternalPackageState(..), emptyModDetails )
 import OccName
 import Var             ( Id, TyVar, idType )
 import Module          ( moduleUserString, mkModule )
@@ -46,7 +46,7 @@ import IfaceEnv               ( lookupOrig )
 import Class           ( Class, classExtraBigSig )
 import TyCon           ( TyCon, AlgTyConRhs(..), tyConTyVars, getSynTyConDefn, 
                          isSynTyCon, isNewTyCon, tyConDataCons, algTyConRhs, isPrimTyCon, isFunTyCon,
-                         tyConArity, isUnLiftedTyCon )
+                         tyConArity, tyConStupidTheta, isUnLiftedTyCon )
 import DataCon         ( DataCon, dataConTyCon, dataConOrigArgTys, dataConStrictMarks, 
                          dataConName, dataConFieldLabels, dataConWrapId, dataConIsInfix, 
                          isVanillaDataCon )
@@ -141,7 +141,7 @@ tc_bracket (TypBr typ)
        -- Result type is Type (= Q Typ)
 
 tc_bracket (DecBr decls)
-  = tcTopSrcDecls [{- no boot-names -}] decls          `thenM_`
+  = tcTopSrcDecls emptyModDetails decls                `thenM_`
        -- Typecheck the declarations, dicarding the result
        -- We'll get all that stuff later, when we splice it in
 
@@ -376,22 +376,29 @@ runMeta expr
        ; this_mod <- getModule
        ; let type_env = tcg_type_env tcg_env
              rdr_env  = tcg_rdr_env tcg_env
-       -- Wrap the compile-and-run in an exception-catcher
-       -- Compiling might fail if linking fails
-       -- Running might fail if it throws an exception
-       ; either_tval <- tryM $ do
-               {       -- Compile it
-                 hval <- ioToTcRn (HscMain.compileExpr 
+
+       -- Compile and link it; might fail if linking fails
+       ; either_hval <- tryM $ ioToTcRn $
+                        HscMain.compileExpr 
                                      hsc_env this_mod 
-                                     rdr_env type_env expr)
-                       -- Coerce it to Q t, and run it
-               ; TH.runQ (unsafeCoerce# hval) }
+                                     rdr_env type_env expr
+       ; case either_hval of {
+           Left exn   -> failWithTc (mk_msg "compile and link" exn) ;
+           Right hval -> do
+
+       {       -- Coerce it to Q t, and run it
+               -- Running might fail if it throws an exception of any kind (hence tryAllM)
+               -- including, say, a pattern-match exception in the code we are running
+         either_tval <- tryAllM (TH.runQ (unsafeCoerce# hval))
 
        ; case either_tval of
-             Left exn -> failWithTc (vcat [text "Exception when trying to run compile-time code:", 
-                                           nest 4 (vcat [text "Code:" <+> ppr expr,
-                                                     text ("Exn: " ++ Panic.showException exn)])])
-             Right v  -> returnM v }
+             Left exn -> failWithTc (mk_msg "run" exn)
+             Right v  -> returnM v
+       }}}
+  where
+    mk_msg s exn = vcat [text "Exception when trying to" <+> text s <+> text "compile-time code:",
+                        nest 2 (text (Panic.showException exn)),
+                        nest 2 (text "Code:" <+> ppr expr)]
 \end{code}
 
 To call runQ in the Tc monad, we need to make TcM an instance of Quasi:
@@ -452,44 +459,37 @@ reify th_name
        ; thing <- tcLookupTh name
                -- ToDo: this tcLookup could fail, which would give a
                --       rather unhelpful error message
+       ; traceIf (text "reify" <+> text (show th_name) <+> brackets (ppr_ns th_name) <+> ppr name)
        ; reifyThing thing
     }
+  where
+    ppr_ns (TH.Name _ (TH.NameG TH.DataName mod)) = text "data"
+    ppr_ns (TH.Name _ (TH.NameG TH.TcClsName mod)) = text "tc"
+    ppr_ns (TH.Name _ (TH.NameG TH.VarName mod)) = text "var"
 
 lookupThName :: TH.Name -> TcM Name
-lookupThName (TH.Name occ (TH.NameG th_ns mod))
-  = lookupOrig (mkModule (TH.modString mod))
-              (OccName.mkOccName ghc_ns (TH.occString occ))
-  where
-    ghc_ns = case th_ns of
-               TH.DataName  -> dataName
-               TH.TcClsName -> tcClsName
-               TH.VarName   -> varName
+lookupThName th_name
+  =  do { let rdr_name = thRdrName guessed_ns th_name
 
-lookupThName (TH.Name occ (TH.NameU uniq)) 
-  = return (mkInternalName (mk_uniq uniq) (OccName.mkOccFS bogus_ns occ_fs) noSrcLoc)
-  where
-    occ_fs = mkFastString (TH.occString occ)
-    bogus_ns = OccName.varName -- Not yet recorded in the TH name
-                               -- but only the unique matters
-
-lookupThName th_name@(TH.Name occ flavour)     -- NameS or NameQ
-  =  do { let occ = OccName.mkOccFS ns occ_fs
-             rdr_name = case flavour of
-                           TH.NameS   -> mkRdrUnqual occ
-                           TH.NameQ m -> mkRdrQual (mkModule (TH.modString m)) occ
+       -- Repeat much of lookupOccRn, becase we want
+       -- to report errors in a TH-relevant way
        ; rdr_env <- getLocalRdrEnv
        ; case lookupLocalRdrEnv rdr_env rdr_name of
-               Just name -> return name
-               Nothing   -> do
-       { mb_name <- lookupSrcOcc_maybe rdr_name
-       ; case mb_name of
-           Just name -> return name ;
-           Nothing   -> failWithTc (notInScope th_name)
-       }}
+           Just name -> return name
+           Nothing | not (isSrcRdrName rdr_name)       -- Exact, Orig
+                   -> lookupImportedName rdr_name
+                   | otherwise                         -- Unqual, Qual
+                   -> do { 
+                                 mb_name <- lookupSrcOcc_maybe rdr_name
+                         ; case mb_name of
+                             Just name -> return name
+                             Nothing   -> failWithTc (notInScope th_name) }
+       }
   where
-    ns | isLexCon occ_fs = OccName.dataName
-       | otherwise      = OccName.varName
-    occ_fs = mkFastString (TH.occString occ)
+       -- guessed_ns is the name space guessed from looking at the TH name
+    guessed_ns | isLexCon occ_fs = OccName.dataName
+              | otherwise       = OccName.varName
+    occ_fs = mkFastString (TH.nameBase th_name)
 
 tcLookupTh :: Name -> TcM TcTyThing
 -- This is a specialised version of TcEnv.tcLookup; specialised mainly in that
@@ -497,8 +497,8 @@ tcLookupTh :: Name -> TcM TcTyThing
 -- tcLookup, failure is a bug.
 tcLookupTh name
   = do { (gbl_env, lcl_env) <- getEnvs
-       ; case lookupNameEnv (tcl_env lcl_env) name of
-               Just thing -> returnM thing
+       ; case lookupNameEnv (tcl_env lcl_env) name of {
+               Just thing -> returnM thing;
                Nothing    -> do
        { if nameIsLocalOrFrom (tcg_mod gbl_env) name
          then  -- It's defined in this module
@@ -514,7 +514,7 @@ tcLookupTh name
                             ; return (AGlobal thing) }
                -- Imported names should always be findable; 
                -- if not, we fail hard in tcImportDecl
-    }}}
+    }}}}
 
 mk_uniq :: Int# -> Unique
 mk_uniq u = mkUniqueGrimily (I# u)
@@ -551,7 +551,7 @@ reifyThing (AGlobal (ADataCon dc))
        ; fix <- reifyFixity name
        ; return (TH.DataConI (reifyName name) ty (reifyName (dataConTyCon dc)) fix) }
 
-reifyThing (ATcId id _ _) 
+reifyThing (ATcId id _) 
   = do { ty1 <- zonkTcType (idType id) -- Make use of all the info we have, even
                                        -- though it may be incomplete
        ; ty2 <- reifyType ty1
@@ -576,12 +576,13 @@ reifyTyCon tc
 reifyTyCon tc
   = case algTyConRhs tc of
       NewTyCon data_con _ _ 
-       -> do   { con <- reifyDataCon data_con
-               ; return (TH.TyConI $ TH.NewtypeD [] (reifyName tc) (reifyTyVars (tyConTyVars tc))
+       -> do   { cxt <- reifyCxt (tyConStupidTheta tc)
+               ; con <- reifyDataCon data_con
+               ; return (TH.TyConI $ TH.NewtypeD cxt (reifyName tc) (reifyTyVars (tyConTyVars tc))
                                                  con [{- Don't know about deriving -}]) }
 
-      DataTyCon mb_cxt cons _
-       -> do   { cxt <- reifyCxt (mb_cxt `orElse` [])
+      DataTyCon cons _
+       -> do   { cxt <- reifyCxt (tyConStupidTheta tc)
                ; cons <- mapM reifyDataCon (tyConDataCons tc)
                ; return (TH.TyConI $ TH.DataD cxt (reifyName tc) (reifyTyVars (tyConTyVars tc))
                                               cons [{- Don't know about deriving -}]) }