on master help sign in
:r and :e at the REPL.
commit22546bcde96bfe900518c1ac517193274961b17c authorEdwin Brady <eb@cs.st-andrews.ac.uk> dateThu 3 Nov 2011, 01:54 (15 years ago) parent1b1a055
8 files changed+140−70
interp.idr+1−1 src/Idris/AbsSyntax.hs+14−3 src/Idris/ElabDecls.hs+4−1 src/Idris/Error.hs+10 src/Idris/Parser.hs+28−14 src/Idris/REPL.hs+79−46 src/Idris/REPLParser.hs+2 src/Main.hs+2−5
interp.idr+1−1
@@ -67,7 +67,7 @@ test : Int;
6767test = interp Empty eProg 2 2;
6868
6969testFac : Int;
70−testFac = interp Empty eFac 3;
70+testFac = interp Empty eFac 4;
7171
7272intToStr : Int -> String;
7373intToStr 0 = "O";
src/Idris/AbsSyntax.hs+14−3
@@ -38,11 +38,12 @@ data IState = IState { tt_ctxt :: Context,
3838 syntax_rules :: [Syntax],
3939 syntax_keywords :: [String],
4040 imported :: [FilePath],
41− idris_prims :: [(Name, ([E.Name], E.Term))]
41+ idris_prims :: [(Name, ([E.Name], E.Term))],
42+ errLine :: Maybe Int
4243 }
4344
4445idrisInit = IState emptyContext [] emptyContext emptyContext
45− "" defaultOpts 6 [] [] [] [] []
46+ "" defaultOpts 6 [] [] [] [] [] Nothing
4647
4748-- The monad for the main REPL - reading and processing files and updating
4849-- global state (hence the IO inner monad).
@@ -51,6 +52,16 @@ type Idris a = StateT IState IO a
5152getContext :: Idris Context
5253getContext = do i <- get; return (tt_ctxt i)
5354
55+setErrLine :: Int -> Idris ()
56+setErrLine x = do i <- get;
57+ case (errLine i) of
58+ Nothing -> put (i { errLine = Just x })
59+ Just _ -> return ()
60+
61+clearErr :: Idris ()
62+clearErr = do i <- get
63+ put (i { errLine = Nothing })
64+
5465getIState :: Idris IState
5566getIState = get
5667
@@ -124,7 +135,7 @@ setTypeCase t = do i <- get
124135
125136-- Commands in the REPL
126137
127−data Command = Quit | Help | Eval PTerm
138+data Command = Quit | Help | Eval PTerm | Reload | Edit
128139 | Compile String
129140 | Metavars | Prove Name
130141 | TTShell
src/Idris/ElabDecls.hs+4−1
@@ -303,7 +303,10 @@ pvars ist _ = []
303303-- TODO: Also build a 'binary' version of each declaration for fast reloading
304304
305305elabDecl :: ElabInfo -> PDecl -> Idris ()
306−elabDecl info d = idrisCatch (elabDecl' info d) (\e -> iputStrLn (report e))
306+elabDecl info d = idrisCatch (elabDecl' info d)
307+ (\e -> do let msg = report e
308+ setErrLine (getErrLine msg)
309+ iputStrLn msg)
307310
308311elabDecl' info (PFix _ _ _) = return () -- nothing to elaborate
309312elabDecl' info (PSyntax _ p) = return () -- nothing to elaborate
src/Idris/Error.hs+10
@@ -8,6 +8,7 @@ import Core.Typecheck
88
99import Control.Monad.State
1010import System.IO.Error
11+import Data.Char
1112
1213report :: IOError -> String
1314report e
@@ -27,5 +28,14 @@ tclift :: Show a => TC a -> Idris a
2728tclift tc = case tc of
2829 OK v -> return v
2930 Error err -> do i <- get
31+ case err of
32+ At (FC f l) e -> setErrLine l
33+ _ -> return ()
3034 fail (pshow i err)
3135
36+getErrLine str
37+ = case span (/=':') str of
38+ (_, ':':rest) -> case span isDigit rest of
39+ (num, _) -> read num
40+ _ -> 0
41+
src/Idris/Parser.hs+28−14
@@ -2,14 +2,16 @@ module Idris.Parser where
22
33import Idris.AbsSyntax
44import Idris.Imports
5−import Paths_miniidris
5+import Idris.Error
66import Idris.ElabDecls
7+import Paths_miniidris
78
89import Core.CoreParser
910import Core.TT
1011import Core.Evaluate
1112
1213import Text.ParserCombinators.Parsec
14+import Text.ParserCombinators.Parsec.Error
1315import Text.ParserCombinators.Parsec.Expr
1416import Text.ParserCombinators.Parsec.Language
1517import qualified Text.ParserCombinators.Parsec.Token as PTok
@@ -47,17 +49,22 @@ lchar = lexeme.char
4749-- Loading modules
4850
4951loadModule :: FilePath -> Idris String
50−loadModule f = do datadir <- lift $ getDataDir
51− fp <- lift $ findImport [".", datadir] f
52− i <- getIState
53− if (f `elem` imported i)
54− then iLOG $ "Already read " ++ f
55− else do putIState (i { imported = f : imported i })
56− case fp of
57− IDR fn -> loadSource fn
58− IBC fn -> error "Not implemented"
59− let (dir, fh) = splitFileName f
60− return (dropExtension fh)
52+loadModule f
53+ = idrisCatch (do datadir <- lift $ getDataDir
54+ fp <- lift $ findImport [".", datadir] f
55+ i <- getIState
56+ if (f `elem` imported i)
57+ then iLOG $ "Already read " ++ f
58+ else do putIState (i { imported = f : imported i })
59+ case fp of
60+ IDR fn -> loadSource fn
61+ IBC fn -> error "Not implemented"
62+ let (dir, fh) = splitFileName f
63+ return (dropExtension fh))
64+ (\e -> do let msg = report e
65+ setErrLine (getErrLine msg)
66+ iputStrLn msg
67+ return "")
6168
6269loadSource :: FilePath -> Idris ()
6370loadSource f = do iLOG ("Reading " ++ f)
@@ -84,9 +91,13 @@ parseImports fname input
8491 rest <- getInput
8592 pos <- getPosition
8693 return ((ps, rest, pos), i)) i fname input) of
87− Left err -> fail (show err)
94+ Left err -> fail (ishow err)
8895 Right (x, i) -> do put i
8996 return x
97+ where ishow err = let ln = sourceLine (errorPos err) in
98+ fname ++ ":" ++ show ln ++ ":parse error"
99+-- show (map messageString (errorMessages err))
100+
90101
91102pfc :: IParser FC
92103pfc = do s <- getPosition
@@ -111,9 +122,12 @@ parseProg syn fname input pos
111122 eof
112123 i' <- getState
113124 return (concat ps, i')) i fname input) of
114− Left err -> fail (show err)
125+ Left err -> fail (ishow err)
115126 Right (x, i) -> do put i
116127 return (collect x)
128+ where ishow err = let ln = sourceLine (errorPos err) in
129+ fname ++ ":" ++ show ln ++ ":parse error"
130+-- show (map messageString (errorMessages err))
117131
118132-- Collect PClauses with the same function name
119133
src/Idris/REPL.hs+79−46
@@ -9,69 +9,102 @@ import Idris.Error
99import Idris.Delaborate
1010import Idris.Compiler
1111import Idris.Prover
12+import Idris.Parser
1213
1314import Core.Evaluate
1415import Core.ProofShell
1516import Core.TT
1617
1718import System.Console.Readline
19+import System.FilePath
20+import System.Environment
21+import System.Process
1822import Control.Monad
1923import Control.Monad.State
2024import Data.List
25+import Data.Char
2126
22−repl :: String -> Idris ()
23−repl prompt
24− = do x <- lift $ readline (prompt ++ "> ")
27+repl :: IState -> [FilePath] -> Idris ()
28+repl orig mods
29+ = do let prompt = mkPrompt mods
30+ x <- lift $ readline (prompt ++ "> ")
2531 case x of
26− Nothing -> repl prompt
32+ Nothing -> repl orig mods
2733 Just input -> do lift $ addHistory input
28− continue <- processInput input
29− when continue (repl prompt)
34+ ms <- processInput input orig mods
35+ case ms of
36+ Just mods -> repl orig mods
37+ Nothing -> return ()
3038
31−processInput :: String -> Idris Bool
32−processInput cmd
39+mkPrompt [] = "Idris"
40+mkPrompt [x] = "*" ++ dropExtension x
41+mkPrompt (x:xs) = "*" ++ dropExtension x ++ " " ++ mkPrompt xs
42+
43+processInput :: String -> IState -> [FilePath] -> Idris (Maybe [FilePath])
44+processInput cmd orig inputs
3345 = do i <- get
46+ let fn = case inputs of
47+ (f:_) -> f
48+ _ -> ""
3449 case parseCmd i cmd of
3550 Left err -> do lift $ print err
36− return True
51+ return (Just inputs)
52+ Right Reload -> do put orig
53+ clearErr
54+ mods <- mapM loadModule inputs
55+ return (Just inputs)
3756 Right Quit -> do iputStrLn "Bye bye"
38− return False
39− Right cmd -> do idrisCatch (process cmd)
57+ return Nothing
58+ Right cmd -> do idrisCatch (process fn cmd)
4059 (\e -> iputStrLn (report e))
41− return True
42−
43−process :: Command -> Idris ()
44−process Help
60+ return (Just inputs)
61+
62+process :: FilePath -> Command -> Idris ()
63+process _ Help
4564 = iputStrLn "At some point I'll write some help text. Thanks for asking though."
46−process (Eval t) = do (tm, ty) <- elabVal toplevel t
47− ctxt <- getContext
48− ist <- get
49− let tm' = normaliseC ctxt [] tm
50− let ty' = normaliseC ctxt [] ty
51− logLvl 3 $ "Raw: " ++ show (tm', ty')
52− iputStrLn (show (delab ist tm') ++ " : " ++
53− show (delab ist ty'))
54−process (Spec t) = do (tm, ty) <- elabVal toplevel t
55− ctxt <- getContext
56− ist <- get
57− let tm' = specialise ctxt (idris_statics ist) tm
58− iputStrLn (show (delab ist tm'))
59−process (Prove n) = prover n
60−process (HNF t) = do (tm, ty) <- elabVal toplevel t
61− ctxt <- getContext
62− ist <- get
63− let tm' = hnf ctxt [] tm
64− iputStrLn (show (delab ist tm'))
65−process TTShell = do ist <- get
66− let shst = initState (tt_ctxt ist)
67− shst' <- lift $ runShell shst
68− return ()
69−process (Compile f) = do compile f
70−process (LogLvl i) = setLogLevel i
71−process Metavars = do ist <- get
72− let mvs = idris_metavars ist \\ primDefs
73− case mvs of
74− [] -> iputStrLn "No global metavariables to solve"
75− _ -> iputStrLn $ "Global metavariables:\n\t" ++ show mvs
76−process NOP = return ()
65+process "" Edit = iputStrLn "Nothing to edit"
66+process f Edit
67+ = do i <- get
68+ env <- lift $ getEnvironment
69+ let editor = getEditor env
70+ let line = case errLine i of
71+ Just l -> " +" ++ show l ++ " "
72+ Nothing -> " "
73+ let cmd = editor ++ line ++ f
74+ lift $ system cmd
75+ return ()
76+ where getEditor env | Just ed <- lookup "EDITOR" env = ed
77+ | Just ed <- lookup "VISUAL" env = ed
78+ | otherwise = "vi"
79+process _ (Eval t) = do (tm, ty) <- elabVal toplevel t
80+ ctxt <- getContext
81+ ist <- get
82+ let tm' = normaliseC ctxt [] tm
83+ let ty' = normaliseC ctxt [] ty
84+ logLvl 3 $ "Raw: " ++ show (tm', ty')
85+ iputStrLn (show (delab ist tm') ++ " : " ++
86+ show (delab ist ty'))
87+process _ (Spec t) = do (tm, ty) <- elabVal toplevel t
88+ ctxt <- getContext
89+ ist <- get
90+ let tm' = specialise ctxt (idris_statics ist) tm
91+ iputStrLn (show (delab ist tm'))
92+process _ (Prove n) = prover n
93+process _ (HNF t) = do (tm, ty) <- elabVal toplevel t
94+ ctxt <- getContext
95+ ist <- get
96+ let tm' = hnf ctxt [] tm
97+ iputStrLn (show (delab ist tm'))
98+process _ TTShell = do ist <- get
99+ let shst = initState (tt_ctxt ist)
100+ shst' <- lift $ runShell shst
101+ return ()
102+process _ (Compile f) = do compile f
103+process _ (LogLvl i) = setLogLevel i
104+process _ Metavars = do ist <- get
105+ let mvs = idris_metavars ist \\ primDefs
106+ case mvs of
107+ [] -> iputStrLn "No global metavariables to solve"
108+ _ -> iputStrLn $ "Global metavariables:\n\t" ++ show mvs
109+process _ NOP = return ()
77110
src/Idris/REPLParser.hs+2
@@ -22,6 +22,8 @@ cmd xs = do lchar ':'; docmd (sortBy (\x y -> compare (length y) (length x)) xs)
2222pCmd :: IParser Command
2323pCmd = try (do cmd ["q", "quit"]; eof; return Quit)
2424 <|> try (do cmd ["h", "?", "help"]; eof; return Help)
25+ <|> try (do cmd ["r", "reload"]; eof; return Reload)
26+ <|> try (do cmd ["e", "edit"]; eof; return Edit)
2527 <|> try (do cmd ["ttshell"]; eof; return TTShell)
2628 <|> try (do cmd ["c", "compile"]; f <- identifier; eof; return (Compile f))
2729 <|> try (do cmd ["m", "metavars"]; eof; return Metavars)
src/Main.hs+2−5
@@ -48,17 +48,14 @@ runIdris opts =
4848 when (not (NoPrelude `elem` opts)) $ do x <- loadModule "prelude"
4949 return ()
5050 when runrepl $ iputStrLn banner
51+ ist <- get
5152 mods <- mapM loadModule inputs
52− when runrepl $ repl (mkPrompt mods)
53+ when runrepl $ repl ist inputs
5354 where
5455 makeOption (OLogging i) = setLogLevel i
5556 makeOption TypeCase = setTypeCase True
5657 makeOption _ = return ()
5758
58−mkPrompt [] = "Idris"
59−mkPrompt [x] = "*" ++ x
60−mkPrompt (x:xs) = "*" ++ x ++ " " ++ mkPrompt xs
61−
6259getFile :: Opt -> Maybe String
6360getFile (Filename str) = Just str
6461getFile _ = Nothing