summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorrow <themorrowm@gmail.com>2021-10-04 02:30:47 +0300
committerZubin <zubin.duggal@gmail.com>2021-11-17 11:14:37 +0000
commit7850142c09090a2eef1e1b0281acd641e843356a (patch)
tree962450cf647b18af467fe890bb212cf2ce759d59
parent16d86b97ee3056b54441e7dfd349477f32347a26 (diff)
downloadhaskell-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.hs14
-rw-r--r--ghc/GHCi/UI.hs25
-rw-r--r--testsuite/tests/ghc-e/should_fail/T9905fail2.stderr2
-rw-r--r--testsuite/tests/ghci/scripts/T10663.script3
-rw-r--r--testsuite/tests/ghci/scripts/T10663.stderr1
-rw-r--r--testsuite/tests/ghci/scripts/T10663.stdout1
-rw-r--r--testsuite/tests/ghci/scripts/T20473a.script7
-rw-r--r--testsuite/tests/ghci/scripts/T20473a.stdout1
-rw-r--r--testsuite/tests/ghci/scripts/T20473b.script2
-rw-r--r--testsuite/tests/ghci/scripts/T20473b.stdout1
-rw-r--r--testsuite/tests/ghci/scripts/T6007.stderr2
-rwxr-xr-xtestsuite/tests/ghci/scripts/all.T2
-rw-r--r--testsuite/tests/th/T10019.stdout2
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"