Guest User

Untitled

a guest
Sep 21st, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.52 KB | None | 0 0
  1. use std::marker::{PhantomData};
  2. use std::mem::{transmute};
  3.  
  4. /// `Exp<T>` represents a simple expression with type `T`.
  5. #[derive(Clone)]
  6. pub struct Exp<T> {
  7. phan: PhantomData<T>,
  8. rep: Box<Rep>,
  9. }
  10.  
  11. #[derive(Clone)]
  12. enum Rep {
  13. Constant(Val),
  14. Less(Exp<i32>, Exp<i32>),
  15. Cond(Exp<bool>, Box<Rep>, Box<Rep>),
  16. }
  17.  
  18. #[derive(Copy, Clone)]
  19. enum Type { I, B }
  20.  
  21. #[derive(Copy, Clone)]
  22. enum Val { I(i32), B(bool) }
  23.  
  24. ////////////////////////////////////////////////////////////////////////////////////////////////////
  25.  
  26. pub fn num(x: i32) -> Exp<i32> {
  27. Exp::new(Rep::Constant(Val::I(x)))
  28. }
  29.  
  30. pub fn bol(x: bool) -> Exp<bool> {
  31. Exp::new(Rep::Constant(Val::B(x)))
  32. }
  33.  
  34. pub fn less(a: Exp<i32>, b: Exp<i32>) -> Exp<bool> {
  35. Exp::new(Rep::Less(a, b))
  36. }
  37.  
  38. pub fn cond<T>(a: Exp<bool>, b: Exp<T>, c: Exp<T>) -> Exp<T> {
  39. Exp::new(Rep::Cond(a, b.rep, c.rep))
  40. }
  41.  
  42. impl<T> Exp<T> {
  43. fn new(rep: Rep) -> Self {
  44. Exp { phan: PhantomData, rep: Box::new(rep) }
  45. }
  46. }
  47.  
  48. impl<T: Copy> Exp<T> {
  49. pub fn eval(&self) -> T {
  50. match self.rep.type_of() {
  51. Type::I =>
  52. *unsafe { transmute::<&i32, &T>(&self.rep.eval().into_int()) },
  53. Type::B =>
  54. *unsafe { transmute::<&bool, &T>(&self.rep.eval().into_bool()) },
  55. }
  56. }
  57. }
  58.  
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////
  60.  
  61. impl Rep {
  62. fn type_of(&self) -> Type {
  63. match *self {
  64. Rep::Constant(Val::I(_)) => Type::I,
  65. Rep::Constant(Val::B(_)) => Type::B,
  66. Rep::Less(_, _) => Type::B,
  67. Rep::Cond(_, ref a, _) => a.type_of(),
  68. }
  69. }
  70.  
  71. fn eval(&self) -> Val {
  72. match *self {
  73. Rep::Constant(v) =>
  74. v,
  75.  
  76. Rep::Less(ref x, ref y) =>
  77. Val::B(x.eval() < y.eval()),
  78.  
  79. Rep::Cond(ref c, ref x, ref y) =>
  80. if c.eval() {
  81. x.eval()
  82. } else {
  83. y.eval()
  84. },
  85. }
  86. }
  87. }
  88.  
  89. impl Val {
  90. fn into_int(self) -> i32 {
  91. match self {
  92. Val::I(x) => x,
  93. Val::B(_) => unreachable!(),
  94. }
  95. }
  96.  
  97. fn into_bool(self) -> bool {
  98. match self {
  99. Val::B(x) => x,
  100. Val::I(_) => unreachable!(),
  101. }
  102. }
  103. }
  104.  
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////
  106.  
  107. fn main() {
  108.  
  109. let e1: Exp<i32> =
  110. cond(less(num(4), num(8)),
  111. num(100),
  112. num(200));
  113.  
  114. let e2: Exp<bool> =
  115. less(e1.clone(), num(99));
  116.  
  117. // let e3 =
  118. // cond(less(num(4), num(8)),
  119. // num(100),
  120. // bol(true)); // static type error - type mismatch on branches
  121.  
  122. print!("e1 --> {}\n", e1.eval());
  123. print!("e2 --> {}\n", e2.eval());
  124. }
Add Comment
Please, Sign In to add comment