On 13/02/12 21:13, David Terei wrote:

Originally you'd get this behaviour:

Prelude>  :set -XSafe
Prelude>  import System.IO.Unsafe

<no location info>:
     base:System.IO.Unsafe can't be safely imported! The module itself
isn't safe.

Prelude>  import Data.Char

<no location info>:
     base:System.IO.Unsafe can't be safely imported! The module itself
isn't safe.

Prelude Data.Char>

My understanding of all this code is:

* ghci maintains its own import context as GHC will drop the context
under some situations so ghci needs to do this for persistence
* checkAdd makes sure a module is OK to import (e.g exists, is byte
code form if required, [and now] is safe if required). At least that
seems the purpose of checkAdd to me but maybe I'm wrong as I find the
code structure strange.
* setGHCContext... functions take the context ghci maintains and loads
it into ghc.
* sometimes we want to load a bunch of imports as a batch operation.

Right, but I think what you're missing is that we sometimes need to keep modules in the context even when they can't currently be imported. There are a couple of comments about this - one on setGHCContextFromGHCiState and one in GhciMonad pointing to the relevant tickets.

My problem with the code is all the entry points. It feels as if the
code has just grown more complex for each case required and is quite
spaghetti like now.

The structure does have some logic behind it.  I'll try to explain:

 - At the top we have moduleCmd, which handles ":module".  It
   calls one of 3 functions in the next layer, depending on
   what form the command has.

 - addModulesToContext, remModulesFromContext, setContext
   correspond to the 3 forms of the :module command (note
   they are together in the source).  addImportToContext
   is also at this layer, corresponding to the "import"
   command.

   Note all these functions follow the same pattern: they
   - do some error checking,
   - modify the context in the state
   - call setGHCContextFromGHCiState

 - checkAdd is a utility used by the above layer (and also
   reused later); it checks whether a module can be imported,
   throwing an exception if not.

 - setGHCContextFromGHCiState is the lowest layer; see its
   comment.  Note it re-uses checkAdd, but in such a way
   that the exception is (deliberately) caught and not
   printed.

 - setGHCContext is used by the above.  It could be
   inlined to avoid confusion, except for the other call
   during initialisation, but as you'll see that could be
   replaced trivially.

Does that help? I see now, that the design which was so clear to me when I wrote the code is probably rather opaque to someone else. Maybe some clearer grouping in the source, or renaming of functions would help (obviously there are too many things called setXXXContext).

So there's an easy fix for your bug BTW. See the fix I made for #5836, you just need to do something else there.

Cheers,
        Simon


e.g the 'setContext' function takes two lists of imports, maps
'checkAdd' over them and saves the new context. It then calls
'setGHCContextFromGHCiState' which does basically (map over the input
with checkAdd) the same thing but calls into GHC at the end to set the
actual context.

What I want is one interface to this all. So a setContext method that
handles calling 'checkAdd'  and 'addNotSubsumed' and can handle batch
or individual additions. Then for all the :module, :import commands I
just call this 'setContext'. Based on how I've seen the code used this
seems quite doable.

Cheers,
David.






+checkAdd :: Bool ->    String ->    GHCi (InteractiveImport)
  checkAdd star mstr = do
    dflags<- getDynFlags
    case safeLanguageOn dflags of
@@ -1664,8 +1661,8 @@ checkAdd star mstr = do
                 s<- GHC.isModuleTrusted m
                 case s of
                   True  ->    return $ IIDecl (simpleImportDecl $ moduleName
m)
-                 False ->    ghcError $ CmdLineError $ "can't import " ++
mstr
-                                                 ++ " as it isn't
trusted."
+                 False ->    ghcError $ CmdLineError $
+                     "can't import " ++ mstr ++ " as it isn't trusted."

      False | star ->    do m<- wantInterpretedModule mstr
                         return $ IIModule m
@@ -1687,12 +1684,26 @@ checkAdd star mstr = do
  --
  setGHCContextFromGHCiState :: GHCi ()
  setGHCContextFromGHCiState = do
-  let ok (IIModule m) = checkAdd True  (moduleNameString (moduleName m))
-      ok (IIDecl   d) = checkAdd False (moduleNameString (unLoc
(ideclName d)))
    st<- getGHCiState
-  iidecls<- filterM (tryBool . ok) (transient_ctx st ++ remembered_ctx
st)
-  setGHCContext iidecls
+  goodTran<- filterM (tryBool . ok) $ transient_ctx st
+  goodRemb<- filterM (tryBool . ok) $ remembered_ctx st
+  -- drop bad imports so we don't keep replaying it to the user!
+  modifyGHCiState $ \s ->    s { transient_ctx  = goodTran }
+  modifyGHCiState $ \s ->    s { remembered_ctx = goodRemb }
+  setGHCContext (goodTran ++ goodRemb)

+  where
+    ok (IIModule m) = checkAdd True  (moduleNameString (moduleName m))
+    ok (IIDecl   d) = checkAdd False (moduleNameString (unLoc (ideclName
d)))
+
+setContext :: [String] ->    [String] ->    GHCi ()
+setContext starred not_starred = do
+  is1<- mapM (checkAdd True)  starred
+  is2<- mapM (checkAdd False) not_starred
+  let iss = foldr addNotSubsumed [] (is1++is2)
+  modifyGHCiState $ \st ->    st { remembered_ctx = iss, transient_ctx = []
}
+                                -- delete the transient context
+  setGHCContextFromGHCiState

  -- | Sets the GHC contexts to the given set of imports, adding a Prelude
  -- import if there isn't an explicit one already.
@@ -2745,7 +2756,7 @@ tryBool :: GHCi a ->    GHCi Bool
  tryBool m = do
      r<- ghciTry m
      case r of
-      Left _  ->    return False
+      Left e  ->    showException e>>    return False
        Right _ ->    return True

  --
----------------------------------------------------------------------------



_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc




_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to