Fix Trac #1814 (staging interaction in Template Haskell and GHCi), and add comments
[ghc-hetmet.git] / compiler / typecheck / TcSplice.lhs
index aa4c64c..9ec400d 100644 (file)
@@ -75,6 +75,83 @@ import Control.Monad ( liftM )
 import qualified Control.Exception  as Exception( userErrors )
 \end{code}
 
+Note [Template Haskell levels]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Imported things are impLevel (= 0)
+
+* In GHCi, variables bound by a previous command are treated
+  as impLevel, because we have bytecode for them.
+
+* Variables are bound at the "current level"
+
+* The current level starts off at topLevel (= 1)
+
+* The level is decremented by splicing $(..)
+              incremented by brackets [| |]
+              incremented by name-quoting 'f
+
+When a variable is used, we compare 
+       bind:  binding level, and
+       use:   current level at usage site
+
+  Generally
+       bind > use      Always error (bound later than used)
+                       [| \x -> $(f x) |]
+                       
+       bind = use      Always OK (bound same stage as used)
+                       [| \x -> $(f [| x |]) |]
+
+       bind < use      Inside brackets, it depends
+                       Inside splice, OK
+                       Inside neither, OK
+
+  For (bind < use) inside brackets, there are three cases:
+    - Imported things  OK      f = [| map |]
+    - Top-level things OK      g = [| f |]
+    - Non-top-level    Only if there is a liftable instance
+                               h = \(x:Int) -> [| x |]
+
+See Note [What is a top-level Id?]
+
+Note [Quoting names]
+~~~~~~~~~~~~~~~~~~~~
+A quoted name 'n is a bit like a quoted expression [| n |], except that we 
+have no cross-stage lifting (c.f. TcExpr.thBrackId).  So, after incrementing
+the use-level to account for the brackets, the cases are:
+
+       bind > use                      Error
+       bind = use                      OK
+       bind < use      
+               Imported things         OK
+               Top-level things        OK
+               Non-top-level           Error
+
+See Note [What is a top-level Id?] in TcEnv.  Examples:
+
+  f 'map       -- OK; also for top-level defns of this module
+
+  \x. f 'x     -- Not ok (whereas \x. f [| x |] might have been ok, by
+               --                               cross-stage lifting
+
+  \y. [| \x. $(f 'y) |]        -- Not ok (same reason)
+
+  [| \x. $(f 'x) |]    -- OK
+
+
+Note [What is a top-level Id?]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In the level-control criteria above, we need to know what a "top level Id" is.
+There are three kinds:
+  * Imported from another module               (GlobalId, ExternalName)
+  * Bound at the top level of this module      (ExternalName)
+  * In GHCi, bound by a previous stmt          (GlobalId)
+It's strange that there is no one criterion tht picks out all three, but that's
+how it is right now.  (The obvious thing is to give an ExternalName to GHCi Ids 
+bound in an earlier Stmt, but what module would you choose?  See 
+Note [Interactively-bound Ids in GHCi] in TcRnDriver.)
+
+The predicate we use is TcEnv.thTopLevelId.
+
 
 %************************************************************************
 %*                                                                     *
@@ -128,7 +205,7 @@ tcBracket brack res_ty
     getLIEVar                          `thenM` \ lie_var ->
 
     setStage (Brack next_level pending_splices lie_var) (
-       getLIE (tc_bracket brack)
+       getLIE (tc_bracket next_level brack)
     )                                  `thenM` \ (meta_ty, lie) ->
     tcSimplifyBracket lie              `thenM_`  
 
@@ -140,35 +217,34 @@ tcBracket brack res_ty
     returnM (noLoc (HsBracketOut brack pendings))
     }
 
-tc_bracket :: HsBracket Name -> TcM TcType
-tc_bracket (VarBr name)        -- Note [Quoting names]
+tc_bracket :: ThLevel -> HsBracket Name -> TcM TcType
+tc_bracket use_lvl (VarBr name)        -- Note [Quoting names]
   = do { thing <- tcLookup name
        ; case thing of
            AGlobal _ -> return ()
-           ATcId { tct_level = bind_lvl }
-               | isExternalName name   -- C.f isExternalName case of
-               -> keepAliveTc name     --     TcExpr.thBrackId
+           ATcId { tct_level = bind_lvl, tct_id = id }
+               | thTopLevelId id       -- C.f thTopLevelId case of
+               -> keepAliveTc id       --     TcExpr.thBrackId
                | otherwise
-               -> do { use_stage <- getStage
-                     ; checkTc (thLevel use_stage == bind_lvl)
+               -> do { checkTc (use_lvl == bind_lvl)
                                (quotedNameStageErr name) }
            other -> pprPanic "th_bracket" (ppr name)
 
        ; tcMetaTy nameTyConName        -- Result type is Var (not Q-monadic)
        }
 
-tc_bracket (ExpBr expr) 
+tc_bracket use_lvl (ExpBr expr) 
   = do { any_ty <- newFlexiTyVarTy liftedTypeKind
        ; tcMonoExpr expr any_ty
        ; tcMetaTy expQTyConName }
        -- Result type is Expr (= Q Exp)
 
-tc_bracket (TypBr typ) 
+tc_bracket use_lvl (TypBr typ) 
   = do { tcHsSigType ExprSigCtxt typ
        ; tcMetaTy typeQTyConName }
        -- Result type is Type (= Q Typ)
 
-tc_bracket (DecBr decls)
+tc_bracket use_lvl (DecBr decls)
   = do {  tcTopSrcDecls emptyModDetails decls
        -- Typecheck the declarations, dicarding the result
        -- We'll get all that stuff later, when we splice it in
@@ -179,7 +255,7 @@ tc_bracket (DecBr decls)
        -- Result type is Q [Dec]
     }
 
-tc_bracket (PatBr _)
+tc_bracket use_lvl (PatBr _)
   = failWithTc (ptext SLIT("Tempate Haskell pattern brackets are not supported yet"))
 
 quotedNameStageErr v 
@@ -187,19 +263,6 @@ quotedNameStageErr v
        , ptext SLIT("must be used at the same stage at which is is bound")]
 \end{code}
 
-Note [Quoting names]
-~~~~~~~~~~~~~~~~~~~~
-A quoted name is a bit like a quoted expression, except that we have no 
-cross-stage lifting (c.f. TcExpr.thBrackId).  Examples:
-
-  f 'map       -- OK; also for top-level defns of this module
-
-  \x. f 'x     -- Not ok (whereas \x. f [| x |] might have been ok, by
-               --                               cross-stage lifting
-
-  \y. [| \x. $(f 'y) |]        -- Not ok (same reason)
-
-  [| \x. $(f 'x) |]    -- OK
 
 %************************************************************************
 %*                                                                     *