aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/backend/sjs/JSPrimitives.scala
blob: 52b5dc4b964b774b91c4073cb6f1e0c8fdbaee64 (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
119
120
121
122
123
124
125
126
127
128
129
130
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

    // For some reason, the JVM primitive set does not register those
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newBooleanArray")), NEW_ZARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newByteArray")), NEW_BARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newShortArray")), NEW_SARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newCharArray")), NEW_CARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newIntArray")), NEW_IARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newLongArray")), NEW_LARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newFloatArray")), NEW_FARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newDoubleArray")), NEW_DARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newRefArray")), NEW_OARRAY)
    addPrimitive(defn.DottyArraysModule.requiredMethod(Names.termName("newUnitArray")), NEW_OARRAY)

    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
  }

}