aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/Compiler.scala
blob: ad3249be242790dd949215f743d2202484d9b2ac (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package dotty.tools
package dotc

import core._
import Contexts._
import Periods._
import Symbols._
import Types._
import Scopes._
import typer.{FrontEnd, Typer, ImportInfo, RefChecks}
import reporting.{Reporter, ConsoleReporter}
import Phases.Phase
import transform._
import util.FreshNameCreator
import transform.TreeTransforms.{TreeTransform, TreeTransformer}
import core.DenotTransformers.DenotTransformer
import core.Denotations.SingleDenotation

import dotty.tools.backend.jvm.{LabelDefs, GenBCode, CollectSuperCalls}

/** The central class of the dotc compiler. The job of a compiler is to create
 *  runs, which process given `phases` in a given `rootContext`.
 */
class Compiler {

  /** Meta-ordering constraint:
   *
   *  DenotTransformers that change the signature of their denotation's info must go
   *  after erasure. The reason is that denotations are permanently referred to by
   *  TermRefs which contain a signature. If the signature of a symbol would change,
   *  all refs to it would become outdated - they could not be dereferenced in the
   *  new phase.
   *
   *  After erasure, signature changing denot-transformers are OK because erasure
   *  will make sure that only term refs with fixed SymDenotations survive beyond it. This
   *  is possible because:
   *
   *   - splitter has run, so every ident or select refers to a unique symbol
   *   - after erasure, asSeenFrom is the identity, so every reference has a
   *     plain SymDenotation, as opposed to a UniqueRefDenotation.
   */
  def phases: List[List[Phase]] =
    List(
      List(new FrontEnd),           // Compiler frontend: scanner, parser, namer, typer
      List(new sbt.ExtractDependencies), // Sends information on classes' dependencies to sbt via callbacks
      List(new PostTyper),          // Additional checks and cleanups after type checking
      List(new sbt.ExtractAPI),     // Sends a representation of the API of classes to sbt via callbacks
      List(new Pickler),            // Generate TASTY info
      List(new FirstTransform,      // Some transformations to put trees into a canonical form
           new CheckReentrant),     // Internal use only: Check that compiled program has no data races involving global vars
      List(new RefChecks,           // Various checks mostly related to abstract members and overriding
           new CheckStatic,         // Check restrictions that apply to @static members
           new ElimRepeated,        // Rewrite vararg parameters and arguments
           new NormalizeFlags,      // Rewrite some definition flags
           new ExtensionMethods,    // Expand methods of value classes with extension methods
           new ExpandSAMs,          // Expand single abstract method closures to anonymous classes
           new TailRec,             // Rewrite tail recursion to loops
           new LiftTry,             // Put try expressions that might execute on non-empty stacks into their own methods
           new ClassOf),            // Expand `Predef.classOf` calls.
      List(new TryCatchPatterns,    // Compile cases in try/catch
           new PatternMatcher,      // Compile pattern matches
           new ExplicitOuter,       // Add accessors to outer classes from nested ones.
           new ExplicitSelf,        // Make references to non-trivial self types explicit as casts
           new CrossCastAnd,        // Normalize selections involving intersection types.
           new Splitter),           // Expand selections involving union types into conditionals
      List(new VCInlineMethods,     // Inlines calls to value class methods
           new IsInstanceOfEvaluator, // Issues warnings when unreachable statements are present in match/if expressions
           new SeqLiterals,         // Express vararg arguments as arrays
           new InterceptedMethods,  // Special handling of `==`, `|=`, `getClass` methods
           new Getters,             // Replace non-private vals and vars with getter defs (fields are added later)
           new ElimByName,          // Expand by-name parameters and arguments
           new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings
           new ResolveSuper,        // Implement super accessors and add forwarders to trait methods
           new ArrayConstructors),  // Intercept creation of (non-generic) arrays and intrinsify.
      List(new Erasure),            // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
      List(new ElimErasedValueType, // Expand erased value types to their underlying implmementation types
           new VCElideAllocations,  // Peep-hole optimization to eliminate unnecessary value class allocations
           new Mixin,               // Expand trait fields and trait initializers
           new LazyVals,            // Expand lazy vals
           new Memoize,             // Add private fields to getters and setters
           new LinkScala2ImplClasses, // Forward calls to the implementation classes of traits defined by Scala 2.11
           new NonLocalReturns,     // Expand non-local returns
           new CapturedVars,        // Represent vars captured by closures as heap objects
           new Constructors,        // Collect initialization code in primary constructors
                                       // Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
           new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
           new GetClass),           // Rewrites getClass calls on primitive types.
      List(new LambdaLift,          // Lifts out nested functions to class scope, storing free variables in environments
                                       // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
           new ElimStaticThis,      // Replace `this` references to static objects by global identifiers
           new Flatten,             // Lift all inner classes to package scope
           new RestoreScopes),      // Repair scopes rendered invalid by moving definitions in prior phases of the group
      List(new ExpandPrivate,       // Widen private definitions accessed from nested classes
           new SelectStatic,        // get rid of selects that would be compiled into GetStatic
           new CollectEntryPoints,  // Find classes with main methods
           new CollectSuperCalls,   // Find classes that are called with super
           new DropInlined,         // Drop Inlined nodes, since backend has no use for them
           new MoveStatics,         // Move static methods to companion classes
           new LabelDefs),          // Converts calls to labels to jumps
      List(new GenBCode)            // Generate JVM bytecode
    )

  var runId = 1
  def nextRunId = {
    runId += 1; runId
  }

  /** Produces the following contexts, from outermost to innermost
   *
   *    bootStrap:   A context with next available runId and a scope consisting of
   *                 the RootPackage _root_
   *    start        A context with RootClass as owner and the necessary initializations
   *                 for type checking.
   *    imports      For each element of RootImports, an import context
   */
  def rootContext(implicit ctx: Context): Context = {
    ctx.initialize()(ctx)
    ctx.setPhasePlan(phases)
    val rootScope = new MutableScope
    val bootstrap = ctx.fresh
      .setPeriod(Period(nextRunId, FirstPhaseId))
      .setScope(rootScope)
    rootScope.enter(ctx.definitions.RootPackage)(bootstrap)
    val start = bootstrap.fresh
      .setOwner(defn.RootClass)
      .setTyper(new Typer)
      .setMode(Mode.ImplicitsEnabled)
      .setTyperState(new MutableTyperState(ctx.typerState, ctx.typerState.reporter, isCommittable = true))
      .setFreshNames(new FreshNameCreator.Default)
  ctx.initialize()(start) // re-initialize the base context with start
    def addImport(ctx: Context, refFn: () => TermRef) =
      ctx.fresh.setImportInfo(ImportInfo.rootImport(refFn)(ctx))
    (start.setRunInfo(new RunInfo(start)) /: defn.RootImportFns)(addImport)
  }

  def reset()(implicit ctx: Context): Unit = {
    ctx.base.reset()
    ctx.runInfo.clear()
  }

  def newRun(implicit ctx: Context): Run = {
    reset()
    new Run(this)(rootContext)
  }
}