Skip to content

Make dotty compile backend. #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 9, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ object DottyBuild extends Build {
// get reflect and xml onboard
libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.scala-lang.modules" %% "scala-xml" % "1.0.1",
"me.d-d" % "scala-compiler" % "2.11.5-20150416-144435-09c4a520e1",
"me.d-d" % "scala-compiler" % "2.11.5-20150506-175515-8fc7635b56",
"org.scala-lang.modules" %% "scala-partest" % "1.0.5" % "test",
"jline" % "jline" % "2.12"),

Expand Down
57 changes: 41 additions & 16 deletions src/dotty/tools/backend/jvm/DottyBackendInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import StdNames.nme
import NameOps._

class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
trait NonExistentTree extends tpd.Tree
type Symbol = Symbols.Symbol
type Type = Types.Type
type Tree = tpd.Tree
Expand Down Expand Up @@ -68,8 +67,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
type Modifiers = tpd.Modifiers
type Annotation = Annotations.Annotation
type ArrayValue = tpd.JavaSeqLiteral
type ApplyDynamic = NonExistentTree
type ModuleDef = NonExistentTree
type ApplyDynamic = Null
type ModuleDef = Null
type LabelDef = tpd.DefDef
type Closure = tpd.Closure

Expand Down Expand Up @@ -230,7 +229,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{

private def emitArgument(av: AnnotationVisitor,
name: String,
arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) {
arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
(arg: @unchecked) match {

case Literal(const @ Constant(_)) =>
Expand Down Expand Up @@ -296,7 +295,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
}
}

override def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) {
override def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)
(innerClasesStore: bcodeStore.BCInnerClassGen) = {
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
val typ = annot.atp
val assocs = annot.assocs
Expand All @@ -305,14 +305,20 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
}
}

private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) {
for ((name, value) <- assocs) {
emitArgument(av, name.toString(), value.asInstanceOf[Tree], bcodeStore)(innerClasesStore)
private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers)
(innerClasesStore: bcodeStore.BCInnerClassGen) = {
//for ((name, value) <- assocs) { // dotty deviation, does not work

for (nv <- assocs) {
val name = nv._1
val value = nv._2
emitArgument(av, name.toString, value.asInstanceOf[Tree], bcodeStore)(innerClasesStore)
}
av.visitEnd()
}

override def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) {
override def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)
(innerClasesStore: bcodeStore.BCInnerClassGen) = {
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
val typ = annot.atp
val assocs = annot.assocs
Expand All @@ -321,7 +327,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
}
}

override def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) {
override def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)
(innerClasesStore: bcodeStore.BCInnerClassGen) = {
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
val typ = annot.atp
val assocs = annot.assocs
Expand All @@ -330,7 +337,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
}
}

override def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) {
override def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]], bcodeStore: BCodeHelpers)
(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
val annotationss = pannotss map (_ filter shouldEmitAnnotation)
if (annotationss forall (_.isEmpty)) return
for ((annots, idx) <- annotationss.zipWithIndex;
Expand Down Expand Up @@ -678,8 +686,24 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{

// members
def primaryConstructor: Symbol = toDenot(sym).primaryConstructor
def nestedClasses: List[Symbol] = memberClasses //exitingPhase(currentRun.lambdaliftPhase)(sym.memberClasses)
def memberClasses: List[Symbol] = toDenot(sym).info.memberClasses.map(_.symbol).toList

/** For currently compiled classes: All locally defined classes including local classes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between a "locally defined class" and a "local class"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is:

class A{
  class B
  def foo = {
    class C
  }
}

Class B is locally defined, class C is local.
Though the naming here is indeed confusing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, "local classes" is Java lingo.

On Fri, May 8, 2015 at 4:43 PM, Dmitry Petrashko [email protected]
wrote:

In src/dotty/tools/backend/jvm/DottyBackendInterface.scala
#543 (comment):

@@ -678,8 +686,24 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{

 // members
 def primaryConstructor: Symbol = toDenot(sym).primaryConstructor
  • def nestedClasses: List[Symbol] = memberClasses //exitingPhase(currentRun.lambdaliftPhase)(sym.memberClasses)
  • def memberClasses: List[Symbol] = toDenot(sym).info.memberClasses.map(_.symbol).toList
  • /** For currently compiled classes: All locally defined classes including local classes.

My guess is:

class A{
class B
def foo = {
class C
}
}

Class B is locally defined, class C is local.
Though the naming here is indeed confusing.


Reply to this email directly or view it on GitHub
https://github.com/lampepfl/dotty/pull/543/files#r29944973.

Martin Odersky
EPFL

* The empty list for classes that are not currently compiled.
*/
def nestedClasses: List[Symbol] = definedClasses(ctx.flattenPhase)

/** For currently compiled classes: All classes that are declared as members of this class
* (but not inherited ones). The empty list for classes that are not currently compiled.
*/
def memberClasses: List[Symbol] = definedClasses(ctx.lambdaLiftPhase)

private def definedClasses(phase: Phase) =
if (sym.isDefinedInCurrentRun)
ctx.atPhase(phase) { implicit ctx =>
toDenot(sym).info.decls.filter(_.isClass).toList
}
else Nil

def annotations: List[Annotation] = Nil
def companionModuleMembers: List[Symbol] = {
// phase travel to exitingPickler: this makes sure that memberClassesOf only sees member classes,
Expand Down Expand Up @@ -781,7 +805,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
def primitiveOrClassToBType(sym: Symbol): BType = {
assert(sym.isClass, sym)
assert(sym != ArrayClass || isCompilingArray, sym)
primitiveTypeMap.getOrElse(sym, storage.getClassBTypeAndRegisterInnerClass(sym.asInstanceOf[ct.int.Symbol]))
primitiveTypeMap.getOrElse(sym.asInstanceOf[ct.bTypes.coreBTypes.bTypes.int.Symbol],
storage.getClassBTypeAndRegisterInnerClass(sym.asInstanceOf[ct.int.Symbol])).asInstanceOf[BType]
}

/**
Expand All @@ -790,7 +815,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
*/
def nonClassTypeRefToBType(sym: Symbol): ClassBType = {
assert(sym.isType && isCompilingArray, sym)
ObjectReference
ObjectReference.asInstanceOf[ct.bTypes.ClassBType]
}

tp.widenDealias match {
Expand Down Expand Up @@ -835,7 +860,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
"If possible, please file a bug on issues.scala-lang.org.")

tp match {
case ThisType(ArrayClass) => ObjectReference // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test
case ThisType(ArrayClass) => ObjectReference.asInstanceOf[ct.bTypes.ClassBType] // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test
case ThisType(sym) => storage.getClassBTypeAndRegisterInnerClass(sym.asInstanceOf[ct.int.Symbol])
// case t: SingletonType => primitiveOrClassToBType(t.classSymbol)
case t: SingletonType => t.underlying.toTypeKind(ct)(storage)
Expand Down
20 changes: 10 additions & 10 deletions src/dotty/tools/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter

val caseInsensitively = scala.collection.mutable.Map.empty[String, Symbol]

def run() {
def run(): Unit = {
while (true) {
val item = q1.poll
if (item.isPoison) {
Expand All @@ -140,7 +140,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
* enqueues them in queue-2.
*
*/
def visit(item: Item1) {
def visit(item: Item1) = {
val Item1(arrivalPos, cd, cunit) = item
val claszSymbol = cd.symbol

Expand Down Expand Up @@ -218,7 +218,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
/*BackendStats.timed(BackendStats.methodOptTimer)*/(localOpt.methodOptimizations(classNode))
}

def run() {
def run(): Unit = {
while (true) {
val item = q2.poll
if (item.isPoison) {
Expand All @@ -238,7 +238,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
}
}

private def addToQ3(item: Item2) {
private def addToQ3(item: Item2) = {

def getByteArray(cn: asm.tree.ClassNode): Array[Byte] = {
val cw = new CClassWriter(extraProc)
Expand Down Expand Up @@ -277,7 +277,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
* (c) tear down (closing the classfile-writer and clearing maps)
*
*/
def run(t: Tree) {
def run(t: Tree) = {
this.tree = t

// val bcodeStart = Statistics.startTimer(BackendStats.bcodeTimer)
Expand Down Expand Up @@ -321,7 +321,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
* (c) dequeue one at a time from queue-2, convert it to byte-array, place in queue-3
* (d) serialize to disk by draining queue-3.
*/
private def buildAndSendToDisk(needsOutFolder: Boolean) {
private def buildAndSendToDisk(needsOutFolder: Boolean) = {

feedPipeline1()
// val genStart = Statistics.startTimer(BackendStats.bcodeGenStat)
Expand All @@ -337,8 +337,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
}

/* Feed pipeline-1: place all ClassDefs on q1, recording their arrival position. */
private def feedPipeline1() {
def gen(tree: Tree) {
private def feedPipeline1() = {
def gen(tree: Tree): Unit = {
tree match {
case EmptyTree => ()
case PackageDef(_, stats) => stats foreach gen
Expand All @@ -353,9 +353,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
}

/* Pipeline that writes classfile representations to disk. */
private def drainQ3() {
private def drainQ3() = {

def sendToDisk(cfr: SubItem3, outFolder: scala.tools.nsc.io.AbstractFile) {
def sendToDisk(cfr: SubItem3, outFolder: scala.tools.nsc.io.AbstractFile): Unit = {
if (cfr != null){
val SubItem3(jclassName, jclassBytes) = cfr
try {
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/backend/jvm/LabelDefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class LabelDefs extends MiniPhaseTransform {
}
}

val collectLabelDefs = new TreeMap() {
object collectLabelDefs extends TreeMap() {

// label calls from this DefDef
var parentLabelCalls: mutable.Set[Tree] = new mutable.HashSet[Tree]()
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/backend/jvm/scalaPrimitives.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class DottyPrimitives(ctx: Context) {
/** Initialize the primitive map */
private def init: immutable.Map[Symbol, Int] = {

implicit val ctx = this.ctx
implicit val ctx: Context = this.ctx

import core.Symbols.defn
val primitives = new mutable.HashMap[Symbol, Int]()
Expand Down
35 changes: 27 additions & 8 deletions src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dotty.tools
package dotc
package core

import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation }
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, NotDefinedHereDenotation }
import Contexts.{Context, ContextBase}
import Names.{Name, PreName}
import Names.TypeName
Expand Down Expand Up @@ -128,7 +128,17 @@ object Denotations {
*/
def atSignature(sig: Signature, site: Type = NoPrefix)(implicit ctx: Context): SingleDenotation

/** The variant of this denotation that's current in the given context. */
/** The variant of this denotation that's current in the given context, or
* `NotDefinedHereDenotation` if this denotation does not exist at current phase, but
* is defined elsewhere in this run.
*/
def currentIfExists(implicit ctx: Context): Denotation

/** The variant of this denotation that's current in the given context.
* If no such denotation exists: If Mode.FutureDefs is set, the
* denotation with each alternative at its first point of definition,
* otherwise a `NotDefinedHere` exception is thrown.
*/
def current(implicit ctx: Context): Denotation

/** Is this denotation different from NoDenotation or an ErrorDenotation? */
Expand Down Expand Up @@ -349,6 +359,8 @@ object Denotations {
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
def atSignature(sig: Signature, site: Type)(implicit ctx: Context): SingleDenotation =
denot1.atSignature(sig, site) orElse denot2.atSignature(sig, site)
def currentIfExists(implicit ctx: Context): Denotation =
derivedMultiDenotation(denot1.currentIfExists, denot2.currentIfExists)
def current(implicit ctx: Context): Denotation =
derivedMultiDenotation(denot1.current, denot2.current)
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
Expand Down Expand Up @@ -530,7 +542,7 @@ object Denotations {
* is brought forward to be valid in the new runId. Otherwise
* the symbol is stale, which constitutes an internal error.
*/
def current(implicit ctx: Context): SingleDenotation = {
def currentIfExists(implicit ctx: Context): SingleDenotation = {
val currentPeriod = ctx.period
val valid = myValidFor
if (valid.code <= 0) {
Expand Down Expand Up @@ -593,17 +605,24 @@ object Denotations {
//println(s"searching: $cur at $currentPeriod, valid for ${cur.validFor}")
cur = cur.nextInRun
cnt += 1
if (cnt > MaxPossiblePhaseId)
if (ctx.mode is Mode.FutureDefsOK)
return current(ctx.withPhase(coveredInterval.firstPhaseId))
else
throw new NotDefinedHere(demandOutsideDefinedMsg)
if (cnt > MaxPossiblePhaseId) return NotDefinedHereDenotation
}
cur
}
}
}

def current(implicit ctx: Context): SingleDenotation = {
val d = currentIfExists
if (d ne NotDefinedHereDenotation) d else currentNoDefinedHere
}

private def currentNoDefinedHere(implicit ctx: Context): SingleDenotation =
if (ctx.mode is Mode.FutureDefsOK)
current(ctx.withPhase(coveredInterval.firstPhaseId))
else
throw new NotDefinedHere(demandOutsideDefinedMsg)

private def demandOutsideDefinedMsg(implicit ctx: Context): String =
s"demanding denotation of $this at phase ${ctx.phase}(${ctx.phaseId}) outside defined interval: defined periods are${definedPeriodsString}"

Expand Down
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/core/Phases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ object Phases {
private val extensionMethodsCache = new PhaseCache(classOf[ExtensionMethods])
private val erasureCache = new PhaseCache(classOf[Erasure])
private val patmatCache = new PhaseCache(classOf[PatternMatcher])
private val lambdaLiftCache = new PhaseCache(classOf[LambdaLift])
private val flattenCache = new PhaseCache(classOf[Flatten])
private val explicitOuterCache = new PhaseCache(classOf[ExplicitOuter])
private val gettersCache = new PhaseCache(classOf[Getters])
Expand All @@ -245,6 +246,7 @@ object Phases {
def extensionMethodsPhase = extensionMethodsCache.phase
def erasurePhase = erasureCache.phase
def patmatPhase = patmatCache.phase
def lambdaLiftPhase = lambdaLiftCache.phase
def flattenPhase = flattenCache.phase
def explicitOuterPhase = explicitOuterCache.phase
def gettersPhase = gettersCache.phase
Expand Down
5 changes: 4 additions & 1 deletion src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1650,7 +1650,7 @@ object SymDenotations {
}
}

object NoDenotation extends SymDenotation(
class NoDenotation extends SymDenotation(
NoSymbol, NoSymbol, "<none>".toTermName, Permanent, NoType) {
override def exists = false
override def isTerm = false
Expand All @@ -1660,6 +1660,9 @@ object SymDenotations {
validFor = Period.allInRun(NoRunId) // will be brought forward automatically
}

val NoDenotation = new NoDenotation
val NotDefinedHereDenotation = new NoDenotation

// ---- Completion --------------------------------------------------------

/** Instances of LazyType are carried by uncompleted symbols.
Expand Down
8 changes: 6 additions & 2 deletions src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,12 @@ object Symbols {
}

/** Subclass tests and casts */
final def isTerm(implicit ctx: Context): Boolean = denot.isTerm
final def isType(implicit ctx: Context): Boolean = denot.isType
final def isTerm(implicit ctx: Context): Boolean =
(if(isDefinedInCurrentRun) lastDenot else denot).isTerm

final def isType(implicit ctx: Context): Boolean =
(if(isDefinedInCurrentRun) lastDenot else denot).isType

final def isClass: Boolean = isInstanceOf[ClassSymbol]

final def asTerm(implicit ctx: Context): TermSymbol = { assert(isTerm, s"asTerm called on not-a-Term $this" ); asInstanceOf[TermSymbol] }
Expand Down
5 changes: 4 additions & 1 deletion src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,10 @@ object Types {
}
case d =>
if (d.validFor.runId != ctx.period.runId) loadDenot
else d.current
else {
val newd = d.currentIfExists
if (newd ne NotDefinedHereDenotation) newd else loadDenot
}
}
if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot")
else if (d.exists) {
Expand Down
Loading