- Write Yourself a Scheme in 48 Hours/Building a REPL
- http://jonathan.tang.name/files/scheme_in_48/code/listing7.hs
REPLとは Read-eval-print loopの略。読み込んで評価をしてそれを表示・・・その繰り返しをする対話型評価環境を作ります。
import IO hiding (try) -- Parsec の try 関数と重複するので.
flushStr は引数の文字列を表示する。
flushStr :: String -> IO () flushStr str = putStr str >> hFlush stdout > flushStr "test\n" -- > test
readPrompt は引数の文字列を表示して入力された文字列を返す。
readPrompt :: String -> IO String readPrompt prompt = flushStr prompt >> getLine > readPrompt "lisp >>>" lisp >>>input -- > "input"
evalString は引数の文字列をパース、評価。例外を処理した文字列を返す。
extractValue では Right を取り去る。
evalString :: String -> IO String evalString expr = return $ extractValue $ trapError (liftM show $ readExpr expr >>= eval) > evalString "(+ 1 2 3)" -- > "6"
evalAndPrint は evalString を表示。
evalAndPrint :: String -> IO () evalAndPrint expr = evalString expr >>= putStrLn > evalAndPrint "(+ 1 2 3)" -- > 6
until_ は再帰でループします。
until_ の _ は値を返さない繰り返し処理のときに使われる命名規則です。( sequence_ 等)
pred : ループの終了条件
prompt : 読み込みをするための関数
action : 評価実行をする関数
until_ :: Monad m => (a -> Bool) -> m a -> (a -> m ()) -> m () until_ pred prompt action = do result <- prompt if pred result then return () else action result >> until_ pred prompt action > until_ (== "quit") (readPrompt "Lisp>>> ") evalAndPrint Lisp>>> (car '(a b)) a Lisp>>> quit
REPL の定義
runRepl :: IO () runRepl = until_ (== "quit") (readPrompt "Lisp>>> ") evalAndPrint
引数なしで起動されてときは REPL モード。
引数がひとつのときはその引数を評価。
それ以外はエラーを表示します。
main :: IO () main = do args <- getArgs case length args of 0 -> runRepl 1 -> evalAndPrint $ args !! 0 otherwise -> putStrLn "Program takes only 0 or 1 argument"
$ ghc -package parsec -fglasgow-exts -o lisp listing7.hs listing7.hs:180:0: Warning: Pattern match(es) are overlapped In the definition of `cdr': cdr [DottedList [xs] x] = ... $ rlwrap ./lisp Lisp>>> 123 123 Lisp>>> (+ 1 2 3) 6 Lisp>>> quit $ rlwrap ./lisp (+ 1 2) 3
rlwrap はキーボードからコマンドへの入力に GNU readline ライブラリを使えるようにするラッパーです。コマンドごとに個別の入力履歴を記録し、これまでに入力した単語やユーザが指定したファイルに含まれる単語を使って Tab 補完をすることができます。(SourceForge.JP > ソフトウェアを探す > rlwrap > 概要)