aboutsummaryrefslogtreecommitdiff
path: root/sjs/backend/sjs/JSPrimitives.scala
blob: 6c3c5715cac970a7d6d3b7d3a9a4e05d8abd55fd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package dotty.tools.backend.sjs

import dotty.tools.dotc.core._
import Names.TermName
import StdNames._
import Types._
import Contexts._
import Symbols._

import dotty.tools.dotc.ast.tpd._
import dotty.tools.dotc.backend.jvm.DottyPrimitives

import scala.collection.mutable

object JSPrimitives {

  final val GETCLASS = 301 // jl.Object.getClass()

  final val F2JS = 302     // js.Any.fromFunctionN
  final val F2JSTHIS = 303 // js.ThisFunction.fromFunctionN

  final val DYNNEW = 304     // js.Dynamic.newInstance
  final val DYNLIT = 305     // js.Dynamic.literal.applyDynamic{,Named}
  final val DICT_DEL = 306   // js.Dictionary.delete
  final val ARR_CREATE = 307 // js.Array.apply (array literal syntax)

  final val TYPEOF = 308    // js.typeOf(x)
  final val DEBUGGER = 309  // js.debugger()
  final val HASPROP = 310   // js.Object.hasProperty(o, p), equiv to `p in o` in JS
  final val OBJPROPS = 311  // js.Object.properties(o), equiv to `for (p in o)` in JS
  final val JS_NATIVE = 312 // js.native. Marker method. Fails if tried to be emitted.

  final val UNITVAL = 313  // () value, which is undefined
  final val UNITTYPE = 314 // BoxedUnit.TYPE (== classOf[Unit])

  final val CONSTRUCTOROF = 315 // runtime.constructorOf(clazz)
  final val ENV_INFO = 316      // runtime.environmentInfo
  final val LINKING_INFO = 317  // runtime.linkingInfo

  final val THROW = 318 // <special-ops>.throw

}

class JSPrimitives(ctx: Context) extends DottyPrimitives(ctx) {
  import JSPrimitives._
  import scala.tools.nsc.backend.ScalaPrimitives._

  private lazy val jsPrimitives: Map[Symbol, Int] = initJSPrimitives(ctx)

  override def getPrimitive(sym: Symbol): Int =
    jsPrimitives.getOrElse(sym, super.getPrimitive(sym))

  override def getPrimitive(app: Apply, tpe: Type)(implicit ctx: Context): Int =
    jsPrimitives.getOrElse(app.fun.symbol, super.getPrimitive(app, tpe))

  override def isPrimitive(fun: Tree): Boolean =
    jsPrimitives.contains(fun.symbol(ctx)) || super.isPrimitive(fun)

  /** Initialize the primitive map */
  private def initJSPrimitives(implicit ctx: Context): Map[Symbol, Int] = {

    val primitives = new mutable.HashMap[Symbol, Int]()

    // !!! Code duplicate with DottyPrimitives
    /** Add a primitive operation to the map */
    def addPrimitive(s: Symbol, code: Int): Unit = {
      assert(!(primitives contains s), "Duplicate primitive " + s)
      primitives(s) = code
    }

    def addPrimitives(cls: Symbol, method: TermName, code: Int)(implicit ctx: Context): Unit = {
      val alts = cls.info.member(method).alternatives.map(_.symbol)
      if (alts.isEmpty) {
        ctx.error(s"Unknown primitive method $cls.$method")
      } else {
        for (s <- alts)
          addPrimitive(s, code)
      }
    }

    val jsdefn = JSDefinitions.jsdefn

    addPrimitive(defn.Any_getClass, GETCLASS)

    for (i <- 0 to 22)
      addPrimitive(jsdefn.JSAny_fromFunction(i), F2JS)
    for (i <- 1 to 22)
      addPrimitive(jsdefn.JSThisFunction_fromFunction(i), F2JSTHIS)

    addPrimitive(jsdefn.JSDynamic_newInstance, DYNNEW)

    addPrimitive(jsdefn.JSDynamicLiteral_applyDynamicNamed, DYNLIT)
    addPrimitive(jsdefn.JSDynamicLiteral_applyDynamic, DYNLIT)

    addPrimitive(jsdefn.JSDictionary_delete, DICT_DEL)

    //addPrimitive(jsdefn.JSArray_create, ARR_CREATE)

    addPrimitive(jsdefn.JSPackage_typeOf, TYPEOF)
    addPrimitive(jsdefn.JSPackage_debugger, DEBUGGER)
    addPrimitive(jsdefn.JSPackage_native, JS_NATIVE)

    addPrimitive(jsdefn.JSObject_hasProperty, HASPROP)
    addPrimitive(jsdefn.JSObject_properties, OBJPROPS)

    addPrimitive(defn.BoxedUnit_UNIT, UNITVAL)
    //addPrimitive(defn.BoxedUnit_TYPE, UNITTYPE)

    //addPrimitive(jsdefn.Runtime_constructorOf, CONSTRUCTOROF)
    //addPrimitive(jsdefn.Runtime_environmentInfo, ENV_INFO)
    //addPrimitive(jsdefn.Runtime_linkingInfo, LINKING_INFO)

    addPrimitive(defn.throwMethod, THROW)

    primitives.toMap
  }

}