Advertisement
Guest User

Untitled

a guest
Mar 5th, 2015
288
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.54 KB | None | 0 0
  1. import scala.collection.mutable
  2. import scala.language.dynamics
  3.  
  4. trait Properties extends Dynamic {
  5.   def properties: mutable.Map[String, Any]
  6.  
  7.   /*
  8.   def applyDynamic(name: String)(tuples: (String, Any)*): Any =
  9.     ???
  10.   */
  11.  
  12.   import Properties.seqToTuple
  13.  
  14.   def applyDynamic(name: String)(args: Any*): Any = {
  15.     val o = selectDynamic(name)
  16.     if (!o.isInstanceOf[JSFunction[_]]) {
  17.       throw new Exception()
  18.     }
  19.  
  20.     val f = o.asInstanceOf[JSFunction[Any]]
  21.     f(seqToTuple(args))
  22.   }
  23.  
  24.   def selectDynamic(name: String): Any =
  25.     properties.get(name).getOrElse(JSUndefined)
  26.  
  27.   def updateDynamic(name: String)(value: Any): Unit =
  28.     properties(name) = value
  29.  
  30.   def stringify: String = {
  31.     val props = properties.iterator.map {
  32.       case (key, value) => s"'$key': $value"
  33.     }.mkString(", ")
  34.     s"{$props}"
  35.   }
  36. }
  37.  
  38. object Properties {
  39.   def buildMap(props: (Any, Any)*): mutable.Map[String, Any] = {
  40.     val builder = mutable.Map.newBuilder[String, Any]
  41.     props.foreach {
  42.       case prop @ (key: String, _) => builder += prop.asInstanceOf[(String, Any)]
  43.       case (key: Symbol, value) => builder += (key.name -> value)
  44.       case (key, value) => builder += (key.toString -> value)
  45.     }
  46.     builder.result
  47.   }
  48.  
  49.   def seqToTuple(seq: Seq[Any]): Product = seq match {
  50.     case Seq(a) => Tuple1(a)
  51.     case Seq(a, b) => (a, b)
  52.     case Seq(a, b, c) => (a, b, c)
  53.     case Seq(a, b, c, d) => (a, b, c, d)
  54.     case Seq(a, b, c, d, e) => (a, b, c, d, e)
  55.   }
  56. }
  57.  
  58. trait BooleanLike {
  59.   def toJSBoolean: JSBoolean
  60.   def truthy: Boolean = (toJSBoolean == JSTrue)
  61.   def falsy: Boolean = (toJSBoolean == JSFalse)
  62. }
  63.  
  64. sealed trait JSValue
  65.  
  66. case object JSInfinity extends JSValue with BooleanLike {
  67.   override def toString = "Infinity"
  68.   val toJSBoolean = JSTrue
  69. }
  70.  
  71. case object NaN extends JSValue with BooleanLike {
  72.   override def toString = "NaN"
  73.   override def equals(that: Any): Boolean = false
  74.   val toJSBoolean = JSFalse
  75. }
  76.  
  77. case object JSUndefined extends JSValue with BooleanLike {
  78.   override def toString = "undefined"
  79.   val toJSBoolean = JSFalse
  80. }
  81.  
  82. case object JSNull extends JSValue with BooleanLike {
  83.   override def toString = "null"
  84.   val toJSBoolean = JSFalse
  85. }
  86.  
  87. trait ObjectLike
  88.   extends JSValue
  89.   with Properties
  90.   with BooleanLike
  91. {
  92.   override def toString = stringify
  93.   def toJSBoolean = JSTrue
  94. }
  95.  
  96. case class JSObject(properties: mutable.Map[String, Any]) extends ObjectLike
  97.  
  98. object JSObject {
  99.   def apply(props: (Any, Any)*): JSObject =
  100.     new JSObject(Properties.buildMap(props: _*))
  101. }
  102.  
  103. class JSFunction[R](args: Seq[Symbol], f: Product => R)
  104.   extends JSValue
  105.   with Properties
  106.   with BooleanLike
  107. {
  108.   val properties = mutable.Map[String, Any]()
  109.   val toJSBoolean = JSTrue
  110.  
  111.   def apply(product: Product): R =
  112.     f(product)
  113. }
  114.  
  115. object JSFunction {
  116.   def function[R](args: Symbol*)(f: Product => R): JSFunction[R] =
  117.     new JSFunction(args, f)
  118. }
  119.  
  120. import JSFunction._
  121.  
  122. abstract class JSBoolean extends JSValue with BooleanLike {
  123.   def toJSBoolean = this
  124. }
  125.  
  126. case object JSTrue extends JSBoolean
  127. case object JSFalse extends JSBoolean
  128.  
  129. class JSError extends JSValue
  130.  
  131. case class JSNumber(number: Long) extends JSValue
  132.  
  133. object JSMath
  134. object JSDate
  135.  
  136. case class JSString(string: String) extends JSValue with BooleanLike {
  137.   def toJSBoolean =
  138.     if (string.isEmpty) JSFalse else JSTrue
  139. }
  140.  
  141. case class JSRegExp(regex: scala.util.matching.Regex) extends JSValue
  142.  
  143. case class JSArray(seq: IndexedSeq[JSValue]) extends ObjectLike {
  144.   val properties = mutable.Map[String, Any]()
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement