超似非G-Machineを実装してみた

http://www.jaist.ac.jp/~kiyoshiy/writing/
http://www.jaist.ac.jp/~kiyoshiy/writing/gmachine.pdf
前半だけ読んで、ざっと書いてみました。


Graph-Reductionとか正直分からなかったので、それを考慮して書こうと思ったのですが、普通にちっこいλ式解釈機になってしましました・・・。
ここに書いている様なβ簡約とかδ簡約は書けていませんが、Call-by-needな感じになりました。

data Exp = Var String | Lit Int | Lam Exp Exp | App Exp Exp | Add Exp Exp deriving Show

get_varg (Lam (Var str) _) = str
get_body (Lam _ body)      = body

eval_exp (App (Lam (Var str) body) arg) env = let varg = str
                                                  env' = (varg,arg):env
                                              in eval_exp body env' 
                                             
eval_exp (App (App a b) c) env = do (intern,env') <- eval_exp (App a b) env
                                    eval_exp (get_body intern) ((get_varg intern,c):env')

eval_exp (Var s) env = do exp <- lookup_var (Var s) env
                          env' <- (do return $ modify_env (Var s) exp env) -- call-by-need
                          return (exp,env')

eval_exp (Lit l) env = return (Lit l,env)

eval_exp (Add l r) env = do (Lit l',_) <- eval_exp l env
                            (Lit r',_) <- eval_exp r env
                            return (Lit(l'+r'),env)

eval_exp (Lam (Var str) body) env  = Just (Lam (Var str) body,env)

lookup_var :: Exp -> [(String,Exp)] -> Maybe Exp
lookup_var (Var s) ((name,val):res)
    | s == name  = eval_exp val [] >>= return.fst
    | null res   = Nothing
    | otherwise  = lookup_var (Var s) res

modify_env :: Exp -> Exp -> [(String,Exp)] -> [(String,Exp)]
modify_env (Var s) exp ((name,val):res)
    | s == name  = (s,exp):res
    | otherwise  = (name,val):(modify_env (Var s) exp res)

{-
eval_exp (App (Lam (Var "x") (Add (Var "x") (Lit 10))) (Lit 100)) []

eval_exp (App (Lam (Var "x") (Lam (Var "y") (Add (Var "x") (Var "y")))) (Lit 1)) []

eval_exp (App (App (Lam (Var "x") (Lam (Var "y") (Add (Var "x") (Var "y")))) (Lit 1)) (Lit 2)) []

eval_exp (App (Lam (Var "x") (Add (App (Lam (Var "y") (Var "y")) (Lit 1)) (Var "x"))) (Lit 2)) []

eval_exp (Add (App (Lam (Var "x") (Var "x")) (Lit 1)) (App (Lam (Var "x") (Var "x")) (Lit 2))) []

eval_exp (App (App (Lam (Var "x") (Lam (Var "y") (Add (Var "x") (Var "x")))) (Lit 10)) (Lit 50)) []

eval_exp (App (Lam (Var "x") (Add (Var "x") (Var "x"))) (Add (Lit 10) (Lit 20))) []

eval_exp (App (App (Lam (Var "x") (Lam (Var "y") (Add (Var "x") (Var "x")))) (Add (Lit 1) (Lit 2))) (Add (Lit 10) (Lit 20))) []

eval_exp (App (Lam (Var "x") (Var "x")) (Add (Lit 10) (Lit 20))) []
-}

環境の扱いが気持ち悪いのと、間接ノードを導入しないで、環境内を書き換えています。(最後の例を実行すると、環境の中に(Lit 30)とか見えたり)


このpaperはこの後もあるので、一通りちゃんと読めたらもう一度書き直してみようかと。