Add Virtual CEK and Krivine machines
authorEvgenii Akentev <hi@ak3n.com>
Sat, 7 Sep 2024 10:54:54 +0000 (14:54 +0400)
committerEvgenii Akentev <hi@ak3n.com>
Sat, 7 Sep 2024 10:54:54 +0000 (14:54 +0400)
machines.cabal
src/Virtual/CEK.hs [new file with mode: 0644]
src/Virtual/Krivine.hs [new file with mode: 0644]

index b28c8023e4452fa6983af6ac54af537e01670b94..1d40bf5f7376e0eeacc394b8634c7e4a317d8b7c 100644 (file)
@@ -17,7 +17,10 @@ library
                       Abstract.SECD,
                       Abstract.SEC,
                       Abstract.SE,
-                      Abstract.EC
+                      Abstract.EC,
+
+                      Virtual.CEK,
+                      Virtual.Krivine
     build-depends:    base ^>=4.18.2.1
     hs-source-dirs:   src
     default-language: Haskell2010
diff --git a/src/Virtual/CEK.hs b/src/Virtual/CEK.hs
new file mode 100644 (file)
index 0000000..ff1e9d5
--- /dev/null
@@ -0,0 +1,59 @@
+{-# 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
diff --git a/src/Virtual/Krivine.hs b/src/Virtual/Krivine.hs
new file mode 100644 (file)
index 0000000..e23e1e8
--- /dev/null
@@ -0,0 +1,51 @@
+{-# 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