diff options
author | Morrow <themorrowm@gmail.com> | 2021-10-04 02:30:47 +0300 |
---|---|---|
committer | Zubin <zubin.duggal@gmail.com> | 2021-11-17 11:14:37 +0000 |
commit | 7850142c09090a2eef1e1b0281acd641e843356a (patch) | |
tree | 962450cf647b18af467fe890bb212cf2ce759d59 | |
parent | 16d86b97ee3056b54441e7dfd349477f32347a26 (diff) | |
download | haskell-7850142c09090a2eef1e1b0281acd641e843356a.tar.gz |
Improve handling of import statements in GHCi (#20473)
Currently in GHCi, when given a line of user input we:
1. Attempt to parse and handle it as a statement
2. Otherwise, attempt to parse and handle a single import
3. Otherwise, check if there are imports present (and if so display an error message)
4. Otherwise, attempt to parse a module and only handle the declarations
This patch simplifies the process to:
Attempt to parse and handle it as a statement
Otherwise, attempt to parse a module and handle the imports and declarations
This means that multiple imports in a multiline are now accepted, and a multiline containing both imports and declarations is now accepted (as well as when separated by semicolons).
-rw-r--r-- | compiler/GHC/Driver/Main.hs | 14 | ||||
-rw-r--r-- | ghc/GHCi/UI.hs | 25 | ||||
-rw-r--r-- | testsuite/tests/ghc-e/should_fail/T9905fail2.stderr | 2 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T10663.script | 3 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T10663.stderr | 1 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T10663.stdout | 1 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20473a.script | 7 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20473a.stdout | 1 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20473b.script | 2 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20473b.stdout | 1 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T6007.stderr | 2 | ||||
-rwxr-xr-x | testsuite/tests/ghci/scripts/all.T | 2 | ||||
-rw-r--r-- | testsuite/tests/th/T10019.stdout | 2 |
13 files changed, 37 insertions, 26 deletions
diff --git a/compiler/GHC/Driver/Main.hs b/compiler/GHC/Driver/Main.hs index 26647df369..ffc0cef89d 100644 --- a/compiler/GHC/Driver/Main.hs +++ b/compiler/GHC/Driver/Main.hs @@ -74,6 +74,7 @@ module GHC.Driver.Main , hscTcRnLookupRdrName , hscStmt, hscParseStmtWithLocation, hscStmtWithLocation, hscParsedStmt , hscDecls, hscParseDeclsWithLocation, hscDeclsWithLocation, hscParsedDecls + , hscParseModuleWithLocation , hscTcExpr, TcRnExprMode(..), hscImport, hscKcType , hscParseExpr , hscParseType @@ -1937,12 +1938,17 @@ hscDecls :: HscEnv -> IO ([TyThing], InteractiveContext) hscDecls hsc_env str = hscDeclsWithLocation hsc_env str "<interactive>" 1 -hscParseDeclsWithLocation :: HscEnv -> String -> Int -> String -> IO [LHsDecl GhcPs] -hscParseDeclsWithLocation hsc_env source line_num str = do - L _ (HsModule{ hsmodDecls = decls }) <- +hscParseModuleWithLocation :: HscEnv -> String -> Int -> String -> IO HsModule +hscParseModuleWithLocation hsc_env source line_num str = do + L _ mod <- runInteractiveHsc hsc_env $ hscParseThingWithLocation source line_num parseModule str - return decls + return mod + +hscParseDeclsWithLocation :: HscEnv -> String -> Int -> String -> IO [LHsDecl GhcPs] +hscParseDeclsWithLocation hsc_env source line_num str = do + HsModule { hsmodDecls = decls } <- hscParseModuleWithLocation hsc_env source line_num str + return decls -- | Compile a decls hscDeclsWithLocation :: HscEnv diff --git a/ghc/GHCi/UI.hs b/ghc/GHCi/UI.hs index fc19207cc2..362fe0b40a 100644 --- a/ghc/GHCi/UI.hs +++ b/ghc/GHCi/UI.hs @@ -59,7 +59,7 @@ import GHC ( LoadHowMuch(..), Target(..), TargetId(..), Resume, SingleStep, Ghc, GetDocsFailure(..), putLogMsgM, pushLogHookM, getModuleGraph, handleSourceError, ms_mod ) -import GHC.Driver.Main (hscParseDeclsWithLocation, hscParseStmtWithLocation) +import GHC.Driver.Main (hscParseModuleWithLocation, hscParseStmtWithLocation) import GHC.Hs.ImpExp import GHC.Hs import GHC.Driver.Env @@ -1231,16 +1231,8 @@ runStmt input step = do Just stmt -> run_stmt stmt - | GHC.isImport pflags input -> run_import - - -- Every import declaration should be handled by `run_import`. As GHCi - -- in general only accepts one command at a time, we simply throw an - -- exception when the input contains multiple commands of which at least - -- one is an import command (see #10663). - | GHC.hasImport pflags input -> throwGhcException - (CmdLineError "error: expecting a single import declaration") - -- Otherwise assume a declaration (or a list of declarations) + -- and/or import(s) (#20473). -- Note: `GHC.isDecl` returns False on input like -- `data Infix a b = a :@: b; infixl 4 :@:` -- and should therefore not be used here. @@ -1250,14 +1242,14 @@ runStmt input step = do setDumpFilePrefix ic -- `-ddump-to-file` must work for normal GHCi compilations / -- evaluations. (#17500) - decls <- liftIO (hscParseDeclsWithLocation hsc_env source line input) + HsModule { hsmodDecls = decls, hsmodImports = imports } <- + liftIO (hscParseModuleWithLocation hsc_env source line input) + run_imports imports run_decls decls where exec_complete = GHC.ExecComplete (Right []) 0 - run_import = do - addImportToContext input - return (Just exec_complete) + run_imports imports = mapM_ (addImportToContext . unLoc) imports run_stmt :: GhciMonad m => GhciLStmt GhcPs -> m (Maybe GHC.ExecResult) run_stmt stmt = do @@ -2713,9 +2705,8 @@ setContext starred unstarred = restoreContextOnFailure $ do -- delete the transient context addModulesToContext_ starred unstarred -addImportToContext :: GhciMonad m => String -> m () -addImportToContext str = restoreContextOnFailure $ do - idecl <- GHC.parseImportDecl str +addImportToContext :: GhciMonad m => ImportDecl GhcPs -> m () +addImportToContext idecl = restoreContextOnFailure $ do addII (IIDecl idecl) -- #5836 setGHCContextFromGHCiState diff --git a/testsuite/tests/ghc-e/should_fail/T9905fail2.stderr b/testsuite/tests/ghc-e/should_fail/T9905fail2.stderr index 2e3e2d94cc..9143eccae4 100644 --- a/testsuite/tests/ghc-e/should_fail/T9905fail2.stderr +++ b/testsuite/tests/ghc-e/should_fail/T9905fail2.stderr @@ -1,3 +1,3 @@ -<interactive>:1:19: error: +<interactive>:0:19: error: Module ‘Data.List’ does not export ‘bogusIdentifier’ diff --git a/testsuite/tests/ghci/scripts/T10663.script b/testsuite/tests/ghci/scripts/T10663.script index 10be57f52a..406d0ca7ee 100644 --- a/testsuite/tests/ghci/scripts/T10663.script +++ b/testsuite/tests/ghci/scripts/T10663.script @@ -1 +1,2 @@ -import Data.List; sort [2, 1]
\ No newline at end of file +import Data.List; xs = sort [2, 1] +xs
\ No newline at end of file diff --git a/testsuite/tests/ghci/scripts/T10663.stderr b/testsuite/tests/ghci/scripts/T10663.stderr deleted file mode 100644 index 7170dbf29c..0000000000 --- a/testsuite/tests/ghci/scripts/T10663.stderr +++ /dev/null @@ -1 +0,0 @@ -error: expecting a single import declaration
\ No newline at end of file diff --git a/testsuite/tests/ghci/scripts/T10663.stdout b/testsuite/tests/ghci/scripts/T10663.stdout new file mode 100644 index 0000000000..3169929f69 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T10663.stdout @@ -0,0 +1 @@ +[1,2]
\ No newline at end of file diff --git a/testsuite/tests/ghci/scripts/T20473a.script b/testsuite/tests/ghci/scripts/T20473a.script new file mode 100644 index 0000000000..d84edb4129 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T20473a.script @@ -0,0 +1,7 @@ +:{ +import Data.List + +xs :: [Int] +xs = sort [2,1] +:} +sort xs diff --git a/testsuite/tests/ghci/scripts/T20473a.stdout b/testsuite/tests/ghci/scripts/T20473a.stdout new file mode 100644 index 0000000000..6ed63af507 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T20473a.stdout @@ -0,0 +1 @@ +[1,2] diff --git a/testsuite/tests/ghci/scripts/T20473b.script b/testsuite/tests/ghci/scripts/T20473b.script new file mode 100644 index 0000000000..4fb53badf3 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T20473b.script @@ -0,0 +1,2 @@ +import Data.List; import Data.Function +on (==) sort [1,2] [2,1] diff --git a/testsuite/tests/ghci/scripts/T20473b.stdout b/testsuite/tests/ghci/scripts/T20473b.stdout new file mode 100644 index 0000000000..0ca95142bb --- /dev/null +++ b/testsuite/tests/ghci/scripts/T20473b.stdout @@ -0,0 +1 @@ +True diff --git a/testsuite/tests/ghci/scripts/T6007.stderr b/testsuite/tests/ghci/scripts/T6007.stderr index aa2be4ee6d..bd5c31dd57 100644 --- a/testsuite/tests/ghci/scripts/T6007.stderr +++ b/testsuite/tests/ghci/scripts/T6007.stderr @@ -2,5 +2,5 @@ <interactive>:1:19: Module ‘System.IO’ does not export ‘does_not_exist’ -<interactive>:1:20: +<interactive>:3:20: Module ‘Data.Maybe’ does not export ‘does_not_exist’ diff --git a/testsuite/tests/ghci/scripts/all.T b/testsuite/tests/ghci/scripts/all.T index d67ff95308..884df5a811 100755 --- a/testsuite/tests/ghci/scripts/all.T +++ b/testsuite/tests/ghci/scripts/all.T @@ -348,3 +348,5 @@ test('T20206', normal, ghci_script, ['T20206.script']) test('T20217', normal, ghci_script, ['T20217.script']) test('T7388', normal, ghci_script, ['T7388.script']) test('T20627', normal, ghci_script, ['T20627.script']) +test('T20473a', normal, ghci_script, ['T20473a.script']) +test('T20473b', normal, ghci_script, ['T20473b.script']) diff --git a/testsuite/tests/th/T10019.stdout b/testsuite/tests/th/T10019.stdout index 85510c1af1..413d875440 100644 --- a/testsuite/tests/th/T10019.stdout +++ b/testsuite/tests/th/T10019.stdout @@ -1 +1 @@ -"Constructor from Ghci1.Option: Ghci1.Some :: forall (a_0 :: *) .\n a_0 %1 -> Ghci1.Option a_0" +"Constructor from Ghci2.Option: Ghci2.Some :: forall (a_0 :: *) .\n a_0 %1 -> Ghci2.Option a_0" |