Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::marker::{PhantomData};
- use std::mem::{transmute};
- /// `Exp<T>` represents a simple expression with type `T`.
- #[derive(Clone)]
- pub struct Exp<T> {
- phan: PhantomData<T>,
- rep: Box<Rep>,
- }
- #[derive(Clone)]
- enum Rep {
- Constant(Val),
- Less(Exp<i32>, Exp<i32>),
- Cond(Exp<bool>, Box<Rep>, Box<Rep>),
- }
- #[derive(Copy, Clone)]
- enum Type { I, B }
- #[derive(Copy, Clone)]
- enum Val { I(i32), B(bool) }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- pub fn num(x: i32) -> Exp<i32> {
- Exp::new(Rep::Constant(Val::I(x)))
- }
- pub fn bol(x: bool) -> Exp<bool> {
- Exp::new(Rep::Constant(Val::B(x)))
- }
- pub fn less(a: Exp<i32>, b: Exp<i32>) -> Exp<bool> {
- Exp::new(Rep::Less(a, b))
- }
- pub fn cond<T>(a: Exp<bool>, b: Exp<T>, c: Exp<T>) -> Exp<T> {
- Exp::new(Rep::Cond(a, b.rep, c.rep))
- }
- impl<T> Exp<T> {
- fn new(rep: Rep) -> Self {
- Exp { phan: PhantomData, rep: Box::new(rep) }
- }
- }
- impl<T: Copy> Exp<T> {
- pub fn eval(&self) -> T {
- match self.rep.type_of() {
- Type::I =>
- *unsafe { transmute::<&i32, &T>(&self.rep.eval().into_int()) },
- Type::B =>
- *unsafe { transmute::<&bool, &T>(&self.rep.eval().into_bool()) },
- }
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- impl Rep {
- fn type_of(&self) -> Type {
- match *self {
- Rep::Constant(Val::I(_)) => Type::I,
- Rep::Constant(Val::B(_)) => Type::B,
- Rep::Less(_, _) => Type::B,
- Rep::Cond(_, ref a, _) => a.type_of(),
- }
- }
- fn eval(&self) -> Val {
- match *self {
- Rep::Constant(v) =>
- v,
- Rep::Less(ref x, ref y) =>
- Val::B(x.eval() < y.eval()),
- Rep::Cond(ref c, ref x, ref y) =>
- if c.eval() {
- x.eval()
- } else {
- y.eval()
- },
- }
- }
- }
- impl Val {
- fn into_int(self) -> i32 {
- match self {
- Val::I(x) => x,
- Val::B(_) => unreachable!(),
- }
- }
- fn into_bool(self) -> bool {
- match self {
- Val::B(x) => x,
- Val::I(_) => unreachable!(),
- }
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- fn main() {
- let e1: Exp<i32> =
- cond(less(num(4), num(8)),
- num(100),
- num(200));
- let e2: Exp<bool> =
- less(e1.clone(), num(99));
- // let e3 =
- // cond(less(num(4), num(8)),
- // num(100),
- // bol(true)); // static type error - type mismatch on branches
- print!("e1 --> {}\n", e1.eval());
- print!("e2 --> {}\n", e2.eval());
- }
Add Comment
Please, Sign In to add comment