Created
April 8, 2018 19:38
-
-
Save zehnpaard/de0c4071b49d4c850641c48c67289bea to your computer and use it in GitHub Desktop.
Ultra-Minimal Lisp REPL written in Haskell - Atom only
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Text.ParserCombinators.Parsec | |
import System.Environment | |
import System.IO | |
import Control.Monad | |
-- Lisp Value Data Type | |
data LispVal = Atom String | |
instance Show LispVal where show = showVal | |
showVal :: LispVal -> String | |
showVal (Atom name) = name | |
-- Parsers | |
readExpr :: String -> LispVal | |
readExpr input = case (parse parseExpr "lisp" input) of | |
Left err -> Atom $ "No match: " ++ show err | |
Right val -> val | |
parseExpr :: Parser LispVal | |
parseExpr = parseAtom | |
symbol :: Parser Char | |
symbol = oneOf "!#$%&|*+-/:<=>?@^_~" | |
parseAtom :: Parser LispVal | |
parseAtom = do { | |
first <- (letter <|> symbol); | |
rest <- many (letter <|> digit <|> symbol); | |
return $ Atom (first:rest); | |
} | |
-- Evaluator | |
eval :: LispVal -> LispVal | |
eval lispVal = lispVal | |
-- Repl | |
readPrompt :: String -> IO String | |
readPrompt prompt = putStr prompt >> hFlush stdout >> getLine | |
readEvalPrint :: String -> IO() | |
readEvalPrint = putStrLn . show . eval . readExpr | |
loopUntil :: (a -> Bool) -> IO a -> (a -> IO ()) -> IO () | |
loopUntil pred prompt action = do { | |
x <- prompt; | |
if pred x | |
then return () | |
else (action x >> loopUntil pred prompt action) | |
} | |
-- main | |
main :: IO () | |
main = loopUntil (== "quit") (readPrompt ">> ") readEvalPrint |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment