repos / machines.hs.git


machines.hs.git / src / Virtual
Evgenii Akentev  ·  2024-09-07

VEC.hs

 1{-# language LambdaCase #-}
 2
 3module Virtual.VEC where
 4
 5-- From Interpreter to Compiler and
 6-- Virtual Machine: A Functional Derivation
 7-- https://pdfs.semanticscholar.org/08f9/c12239dd720cb28a1039db9ce706cc7ee3b2.pdf
 8
 9data Term = App Term Term | CBNLam String Term | CBVLam String Term | Var String | Lit Literal | Succ Term | IfThenElse Term Term Term 
10data Literal = BoolLit Bool | NumLit Int
11  deriving (Show)
12data Inst = Pushclosure [Inst] | Pushconst Literal | Call | Return | Push String | Bind String | Incr | Test [Inst] [Inst]
13  deriving (Show)
14type Env = [(String, Val)]
15data Val = Closure [Inst] Env | Primitive Literal
16  deriving (Show)
17
18compile :: Term -> [Inst]
19compile = \case
20  (App t0 t1) -> Pushclosure (compile t1 ++ [Return]) : compile t0 ++ [Call] 
21  (CBNLam x t) -> [Pushclosure (Bind x : compile t ++ [Return])]
22  (CBVLam x t) -> [Pushclosure (Call : Bind x : compile t ++ [Return])]
23  (Var x) -> [Push x]
24  (Lit l) -> [Pushconst l]
25  (Succ t) -> compile t ++ [Incr]
26  (IfThenElse t0 t1 t2) -> compile t0 ++ [Test (compile t1) (compile t2)]
27
28run :: [Val] -> [Env] -> [Inst] -> Val
29run vs (e : es) (Pushclosure c':cs) = run (Closure c' e : vs) (e : es) cs
30run vs es (Pushconst l : cs) = run (Primitive l:vs) es cs
31run (Closure c' e : vs) es (Call : cs) = run vs (e : es) (c' ++ cs)
32run vs (_:es) (Return : cs) = run vs es cs
33run vs (e:es) (Push x : cs) = case lookup x e of
34  Just v@(Primitive _) -> run (v : vs) (e : es) cs
35  Just (Closure c' e') -> run vs (e' : e : es) (c' ++ cs) 
36  Nothing -> error "var not in scope"
37run (v : vs) (e : es) (Bind x : cs) = run vs (((x, v):e) : es) cs
38run (Primitive (NumLit n) : vs) es (Incr : cs) = run (Primitive (NumLit $ n + 1) : vs) es cs
39run (Primitive (BoolLit True) : vs) es (Test c1 _ : cs) = run vs es (c1 ++ cs)
40run (Primitive (BoolLit False) : vs) es (Test _ c2 : cs) = run vs es (c2 ++ cs)
41run (v:_) _ [] = v 
42run _ _ _ = error "Impossible"
43
44eval :: Term -> Val
45eval t = run [] [[]] $ compile t
46
47t1 :: Term
48t1 = Succ $ (Lit $ NumLit 2)
49
50ex1 :: Val 
51ex1 = eval t1
52
53--((λ 0) (λ 0)) (λ 0)
54t2 :: Term
55t2 = App (App (CBNLam "x" $ Var "x") (CBNLam "x" $ Var "x")) (CBNLam "x" $ Var "x")
56
57ex2 :: Val 
58ex2 = eval t2
59
60t3 :: Term
61t3 = App (App (App (CBNLam "x" $ CBNLam "y" $ CBNLam "z" $ IfThenElse (Var "x") (Succ $ Var "y") (Var "z")) (Lit $ BoolLit True)) (Lit $ NumLit 2)) (Lit $ NumLit 7)
62
63ex3 :: Val
64ex3 = eval t3