3Description : Main function to decide Idris' mode of use.
5Maintainer : The Idris Community.
11 , runClient -- taken from Idris.REPL.
12 , loadInputs -- taken from Idris.ModeCommon
16import Idris.Core.Execute (execute)
19import Idris.Elab.Value
24import Idris.ModeCommon
27import Idris.Parser hiding (indent)
29import Idris.REPL.Commands
30import Idris.REPL.Parser
31import IRTS.CodegenCommon
35import Control.Category
38import Control.Monad.Trans (lift)
39import Control.Monad.Trans.Except (runExceptT)
40import Control.Monad.Trans.State.Strict (execStateT)
43import Prelude hiding (id, (.), (<$>))
44import System.Console.Haskeline as H
45import System.Directory
49import System.IO.CodePage (withCP65001)
51-- | How to run Idris programs.
52runMain :: Idris () -> IO ()
53runMain prog = withCP65001 $ do
54 -- Run in codepage 65001 on Windows so that UTF-8 characters can
55 -- be displayed properly. See #3000.
56 res <- runExceptT $ execStateT prog idrisInit
59 putStrLn $ "Uncaught error: " ++ show err
63-- | The main function of Idris that when given a set of Options will
64-- launch Idris into the desired interaction mode either: REPL;
65-- Compiler; Script execution; or IDE Mode.
66idrisMain :: [Opt] -> Idris ()
68 do mapM_ setWidth (opt getConsoleWidth opts)
69 let inputs = opt getFile opts
70 let quiet = Quiet `elem` opts
71 let nobanner = NoBanner `elem` opts
72 let idesl = Idemode `elem` opts || IdemodeSocket `elem` opts
73 let runrepl = not (NoREPL `elem` opts)
74 let output = opt getOutput opts
75 let ibcsubdir = opt getIBCSubDir opts
76 let importdirs = opt getImportDir opts
77 let sourcedirs = opt getSourceDir opts
78 setSourceDirs sourcedirs
79 let bcs = opt getBC opts
80 let pkgdirs = opt getPkgDir opts
81 -- Set default optimisations
82 let optimise = case opt getOptLevel opts of
87 let outty = case opt getOutputTy opts of
88 [] -> if Interface `elem` opts then
89 Object else Executable
91 let cgn = case opt getCodegen opts of
92 [] -> Via IBCFormat "c"
94 let cgFlags = opt getCodegenArgs opts
96 -- Now set/unset specifically chosen optimisations
97 let os = opt getOptimisation opts
99 mapM_ processOptimisation os
101 script <- case opt getExecScript opts of
103 x:y:xs -> do iputStrLn "More than one interpreter expression found."
104 runIO $ exitWith (ExitFailure 1)
105 [expr] -> return (Just expr)
106 let immediate = opt getEvalExpr opts
107 let port = case getPort opts of
108 Nothing -> ListenPort defaultPort
111 when (DefaultTotal `elem` opts) $ do i <- getIState
112 putIState (i { default_total = DefaultCheckingTotal })
114 setColourise $ not quiet && last (tty : opt getColour opts)
118 mapM_ addLangExt (opt getLanguageExt opts)
120 setQuiet (quiet || isJust script || not (null immediate))
126 mapM_ (addFlag cgn) cgFlags
127 mapM_ makeOption opts
129 when (runrepl && vlevel == 0) $ setVerbose 1
131 -- if we have the --bytecode flag, drop into the bytecode assembler
134 xs -> return () -- runIO $ mapM_ bcAsm xs
136 [] -> setIBCSubDir ""
137 (d:_) -> setIBCSubDir d
138 setImportDirs importdirs
142 -- Check if listed packages are actually installed
144 idrisCatch (do ipkgs <- runIO $ getIdrisInstalledPackages
145 let diff_pkgs = (\\) pkgdirs ipkgs
147 when (not $ null diff_pkgs) $ do
148 iputStrLn "The following packages were specified but cannot be found:"
149 iputStr $ unlines $ map (\x -> unwords ["-", x]) diff_pkgs
150 runIO $ exitWith (ExitFailure 1))
153 when (not (NoBasePkgs `elem` opts)) $ do
157 mapM_ addPkgDir pkgdirs
159 when (not (NoBuiltins `elem` opts)) $ do x <- loadModule "Builtins" (IBC_REPL False)
160 addAutoImport "Builtins"
162 when (not (NoPrelude `elem` opts)) $ do x <- loadModule "Prelude" (IBC_REPL False)
163 addAutoImport "Prelude"
165 when (runrepl && not idesl) initScript
167 nobanner <- getNoBanner
172 not (isJust script) &&
179 mods <- if idesl then return [] else loadInputs inputs Nothing
180 let efile = case inputs of
184 runIO $ hSetBuffering stdout LineBuffering
187 when ok $ case output of
189 (o:_) -> idrisCatch (process "" (Compile cgn o))
190 (\e -> do ist <- getIState ; iputStrLn $ pshow ist e)
194 exprs -> do setWidth InfinitelyWide
195 mapM_ (\str -> do ist <- getIState
197 case parseExpr ist str of
198 Left err -> do iputStrLn . show . fixColour c . parseErrorDoc $ err
199 runIO $ exitWith (ExitFailure 1)
200 Right e -> process "" (Eval e))
207 Just expr -> execScript expr
209 -- Create Idris data dir + repl history and config dir
210 idrisCatch (do dir <- runIO $ getIdrisUserDataDir
211 exists <- runIO $ doesDirectoryExist dir
212 unless exists $ logLvl 1 ("Creating " ++ dir)
213 runIO $ createDirectoryIfMissing True (dir </> "repl"))
216 historyFile <- runIO $ getIdrisHistoryFile
218 when ok $ case opt getPkgIndex opts of
219 (f : _) -> writePkgIndex f
222 when (runrepl && not idesl) $ do
225 DontListen -> return ()
226 ListenPort port' -> startServer port' orig mods
227 runInputT (replSettings (Just historyFile)) $ repl (force orig) mods efile
228 let idesock = IdemodeSocket `elem` opts
229 when (idesl) $ idemodeStart idesock orig inputs
231 when (not ok) $ runIO (exitWith (ExitFailure 1))
233 makeOption (OLogging i) = setLogLevel i
234 makeOption (OLogCats cs) = setLogCats cs
235 makeOption (Verbose v) = setVerbose v
236 makeOption TypeCase = setTypeCase True
237 makeOption TypeInType = setTypeInType True
238 makeOption NoCoverage = setCoverage False
239 makeOption ErrContext = setErrContext True
240 makeOption (IndentWith n) = setIndentWith n
241 makeOption (IndentClause n) = setIndentClause n
242 makeOption _ = return ()
244 processOptimisation :: (Bool,Optimisation) -> Idris ()
245 processOptimisation (True, p) = addOptimise p
246 processOptimisation (False, p) = removeOptimise p
248 addPkgDir :: String -> Idris ()
249 addPkgDir p = do ddir <- runIO getIdrisLibDir
250 addImportDir (ddir </> p)
251 addIBC (IBCImportDir (ddir </> p))
255-- | Invoke as if from command line. It is an error if there are
256-- unresolved totality problems.
257idris :: [Opt] -> IO (Maybe IState)
258idris opts = do res <- runExceptT $ execStateT totalMain idrisInit
260 Left err -> do putStrLn $ pshow idrisInit err
262 Right ist -> return (Just ist)
263 where totalMain = do idrisMain opts
265 case idris_totcheckfail ist of
266 ((fc, msg):_) -> ierror . At fc . Msg $ "Could not build: "++ msg
270-- | Execute the provided Idris expression.
271execScript :: String -> Idris ()
272execScript expr = do i <- getIState
274 case parseExpr i expr of
275 Left err -> do iputStrLn . show . fixColour c . parseErrorDoc $ err
276 runIO $ exitWith (ExitFailure 1)
277 Right term -> do ctxt <- getContext
278 (tm, _) <- elabVal (recinfo (fileFC "toplevel")) ERHS term
282-- | Run the initialisation script
283initScript :: Idris ()
284initScript = do script <- runIO $ getIdrisInitScript
285 idrisCatch (do go <- runIO $ doesFileExist script
287 h <- runIO $ openFile script ReadMode
290 (\e -> iPrintError $ "Error reading init file: " ++ show e)
291 where runInit :: Handle -> Idris ()
292 runInit h = do eof <- lift . lift $ hIsEOF h
295 line <- runIO $ hGetLine h
296 script <- runIO $ getIdrisInitScript
298 processLine ist line script c
300 processLine i cmd input clr =
301 case parseCmd i input cmd of
302 Left err -> runIO . print . fixColour clr . parseErrorDoc $ err
303 Right (Right Reload) -> iPrintError "Init scripts cannot reload the file"
304 Right (Right (Load f _)) -> iPrintError "Init scripts cannot load files"
305 Right (Right (ModImport f)) -> iPrintError "Init scripts cannot import modules"
306 Right (Right Edit) -> iPrintError "Init scripts cannot invoke the editor"
307 Right (Right Proofs) -> proofs i
308 Right (Right Quit) -> iPrintError "Init scripts cannot quit Idris"
309 Right (Right cmd ) -> process [] cmd
310 Right (Left err) -> runIO $ print err
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list