Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import scala.collection.mutable
- import scala.language.dynamics
- trait Properties extends Dynamic {
- def properties: mutable.Map[String, Any]
- /*
- def applyDynamic(name: String)(tuples: (String, Any)*): Any =
- ???
- */
- import Properties.seqToTuple
- def applyDynamic(name: String)(args: Any*): Any = {
- val o = selectDynamic(name)
- if (!o.isInstanceOf[JSFunction[_]]) {
- throw new Exception()
- }
- val f = o.asInstanceOf[JSFunction[Any]]
- f(seqToTuple(args))
- }
- def selectDynamic(name: String): Any =
- properties.get(name).getOrElse(JSUndefined)
- def updateDynamic(name: String)(value: Any): Unit =
- properties(name) = value
- def stringify: String = {
- val props = properties.iterator.map {
- case (key, value) => s"'$key': $value"
- }.mkString(", ")
- s"{$props}"
- }
- }
- object Properties {
- def buildMap(props: (Any, Any)*): mutable.Map[String, Any] = {
- val builder = mutable.Map.newBuilder[String, Any]
- props.foreach {
- case prop @ (key: String, _) => builder += prop.asInstanceOf[(String, Any)]
- case (key: Symbol, value) => builder += (key.name -> value)
- case (key, value) => builder += (key.toString -> value)
- }
- builder.result
- }
- def seqToTuple(seq: Seq[Any]): Product = seq match {
- case Seq(a) => Tuple1(a)
- case Seq(a, b) => (a, b)
- case Seq(a, b, c) => (a, b, c)
- case Seq(a, b, c, d) => (a, b, c, d)
- case Seq(a, b, c, d, e) => (a, b, c, d, e)
- }
- }
- trait BooleanLike {
- def toJSBoolean: JSBoolean
- def truthy: Boolean = (toJSBoolean == JSTrue)
- def falsy: Boolean = (toJSBoolean == JSFalse)
- }
- sealed trait JSValue
- case object JSInfinity extends JSValue with BooleanLike {
- override def toString = "Infinity"
- val toJSBoolean = JSTrue
- }
- case object NaN extends JSValue with BooleanLike {
- override def toString = "NaN"
- override def equals(that: Any): Boolean = false
- val toJSBoolean = JSFalse
- }
- case object JSUndefined extends JSValue with BooleanLike {
- override def toString = "undefined"
- val toJSBoolean = JSFalse
- }
- case object JSNull extends JSValue with BooleanLike {
- override def toString = "null"
- val toJSBoolean = JSFalse
- }
- trait ObjectLike
- extends JSValue
- with Properties
- with BooleanLike
- {
- override def toString = stringify
- def toJSBoolean = JSTrue
- }
- case class JSObject(properties: mutable.Map[String, Any]) extends ObjectLike
- object JSObject {
- def apply(props: (Any, Any)*): JSObject =
- new JSObject(Properties.buildMap(props: _*))
- }
- class JSFunction[R](args: Seq[Symbol], f: Product => R)
- extends JSValue
- with Properties
- with BooleanLike
- {
- val properties = mutable.Map[String, Any]()
- val toJSBoolean = JSTrue
- def apply(product: Product): R =
- f(product)
- }
- object JSFunction {
- def function[R](args: Symbol*)(f: Product => R): JSFunction[R] =
- new JSFunction(args, f)
- }
- import JSFunction._
- abstract class JSBoolean extends JSValue with BooleanLike {
- def toJSBoolean = this
- }
- case object JSTrue extends JSBoolean
- case object JSFalse extends JSBoolean
- class JSError extends JSValue
- case class JSNumber(number: Long) extends JSValue
- object JSMath
- object JSDate
- case class JSString(string: String) extends JSValue with BooleanLike {
- def toJSBoolean =
- if (string.isEmpty) JSFalse else JSTrue
- }
- case class JSRegExp(regex: scala.util.matching.Regex) extends JSValue
- case class JSArray(seq: IndexedSeq[JSValue]) extends ObjectLike {
- val properties = mutable.Map[String, Any]()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement