diff options
Diffstat (limited to 'compiler/GHC/Runtime/Eval.hs')
-rw-r--r-- | compiler/GHC/Runtime/Eval.hs | 305 |
1 files changed, 162 insertions, 143 deletions
diff --git a/compiler/GHC/Runtime/Eval.hs b/compiler/GHC/Runtime/Eval.hs index e4f4de3fc5..e48ec1a93b 100644 --- a/compiler/GHC/Runtime/Eval.hs +++ b/compiler/GHC/Runtime/Eval.hs @@ -13,6 +13,7 @@ -- ----------------------------------------------------------------------------- module GHC.Runtime.Eval ( + GhciMonad(..), modifyInteractiveContextM, Resume(..), History(..), execStmt, execStmt', ExecOptions(..), execOptions, ExecResult(..), resumeExec, runDecls, runDeclsWithLocation, runParsedDecls, @@ -47,6 +48,7 @@ module GHC.Runtime.Eval ( import GHC.Prelude import GHC.Driver.Monad +import GHC.Driver.Monad.Interactive import GHC.Driver.Main import GHC.Driver.Errors.Types ( hoistTcRnMessage ) import GHC.Driver.Env @@ -140,8 +142,8 @@ import GHC.Unit.Env -- ----------------------------------------------------------------------------- -- running a statement interactively -getResumeContext :: GhcMonad m => m [Resume] -getResumeContext = withSession (return . ic_resume . hsc_IC) +getResumeContext :: GhciMonad m => m [Resume] +getResumeContext = ic_resume <$> getInteractiveContext mkHistory :: HscEnv -> ForeignHValue -> BreakInfo -> History mkHistory hsc_env hval bi = History hval bi (findEnclosingDecls hsc_env bi) @@ -168,11 +170,10 @@ findEnclosingDecls hsc_env (BreakInfo modl ix) = in modBreaks_decls mb ! ix -- | Update fixity environment in the current interactive context. -updateFixityEnv :: GhcMonad m => FixityEnv -> m () +updateFixityEnv :: GhciMonad m => FixityEnv -> m () updateFixityEnv fix_env = do - hsc_env <- getSession - let ic = hsc_IC hsc_env - setSession $ hsc_env { hsc_IC = ic { ic_fix_env = fix_env } } + ic <- getInteractiveContext + setInteractiveContext $ ic { ic_fix_env = fix_env } -- ----------------------------------------------------------------------------- -- execStmt @@ -188,16 +189,17 @@ execOptions = ExecOptions -- | Run a statement in the current interactive context. execStmt - :: GhcMonad m + :: GhciMonad m => String -- ^ a statement (bind or expression) -> ExecOptions -> m ExecResult execStmt input exec_opts@ExecOptions{..} = do hsc_env <- getSession + ic <- getInteractiveContext mb_stmt <- liftIO $ - runInteractiveHsc hsc_env $ + runInteractiveHsc hsc_env ic $ hscParseStmtWithLocation execSourceFile execLineNumber input case mb_stmt of @@ -208,18 +210,19 @@ execStmt input exec_opts@ExecOptions{..} = do -- | Like `execStmt`, but takes a parsed statement as argument. Useful when -- doing preprocessing on the AST before execution, e.g. in GHCi (see -- GHCi.UI.runStmt). -execStmt' :: GhcMonad m => GhciLStmt GhcPs -> String -> ExecOptions -> m ExecResult +execStmt' :: GhciMonad m => GhciLStmt GhcPs -> String -> ExecOptions -> m ExecResult execStmt' stmt stmt_text ExecOptions{..} = do hsc_env <- getSession + ic <- getInteractiveContext let interp = hscInterp hsc_env -- Turn off -fwarn-unused-local-binds when running a statement, to hide -- warnings about the implicit bindings we introduce. - let ic = hsc_IC hsc_env -- use the interactive dflags - idflags' = ic_dflags ic `wopt_unset` Opt_WarnUnusedLocalBinds - hsc_env' = mkInteractiveHscEnv (hsc_env{ hsc_IC = ic{ ic_dflags = idflags' }}) + let idflags' = ic_dflags ic `wopt_unset` Opt_WarnUnusedLocalBinds + ic' = ic { ic_dflags = idflags' } + hsc_env' = mkInteractiveHscEnv hsc_env ic' - r <- liftIO $ hscParsedStmt hsc_env' stmt + r <- liftIO $ hscParsedStmt hsc_env' ic' stmt case r of Nothing -> @@ -234,37 +237,39 @@ execStmt' stmt stmt_text ExecOptions{..} = do let eval_opts = initEvalOpts idflags' (isStep execSingleStep) evalStmt interp eval_opts (execWrap hval) - let ic = hsc_IC hsc_env - bindings = (ic_tythings ic, ic_gre_cache ic) + ic <- getInteractiveContext + let bindings = (ic_tythings ic, ic_gre_cache ic) size = ghciHistSize idflags' handleRunStatus execSingleStep stmt_text bindings ids status (emptyHistory size) -runDecls :: GhcMonad m => String -> m [Name] +runDecls :: GhciMonad m => String -> m [Name] runDecls = runDeclsWithLocation "<interactive>" 1 -- | Run some declarations and return any user-visible names that were brought -- into scope. -runDeclsWithLocation :: GhcMonad m => String -> Int -> String -> m [Name] +runDeclsWithLocation :: GhciMonad m => String -> Int -> String -> m [Name] runDeclsWithLocation source line_num input = do hsc_env <- getSession - decls <- liftIO (hscParseDeclsWithLocation hsc_env source line_num input) + ic <- getInteractiveContext + decls <- liftIO (hscParseDeclsWithLocation hsc_env ic source line_num input) runParsedDecls decls -- | Like `runDeclsWithLocation`, but takes parsed declarations as argument. -- Useful when doing preprocessing on the AST before execution, e.g. in GHCi -- (see GHCi.UI.runStmt). -runParsedDecls :: GhcMonad m => [LHsDecl GhcPs] -> m [Name] +runParsedDecls :: GhciMonad m => [LHsDecl GhcPs] -> m [Name] runParsedDecls decls = do hsc_env <- getSession - (tyThings, ic) <- liftIO (hscParsedDecls hsc_env decls) + ic0 <- getInteractiveContext + (tyThings, ic) <- liftIO (hscParsedDecls hsc_env ic0 decls) - setSession $ hsc_env { hsc_IC = ic } + setInteractiveContext ic hsc_env <- getSession - hsc_env' <- liftIO $ rttiEnvironment hsc_env - setSession hsc_env' + ic1 <- liftIO $ rttiEnvironment hsc_env ic + setInteractiveContext ic1 return $ filter (not . isDerivedOccName . nameOccName) -- For this filter, see Note [What to show to users] $ map getName tyThings @@ -279,7 +284,7 @@ them. The relevant predicate is OccName.isDerivedOccName. See #11051 for more background and examples. -} -withVirtualCWD :: GhcMonad m => m a -> m a +withVirtualCWD :: GhciMonad m => m a -> m a withVirtualCWD m = do hsc_env <- getSession @@ -288,7 +293,7 @@ withVirtualCWD m = do case interpInstance <$> hsc_interp hsc_env of Just (ExternalInterp {}) -> m _ -> do - let ic = hsc_IC hsc_env + ic <- getInteractiveContext let set_cwd = do dir <- liftIO $ getCurrentDirectory case ic_cwd ic of @@ -298,20 +303,21 @@ withVirtualCWD m = do reset_cwd orig_dir = do virt_dir <- liftIO $ getCurrentDirectory - hsc_env <- getSession - let old_IC = hsc_IC hsc_env - setSession hsc_env{ hsc_IC = old_IC{ ic_cwd = Just virt_dir } } + old_ic <- getInteractiveContext + setInteractiveContext old_ic{ ic_cwd = Just virt_dir } liftIO $ setCurrentDirectory orig_dir MC.bracket set_cwd reset_cwd $ \_ -> m -parseImportDecl :: GhcMonad m => String -> m (ImportDecl GhcPs) -parseImportDecl expr = withSession $ \hsc_env -> liftIO $ hscImport hsc_env expr +parseImportDecl :: GhciMonad m => String -> m (ImportDecl GhcPs) +parseImportDecl expr = withSession $ \hsc_env -> do + ic <- getInteractiveContext + liftIO $ hscImport hsc_env ic expr emptyHistory :: Int -> BoundedList History emptyHistory size = nilBL size -handleRunStatus :: GhcMonad m +handleRunStatus :: GhciMonad m => SingleStep -> String -> ResumeBindings -> [Id] @@ -369,8 +375,9 @@ handleRunStatus step expr bindings final_ids status history modl = mi_module (hm_iface hmi) bp | is_exception = Nothing | otherwise = Just (BreakInfo modl ix) - (hsc_env1, names, span, decl) <- liftIO $ - bindLocalsAtBreakpoint hsc_env apStack_fhv bp + ictxt0 <- getInteractiveContext + (ictxt1, names, span, decl) <- liftIO $ + bindLocalsAtBreakpoint hsc_env ictxt0 apStack_fhv bp let resume = Resume { resumeStmt = expr, resumeContext = resume_ctxt_fhv @@ -381,20 +388,21 @@ handleRunStatus step expr bindings final_ids status history , resumeDecl = decl , resumeCCS = ccs , resumeHistoryIx = 0 } - hsc_env2 = pushResume hsc_env1 resume + ictxt2 = pushResume ictxt1 resume - setSession hsc_env2 + setInteractiveContext ictxt2 return (ExecBreak names bp) -- Completed successfully | EvalComplete allocs (EvalSuccess hvals) <- status = do hsc_env <- getSession - let final_ic = extendInteractiveContextWithIds (hsc_IC hsc_env) final_ids + ic <- getInteractiveContext + let final_ic = extendInteractiveContextWithIds ic final_ids final_names = map getName final_ids interp = hscInterp hsc_env liftIO $ Loader.extendLoadedEnv interp (zip final_names hvals) - hsc_env' <- liftIO $ rttiEnvironment hsc_env{hsc_IC=final_ic} - setSession hsc_env' + ic' <- liftIO $ rttiEnvironment hsc_env final_ic + setInteractiveContext ic' return (ExecComplete (Right final_names) allocs) -- Completed with an exception @@ -407,13 +415,13 @@ handleRunStatus step expr bindings final_ids status history #endif -resumeExec :: GhcMonad m => (SrcSpan->Bool) -> SingleStep -> Maybe Int +resumeExec :: GhciMonad m => (SrcSpan->Bool) -> SingleStep -> Maybe Int -> m ExecResult resumeExec canLogSpan step mbCnt = do hsc_env <- getSession - let ic = hsc_IC hsc_env - resume = ic_resume ic + ic <- getInteractiveContext + let resume = ic_resume ic case resume of [] -> liftIO $ @@ -426,7 +434,7 @@ resumeExec canLogSpan step mbCnt ic' = ic { ic_tythings = resume_tmp_te, ic_gre_cache = resume_gre_cache, ic_resume = rs } - setSession hsc_env{ hsc_IC = ic' } + setInteractiveContext ic' -- remove any bindings created since the breakpoint from the -- linker's environment @@ -472,16 +480,17 @@ setupBreakpoint hsc_env brkInfo cnt = do _ <- liftIO $ GHCi.storeBreakpoint interp breakarray ix cnt pure () -back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan, String) +back :: GhciMonad m => Int -> m ([Name], Int, SrcSpan, String) back n = moveHist (+n) -forward :: GhcMonad m => Int -> m ([Name], Int, SrcSpan, String) +forward :: GhciMonad m => Int -> m ([Name], Int, SrcSpan, String) forward n = moveHist (subtract n) -moveHist :: GhcMonad m => (Int -> Int) -> m ([Name], Int, SrcSpan, String) +moveHist :: GhciMonad m => (Int -> Int) -> m ([Name], Int, SrcSpan, String) moveHist fn = do hsc_env <- getSession - case ic_resume (hsc_IC hsc_env) of + ic <- getInteractiveContext + case ic_resume ic of [] -> liftIO $ throwGhcExceptionIO (ProgramError "not stopped at a breakpoint") (r:rs) -> do @@ -496,13 +505,13 @@ moveHist fn = do let update_ic apStack mb_info = do - (hsc_env1, names, span, decl) <- - liftIO $ bindLocalsAtBreakpoint hsc_env apStack mb_info - let ic = hsc_IC hsc_env1 - r' = r { resumeHistoryIx = new_ix } - ic' = ic { ic_resume = r':rs } + ic <- getInteractiveContext + (ic1, names, span, decl) <- + liftIO $ bindLocalsAtBreakpoint hsc_env ic apStack mb_info + let r' = r { resumeHistoryIx = new_ix } + ic2 = ic1 { ic_resume = r':rs } - setSession hsc_env1{ hsc_IC = ic' } + setInteractiveContext ic2 return (names, new_ix, span, decl) @@ -527,34 +536,34 @@ result_fs = fsLit "_result" bindLocalsAtBreakpoint :: HscEnv + -> InteractiveContext -> ForeignHValue -> Maybe BreakInfo - -> IO (HscEnv, [Name], SrcSpan, String) + -> IO (InteractiveContext, [Name], SrcSpan, String) -- Nothing case: we stopped when an exception was raised, not at a -- breakpoint. We have no location information or local variables to -- bind, all we can do is bind a local variable to the exception -- value. -bindLocalsAtBreakpoint hsc_env apStack Nothing = do +bindLocalsAtBreakpoint hsc_env ictxt0 apStack Nothing = do let exn_occ = mkVarOccFS (fsLit "_exception") span = mkGeneralSrcSpan (fsLit "<unknown>") - exn_name <- newInteractiveBinder hsc_env exn_occ span + exn_name <- newInteractiveBinder hsc_env ictxt0 exn_occ span let e_fs = fsLit "e" e_name = mkInternalName (getUnique e_fs) (mkTyVarOccFS e_fs) span e_tyvar = mkRuntimeUnkTyVar e_name liftedTypeKind exn_id = Id.mkVanillaGlobal exn_name (mkTyVarTy e_tyvar) - ictxt0 = hsc_IC hsc_env ictxt1 = extendInteractiveContextWithIds ictxt0 [exn_id] interp = hscInterp hsc_env -- Loader.extendLoadedEnv interp [(exn_name, apStack)] - return (hsc_env{ hsc_IC = ictxt1 }, [exn_name], span, "<exception thrown>") + return (ictxt1, [exn_name], span, "<exception thrown>") -- Just case: we stopped at a breakpoint, we have information about the location -- of the breakpoint and the free variables of the expression. -bindLocalsAtBreakpoint hsc_env apStack_fhv (Just BreakInfo{..}) = do +bindLocalsAtBreakpoint hsc_env ictxt0 apStack_fhv (Just BreakInfo{..}) = do let hmi = expectJust "bindLocalsAtBreakpoint" $ lookupHpt (hsc_HPT hsc_env) (moduleName breakInfo_module) @@ -594,7 +603,7 @@ bindLocalsAtBreakpoint hsc_env apStack_fhv (Just BreakInfo{..}) = do map (substTy tv_subst . idType) filtered_ids new_ids <- zipWith3M mkNewId occs'' tidy_tys filtered_ids - result_name <- newInteractiveBinder hsc_env (mkVarOccFS result_fs) span + result_name <- newInteractiveBinder hsc_env ictxt0 (mkVarOccFS result_fs) span let result_id = Id.mkVanillaGlobal result_name (substTy tv_subst result_ty) @@ -602,15 +611,14 @@ bindLocalsAtBreakpoint hsc_env apStack_fhv (Just BreakInfo{..}) = do final_ids | result_ok = result_id : new_ids | otherwise = new_ids - ictxt0 = hsc_IC hsc_env ictxt1 = extendInteractiveContextWithIds ictxt0 final_ids names = map idName new_ids let fhvs = catMaybes mb_hValues Loader.extendLoadedEnv interp (zip names fhvs) when result_ok $ Loader.extendLoadedEnv interp [(result_name, apStack_fhv)] - hsc_env1 <- rttiEnvironment hsc_env{ hsc_IC = ictxt1 } - return (hsc_env1, if result_ok then result_name:names else names, span, decl) + ictxt2 <- rttiEnvironment hsc_env ictxt1 + return (ictxt2, if result_ok then result_name:names else names, span, decl) where -- We need a fresh Unique for each Id we bind, because the linker -- state is single-threaded and otherwise we'd spam old bindings @@ -618,7 +626,7 @@ bindLocalsAtBreakpoint hsc_env apStack_fhv (Just BreakInfo{..}) = do -- saved/restored, but not the linker state. See #1743, test break026. mkNewId :: OccName -> Type -> Id -> IO Id mkNewId occ ty old_id - = do { name <- newInteractiveBinder hsc_env occ (getSrcSpan old_id) + = do { name <- newInteractiveBinder hsc_env ictxt0 occ (getSrcSpan old_id) ; return (Id.mkVanillaGlobalWithInfo name ty (idInfo old_id)) } newTyVars :: UniqSupply -> [TcTyVar] -> TCvSubst @@ -648,31 +656,31 @@ bindLocalsAtBreakpoint hsc_env apStack_fhv (Just BreakInfo{..}) = do joinOccs = zipWithEqual "bindLocalsAtBreakpoint" joinOcc joinOcc mbV oc = (\(a,b) c -> (a,b,c)) <$> mbV <*> pure oc -rttiEnvironment :: HscEnv -> IO HscEnv -rttiEnvironment hsc_env@HscEnv{hsc_IC=ic} = do - let tmp_ids = [id | AnId id <- ic_tythings ic] +rttiEnvironment :: HscEnv -> InteractiveContext -> IO InteractiveContext +rttiEnvironment hsc_env ic0 = do + let tmp_ids = [id | AnId id <- ic_tythings ic0] incompletelyTypedIds = [id | id <- tmp_ids , not $ noSkolems id , (occNameFS.nameOccName.idName) id /= result_fs] - foldM improveTypes hsc_env (map idName incompletelyTypedIds) + foldM (improveTypes hsc_env) ic0 (map idName incompletelyTypedIds) where noSkolems = noFreeVarsOfType . idType - improveTypes hsc_env@HscEnv{hsc_IC=ic} name = do + improveTypes hsc_env ic name = do let tmp_ids = [id | AnId id <- ic_tythings ic] Just id = find (\i -> idName i == name) tmp_ids if noSkolems id - then return hsc_env + then return ic else do - mb_new_ty <- reconstructType hsc_env 10 id + mb_new_ty <- reconstructType hsc_env ic 10 id let old_ty = idType id case mb_new_ty of - Nothing -> return hsc_env + Nothing -> return ic Just new_ty -> do case improveRTTIType hsc_env old_ty new_ty of Nothing -> return $ warnPprTrace True (":print failed to calculate the " - ++ "improvement for a type") empty hsc_env + ++ "improvement for a type") empty ic Just subst -> do let logger = hsc_logger hsc_env putDumpFileMaybe logger Opt_D_dump_rtti "RTTI" @@ -680,14 +688,12 @@ rttiEnvironment hsc_env@HscEnv{hsc_IC=ic} = do (fsep [text "RTTI Improvement for", ppr id, equals, ppr subst]) - let ic' = substInteractiveContext ic subst - return hsc_env{hsc_IC=ic'} + pure $ substInteractiveContext ic subst -pushResume :: HscEnv -> Resume -> HscEnv -pushResume hsc_env resume = hsc_env { hsc_IC = ictxt1 } - where - ictxt0 = hsc_IC hsc_env - ictxt1 = ictxt0 { ic_resume = resume : ic_resume ictxt0 } +pushResume :: InteractiveContext -> Resume -> InteractiveContext +pushResume ictxt0 resume = ictxt0 + { ic_resume = resume : ic_resume ictxt0 + } {- @@ -721,29 +727,29 @@ pushResume hsc_env resume = hsc_env { hsc_IC = ictxt1 } -- ----------------------------------------------------------------------------- -- Abandoning a resume context -abandon :: GhcMonad m => m Bool +abandon :: GhciMonad m => m Bool abandon = do hsc_env <- getSession - let ic = hsc_IC hsc_env - resume = ic_resume ic + ic <- getInteractiveContext + let resume = ic_resume ic interp = hscInterp hsc_env case resume of [] -> return False r:rs -> do - setSession hsc_env{ hsc_IC = ic { ic_resume = rs } } + setInteractiveContext ic{ ic_resume = rs } liftIO $ abandonStmt interp (resumeContext r) return True -abandonAll :: GhcMonad m => m Bool +abandonAll :: GhciMonad m => m Bool abandonAll = do hsc_env <- getSession - let ic = hsc_IC hsc_env - resume = ic_resume ic + ic <- getInteractiveContext + let resume = ic_resume ic interp = hscInterp hsc_env case resume of [] -> return False rs -> do - setSession hsc_env{ hsc_IC = ic { ic_resume = [] } } + setInteractiveContext ic{ ic_resume = [] } liftIO $ mapM_ (abandonStmt interp. resumeContext) rs return True @@ -783,30 +789,33 @@ fromListBL bound l = BL (length l) bound l [] -- We retain in scope all the things defined at the prompt, and kept -- in ic_tythings. (Indeed, they shadow stuff from ic_imports.) -setContext :: GhcMonad m => [InteractiveImport] -> m () +setContext :: GhciMonad m => [InteractiveImport] -> m () setContext imports = do { hsc_env <- getSession ; let dflags = hsc_dflags hsc_env - ; all_env_err <- liftIO $ findGlobalRdrEnv hsc_env imports + ; old_ic <- getInteractiveContext + ; all_env_err <- liftIO $ findGlobalRdrEnv hsc_env old_ic imports ; case all_env_err of Left (mod, err) -> liftIO $ throwGhcExceptionIO (formatError dflags mod err) Right all_env -> do { - ; let old_ic = hsc_IC hsc_env - !final_gre_cache = ic_gre_cache old_ic `replaceImportEnv` all_env - ; setSession - hsc_env{ hsc_IC = old_ic { ic_imports = imports - , ic_gre_cache = final_gre_cache }}}} + ; let !final_gre_cache = ic_gre_cache old_ic `replaceImportEnv` all_env + ; setInteractiveContext + old_ic { ic_imports = imports + , ic_gre_cache = final_gre_cache + } + }} where formatError dflags mod err = ProgramError . showSDoc dflags $ text "Cannot add module" <+> ppr mod <+> text "to context:" <+> text err -findGlobalRdrEnv :: HscEnv -> [InteractiveImport] +findGlobalRdrEnv :: HscEnv -> InteractiveContext + -> [InteractiveImport] -> IO (Either (ModuleName, String) GlobalRdrEnv) -- Compute the GlobalRdrEnv for the interactive context -findGlobalRdrEnv hsc_env imports - = do { idecls_env <- hscRnImportDecls hsc_env idecls +findGlobalRdrEnv hsc_env ic imports + = do { idecls_env <- hscRnImportDecls hsc_env ic idecls -- This call also loads any orphan modules ; return $ case partitionEithers (map mkEnv imods) of ([], imods_env) -> Right (foldr plusGlobalRdrEnv idecls_env imods_env) @@ -834,9 +843,8 @@ mkTopLevEnv hpt modl -- | Get the interactive evaluation context, consisting of a pair of the -- set of modules from which we take the full top-level scope, and the set -- of modules from which we take just the exports respectively. -getContext :: GhcMonad m => m [InteractiveImport] -getContext = withSession $ \HscEnv{ hsc_IC=ic } -> - return (ic_imports ic) +getContext :: GhciMonad m => m [InteractiveImport] +getContext = ic_imports <$> getInteractiveContext -- | Returns @True@ if the specified module is interpreted, and hence has -- its full top-level scope available. @@ -853,15 +861,16 @@ moduleIsInterpreted modl = withSession $ \h -> -- are in scope (qualified or otherwise). Otherwise we list a whole lot too many! -- The exact choice of which ones to show, and which to hide, is a judgement call. -- (see #1581) -getInfo :: GhcMonad m => Bool -> Name +getInfo :: GhciMonad m => Bool -> Name -> m (Maybe (TyThing,Fixity,[ClsInst],[FamInst], SDoc)) getInfo allInfo name = withSession $ \hsc_env -> - do mb_stuff <- liftIO $ hscTcRnGetInfo hsc_env name + do ic <- getInteractiveContext + mb_stuff <- liftIO $ hscTcRnGetInfo hsc_env ic name case mb_stuff of Nothing -> return Nothing Just (thing, fixity, cls_insts, fam_insts, docs) -> do - let rdr_env = icReaderEnv (hsc_IC hsc_env) + let rdr_env = icReaderEnv ic -- Filter the instances based on whether the constituent names of their -- instance heads are all in scope. @@ -883,16 +892,17 @@ getInfo allInfo name | otherwise = True -- | Returns all names in scope in the current interactive context -getNamesInScope :: GhcMonad m => m [Name] -getNamesInScope = withSession $ \hsc_env -> - return (map greMangledName (globalRdrEnvElts (icReaderEnv (hsc_IC hsc_env)))) +getNamesInScope :: GhciMonad m => m [Name] +getNamesInScope = + map greMangledName . globalRdrEnvElts . icReaderEnv + <$> getInteractiveContext -- | Returns all 'RdrName's in scope in the current interactive -- context, excluding any that are internally-generated. -getRdrNamesInScope :: GhcMonad m => m [RdrName] -getRdrNamesInScope = withSession $ \hsc_env -> do +getRdrNamesInScope :: GhciMonad m => m [RdrName] +getRdrNamesInScope = do + ic <- getInteractiveContext let - ic = hsc_IC hsc_env gbl_rdrenv = icReaderEnv ic gbl_names = concatMap greRdrNames $ globalRdrEnvElts gbl_rdrenv -- Exclude internally generated names; see e.g. #11328 @@ -901,13 +911,15 @@ getRdrNamesInScope = withSession $ \hsc_env -> do -- | Parses a string as an identifier, and returns the list of 'Name's that -- the identifier can refer to in the current interactive context. -parseName :: GhcMonad m => String -> m [Name] -parseName str = withSession $ \hsc_env -> liftIO $ - do { lrdr_name <- hscParseIdentifier hsc_env str - ; hscTcRnLookupRdrName hsc_env lrdr_name } +parseName :: GhciMonad m => String -> m [Name] +parseName str = withSession $ \hsc_env -> do + ic <- getInteractiveContext + liftIO $ do + lrdr_name <- hscParseIdentifier hsc_env ic str + hscTcRnLookupRdrName hsc_env ic lrdr_name -getDocs :: GhcMonad m +getDocs :: GhciMonad m => Name -> m (Either GetDocsFailure (Maybe [HsDoc GhcRn], IntMap (HsDoc GhcRn))) -- TODO: What about docs for constructors etc.? @@ -919,7 +931,8 @@ getDocs name = if isInteractiveModule mod then pure (Left InteractiveName) else do - iface <- liftIO $ hscGetModuleInterface hsc_env mod + ic <- getInteractiveContext + iface <- liftIO $ hscGetModuleInterface hsc_env ic mod case mi_docs iface of Nothing -> pure (Left (NoDocsInIface mod compiled)) Just Docs { docs_decls = decls @@ -967,18 +980,20 @@ instance Outputable GetDocsFailure where -- | Get the type of an expression -- Returns the type as described by 'TcRnExprMode' -exprType :: GhcMonad m => TcRnExprMode -> String -> m Type +exprType :: GhciMonad m => TcRnExprMode -> String -> m Type exprType mode expr = withSession $ \hsc_env -> do - ty <- liftIO $ hscTcExpr hsc_env mode expr + ic <- getInteractiveContext + ty <- liftIO $ hscTcExpr hsc_env ic mode expr return $ tidyType emptyTidyEnv ty -- ----------------------------------------------------------------------------- -- Getting the kind of a type -- | Get the kind of a type -typeKind :: GhcMonad m => Bool -> String -> m (Type, Kind) -typeKind normalise str = withSession $ \hsc_env -> - liftIO $ hscKcType hsc_env normalise str +typeKind :: GhciMonad m => Bool -> String -> m (Type, Kind) +typeKind normalise str = withSession $ \hsc_env -> do + ic <- getInteractiveContext + liftIO $ hscKcType hsc_env ic normalise str -- ---------------------------------------------------------------------------- -- Getting the class instances for a type @@ -1027,23 +1042,25 @@ typeKind normalise str = withSession $ \hsc_env -> -} -- Find all instances that match a provided type -getInstancesForType :: GhcMonad m => Type -> m [ClsInst] -getInstancesForType ty = withSession $ \hsc_env -> - liftIO $ runInteractiveHsc hsc_env $ - ioMsgMaybe $ hoistTcRnMessage $ runTcInteractive hsc_env $ do +getInstancesForType :: GhciMonad m => Type -> m [ClsInst] +getInstancesForType ty = withSession $ \hsc_env -> do + ic <- getInteractiveContext + liftIO $ runInteractiveHsc hsc_env ic $ + ioMsgMaybe $ hoistTcRnMessage $ runTcInteractive hsc_env ic $ do -- Bring class and instances from unqualified modules into scope, this fixes #16793. - loadUnqualIfaces hsc_env (hsc_IC hsc_env) + loadUnqualIfaces hsc_env ic matches <- findMatchingInstances ty fmap catMaybes . forM matches $ uncurry checkForExistence -- Parse a type string and turn any holes into skolems -parseInstanceHead :: GhcMonad m => String -> m Type +parseInstanceHead :: GhciMonad m => String -> m Type parseInstanceHead str = withSession $ \hsc_env0 -> do - (ty, _) <- liftIO $ runInteractiveHsc hsc_env0 $ do + ic <- getInteractiveContext + (ty, _) <- liftIO $ runInteractiveHsc hsc_env0 ic $ do hsc_env <- getHscEnv ty <- hscParseType str - ioMsgMaybe $ hoistTcRnMessage $ tcRnType hsc_env SkolemiseFlexi True ty + ioMsgMaybe $ hoistTcRnMessage $ tcRnType hsc_env ic SkolemiseFlexi True ty return ty @@ -1171,25 +1188,26 @@ checkForExistence clsInst mb_inst_tys = do -- | Parse an expression, the parsed expression can be further processed and -- passed to compileParsedExpr. -parseExpr :: GhcMonad m => String -> m (LHsExpr GhcPs) -parseExpr expr = withSession $ \hsc_env -> - liftIO $ runInteractiveHsc hsc_env $ hscParseExpr expr +parseExpr :: GhciMonad m => String -> m (LHsExpr GhcPs) +parseExpr expr = withSession $ \hsc_env -> do + ic <- getInteractiveContext + liftIO $ runInteractiveHsc hsc_env ic $ hscParseExpr expr -- | Compile an expression, run it, and deliver the resulting HValue. -compileExpr :: GhcMonad m => String -> m HValue +compileExpr :: GhciMonad m => String -> m HValue compileExpr expr = do parsed_expr <- parseExpr expr compileParsedExpr parsed_expr -- | Compile an expression, run it, and deliver the resulting HValue. -compileExprRemote :: GhcMonad m => String -> m ForeignHValue +compileExprRemote :: GhciMonad m => String -> m ForeignHValue compileExprRemote expr = do parsed_expr <- parseExpr expr compileParsedExprRemote parsed_expr -- | Compile a parsed expression (before renaming), run it, and deliver -- the resulting HValue. -compileParsedExprRemote :: GhcMonad m => LHsExpr GhcPs -> m ForeignHValue +compileParsedExprRemote :: GhciMonad m => LHsExpr GhcPs -> m ForeignHValue compileParsedExprRemote expr@(L loc _) = withSession $ \hsc_env -> do let dflags = hsc_dflags hsc_env let interp = hscInterp hsc_env @@ -1205,7 +1223,8 @@ compileParsedExprRemote expr@(L loc _) = withSession $ \hsc_env -> do ValBinds NoAnnSortKey (unitBag $ mkHsVarBind loc' (getRdrName expr_name) expr) [] - pstmt <- liftIO $ hscParsedStmt hsc_env let_stmt + ic <- getInteractiveContext + pstmt <- liftIO $ hscParsedStmt hsc_env ic let_stmt let (hvals_io, fix_env) = case pstmt of Just ([_id], hvals_io', fix_env') -> (hvals_io', fix_env') _ -> panic "compileParsedExprRemote" @@ -1219,14 +1238,14 @@ compileParsedExprRemote expr@(L loc _) = withSession $ \hsc_env -> do liftIO $ throwIO (fromSerializableException e) _ -> panic "compileParsedExpr" -compileParsedExpr :: GhcMonad m => LHsExpr GhcPs -> m HValue +compileParsedExpr :: GhciMonad m => LHsExpr GhcPs -> m HValue compileParsedExpr expr = do fhv <- compileParsedExprRemote expr interp <- hscInterp <$> getSession liftIO $ wormhole interp fhv -- | Compile an expression, run it and return the result as a Dynamic. -dynCompileExpr :: GhcMonad m => String -> m Dynamic +dynCompileExpr :: GhciMonad m => String -> m Dynamic dynCompileExpr expr = do parsed_expr <- parseExpr expr -- > Data.Dynamic.toDyn expr @@ -1269,16 +1288,16 @@ obtainTermFromVal hsc_env _bound _force _ty _x = case interpInstance interp of where interp = hscInterp hsc_env -obtainTermFromId :: HscEnv -> Int -> Bool -> Id -> IO Term -obtainTermFromId hsc_env bound force id = do +obtainTermFromId :: HscEnv -> InteractiveContext -> Int -> Bool -> Id -> IO Term +obtainTermFromId hsc_env ic bound force id = do (hv, _, _) <- Loader.loadName (hscInterp hsc_env) hsc_env (varName id) - cvObtainTerm hsc_env bound force (idType id) hv + cvObtainTerm hsc_env ic bound force (idType id) hv -- Uses RTTI to reconstruct the type of an Id, making it less polymorphic -reconstructType :: HscEnv -> Int -> Id -> IO (Maybe Type) -reconstructType hsc_env bound id = do +reconstructType :: HscEnv -> InteractiveContext -> Int -> Id -> IO (Maybe Type) +reconstructType hsc_env ic bound id = do (hv, _, _) <- Loader.loadName (hscInterp hsc_env) hsc_env (varName id) - cvReconstructType hsc_env bound (idType id) hv + cvReconstructType hsc_env ic bound (idType id) hv mkRuntimeUnkTyVar :: Name -> Kind -> TyVar mkRuntimeUnkTyVar name kind = mkTcTyVar name kind RuntimeUnk |