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文字ずつ読んでた。