Skip to content

Commit c5e1e9a

Browse files
committed
REPL and some minor changes
1 parent 845ac49 commit c5e1e9a

5 files changed

Lines changed: 48 additions & 32 deletions

File tree

app/Main.hs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,41 @@
11
module Main where
22

3+
import Definitions
34
import Evaluation
45
import Parsing
56
import Text.ParserCombinators.Parsec hiding (spaces)
67
import System.Environment
78
import Control.Monad
9+
import System.IO
810

911

12+
flushStr :: String -> IO ()
13+
flushStr str = putStr str >> hFlush stdout
14+
15+
readPrompt :: String -> IO String
16+
readPrompt prompt = flushStr prompt >> getLine
17+
18+
evalString :: String -> IO String
19+
evalString expr = return $ extractValue $
20+
trapError (liftM show $ readExpr expr >>= eval)
21+
22+
evalAndPrint :: String -> IO ()
23+
evalAndPrint expr = evalString expr >>= putStrLn
24+
25+
until_ :: Monad m => (a -> Bool) -> m a -> (a -> m ()) -> m ()
26+
until_ pred prompt action = do
27+
result <- prompt
28+
if pred result
29+
then return ()
30+
else action result >> until_ pred prompt action
31+
32+
runRepl :: IO ()
33+
runRepl = until_ (=="quit") (readPrompt "Lisp>>> ") evalAndPrint
34+
1035
main :: IO ()
1136
main = do
1237
args <- getArgs
13-
evaled <- return $ liftM show $ readExpr (args !! 0) >>= eval
14-
putStrLn $ extractValue $ trapError evaled
38+
case length args of
39+
0 -> runRepl
40+
1 -> evalAndPrint $ args !! 0
41+
_ -> putStrLn "Program takes only 0 or 1 argument"

my-scheme.cabal

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ source-repository head
2525

2626
library
2727
exposed-modules:
28-
Evaluation Parsing
29-
other-modules:
30-
Definitions
3128
Evaluation
3229
Parsing
30+
Definitions
31+
other-modules:
3332
Paths_my_scheme
3433
hs-source-dirs:
3534
src

package.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ dependencies:
2727

2828
library:
2929
source-dirs: src
30-
exposed-modules: Evaluation
31-
Parsing
32-
default-extensions: ExistentialQuantification
30+
exposed-modules:
31+
- Evaluation
32+
- Parsing
33+
- Definitions
34+
default-extensions:
35+
- ExistentialQuantification
3336

3437
executables:
3538
my-scheme-exe:

src/Definitions.hs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,3 @@ trapError action = catchError action (return . show)
6363

6464
extractValue :: ThrowsError a -> a
6565
extractValue (Right val) = val
66-
67-
checkType :: LispVal -> String
68-
checkType (Atom _) = "Atom"
69-
checkType (List _) = "List"
70-
checkType (DottedList _ _) = "DottedList"
71-
checkType (Number _) = "Number"
72-
checkType (Bool _) = "Bool"
73-
checkType (Char _) = "Char"
74-
checkType (Float _) = "Float"
75-
checkType (Ratio _) = "Ratio"
76-
checkType (Complex _) = "Complex"
77-
checkType (Vector _) = "Vector"
78-
checkType _ = "List"

src/Evaluation.hs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ eval (List [Atom "if", pred, conseq, alt]) =
1414
case result of
1515
Bool False -> eval alt
1616
Bool True -> eval conseq
17-
_ -> throwError $ TypeMismatch "Bool" $ checkType pred
17+
_ -> throwError $ TypeMismatch "Bool" pred
1818
eval (List (Atom func : args)) = mapM eval args >>= apply func
1919
eval form@(List (Atom "cond" : clauses)) =
2020
if null clauses
@@ -34,7 +34,7 @@ eval form@(List (Atom "case" : key : clauses)) =
3434
List ((List datums) : exprs) -> do
3535
result <- eval key
3636
equality <- mapM (\x -> eqv [result, x]) datums
37-
if Boolean True `elem` equality
37+
if Bool True `elem` equality
3838
then mapM eval exprs >>= return . last
3939
else eval $ List (Atom "case" : key : tail clauses)
4040
_ -> throwError $ BadSpecialForm "ill-formed case expression: " form
@@ -100,10 +100,10 @@ unpackNum :: LispVal -> ThrowsError Integer
100100
unpackNum (Number n) = return n
101101
unpackNum (String n) = let parsed = reads n :: [(Integer, String)] in
102102
if null parsed
103-
then throwError $ TypeMismatch "number" $ String n
103+
then throwError $ TypeMismatch "Number" $ String n
104104
else return $ fst $ parsed !! 0
105105
unpackNum (List [n]) = unpackNum n
106-
unpackNum notNum = throwError $ TypeMismatch "number" notNum
106+
unpackNum notNum = throwError $ TypeMismatch "Number" notNum
107107

108108
symbolp, integerp, floatp, ratiop, complexp, stringp, boolp, listp, vectorp
109109
:: LispVal -> LispVal
@@ -143,11 +143,11 @@ unpackStr :: LispVal -> ThrowsError String
143143
unpackStr (String s) = return s
144144
unpackStr (Number s) = return $ show s
145145
unpackStr (Bool s) = return $ show s
146-
unpackStr notString = throwError $ TypeMismatch "String" $ checkType notString
146+
unpackStr notString = throwError $ TypeMismatch "String" notString
147147

148148
unpackBool :: LispVal -> ThrowsError Bool
149149
unpackBool (Bool b) = return b
150-
unpackBool notBool = throwError $ TypeMismatch "Bool" $ checkType notBool
150+
unpackBool notBool = throwError $ TypeMismatch "Bool" notBool
151151

152152
symbol2string, string2symbol :: LispVal -> LispVal
153153
symbol2string (Atom s) = String s
@@ -158,14 +158,14 @@ string2symbol _ = Atom ""
158158
car :: [LispVal] -> ThrowsError LispVal
159159
car [List (x : _)] = return x
160160
car [DottedList (x : _) _] = return x
161-
car [badArg] = throwError $ TypeMismatch "Pair" $ checkType badArg
161+
car [badArg] = throwError $ TypeMismatch "Pair" badArg
162162
car badArgList = throwError $ NumArgs 1 badArgList
163163

164164
cdr :: [LispVal] -> ThrowsError LispVal
165165
cdr [List (_ : xs)] = return $ List xs
166166
cdr [DottedList [_] x] = return x
167167
cdr [DottedList (_ : xs) x] = return $ DottedList xs x
168-
cdr [badArg] = throwError $ TypeMismatch "Pair" $ checkType badArg
168+
cdr [badArg] = throwError $ TypeMismatch "Pair" badArg
169169
cdr badArgList = throwError $ NumArgs 1 badArgList
170170

171171
cons :: [LispVal] -> ThrowsError LispVal
@@ -216,14 +216,14 @@ equal badArgList = throwError $ NumArgs 2 badArgList
216216

217217
stringLen :: [LispVal] -> ThrowsError LispVal
218218
stringLen [(String s)] = Right $ Number $ fromIntegral $ length s
219-
stringLen [notString] = throwError $ TypeMismatch "String" $ checkType notString
219+
stringLen [notString] = throwError $ TypeMismatch "String" notString
220220
stringLen badArgList = throwError $ NumArgs 1 badArgList
221221

222222
stringRef :: [LispVal] -> ThrowsError LispVal
223223
stringRef [(String s), (Number k)]
224224
| length s < k' + 1 = throwError $ Default "Out of bound error"
225225
| otherwise = Right $ String $ [s !! k']
226226
where k' = fromIntegral k
227-
stringRef [(String s), notNum] = throwError $ TypeMismatch "Number" $ checkType notNum
228-
stringRef [notString, _] = throwError $ TypeMismatch "String" $ checkType notString
227+
stringRef [(String s), notNum] = throwError $ TypeMismatch "Number" notNum
228+
stringRef [notString, _] = throwError $ TypeMismatch "String" notString
229229
stringRef badArgList = throwError $ NumArgs 2 badArgList

0 commit comments

Comments
 (0)