summaryrefslogtreecommitdiff
path: root/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/Compat210Component.scala
blob: f3573372f7b2190c34a4cd1ce0f70b1519979c45 (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
/* Scala.js compiler
 * Copyright 2013 LAMP/EPFL
 * @author  Sébastien Doeraene
 */

package scala.scalajs.compiler

import scala.tools.nsc._

/** Hacks to have our source code compatible with 2.10 and 2.11.
 *  It exposes 2.11 API in a 2.10 compiler.
 *
 *  @author Sébastien Doeraene
 */
trait Compat210Component {

  val global: Global

  import global._

  // unexpandedName replaces originalName

  implicit final class SymbolCompat(self: Symbol) {
    def unexpandedName: Name = self.originalName
    def originalName: Name = sys.error("infinite loop in Compat")

    def isLocalToBlock: Boolean = self.isLocal
  }

  // enteringPhase/exitingPhase replace beforePhase/afterPhase

  @inline final def enteringPhase[T](ph: Phase)(op: => T): T = {
    global.enteringPhase(ph)(op)
  }

  @inline final def exitingPhase[T](ph: Phase)(op: => T): T = {
    global.exitingPhase(ph)(op)
  }

  private implicit final class GlobalCompat(
      self: Compat210Component.this.global.type) {

    def enteringPhase[T](ph: Phase)(op: => T): T = self.beforePhase(ph)(op)
    def beforePhase[T](ph: Phase)(op: => T): T = sys.error("infinite loop in Compat")

    def exitingPhase[T](ph: Phase)(op: => T): T = self.afterPhase(ph)(op)
    def afterPhase[T](ph: Phase)(op: => T): T = sys.error("infinite loop in Compat")
  }

  // ErasedValueType has a different encoding

  implicit final class ErasedValueTypeCompat(self: global.ErasedValueType) {
    def valueClazz: Symbol = self.original.typeSymbol
    def erasedUnderlying: Type =
      enteringPhase(currentRun.erasurePhase)(
          erasure.erasedValueClassArg(self.original))
    def original: TypeRef = sys.error("infinite loop in Compat")
  }

  // repeatedToSingle

  @inline final def repeatedToSingle(t: Type) =
    global.definitions.repeatedToSingle(t)

  private implicit final class DefinitionsCompat(
    self: Compat210Component.this.global.definitions.type) {

    def repeatedToSingle(t: Type) = t match {
      case TypeRef(_, self.RepeatedParamClass, arg :: Nil) => arg
      case _ => t
    }

  }

  // run.runDefinitions bundles methods and state related to the run
  // that were previously in definitions itself

  implicit final class RunCompat(self: Run) {
    val runDefinitions: Compat210Component.this.global.definitions.type =
      global.definitions
  }

  // Mode.FUNmode replaces analyzer.FUNmode

  object Mode {
    import Compat210Component.AnalyzerCompat
    // No type ascription! Type is different in 2.10 / 2.11
    val FUNmode = analyzer.FUNmode
  }
}

object Compat210Component {
  private object LowPriorityMode {
    object Mode {
      def FUNmode = sys.error("infinite loop in Compat")
    }
  }

  private implicit final class AnalyzerCompat(self: scala.tools.nsc.typechecker.Analyzer) {
    def FUNmode = {
      import Compat210Component.LowPriorityMode._
      {
        import scala.reflect.internal._
        Mode.FUNmode
      }
    }
  }
}