@@ -29,6 +29,8 @@ import Data.List (intercalate, isPrefixOf, nub, sortBy)
29import Data.Maybe (mapMaybe)
29import Data.Maybe (mapMaybe)
30import Data.Traversable (traverse)
30import Data.Traversable (traverse)
32import System.Console.Haskeline
34import System.Console.Haskeline
33import System.Directory (doesFileExist, findExecutable, getHomeDirectory)
35import System.Directory (doesFileExist, findExecutable, getHomeDirectory)
34import System.Exit
36import System.Exit
@@ -36,11 +38,12 @@ import System.Environment.XDG.BaseDir
36import System.FilePath ((</>), isPathSeparator)
38import System.FilePath ((</>), isPathSeparator)
37import System.Process
39import System.Process
41+import Text.Parsec (choice)
39import qualified Data.Map as M
43import qualified Data.Map as M
40import qualified Language.PureScript as P
44import qualified Language.PureScript as P
41import qualified Paths_purescript as Paths
45import qualified Paths_purescript as Paths
42import qualified System.IO.UTF8 as U (readFile)
46import qualified System.IO.UTF8 as U (readFile)
43−import qualified Text.Parsec as Parsec (Parsec, eof, try)
46-- The PSCI state.
49-- The PSCI state.
@@ -69,8 +72,8 @@ ioToState = lift . lift
70-- Updates the state to have more imported modules.
73-- Updates the state to have more imported modules.
72−updateImports :: String -> PSCI -> PSCI
75+updateImports :: P.ModuleName -> PSCI -> PSCI
73−updateImports name (PSCI i m b) = PSCI (P.moduleNameFromString name : i) m b
76+updateImports name (PSCI i m b) = PSCI (name : i) m b
76-- Updates the state to have more loaded files.
79-- Updates the state to have more loaded files.
@@ -115,7 +118,7 @@ getPreludeFilename = Paths.getDataFileName "prelude/prelude.purs"
115-- Loads a file for use with imports.
118-- Loads a file for use with imports.
117loadModule :: FilePath -> IO (Either String [P.Module])
120loadModule :: FilePath -> IO (Either String [P.Module])
118−loadModule = fmap (either (Left . show) Right . P.runIndentParser "" P.parseModules) . U.readFile
121+loadModule = fmap (either (Left . show) Right . parseModules) . U.readFile
121-- Expands tilde in path.
124-- Expands tilde in path.
@@ -196,7 +199,7 @@ createTemporaryModule exec imports lets value =
197 moduleName = P.ModuleName [P.ProperName "Main"]
200 moduleName = P.ModuleName [P.ProperName "Main"]
198 importDecl m = P.ImportDeclaration m Nothing
201 importDecl m = P.ImportDeclaration m Nothing
199− traceModule = P.ModuleName [P.ProperName "Trace"]
202+ traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"]
200 trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))
203 trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))
201 value' = foldr ($) value lets
204 value' = foldr ($) value lets
202 itDecl = P.ValueDeclaration (P.Ident "it") [] Nothing value'
205 itDecl = P.ValueDeclaration (P.Ident "it") [] Nothing value'
@@ -233,24 +236,24 @@ handleTypeOf value (PSCI imports loadedModules lets) = do
233 Just (ty, _) -> outputStrLn . P.prettyPrintType $ ty
236 Just (ty, _) -> outputStrLn . P.prettyPrintType $ ty
234 Nothing -> outputStrLn "Could not find type"
237 Nothing -> outputStrLn "Could not find type"
236−-- Parser helpers
239+-- Commands
239−-- Parser for our PSCI version of @let@.
240−-- This is essentially let from do-notation.
241−-- However, since we don't support the @Eff@ monad, we actually want the normal @let@.
243−parseLet :: Parsec.Parsec String P.ParseState (P.Value -> P.Value)
244−parseLet = P.Let <$> (P.reserved "let" *> P.indented *> P.parseBinder)
245− <*> (P.indented *> P.reservedOp "=" *> P.parseValue)
248−-- Parser for any other valid expression.
242+-- Parses the input and returns either a Metacommand or an expression.
250−parseExpression :: Parsec.Parsec String P.ParseState P.Value
244+getCommand :: InputT IO Command
251−parseExpression = P.whiteSpace *> P.parseValue <* Parsec.eof
245+getCommand = do
252−
246+ firstLine <- getInputLine "> "
253−-- Commands
247+ case firstLine of
248+ Nothing -> return Empty
249+ Just line -> case parseCommands line of
250+ Left err -> return $ Unknown err
251+ Right c -> case c of
252+ Expression expr -> Expression <$> go [expr]
253+ _ -> lift $ return c
255+ go :: [String] -> InputT IO String
256+ go ls = maybe (return . unlines $ reverse ls) (go . (:ls)) =<< getInputLine " "
256-- Performs an action for each meta-command given, and also for expressions..
259-- Performs an action for each meta-command given, and also for expressions..
@@ -258,9 +261,9 @@ parseExpression = P.whiteSpace *> P.parseValue <* Parsec.eof
258handleCommand :: Command -> StateT PSCI (InputT IO) ()
261handleCommand :: Command -> StateT PSCI (InputT IO) ()
259handleCommand Empty = return ()
262handleCommand Empty = return ()
260handleCommand (Expression ls) =
263handleCommand (Expression ls) =
261− case P.runIndentParser "" (Left <$> Parsec.try parseLet <|> Right <$> parseExpression) (unlines ls) of
264+ case psciParser (choice [Left <$> psciLet, Right <$> psciExpression]) ls of
262− Left err -> inputTToState $ outputStrLn (show err)
265+ Left err -> inputTToState $ outputStrLn (show err)
263− Right (Left l) -> modify (updateLets l)
266+ Right (Left l) -> modify (updateLets l)
264 Right (Right decl) -> get >>= inputTToState . handleDeclaration decl
267 Right (Right decl) -> get >>= inputTToState . handleDeclaration decl
265handleCommand Help = inputTToState $ outputStrLn helpMessage
268handleCommand Help = inputTToState $ outputStrLn helpMessage
266handleCommand (Import moduleName) = modify (updateImports moduleName)
269handleCommand (Import moduleName) = modify (updateImports moduleName)
@@ -275,8 +278,8 @@ handleCommand Reload = do
275 (Right prelude) <- ioToState $ loadModule =<< getPreludeFilename
278 (Right prelude) <- ioToState $ loadModule =<< getPreludeFilename
276 put (PSCI defaultImports prelude [])
279 put (PSCI defaultImports prelude [])
277handleCommand (TypeOf expr) =
280handleCommand (TypeOf expr) =
278− case P.runIndentParser "" parseExpression expr of
281+ case parseExpression expr of
279− Left err -> inputTToState $ outputStrLn (show err)
282+ Left err -> inputTToState $ outputStrLn (show err)
280 Right expr' -> get >>= inputTToState . handleTypeOf expr'
283 Right expr' -> get >>= inputTToState . handleTypeOf expr'
281handleCommand _ = outputTStrLn "Unknown command"
284handleCommand _ = outputTStrLn "Unknown command"