Skip to content

Instantly share code, notes, and snippets.

@belisarius222
Last active March 30, 2020 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save belisarius222/deedffd77436995ad5bcdb0792cdde56 to your computer and use it in GitHub Desktop.
Save belisarius222/deedffd77436995ad5bcdb0792cdde56 to your computer and use it in GitHub Desktop.
Uruk interpreter in Rust
extern crate num;
use num::bigint::{BigUint, ToBigUint};
use std::rc::Rc;
#[derive(Clone, Debug, Eq, PartialEq)]
enum Ur { S, K, J, D }
#[derive(Clone, Debug, Eq, PartialEq)]
enum Exp {
N(Ur),
A(Rc<Exp>, Rc<Exp>),
}
use crate::Ur::{S, K, J, D};
use crate::Exp::{N, A};
fn s() -> Rc<Exp> { Rc::new(N(S)) }
fn k() -> Rc<Exp> { Rc::new(N(K)) }
fn j() -> Rc<Exp> { Rc::new(N(J)) }
fn d() -> Rc<Exp> { Rc::new(N(D)) }
fn a(x: Rc<Exp>, y: Rc<Exp>) -> Rc<Exp> { Rc::new(A(x,y)) }
fn eval(e: Rc<Exp>) -> Rc<Exp> {
match reduce(Rc::clone(&e)) {
None => e,
Some(x) => eval(x)
}
}
fn reduce(e: Rc<Exp>) -> Option<Rc<Exp>> {
match &*e {
N(_) => None,
A(c, d) => {
match reduce(Rc::clone(c)) {
Some(cc) => Some(a(Rc::clone(&cc), Rc::clone(d))),
None =>
match reduce(Rc::clone(d)) {
Some(dd) => Some(a(Rc::clone(c), Rc::clone(&dd))),
None =>
match &**c {
N(D) => Some(jam(Rc::clone(d))),
A(op, l) => {
match &**op {
N(K) =>
Some(Rc::clone(&l)),
A(op2, l2) => { match &**op2 { N(S) =>
Some(a(a(Rc::clone(l2), Rc::clone(d)),
a(Rc::clone(l), Rc::clone(d)))),
_ => None
}}, _ => None
}}, _ => None
}}}
}
}
}
fn jam(x: Rc<Exp>) -> Rc<Exp> {
a(a(a(j(), j()), k()), jam_enc(jam_bits(x).1))
}
fn jam_enc(n: num::BigUint) -> Rc<Exp> {
if 0_i32.to_biguint().unwrap() == n {
a(s(), k())
} else {
a(a(s(), a(a(s(), a(k(), s())), k())),
jam_enc(n - 1_i32.to_biguint().unwrap()))
}
}
fn jam_bits(x: Rc<Exp>) -> (u64, num::BigUint) {
match &*x {
N(S) => (3, 0b000_i32.to_biguint().unwrap()),
N(K) => (3, 0b010_i32.to_biguint().unwrap()),
N(J) => (3, 0b100_i32.to_biguint().unwrap()),
N(D) => (3, 0b110_i32.to_biguint().unwrap()),
A(c, d) => {
let (c_s, c_v) = jam_bits(Rc::clone(c));
let (d_s, d_v) = jam_bits(Rc::clone(d));
let r_s = c_s + d_s + 1;
let r_v = 1_i32.to_biguint().unwrap()
+ (c_v << 1)
+ (d_v << ((c_s as usize) + 1));
(r_s, r_v)
}
}
}
fn main() {
//let x = a(a(k(), d()), j());
let x = a(d(), d());
//let x = a(a(a(s(), k()), s()), k());
let y = eval(x);
println!("result: {:?}", y);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment