Skip to content

Commit

Permalink
Merge branch 'master' into ycheck-patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
OlivierBlanvillain authored Feb 12, 2018
2 parents a506b50 + a09f385 commit 66874ed
Show file tree
Hide file tree
Showing 2,327 changed files with 3,709 additions and 2,869 deletions.
5 changes: 5 additions & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ The majority of the dotty codebase is new code, with the exception of the compon
> The lexical and syntactic analysis components were adapted from the current Scala compiler. They were originally authored by Martin Odersky,
> Burak Emir, Paul Phillips, Lex Spoon, Sean McDirmid and others.
`dotty.tools.dotc.profile`

> The per-phase profiling support is taken mostly as is from [scala/scala](https://github.com/scala/scala).
> The original author was Mike Skells.
`dotty.tools.dotc.reporting`

> Adapted from [scala/scala](https://github.com/scala/scala) with some heavy modifications. They were originally authored by Matthias Zenger, Martin Odersky, and others.
Expand Down
21 changes: 3 additions & 18 deletions compiler/sjs/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ class JSCodeGen()(implicit ctx: Context) {
throw new FatalError(s"Assignment to static member ${sym.fullName} not supported")
val genRhs = genExpr(rhs)
val lhs = lhs0 match {
case lhs: Ident => desugarIdent(lhs).getOrElse(lhs)
case lhs: Ident => desugarIdent(lhs)
case lhs => lhs
}
lhs match {
Expand Down Expand Up @@ -850,21 +850,6 @@ class JSCodeGen()(implicit ctx: Context) {
}
} // end of genStatOrExpr()

// !!! DUPLICATE code with DottyBackendInterface
private def desugarIdent(i: Ident): Option[Select] = {
i.tpe match {
case TermRef(prefix: TermRef, name) =>
Some(tpd.ref(prefix).select(i.symbol))
case TermRef(prefix: ThisType, name) =>
Some(tpd.This(prefix.cls).select(i.symbol))
/*case TermRef(NoPrefix, name) =>
if (i.symbol is Method) Some(This(i.symbol.topLevelClass).select(i.symbol)) // workaround #342 todo: remove after fixed
else None*/
case _ =>
None
}
}

private def qualifierOf(fun: Tree): Tree = fun match {
case fun: Ident =>
fun.tpe match {
Expand Down Expand Up @@ -907,7 +892,7 @@ class JSCodeGen()(implicit ctx: Context) {
val sym = tree.fun.symbol

val fun = tree.fun match {
case fun: Ident => desugarIdent(fun).getOrElse(fun)
case fun: Ident => desugarIdent(fun)
case fun => fun
}

Expand Down Expand Up @@ -1571,7 +1556,7 @@ class JSCodeGen()(implicit ctx: Context) {
implicit val pos = tree.pos

val fun = tree.fun match {
case fun: Ident => desugarIdent(fun).get
case fun: Ident => desugarIdent(fun).asInstanceOf[Select]
case fun: Select => fun
}
val receiver = fun.qualifier
Expand Down
15 changes: 5 additions & 10 deletions compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -444,16 +444,12 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
def desugarIdent(i: Ident): Option[tpd.Select] = {
var found = desugared.get(i.tpe)
if (found == null) {
i.tpe match {
case TermRef(prefix: TermRef, _) =>
found = tpd.ref(prefix).select(i.symbol)
case TermRef(prefix: ThisType, _) =>
found = tpd.This(prefix.cls).select(i.symbol)
case TermRef(NoPrefix, _) =>
if (i.symbol is Flags.Method) found = This(i.symbol.topLevelClass).select(i.symbol) // workaround #342 todo: remove after fixed
tpd.desugarIdent(i) match {
case sel: tpd.Select =>
desugared.put(i.tpe, sel)
found = sel
case _ =>
}
if (found != null) desugared.put(i.tpe, found)
}
if (found == null) None else Some(found)
}
Expand Down Expand Up @@ -900,8 +896,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma

def decls: List[Symbol] = tp.decls.toList

def members: List[Symbol] =
tp.memberDenots(takeAllFilter, (name, buf) => buf ++= tp.member(name).alternatives).map(_.symbol).toList
def members: List[Symbol] = tp.allMembers.map(_.symbol).toList

def typeSymbol: Symbol = tp.widenDealias.typeSymbol

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object CompilationUnit {
def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit =
mkCompilationUnit(new SourceFile(clsd.symbol.associatedFile, Seq()), unpickled, forceTrees)

/** Make a compilation unit the given unpickled tree */
/** Make a compilation unit, given picked bytes and unpickled tree */
def mkCompilationUnit(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = {
assert(!unpickled.isEmpty, unpickled)
val unit1 = new CompilationUnit(source)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ class Compiler {
// 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
List(new Flatten, // Lift all inner classes to package scope
new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group
new RenameLifted, // Renames lifted classes to local numbering scheme
new TransformWildcards, // Replace wildcards with default values
new MoveStatics, // Move static methods to companion classes
new ExpandPrivate, // Widen private definitions accessed from nested classes
new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group
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
Expand Down
51 changes: 35 additions & 16 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,26 @@ import Symbols._
import Phases._
import Types._
import Scopes._
import typer.{FrontEnd, Typer, ImportInfo, RefChecks}
import typer.{FrontEnd, ImportInfo, RefChecks, Typer}
import Decorators._
import io.{AbstractFile, PlainFile}

import scala.io.Codec
import util.{Set => _, _}
import reporting.Reporter
import transform.TreeChecker
import rewrite.Rewrites
import java.io.{BufferedWriter, OutputStreamWriter}

import dotty.tools.dotc.profile.Profiler
import printing.XprintMode
import parsing.Parsers.Parser
import typer.ImplicitRunInfo
import collection.mutable

import scala.annotation.tailrec
import dotty.tools.io.VirtualFile

import scala.util.control.NonFatal

/** A compiler run. Exports various methods to compile source files */
Expand Down Expand Up @@ -57,6 +61,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
(start.setRun(this) /: defn.RootImportFns)(addImport)
}

private[this] var compiling = false

private[this] var myCtx = rootContext(ictx)

/** The context created for this run */
Expand All @@ -68,8 +74,6 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
private[this] var myUnits: List[CompilationUnit] = _
private[this] var myUnitsCached: List[CompilationUnit] = _
private[this] var myFiles: Set[AbstractFile] = _
private[this] val myLateUnits = mutable.ListBuffer[CompilationUnit]()
private[this] var myLateFiles = mutable.Set[AbstractFile]()

/** The compilation units currently being compiled, this may return different
* results over time.
Expand All @@ -91,11 +95,11 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
myFiles
}

/** Units that are added from source completers but that are not compiled in current run. */
def lateUnits: List[CompilationUnit] = myLateUnits.toList
/** The source files of all late entered symbols, as a set */
private[this] var lateFiles = mutable.Set[AbstractFile]()

/** The source files of all late units, as a set */
def lateFiles: collection.Set[AbstractFile] = myLateFiles
/** Actions that need to be performed at the end of the current compilation run */
private[this] var finalizeActions = mutable.ListBuffer[() => Unit]()

def getSource(fileName: String): SourceFile = {
val f = new PlainFile(io.Path(fileName))
Expand Down Expand Up @@ -144,6 +148,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint

protected def compileUnits()(implicit ctx: Context) = Stats.maybeMonitored {
ctx.checkSingleThreaded()
compiling = true

// If testing pickler, make sure to stop after pickling phase:
val stopAfter =
Expand All @@ -156,11 +161,15 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint

def runPhases(implicit ctx: Context) = {
var lastPrintedTree: PrintedTree = NoPrintedTree
val profiler = ctx.profiler

for (phase <- ctx.allPhases)
if (phase.isRunnable)
Stats.trackTime(s"$phase ms ") {
val start = System.currentTimeMillis
val profileBefore = profiler.beforePhase(phase)
units = phase.runOn(units)
profiler.afterPhase(phase, profileBefore)
if (ctx.settings.Xprint.value.containsPhase(phase)) {
for (unit <- units) {
lastPrintedTree =
Expand All @@ -172,30 +181,40 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
for (unit <- units)
Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize)
}

profiler.finished()
}

val runCtx = ctx.fresh
runCtx.setProfiler(Profiler())
ctx.phases.foreach(_.initContext(runCtx))
runPhases(runCtx)
if (!ctx.reporter.hasErrors) Rewrites.writeBack()
while (finalizeActions.nonEmpty) {
val action = finalizeActions.remove(0)
action()
}
compiling = false
}

/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
* The newly added symbols replace any previously entered symbols.
* If `typeCheck = true`, also run typer on the compilation unit.
*/
def enterRoots(file: AbstractFile)(implicit ctx: Context): Unit =
def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit =
if (!files.contains(file) && !lateFiles.contains(file)) {
lateFiles += file
val unit = new CompilationUnit(getSource(file.path))
myLateUnits += unit
myLateFiles += file
enterRoots(unit)(runContext.fresh.setCompilationUnit(unit))
def process()(implicit ctx: Context) = {
unit.untpdTree = new Parser(unit.source).parse()
ctx.typer.lateEnter(unit.untpdTree)
def typeCheckUnit() = unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
if (typeCheck)
if (compiling) finalizeActions += (() => typeCheckUnit()) else typeCheckUnit()
}
process()(runContext.fresh.setCompilationUnit(unit))
}

private def enterRoots(unit: CompilationUnit)(implicit ctx: Context): Unit = {
unit.untpdTree = new Parser(unit.source).parse()
ctx.typer.lateEnter(unit.untpdTree)
}

private sealed trait PrintedTree
private /*final*/ case class SomePrintedTree(phase: String, tree: String) extends PrintedTree
private object NoPrintedTree extends PrintedTree
Expand Down
80 changes: 49 additions & 31 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,21 @@ object desugar {
(if (args.isEmpty) tycon else AppliedTypeTree(tycon, args))
.withPos(cdef.pos.startPos)

def appliedRef(tycon: Tree, tparams: List[TypeDef] = constrTparams) =
appliedTypeTree(tycon, tparams map refOfDef)
def appliedRef(tycon: Tree, tparams: List[TypeDef] = constrTparams, widenHK: Boolean = false) = {
val targs = for (tparam <- tparams) yield {
val targ = refOfDef(tparam)
def fullyApplied(tparam: Tree): Tree = tparam match {
case TypeDef(_, LambdaTypeTree(tparams, body)) =>
AppliedTypeTree(targ, tparams.map(_ => TypeBoundsTree(EmptyTree, EmptyTree)))
case TypeDef(_, rhs: DerivedTypeTree) =>
fullyApplied(rhs.watched)
case _ =>
targ
}
if (widenHK) fullyApplied(tparam) else targ
}
appliedTypeTree(tycon, targs)
}

// a reference to the class type bound by `cdef`, with type parameters coming from the constructor
val classTypeRef = appliedRef(classTycon)
Expand Down Expand Up @@ -431,12 +444,16 @@ object desugar {
//
// implicit def eqInstance[T1$1, ..., Tn$1, T1$2, ..., Tn$2](implicit
// ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]])
// : Eq[C[T1$1, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
// : Eq[C[T1$, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
//
// If any of the T_i are higher-kinded, say `Ti[X1 >: L1 <: U1, ..., Xm >: Lm <: Um]`,
// the corresponding type parameters for $ev_i are `Ti$1[_, ..., _], Ti$2[_, ..., _]`
// (with m underscores `_`).
def eqInstance = {
val leftParams = constrTparams.map(derivedTypeParam(_, "$1"))
val rightParams = constrTparams.map(derivedTypeParam(_, "$2"))
val subInstances = (leftParams, rightParams).zipped.map((param1, param2) =>
appliedRef(ref(defn.EqType), List(param1, param2)))
appliedRef(ref(defn.EqType), List(param1, param2), widenHK = true))
DefDef(
name = nme.eqInstance,
tparams = leftParams ++ rightParams,
Expand Down Expand Up @@ -725,6 +742,31 @@ object desugar {
tree
}

/** Translate infix operation expression
*
* l op r ==> l.op(r) if op is left-associative
* ==> r.op(l) if op is right-associative
*/
def binop(left: Tree, op: Ident, right: Tree)(implicit ctx: Context): Apply = {
def assignToNamedArg(arg: Tree) = arg match {
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
case _ => arg
}
def makeOp(fn: Tree, arg: Tree, selectPos: Position) = {
val args: List[Tree] = arg match {
case Parens(arg) => assignToNamedArg(arg) :: Nil
case Tuple(args) => args.mapConserve(assignToNamedArg)
case _ => arg :: Nil
}
Apply(Select(fn, op.name).withPos(selectPos), args)
}

if (isLeftAssoc(op.name))
makeOp(left, right, Position(left.pos.start, op.pos.end, op.pos.start))
else
makeOp(right, left, Position(op.pos.start, right.pos.end))
}

/** Make closure corresponding to function.
* params => body
* ==>
Expand Down Expand Up @@ -832,30 +874,6 @@ object desugar {
Block(ldef, call)
}

/** Translate infix operation expression left op right
*/
def makeBinop(left: Tree, op: Ident, right: Tree): Tree = {
def assignToNamedArg(arg: Tree) = arg match {
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
case _ => arg
}
if (isLeftAssoc(op.name)) {
val args: List[Tree] = right match {
case Parens(arg) => assignToNamedArg(arg) :: Nil
case Tuple(args) => args mapConserve assignToNamedArg
case _ => right :: Nil
}
val selectPos = Position(left.pos.start, op.pos.end, op.pos.start)
Apply(Select(left, op.name).withPos(selectPos), args)
} else {
val x = UniqueName.fresh()
val selectPos = Position(op.pos.start, right.pos.end, op.pos.start)
new InfixOpBlock(
ValDef(x, TypeTree(), left).withMods(synthetic),
Apply(Select(right, op.name).withPos(selectPos), Ident(x).withPos(left.pos)))
}
}

/** Create tree for for-comprehension `<for (enums) do body>` or
* `<for (enums) yield body>` where mapName and flatMapName are chosen
* corresponding to whether this is a for-do or a for-yield.
Expand Down Expand Up @@ -1066,10 +1084,10 @@ object desugar {
if (!op.isBackquoted && op.name == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
else if (!op.isBackquoted && op.name == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
else AppliedTypeTree(op, l :: r :: Nil) // op[l, r]
else if (ctx.mode is Mode.Pattern)
else {
assert(ctx.mode is Mode.Pattern) // expressions are handled separately by `binop`
Apply(op, l :: r :: Nil) // op(l, r)
else // l.op(r), or val x = r; l.op(x), plus handle named args specially
makeBinop(l, op, r)
}
case PostfixOp(t, op) =>
if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == tpnme.raw.STAR) {
val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType
Expand Down
Loading

0 comments on commit 66874ed

Please sign in to comment.