[project @ 2005-02-25 13:06:31 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcSplice.lhs
index a9d632e..67b4e28 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, 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 )
@@ -40,12 +40,13 @@ import NameEnv              ( lookupNameEnv )
 import HscTypes                ( lookupType, ExternalPackageState(..) )
 import OccName
 import Var             ( Id, TyVar, idType )
-import Module          ( moduleUserString, mkModuleName )
+import Module          ( moduleUserString, mkModule )
 import TcRnMonad
 import IfaceEnv                ( lookupOrig )
-import Class           ( Class, classBigSig )
+import Class           ( Class, classExtraBigSig )
 import TyCon           ( TyCon, AlgTyConRhs(..), tyConTyVars, getSynTyConDefn, 
-                         isSynTyCon, isNewTyCon, tyConDataCons, algTyConRhs )
+                         isSynTyCon, isNewTyCon, tyConDataCons, algTyConRhs, isPrimTyCon, isFunTyCon,
+                         tyConArity, isUnLiftedTyCon )
 import DataCon         ( DataCon, dataConTyCon, dataConOrigArgTys, dataConStrictMarks, 
                          dataConName, dataConFieldLabels, dataConWrapId, dataConIsInfix, 
                          isVanillaDataCon )
@@ -397,7 +398,7 @@ To call runQ in the Tc monad, we need to make TcM an instance of Quasi:
 
 \begin{code}
 instance TH.Quasi (IOEnv (Env TcGblEnv TcLclEnv)) where
-  qNewName s = do  { u <- newUnique 
+  qNewName s = do { u <- newUnique 
                  ; let i = getKey u
                  ; return (TH.mkNameU s i) }
 
@@ -451,41 +452,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 (mkModuleName (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@(TH.Name occ TH.NameS) 
-  =  do { let rdr_name = mkRdrUnqual (OccName.mkOccFS ns occ_fs)
+       -- 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)
-
-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
+       -- 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
@@ -506,8 +503,7 @@ tcLookupTh name
        { (eps,hpt) <- getEpsAndHpt
        ; case lookupType hpt (eps_PTE eps) name of 
            Just thing -> return (AGlobal thing)
-           Nothing    -> do { traceIf (text "tcLookupGlobal" <+> ppr name)
-                            ; thing <- initIfaceTcRn (tcImportDecl name)
+           Nothing    -> do { thing <- tcImportDecl name
                             ; return (AGlobal thing) }
                -- Imported names should always be findable; 
                -- if not, we fail hard in tcImportDecl
@@ -540,8 +536,8 @@ reifyThing (AGlobal (AnId id))
            other            -> return (TH.VarI     v ty Nothing fix)
     }
 
-reifyThing (AGlobal (ATyCon tc))   = do { dec <- reifyTyCon tc;  return (TH.TyConI dec) }
-reifyThing (AGlobal (AClass cls))  = do { dec <- reifyClass cls; return (TH.ClassI dec) }
+reifyThing (AGlobal (ATyCon tc))  = reifyTyCon tc
+reifyThing (AGlobal (AClass cls)) = reifyClass cls
 reifyThing (AGlobal (ADataCon dc))
   = do { let name = dataConName dc
        ; ty <- reifyType (idType (dataConWrapId dc))
@@ -555,31 +551,33 @@ reifyThing (ATcId id _ _)
        ; fix <- reifyFixity (idName id)
        ; return (TH.VarI (reifyName id) ty2 Nothing fix) }
 
-reifyThing (ATyVar tv) 
-  = do { ty1 <- zonkTcTyVar tv
+reifyThing (ATyVar tv ty) 
+  = do { ty1 <- zonkTcType ty
        ; ty2 <- reifyType ty1
        ; return (TH.TyVarI (reifyName tv) ty2) }
 
 ------------------------------
-reifyTyCon :: TyCon -> TcM TH.Dec
+reifyTyCon :: TyCon -> TcM TH.Info
 reifyTyCon tc
+  | isFunTyCon tc  = return (TH.PrimTyConI (reifyName tc) 2              False)
+  | isPrimTyCon tc = return (TH.PrimTyConI (reifyName tc) (tyConArity tc) (isUnLiftedTyCon tc))
   | isSynTyCon tc
   = do { let (tvs, rhs) = getSynTyConDefn tc
        ; rhs' <- reifyType rhs
-       ; return (TH.TySynD (reifyName tc) (reifyTyVars tvs) rhs') }
+       ; return (TH.TyConI $ TH.TySynD (reifyName tc) (reifyTyVars tvs) rhs') }
 
 reifyTyCon tc
   = case algTyConRhs tc of
       NewTyCon data_con _ _ 
        -> do   { con <- reifyDataCon data_con
-               ; return (TH.NewtypeD [] (reifyName tc) (reifyTyVars (tyConTyVars tc))
-                                     con [{- Don't know about deriving -}]) }
+               ; return (TH.TyConI $ TH.NewtypeD [] (reifyName tc) (reifyTyVars (tyConTyVars tc))
+                                                 con [{- Don't know about deriving -}]) }
 
       DataTyCon mb_cxt cons _
        -> do   { cxt <- reifyCxt (mb_cxt `orElse` [])
                ; cons <- mapM reifyDataCon (tyConDataCons tc)
-               ; return (TH.DataD cxt (reifyName tc) (reifyTyVars (tyConTyVars tc))
-                                     cons [{- Don't know about deriving -}]) }
+               ; return (TH.TyConI $ TH.DataD cxt (reifyName tc) (reifyTyVars (tyConTyVars tc))
+                                              cons [{- Don't know about deriving -}]) }
 
 reifyDataCon :: DataCon -> TcM TH.Con
 reifyDataCon dc
@@ -604,13 +602,14 @@ reifyDataCon dc
                <+> quotes (ppr dc))
 
 ------------------------------
-reifyClass :: Class -> TcM TH.Dec
+reifyClass :: Class -> TcM TH.Info
 reifyClass cls 
   = do { cxt <- reifyCxt theta
        ; ops <- mapM reify_op op_stuff
-       ; return (TH.ClassD cxt (reifyName cls) (reifyTyVars tvs) ops) }
+       ; return (TH.ClassI $ TH.ClassD cxt (reifyName cls) (reifyTyVars tvs) fds' ops) }
   where
-    (tvs, theta, _, op_stuff) = classBigSig cls
+    (tvs, fds, theta, _, op_stuff) = classExtraBigSig cls
+    fds' = map reifyFunDep fds
     reify_op (op, _) = do { ty <- reifyType (idType op)
                          ; return (TH.SigD (reifyName op) ty) }
 
@@ -629,6 +628,9 @@ reifyType ty@(ForAllTy _ _) = do { cxt' <- reifyCxt cxt;
 reifyTypes = mapM reifyType
 reifyCxt   = mapM reifyPred
 
+reifyFunDep :: ([TyVar], [TyVar]) -> TH.FunDep
+reifyFunDep (xs, ys) = TH.FunDep (map reifyName xs) (map reifyName ys)
+
 reifyTyVars :: [TyVar] -> [TH.Name]
 reifyTyVars = map reifyName
 
@@ -646,6 +648,10 @@ reifyName :: NamedThing n => n -> TH.Name
 reifyName thing
   | isExternalName name = mk_varg mod occ_str
   | otherwise          = TH.mkNameU occ_str (getKey (getUnique name))
+       -- Many of the things we reify have local bindings, and 
+       -- NameL's aren't supposed to appear in binding positions, so
+       -- we use NameU.  When/if we start to reify nested things, that
+       -- have free variables, we may need to generate NameL's for them.
   where
     name    = getName thing
     mod     = moduleUserString (nameModule name)