Unlambdaを実装しよう
Haskellの勉強も、なにか実用的なものを作りながらの方がいいと思ったのでUnlambdaの処理系を作ることにしました。OCamlの実装が104行のすごくわかりやすいコードだったのでこれを移植しようかな。
とりあえずできたところまで(evalがまだ)
{-# OPTIONS_GHC -fglasgow-exts #-} data Func = I | Dot Char | Ques Char | K1 Func | K | S2 Func Func | S1 Func | S | V | D1 Exp | D | Cont Func () -- unit? | C | E | At | Pipe deriving Show data Exp = Func Func | Apply Exp Exp deriving Show -- let current_ch = ref (None : char option);; {- eval :: Func eval = function Func f -> fun cont -> cont f | Apply (rator, rand) -> fun cont -> eval rator (function D -> cont (D1 rand) | erator -> eval rand (fun erand -> apply erator erand cont)) -} gobble ('\n':xs) = parse xs gobble (_:xs) = gobble xs parse :: String -> (Exp, String) parse (x:xs) = case x of '#' -> gobble xs ' ' -> parse xs '\n' -> parse xs '\t' -> parse xs '\r' -> parse xs '`' -> (Apply f1 f2, xs2) where (f1, xs1) = parse xs (f2, xs2) = parse xs1 'i' -> (Func I, xs) 'I' -> (Func I, xs) 'k' -> (Func K, xs) 'K' -> (Func K, xs) 's' -> (Func S, xs) 'S' -> (Func S, xs) 'v' -> (Func V, xs) 'V' -> (Func V, xs) 'd' -> (Func D, xs) 'D' -> (Func D, xs) 'c' -> (Func C, xs) 'C' -> (Func C, xs) 'e' -> (Func E, xs) 'E' -> (Func E, xs) '.' -> (Func (Dot c), rest) where (c:rest) = xs 'r' -> (Func (Dot '\n'), xs) '@' -> (Func At, xs) '?' -> (Func (Ques c), rest) where (c:rest) = xs '|' -> (Func Pipe, xs) main = print ()
parseが、読み取る文字列の残りと、読んだとこの関数とを返すためにタプルだらけになっていてきもちわるい。リストモナドとか使うのかなぁ。元のOCamlのコードでは(input_char input)で標準入力から1文字ずつ読んでた。