Add CAM virtual machine master
authorEvgenii Akentev <hi@ak3n.com>
Thu, 26 Sep 2024 10:06:44 +0000 (14:06 +0400)
committerEvgenii Akentev <hi@ak3n.com>
Thu, 26 Sep 2024 10:06:44 +0000 (14:06 +0400)
src/abstract_machines/krivine.rs
src/lib.rs
src/main.rs
src/virtual_machines/cam.rs [new file with mode: 0644]
src/virtual_machines/mod.rs [new file with mode: 0644]

index db99686809a03d4ccb26da79b98a76896db5531a..956102319dadec382f95626f0d669b5d9ed648c7 100644 (file)
@@ -1,6 +1,6 @@
 #[derive(Clone, Debug, PartialEq)]
 enum V {
-    Free(String),
+//    Free(String),
     Bound(usize),
 }
 
index 0af09f24056577a2dbf39c6abba55c65dbef0cd8..baad7790a699f535b8403d40ee8aa53ce7685b34 100644 (file)
@@ -1 +1,2 @@
 pub mod abstract_machines;
+pub mod virtual_machines;
index d6fa209498fd3b80addf796811eb46fe4a1ba6ff..f95addfa44b4d3b164d646baad15d5a053c26f47 100644 (file)
@@ -1,7 +1,9 @@
 use machines::abstract_machines::cek;
 use machines::abstract_machines::krivine;
+use machines::virtual_machines::cam;
 
 fn main() {
     cek::main();
     krivine::main();
+    cam::main();
 }
diff --git a/src/virtual_machines/cam.rs b/src/virtual_machines/cam.rs
new file mode 100644 (file)
index 0000000..042562a
--- /dev/null
@@ -0,0 +1,140 @@
+#[derive(Clone, Debug)]
+enum Term {
+    Var(usize),
+    Lam(Box<Term>),
+    App(Box<(Term, Term)>),
+    Nil,
+    MkPair(Box<(Term, Term)>),
+    Car(Box<Term>),
+    Cdr(Box<Term>),
+    Lit(usize),
+}
+
+impl Term {
+    fn eval(&self) -> Value {
+        run(self.compile(), Value::Null, vec![])
+    }
+
+    fn compile(&self) -> Vec<Instruction> {
+        match self {
+            Term::Var(0) => vec![Instruction::Snd],
+            Term::Var(n) => {
+                let mut res = vec![Instruction::Fst];
+                res.append(&mut Term::Var(n - 1).compile());
+                res
+            },
+            Term::Lam(t) => vec![Instruction::Cur(t.compile())],
+            Term::App(tuple) => {
+                let (t0, t1) = *tuple.clone();
+                let mut result = vec![Instruction::Push];
+
+                result.append(&mut t0.compile());
+                result.push(Instruction::Swap);
+                result.append(&mut t1.compile());
+                result.push(Instruction::Cons);
+                result.push(Instruction::Call);
+
+                result
+            },
+            Term::Nil => vec![Instruction::Quote(Value::Null)],
+            Term::MkPair(tuple) => {
+                let (t0, t1) = *tuple.clone();
+                let mut result = vec![Instruction::Push];
+
+                result.append(&mut t0.compile());
+                result.push(Instruction::Swap);
+                result.append(&mut t1.compile());
+                result.push(Instruction::Cons);
+
+                result
+            },
+            Term::Car(t) => {
+                let mut result = t.compile();
+                result.push(Instruction::Fst);
+                result
+            },
+            Term::Cdr(t) => {
+                let mut result = t.compile();
+                result.push(Instruction::Snd);
+                result
+            },
+            Term::Lit(n) => vec![Instruction::Quote(Value::Num(*n))],
+            _ => todo!(),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+enum Instruction {
+    Fst,
+    Snd,
+    Push,
+    Swap,
+    Cons,
+    Call,
+    Cur(Vec<Instruction>),
+    Quote(Value),
+}
+
+#[derive(Clone, Debug)]
+enum Value {
+    Null,
+    Pair(Box<(Value, Value)>),
+    Closure(Box<Value>, Vec<Instruction>),
+    Num(usize),
+}
+
+type Stack = Vec<Value>;
+
+fn run(instrs: Vec<Instruction>, v: Value, s: Stack) -> Value {
+
+    match (instrs.split_first(), v.clone(), s.split_first()) {
+        (Some((Instruction::Fst, tail)), Value::Pair(tuple), _) => {
+            let (v1, _) = *tuple.clone();
+            run(tail.to_vec(), v1, s)
+        },
+        (Some((Instruction::Snd, tail)), Value::Pair(tuple), _) => {
+            let (_, v2) = *tuple.clone();
+            run(tail.to_vec(), v2, s)
+        },
+        (Some((Instruction::Quote(val), tail)), _, _) => {
+            run(tail.to_vec(), val.clone(), s)
+        },
+        (Some((Instruction::Cur(steps), tail)), _, _) => {
+            run(tail.to_vec(), Value::Closure(Box::new(v), steps.to_vec()), s)
+        },
+        (Some((Instruction::Push, tail)), _, _) => {
+            let mut new_stack = vec![v.clone()];
+            new_stack.append(&mut s.clone());
+            run(tail.to_vec(), v, new_stack)
+        },
+        (Some((Instruction::Swap, tail)), _, Some((val, s_tail))) => {
+            let mut new_stack = vec![v.clone()];
+            new_stack.append(&mut s_tail.to_vec());
+            run(tail.to_vec(), val.clone(), new_stack)
+        },
+        (Some((Instruction::Cons, tail)), _, Some((val, s_tail))) => {
+            run(tail.to_vec(), Value::Pair(Box::new((val.clone(), v))), s_tail.to_vec())
+        },
+        (Some((Instruction::Call, tail)), Value::Pair(tuple), _) => {
+            let (Value::Closure(v0, steps), v1) = *tuple.clone() else { panic!("Impossible") };
+            let mut new_steps = steps.to_vec();
+            new_steps.append(&mut tail.to_vec());
+            run(new_steps.to_vec(), Value::Pair(Box::new((*v0, v1))), s)
+        },
+        (None, v, None) => v,
+        _ => panic!("Impossible"),
+    }
+}
+
+
+pub fn main() {
+    use Term::*;
+    println!("CAM:");
+
+    let t1 = Car(Box::new(MkPair(Box::new((Lit(1), Lit(2))))));
+    println!("t1: {:?}", t1.eval());
+
+    let t2 = App(Box::new((App(Box::new((Lam(Box::new(Var(0))), Lam(Box::new(Var(0)))))), Lam(Box::new(Var(0))))));
+    println!("t2: {:?}", t2.eval());
+}
diff --git a/src/virtual_machines/mod.rs b/src/virtual_machines/mod.rs
new file mode 100644 (file)
index 0000000..cd0883a
--- /dev/null
@@ -0,0 +1 @@
+pub mod cam;