This repository has been archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Repl.hs
107 lines (94 loc) · 3.24 KB
/
Repl.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{-
PLP - Devoir 2
2.7 REPL
@author Nicolas Crausaz
@author Maxime Scharwath
-}
module Main where
import System.IO ( hFlush, stdout )
import Control.Exception ( catch, ErrorCall )
import Lexer ( lexer )
import Parser ( Expr, parser )
import Eval ( Env, Value, convertEnv, eval )
import Semantics ( typeof )
main :: IO ()
main = do
putStrLn "\n ██╗ ██╗ ██╗███████╗██████╗\n\
\████████╗██║██╔════╝██╔══██╗\n\
\╚██╔═██╔╝██║█████╗ ██████╔╝\n\
\████████╗██║██╔══╝ ██╔══██╗\n\
\╚██╔═██╔╝██║███████╗██║ ██║\n\
\ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ v1.0-alpha"
putStrLn "by Nicolas Crausaz and Maxime Scharwath"
putStrLn "Type :h for help"
loop []
loop :: Env -> IO ()
loop env = do
putStr "#ier> "
hFlush stdout
line <- getLine
--parse line
let (cmd, expr) = parseLine line
if null line then loop env else do
case cmd of
":q" -> return ()
":r" -> do
putStrLn "Resetting environment"
loop []
":h" -> do
putStrLn ":q to quit"
putStrLn ":r to reset"
putStrLn ":t <expr> to show type"
putStrLn ":e to show environment"
putStrLn ":{ to enable multi-line editing"
putStrLn ":} to disable multi-line editing and evaluate"
putStrLn ":h to show this help"
loop env
":t" -> do
let env' = convertEnv env
putStrLn $ "Type of " ++ expr ++ " is " ++ show (typeof (parser $ lexer expr) env')
loop env
":e" -> do
putStrLn $ "Environment is " ++ show env
loop env
":{" -> do
putStrLn "Entering multi-line mode, :} to exit"
multiline env []
_ -> do
let (res, env') = evalAndSemantic (parser $ lexer line) env
hFlush stdout
safePrint res
loop env'
parseLine :: String -> (String, String)
parseLine line = (arg1, arg2)
where
args = words line
arg1 = head args
arg2 = unwords $ tail args
multiline :: Env -> [String] -> IO ()
multiline env lines = do
hFlush stdout
line <- getLine
let (cmd, expr) = parseLine line
case cmd of
":}" -> do
putStrLn "Executing..."
let text = unlines lines
putStrLn text
let (res, env') = evalAndSemantic (parser $ lexer text) env
safePrint res
loop env'
_ -> do
multiline env (lines ++ [line])
evalAndSemantic :: Expr -> Env -> (Value, Env)
evalAndSemantic expr env =
let
t = typeof expr (convertEnv env)
e = eval expr env
in
e
safePrint :: Value -> IO ()
safePrint xs = catch (print xs) handler
where
handler :: ErrorCall -> IO ()
handler e = print (show e)