diff options
author | Roman Shatsov <roshats@gmail.com> | 2015-11-21 15:58:34 +0100 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2015-11-21 11:15:09 -0500 |
commit | b98ff3ccb14e36145404f075349c8689762a2913 (patch) | |
tree | 06eb4336d7637d5ecaa0bc68ae047eb524a3b03d /ghc | |
parent | 2325bd4e0fad0e5872556c5a78d1a6a1873e7201 (diff) | |
download | haskell-b98ff3ccb14e36145404f075349c8689762a2913.tar.gz |
Function definition in GHCi
This patch allows define and re-define functions in ghci. `let` is not
required anymore (but can be used).
Idea: If ghci input string can be parsed as statement then run it as
statement else run it as declaration.
Reviewers: mpickering, bgamari, austin
Reviewed By: mpickering, bgamari, austin
Subscribers: hvr, mpickering, dterei, thomie
Differential Revision: https://phabricator.haskell.org/D1299
GHC Trac Issues: #7253
Diffstat (limited to 'ghc')
-rw-r--r-- | ghc/GhciMonad.hs | 19 | ||||
-rw-r--r-- | ghc/InteractiveUI.hs | 25 |
2 files changed, 23 insertions, 21 deletions
diff --git a/ghc/GhciMonad.hs b/ghc/GhciMonad.hs index 7dd005b99e..6d068be485 100644 --- a/ghc/GhciMonad.hs +++ b/ghc/GhciMonad.hs @@ -19,7 +19,7 @@ module GhciMonad ( TickArray, getDynFlags, - runStmt, runDecls, resume, timeIt, recordBreak, revertCAFs, + isStmt, runStmt, runDecls, resume, timeIt, recordBreak, revertCAFs, printForUser, printForUserPartWay, prettyLocations, initInterpBuffering, turnOffBuffering, flushInterpBuffers, @@ -50,6 +50,10 @@ import System.IO import Control.Monad import GHC.Exts +import qualified Lexer (ParseResult(..), unP, mkPState) +import qualified Parser (parseStmt) +import StringBuffer (stringToStringBuffer) + import System.Console.Haskeline (CompletionFunc, InputT) import qualified System.Console.Haskeline as Haskeline import Control.Monad.Trans.Class @@ -262,6 +266,19 @@ printForUserPartWay doc = do dflags <- getDynFlags liftIO $ Outputable.printForUserPartWay dflags stdout (pprUserLength dflags) unqual doc +isStmt :: String -> GHCi Bool +isStmt stmt = do + st <- getGHCiState + dflags <- GHC.getInteractiveDynFlags + + let buf = stringToStringBuffer stmt + loc = mkRealSrcLoc (fsLit "<interactive>") (line_number st) 1 + parser = Parser.parseStmt + + case Lexer.unP parser (Lexer.mkPState dflags buf loc) of + Lexer.POk _ _ -> return True + Lexer.PFailed _ _ -> return False + -- | Run a single Haskell expression runStmt :: String -> GHC.SingleStep -> GHCi (Maybe GHC.ExecResult) runStmt expr step = do diff --git a/ghc/InteractiveUI.hs b/ghc/InteractiveUI.hs index 8f861eecac..e5c4e11dea 100644 --- a/ghc/InteractiveUI.hs +++ b/ghc/InteractiveUI.hs @@ -897,22 +897,6 @@ enqueueCommands cmds = do cmds `deepseq` return () modifyGHCiState $ \st -> st{ cmdqueue = cmds ++ cmdqueue st } --- | If we one of these strings prefixes a command, then we treat it as a decl --- rather than a stmt. NB that the appropriate decl prefixes depends on the --- flag settings (Trac #9915) -declPrefixes :: DynFlags -> [String] -declPrefixes dflags = keywords ++ concat opt_keywords - where - keywords = [ "class ", "instance " - , "data ", "newtype ", "type " - , "default ", "default(" - ] - - opt_keywords = [ ["foreign " | xopt Opt_ForeignFunctionInterface dflags] - , ["deriving " | xopt Opt_StandaloneDeriving dflags] - , ["pattern " | xopt Opt_PatternSynonyms dflags] - ] - -- | Entry point to execute some haskell code from user. -- The return value True indicates success, as in `runOneCommand`. runStmt :: String -> SingleStep -> GHCi (Maybe GHC.ExecResult) @@ -927,10 +911,11 @@ runStmt stmt step = do addImportToContext stmt; return (Just (GHC.ExecComplete (Right []) 0)) | otherwise - = do dflags <- getDynFlags - if any (stmt `looks_like`) (declPrefixes dflags) - then run_decl - else run_stmt + = do + parse_res <- GhciMonad.isStmt stmt + if parse_res + then run_stmt + else run_decl where run_decl = do _ <- liftIO $ tryIO $ hFlushAll stdin |