--- /dev/null
+{-# LANGUAGE LambdaCase #-}
+
+-- From Interpreter to Compiler and
+-- Virtual Machine: A Functional Derivation
+-- https://pdfs.semanticscholar.org/08f9/c12239dd720cb28a1039db9ce706cc7ee3b2.pdf
+
+module Virtual.CEK where
+
+data Term = Var String | Lam String Term | App Term Term
+ deriving (Show)
+
+data Inst = Access String | Close String [Inst] | Push [Inst]
+ deriving (Show)
+
+compile :: Term -> [Inst]
+compile = \case
+ (Var x) -> [Access x]
+ (Lam x t) -> [Close x (compile t)]
+ (App t0 t1) -> [Push (compile t1)] ++ compile t0
+
+type Env = [(String, Val)]
+data Val = Closure String [Inst] Env
+ deriving (Show)
+
+data Context = C0 | C1 [Inst] Env Context | C2 Val Context
+ deriving (Show)
+
+transition1 :: [Inst] -> Env -> Context -> (Context, Val)
+transition1 (Access x : _) e k = case lookup x e of
+ Just v -> transition2 k v
+ Nothing -> error "var not in scope"
+transition1 (Close x c' : _) e k = transition2 k (Closure x c' e)
+transition1 (Push c' : c) e k = transition1 c e (C1 c' e k)
+
+transition2 :: Context -> Val -> (Context, Val)
+transition2 (C1 c e k) v = transition1 c e (C2 v k)
+transition2 (C2 (Closure x c e) k) v = transition1 c ((x, v):e) k
+transition2 C0 v = (C0, v)
+
+run :: [Inst] -> Val
+run c =
+ let (C0, v) = transition1 c [] C0
+ in v
+
+eval :: Term -> Val
+eval t = run $ compile t
+
+t1 :: Term
+t1 = App (Lam "x" (App (Var "x") (Var "x"))) (Lam "x" (Var "x"))
+
+ex1 :: Val
+ex1 = eval t1
+
+--((λ 0) (λ 0)) (λ 0)
+t2 :: Term
+t2 = App (App (Lam "x" $ Var "x") (Lam "x" $ Var "x")) (Lam "x" $ Var "x")
+
+ex2 :: Val
+ex2 = eval t2
--- /dev/null
+{-# language LambdaCase #-}
+
+-- From Interpreter to Compiler and
+-- Virtual Machine: A Functional Derivation
+-- https://pdfs.semanticscholar.org/08f9/c12239dd720cb28a1039db9ce706cc7ee3b2.pdf
+
+module Virtual.Krivine where
+
+data Term = Var Int | Lam String Term | App Term Term
+ deriving (Show)
+
+data Inst = Access Int | Grab String | Push [Inst]
+ deriving (Show)
+
+compile :: Term -> [Inst]
+compile = \case
+ (Var n) -> [Access n]
+ (Lam x t) -> Grab x : compile t
+ (App t0 t1) -> Push (compile t1) : compile t0
+
+type Env = [Val]
+data Val = Closure [Inst] Env
+ deriving (Show)
+data Res = Result String Env
+ deriving (Show)
+type Stack = [Val]
+
+step :: [Inst] -> Env -> Stack -> Res
+step (Access n : _) e s = let (Closure c' e') = e!!n in step c' e' s
+step (Grab _ : c) e (Closure c' e' :s) = step c (Closure c' e' :e) s
+step (Push c' : c) e s = step c e (Closure c' e : s)
+step (Grab l : c) e [] = Result l e
+
+run :: [Inst] -> Res
+run c = step c [] []
+
+eval :: Term -> Res
+eval t = run $ compile t
+
+t1 :: Term
+t1 = App (Lam "x" (App (Var 0) (Var 0))) (Lam "x" (Var 0))
+
+ex1 :: Res
+ex1 = eval t1
+
+--((λ 0) (λ 0)) (λ 0)
+t2 :: Term
+t2 = App (App (Lam "x" $ Var 0) (Lam "x" $ Var 0)) (Lam "x" $ Var 0)
+
+ex2 :: Res
+ex2 = eval t2