Advertisement
Guest User

Untitled

a guest
May 30th, 2015
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.86 KB | None | 0 0
  1. object exp {
  2.  
  3. sealed trait ExprTpe[T]
  4. sealed trait ExprPrimitiveTpe[T] extends ExprTpe[T]
  5. sealed trait ExprContainerTpe[T] extends ExprTpe[T] {
  6. def mapping: List[(String, ExprTpe[_])]
  7. }
  8.  
  9. case class ContainerTpe2[A, B](_1: ExprTpe[A], nme1: String, _2: ExprTpe[B], nme2: String) extends ExprContainerTpe[(A, B)] {
  10. override def toString = s"""Type container of ${_1} and ${_2}"""
  11.  
  12. override val mapping = List(nme1 -> _1, nme2 -> _2)
  13. }
  14.  
  15. case class TransformingTpe[A, B](_1: ExprTpe[A], _2: ExprTpe[B]) extends ExprTpe[Fn[A, B]] {
  16. override def toString = s"""Type container of ${_1} and ${_2}"""
  17. }
  18.  
  19. case object PInt extends ExprPrimitiveTpe[Int]
  20. case object PDouble extends ExprPrimitiveTpe[Double]
  21. case object PFloat extends ExprPrimitiveTpe[Float]
  22. case object PBoolean extends ExprPrimitiveTpe[Boolean]
  23.  
  24. object ExprTpe {
  25. implicit def pIntProvider: ExprTpe[Int] = PInt
  26. implicit def pDoubleProvider: ExprTpe[Double] = PDouble
  27. implicit def pFloatProvider: ExprTpe[Float] = PFloat
  28. implicit def pBooleanProvider: ExprTpe[Boolean] = PBoolean
  29. implicit def container2[T: ExprTpe, U: ExprTpe]: ExprContainerTpe[(T, U)] =
  30. ContainerTpe2(implicitly[ExprTpe[T]], "_1", implicitly[ExprTpe[U]], "_2")
  31. implicit def exprTpeProvider[A:ExprTpe, B: ExprTpe]: ExprTpe[Fn[A, B]] = TransformingTpe(implicitly, implicitly)
  32. }
  33.  
  34. case class Scope(m: Map[Var[_], Exp[_]]) {
  35. def put[T](pair: (Var[T], Exp[T])): Scope = new Scope(m + pair)
  36. def apply[T](v: Var[T]): Either[String, Exp[T]] = m.get(v) match {
  37. case Some(exp) => Right(exp.asInstanceOf[Exp[T]])
  38. case None => Left(s"$v not found. Scope: $m")
  39. }
  40. }
  41. object Scope {
  42. def empty: Scope = Scope(Map.empty)
  43. }
  44.  
  45. sealed trait Exp[A] {
  46. def tpeInfo: ExprTpe[A]
  47. /**
  48. * Either evaluate the Expression, or return an error string
  49. * (about missing Vars is the only thing that can go wrong)
  50. */
  51. private[exp] def run(scope: Scope): Either[String, A]
  52. }
  53.  
  54. case class Const[A: ExprTpe](get: A) extends Exp[A] {
  55. override val tpeInfo = implicitly[ExprTpe[A]]
  56.  
  57. private[exp] def run(scope: Scope) = Right(get)
  58. }
  59. case class Pair[A: ExprTpe, B: ExprTpe](first: Exp[A], second: Exp[B]) extends Exp[(A, B)] {
  60. override val tpeInfo = implicitly[ExprTpe[(A, B)]]
  61. private[exp] def run(scope: Scope) = for {
  62. a <- first.run(scope).right
  63. b <- second.run(scope).right
  64. } yield (a, b)
  65. }
  66.  
  67. case class Apply[B: ExprTpe, A: ExprTpe](in: Exp[B], fn: Exp[Fn[B, A]]) extends Exp[A] {
  68. override val tpeInfo = implicitly[ExprTpe[A]]
  69. private[exp] def run(scope: Scope) = for {
  70. b <- in.run(scope).right
  71. f <- fn.run(scope).right
  72. } yield f.run(b)
  73. }
  74.  
  75. case class Var[A: ExprTpe](name: String) extends Exp[A] {
  76. override val tpeInfo = implicitly[ExprTpe[A]]
  77. private[exp] def run(scope: Scope) = for {
  78. a <- scope(this).right
  79. result <- a.run(scope).right
  80. } yield result
  81. }
  82. case class Lambda[A: ExprTpe, B: ExprTpe](x: Var[A], result: Exp[B]) extends Exp[Fn[A, B]] {
  83. override val tpeInfo = implicitly[ExprTpe[Fn[A, B]]]
  84. private[exp] def run(scope: Scope) = Right(Fn.LambdaFn(this, scope))
  85. }
  86. // Private Fn class, so we can't write general scala functions
  87. sealed trait Fn[A, B] {
  88. private[exp] def run(a: A): B
  89. }
  90.  
  91.  
  92.  
  93. object Exp {
  94. // would not be here in real life, as it is an escape hatch
  95. // instead, we would convert the Exp to code/source that can
  96. // be run elsewhere
  97. def run[A](e: Exp[A]): Either[String, A] = e.run(Scope.empty)
  98.  
  99. implicit class FnExp[A: ExprTpe, B: ExprTpe](val e: Exp[Fn[A, B]]) {
  100. def apply(a: Exp[A]): Exp[B] = Apply[A, B](a, e)
  101. def andThen[C: ExprTpe](that: Exp[Fn[B, C]]): Exp[Fn[A, C]] = {
  102. val va = Var[A]("a")
  103. val eb = Apply(va, e)
  104. val ec = Apply(eb, that)
  105. Lambda(va, ec)
  106. }
  107. def zip[C: ExprTpe](that: Exp[Fn[A, C]]): Exp[Fn[A, (B, C)]] = {
  108. val va = Var[A]("a")
  109. val b = Apply(va, e)
  110. val c = Apply(va, that)
  111. Lambda(va, Pair(b, c))
  112. }
  113. }
  114. }
  115.  
  116. object Fn {
  117.  
  118. import ExprTpe._
  119. def fst[A: ExprTpe, B: ExprTpe](p: Exp[(A, B)]): Exp[A] = Apply(p, lift(Fst[A, B]()))
  120. def snd[A: ExprTpe, B: ExprTpe](p: Exp[(A, B)]): Exp[B] = Apply(p, lift(Snd[A, B]()))
  121.  
  122. def addInt(a: Exp[Int], b: Exp[Int]): Exp[Int] =
  123. Apply(Pair(a, b), lift(AddInt))
  124.  
  125. def ifThenElse[A: ExprTpe](b: Exp[Boolean], iftrue: Exp[A], iffalse: Exp[A]): Exp[A] =
  126. Apply(Pair(b, Pair(iftrue, iffalse)), lift(IfThenElse[A]()))
  127.  
  128. def select[A, B](a: Exp[A], fieldName: String): Exp[B] = {
  129. a.tpeInfo match {
  130. case container: ExprContainerTpe[_] =>
  131. val indx = container
  132. .mapping
  133. .indexWhere(e => e._1 == fieldName)
  134. require(indx >= 0)
  135. implicit val tpeInfoA: ExprTpe[A] = a.tpeInfo.asInstanceOf[ExprTpe[A]]
  136.  
  137. implicit val tpeInfoB: ExprTpe[B] = container.mapping(indx)._2.asInstanceOf[ExprTpe[B]]
  138. Apply(a, lift(Select[A, B](indx)))
  139. case _ => sys.error("Should not occur, A is a container Tpe")
  140. }
  141. }
  142. // non fundamental ops
  143.  
  144. def lift[A: ExprTpe, B: ExprTpe](f: Fn[A, B]): Exp[Fn[A, B]] = Const(f)
  145. def swap[A: ExprTpe, B: ExprTpe](p: Exp[(A, B)]): Exp[(B, A)] =
  146. Pair(snd(p), fst(p))
  147.  
  148. def curry[A: ExprTpe, B: ExprTpe, C: ExprTpe](fn: Exp[Fn[(A, B), C]]): Exp[Fn[A, Fn[B, C]]] = {
  149. val a = Var[A]("A")
  150. val b = Var[B]("B")
  151. val pair = Pair(a, b)
  152. val c = Apply(pair, fn)
  153. val fnbc = Lambda(b, c)
  154. Lambda(a, fnbc)
  155. }
  156. def uncurry[A: ExprTpe, B: ExprTpe, C: ExprTpe](fn: Exp[Fn[A, Fn[B, C]]]): Exp[Fn[(A, B), C]] = {
  157. val pair = Var[(A, B)]("pair")
  158. val a = fst(pair)
  159. val fnbc = Apply(a, fn)
  160. val b = snd(pair)
  161. val c = Apply(b, fnbc)
  162. Lambda(pair, c)
  163. }
  164.  
  165. // implementations
  166. private[exp] case class LambdaFn[A: ExprTpe, B: ExprTpe](l: Lambda[A, B], scope: Scope) extends Fn[A, B] {
  167. def run(a: A) = {
  168. val newScope = scope.put(l.x -> Const(a))
  169. val b = l.result.run(newScope)
  170. b.right.get
  171. }
  172. }
  173. private case class Fst[A: ExprTpe, B: ExprTpe]() extends Fn[(A, B), A] {
  174. def run(b: (A, B)) = b._1
  175. }
  176. private case class Snd[A: ExprTpe, B: ExprTpe]() extends Fn[(A, B), B] {
  177. def run(b: (A, B)) = b._2
  178. }
  179. private case object AddInt extends Fn[(Int, Int), Int] {
  180. def run(p: (Int, Int)) = p._1 + p._2
  181. }
  182. private case class IfThenElse[A]() extends Fn[(Boolean, (A, A)), A] {
  183. def run(in: (Boolean, (A, A))) = if(in._1) in._2._1 else in._2._2
  184. }
  185. private case class Select[A, B](idx: Int) extends Fn[A, B] {
  186. def run(in: A) = {
  187. val iter = in.asInstanceOf[Product].productIterator
  188. if (idx > 0) iter.drop(idx)
  189. iter.next.asInstanceOf[B]
  190. }
  191. }
  192. }
  193.  
  194. }
  195.  
  196. /*
  197. scala> import exp._
  198. import exp._
  199.  
  200. scala> val c = Const(123, (245.0, 121))
  201. c: exp.Const[(Int, (Double, Int))] = Const((123,(245.0,121)))
  202.  
  203. scala> val sel = Fn.select(Fn.select(c, "_2"), "_1")
  204. sel: exp.Exp[Nothing] = Apply(Apply(Const((123,(245.0,121))),Const(Select(1))),Const(Select(0)))
  205.  
  206. scala> sel.tpeInfo
  207. res37: exp.ExprTpe[Nothing] = PDouble
  208.  
  209. scala>
  210.  
  211. scala> Exp.run(Fn.select(Fn.select(c, "_2"), "_1"))
  212. res38: Either[String,Nothing] = Right(245.0)
  213. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement