[project @ 2002-11-20 12:34:42 by chak]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcSplice.lhs
index 9e1b806..31205e7 100644 (file)
@@ -1,24 +1,22 @@
-%
+2%
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 \section[TcSplice]{Template Haskell splices}
 
 \begin{code}
-module TcSplice( tcSpliceExpr, tcSpliceDecls ) where
+module TcSplice( tcSpliceExpr, tcSpliceDecls, tcBracket ) where
 
 #include "HsVersions.h"
 
 import HscMain         ( compileExpr )
-import TcRnDriver      ( importSupportingDecls )
+import TcRnDriver      ( importSupportingDecls, tcTopSrcDecls )
        -- These imports are the reason that TcSplice 
        -- is very high up the module hierarchy
 
-import CompManager     ( sandboxIO )
-       -- Ditto, but this one could be defined muchlower down
-
 import qualified Language.Haskell.THSyntax as Meta
 
 import HscTypes                ( HscEnv(..), GhciMode(..), PersistentCompilerState(..), unQualInScope )
+import HsSyn           ( HsBracket(..) )
 import Convert         ( convertToHsExpr, convertToHsDecls )
 import RnExpr          ( rnExpr )
 import RdrHsSyn                ( RdrNameHsExpr, RdrNameHsDecl )
@@ -26,14 +24,15 @@ import RnHsSyn              ( RenamedHsExpr )
 import TcExpr          ( tcMonoExpr )
 import TcHsSyn         ( TcExpr, TypecheckedHsExpr, mkHsLet, zonkTopExpr )
 import TcSimplify      ( tcSimplifyTop )
-import TcType          ( TcType )
+import TcType          ( TcType, openTypeKind, mkAppTy )
 import TcEnv           ( spliceOK, tcMetaTy )
 import TcRnTypes       ( TopEnv(..) )
+import TcMType         ( newTyVarTy )
 import Name            ( Name )
 import TcRnMonad
 
 import TysWiredIn      ( mkListTy )
-import PrelNames       ( exprTyConName, declTyConName )
+import DsMeta          ( exprTyConName, declTyConName, decTyConName, qTyConName )
 import Outputable
 import GHC.Base                ( unsafeCoerce# )       -- Should have a better home in the module hierarchy
 \end{code}
@@ -66,6 +65,29 @@ tcSpliceDecls e     = pprPanic "Cant do tcSpliceDecls without GHCi" (ppr e)
 %************************************************************************
 
 \begin{code}
+tcBracket :: HsBracket Name -> TcM TcType
+tcBracket (ExpBr expr) 
+  = newTyVarTy openTypeKind            `thenM` \ any_ty ->
+    tcMonoExpr expr any_ty             `thenM_`
+    tcMetaTy exprTyConName
+       -- Result type is Expr (= Q Exp)
+
+tcBracket (DecBr decls)
+  = tcTopSrcDecls decls                        `thenM_`
+    tcMetaTy decTyConName              `thenM` \ decl_ty ->
+    tcMetaTy qTyConName                        `thenM` \ q_ty ->
+    returnM (mkAppTy q_ty (mkListTy decl_ty))
+       -- Result type is Q [Dec]
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Splicing an expression}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
 tcSpliceExpr name expr res_ty
   = getStage           `thenM` \ level ->
     case spliceOK level of {
@@ -126,6 +148,9 @@ tcTopSplice expr res_ty
        expr2 = convertToHsExpr simple_expr 
     in
     traceTc (text "Got result" <+> ppr expr2)  `thenM_`
+
+    showSplice "expression" 
+              zonked_q_expr (ppr expr2)        `thenM_`
     initRn SourceMode (rnExpr expr2)           `thenM` \ (exp3, fvs) ->
     importSupportingDecls fvs                  `thenM` \ env ->
 
@@ -142,9 +167,10 @@ tcTopSplice expr res_ty
 \begin{code}
 -- Always at top level
 tcSpliceDecls expr
-  = tcMetaTy declTyConName             `thenM` \ meta_dec_ty ->
+  = tcMetaTy decTyConName              `thenM` \ meta_dec_ty ->
+    tcMetaTy qTyConName                `thenM` \ meta_q_ty ->
     setStage topSpliceStage (
-       getLIE (tcMonoExpr expr (mkListTy meta_dec_ty))
+       getLIE (tcMonoExpr expr (mkAppTy meta_q_ty (mkListTy meta_dec_ty)))
     )                                  `thenM` \ (expr', lie) ->
        -- Solve the constraints
     tcSimplifyTop lie                  `thenM` \ const_binds ->
@@ -161,6 +187,9 @@ tcSpliceDecls expr
        decls :: [RdrNameHsDecl]
        decls = convertToHsDecls simple_expr 
     in
+    traceTc (text "Got result" <+> vcat (map ppr decls))       `thenM_`
+    showSplice "declarations"
+              zonked_q_expr (vcat (map ppr decls))             `thenM_`
     returnM decls
 \end{code}
 
@@ -176,13 +205,18 @@ runMetaE :: TypecheckedHsExpr     -- Of type (Q Exp)
         -> TcM Meta.Exp        -- Of type Exp
 runMetaE e = runMeta e
 
-runMetaD :: TypecheckedHsExpr  -- Of type (Q [Dec]
+runMetaD :: TypecheckedHsExpr  -- Of type Q [Dec]
         -> TcM [Meta.Dec]      -- Of type [Dec]
 runMetaD e = runMeta e
 
-runMeta :: TypecheckedHsExpr   -- Of type (Q t)
+-- Warning: if Q is anything other than IO, we need to change this
+tcRunQ :: Meta.Q a -> TcM a
+tcRunQ thing = ioToTcRn thing
+
+
+runMeta :: TypecheckedHsExpr   -- Of type X
        -> TcM t                -- Of type t
-runMeta expr :: TcM t
+runMeta expr
   = getTopEnv          `thenM` \ top_env ->
     getEps             `thenM` \ eps ->
     getNameCache       `thenM` \ name_cache -> 
@@ -198,25 +232,16 @@ runMeta expr :: TcM t
 
        print_unqual = unQualInScope rdr_env
     in
-    if (ghci_mode == OneShot) then
-       failWithTc (ptext SLIT("You must use --make or --interactive to run splice expressions"))
-       -- The reason for this is that the demand-linker doesn't have
-       -- enough information available to link all the things that
-       -- are needed when you try to run a splice
-    else
-    ioToTcRn (do {
-       -- Warning: if Q is anything other than IO, we may need to wrap 
-       -- the expression 'expr' in a runQ before compiling it
-      hval <- HscMain.compileExpr hsc_env pcs this_mod print_unqual expr
-
-       -- hval :: HValue
-       -- Need to coerce it to IO t
-    ; sandboxIO (unsafeCoerce# hval :: IO t) })        `thenM` \ either_tval ->
+    ioToTcRn (HscMain.compileExpr hsc_env pcs this_mod 
+                                 print_unqual expr) `thenM` \ hval ->
+
+    tryM (tcRunQ (unsafeCoerce# hval)) `thenM` \ either_tval ->
 
     case either_tval of
-       Left err -> failWithTc (vcat [text "Exception when running compiled-time code:", 
-                                     nest 4 (text (show err))])
-       Right v  -> returnM v
+         Left exn -> failWithTc (vcat [text "Exception when running compile-time code:", 
+                                       nest 4 (vcat [text "Code:" <+> ppr expr,
+                                                     text ("Exn: " ++ show exn)])])
+         Right v  -> returnM v
 \end{code}
 
 
@@ -315,6 +340,14 @@ Two successive brackets aren't allowed
 %************************************************************************
 
 \begin{code}
+showSplice :: String -> TypecheckedHsExpr -> SDoc -> TcM ()
+showSplice what before after
+  = getSrcLocM         `thenM` \ loc ->
+    traceSplice (vcat [ppr loc <> colon <+> text "Splicing" <+> text what, 
+                      nest 2 (sep [nest 2 (ppr before),
+                                   text "======>",
+                                   nest 2 after])])
+
 illegalSplice level
   = ptext SLIT("Illegal splice at level") <+> ppr level