aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/config/JavaPlatform.scala2
-rw-r--r--src/dotty/tools/dotc/config/PathResolver.scala9
-rw-r--r--src/dotty/tools/dotc/config/Settings.scala3
-rw-r--r--src/dotty/tools/dotc/core/Annotations.scala9
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala74
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala8
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala17
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala16
-rw-r--r--src/dotty/tools/dotc/core/Periods.scala10
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala84
-rw-r--r--src/dotty/tools/dotc/core/Positions.scala1
-rw-r--r--src/dotty/tools/dotc/core/Printers.scala8
-rw-r--r--src/dotty/tools/dotc/core/Scopes.scala2
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala14
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala5
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala79
-rw-r--r--src/dotty/tools/dotc/core/TypedTrees.scala5
-rw-r--r--src/dotty/tools/dotc/core/Types.scala137
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala16
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala96
-rw-r--r--src/dotty/tools/dotc/reporting/ConsoleReporter.scala86
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala133
-rw-r--r--src/dotty/tools/dotc/reporting/StoreReporter.scala28
-rw-r--r--src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala35
-rw-r--r--src/dotty/tools/io/package.scala2
26 files changed, 734 insertions, 147 deletions
diff --git a/src/dotty/tools/dotc/config/JavaPlatform.scala b/src/dotty/tools/dotc/config/JavaPlatform.scala
index ef5fe9475..7f234b613 100644
--- a/src/dotty/tools/dotc/config/JavaPlatform.scala
+++ b/src/dotty/tools/dotc/config/JavaPlatform.scala
@@ -13,7 +13,7 @@ class JavaPlatform extends Platform {
def classPath(implicit ctx: Context): ClassPath = {
if (currentClassPath.isEmpty)
- currentClassPath = Some(new PathResolver(ctx).result)
+ currentClassPath = Some(new PathResolver(ctx.condensed).result)
currentClassPath.get
}
diff --git a/src/dotty/tools/dotc/config/PathResolver.scala b/src/dotty/tools/dotc/config/PathResolver.scala
index 97ea4525e..3aa42defb 100644
--- a/src/dotty/tools/dotc/config/PathResolver.scala
+++ b/src/dotty/tools/dotc/config/PathResolver.scala
@@ -135,7 +135,7 @@ object PathResolver {
def fromPathString(path: String)(implicit cctx: CondensedContext): JavaClassPath = {
val settings = cctx.settings.classpath.update(path)
- new PathResolver()(cctx.fresh.withSettings(settings)).result
+ new PathResolver(cctx.fresh.withSettings(settings)).result
}
/** With no arguments, show the interesting values in Environment and Defaults.
@@ -152,7 +152,7 @@ object PathResolver {
val ArgsSummary(sstate, rest, errors) =
cctx.settings.processArguments(args.toList, true)
errors.foreach(println)
- val pr = new PathResolver()(cctx.fresh.withSettings(sstate))
+ val pr = new PathResolver(cctx.fresh.withSettings(sstate))
println(" COMMAND: 'scala %s'".format(args.mkString(" ")))
println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" ")))
pr.result.show
@@ -161,7 +161,8 @@ object PathResolver {
}
import PathResolver.{ Defaults, Environment, firstNonEmpty, ppcp }
-class PathResolver(implicit cctx: CondensedContext) {
+class PathResolver(cctx: CondensedContext) {
+ implicit def ctx: Context = cctx
import cctx.base.settings
val context = ClassPath.DefaultJavaContext
@@ -257,7 +258,7 @@ class PathResolver(implicit cctx: CondensedContext) {
lazy val result: JavaClassPath = {
val cp = new JavaClassPath(containers.toIndexedSeq, context)
if (settings.Ylogcp.value) {
- Console.println("Classpath built from " + settings.toConciseString(cctx.sstate))
+ Console.println("Classpath built from " + settings.toConciseString(ctx.sstate))
Console.println("Defaults: " + PathResolver.Defaults)
Console.println("Calculated: " + Calculated)
diff --git a/src/dotty/tools/dotc/config/Settings.scala b/src/dotty/tools/dotc/config/Settings.scala
index c1ac1f83a..1f96be342 100644
--- a/src/dotty/tools/dotc/config/Settings.scala
+++ b/src/dotty/tools/dotc/config/Settings.scala
@@ -40,7 +40,7 @@ object Settings {
def fail(msg: String) =
ArgsSummary(sstate, arguments, errors :+ msg)
- }
+ }
case class Setting[T: ClassTag] private[Settings] (
name: String,
@@ -214,6 +214,7 @@ object Settings {
setting
}
+
def BooleanSetting(name: String, descr: String): Setting[Boolean] =
publish(Setting(name, descr, false))
diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala
index 3c8e02d8f..ff05c9faa 100644
--- a/src/dotty/tools/dotc/core/Annotations.scala
+++ b/src/dotty/tools/dotc/core/Annotations.scala
@@ -9,6 +9,9 @@ object Annotations {
def symbol(implicit ctx: Context): Symbol = tree.tpe.typeSymbol
def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.isNonBottomSubClass(cls)
def appliesToModule: Boolean = true // for now; see remark in SymDenotations
+
+ def derivedAnnotation(tree: Tree) =
+ if (tree eq this.tree) this else Annotation(tree)
}
case class ConcreteAnnotation(val tree: Tree) extends Annotation
@@ -42,12 +45,6 @@ object Annotations {
apply(defn.ChildAnnot, List(Ident(NamedType(sym.owner.thisType, sym.name))))
}
- def makeLiteralAnnotArg(const: Constant): Tree = ???
-
- def makeArrayAnnotArg(elems: Array[Tree]): Tree = ???
-
- def makeNestedAnnotArg(annot: Annotation): Tree = annot.tree
-
def ThrowsAnnotation(cls: ClassSymbol)(implicit ctx: Context) =
Annotation(defn.ThrowsAnnot, Ident(cls.symbolicRef))
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 388ae60ce..ff9d3c454 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -1,4 +1,5 @@
-package dotty.tools.dotc
+package dotty.tools
+package dotc
package core
import Decorators._
@@ -8,8 +9,10 @@ import Phases._
import Types._
import Symbols._
import TypeComparers._, Printers._, NameOps._, SymDenotations._, Positions._
+import TypedTrees.tpd._
import config.Settings._
import config.ScalaSettings
+import reporting._
import collection.mutable
import collection.immutable.BitSet
import config.{Settings, Platform, JavaPlatform}
@@ -38,17 +41,26 @@ object Contexts {
abstract class Context extends Periods
with Substituters
with TypeOps
+ with Phases
with Printers
with Symbols
with SymDenotations
- with Cloneable {
+ with Reporting
+ with Cloneable { thiscontext =>
implicit val ctx: Context = this
val base: ContextBase
- private[this] var _underlying: Context = _
- protected def underlying_=(underlying: Context) = _underlying = underlying
- def underlying: Context = _underlying
+ def outersIterator = new Iterator[Context] {
+ var current = thiscontext
+ def hasNext = current != NoContext
+ def next = { val c = current; current = current.outer; c }
+ }
+
+
+ private[this] var _outer: Context = _
+ protected def outer_=(outer: Context) = _outer = outer
+ def outer: Context = _outer
private[this] var _period: Period = _
protected def period_=(period: Period) = _period = period
@@ -62,8 +74,8 @@ object Contexts {
protected def typeComparer_=(typeComparer: TypeComparer) = _typeComparer = typeComparer
def typeComparer: TypeComparer = {
- if ((_typeComparer eq underlying.typeComparer) &&
- (constraints ne underlying.constraints))
+ if ((_typeComparer eq outer.typeComparer) &&
+ (constraints ne outer.constraints))
_typeComparer = new TypeComparer(this)
_typeComparer
}
@@ -80,8 +92,6 @@ object Contexts {
protected def refinedPrinter_=(refinedPrinter: Context => Printer) = _refinedPrinter = refinedPrinter
def refinedPrinter: Context => Printer = _refinedPrinter
- def printer = if (base.settings.debug.value) plainPrinter else refinedPrinter
-
private[this] var _owner: Symbol = _
protected def owner_=(owner: Symbol) = _owner = owner
def owner: Symbol = _owner
@@ -90,17 +100,26 @@ object Contexts {
protected def sstate_=(sstate: SettingsState) = _sstate = sstate
def sstate: SettingsState = _sstate
- def phase: Phase = ??? // phase(period.phaseId)
- def enclClass: Context = ???
- def erasedTypes: Boolean = ???
- def debug: Boolean = ???
- def error(msg: String): Unit = ???
- def warning(msg: String): Unit = ???
- def log(msg: String): Unit = ???
- def debuglog(msg: String): Unit = ???
- def inform(msg: String) = ???
- def informTime(msg: String, start: Long): Unit = ???
- def beforeTyper[T](op: => T): T = ???
+ private[this] var _tree: Tree = _
+ protected def tree_=(tree: Tree) = _tree = tree
+ def tree: Tree = _tree
+
+ private[this] var _reporter: Reporter = _
+ protected def reporter_=(reporter: Reporter) = _reporter = reporter
+ def reporter: Reporter = _reporter
+
+ /** The next outer context whose tree is a template or package definition */
+ def enclTemplate: Context = {
+ var c = this
+ while (c != NoContext && !c.tree.isInstanceOf[Template] && !c.tree.isInstanceOf[PackageDef])
+ c = c.outer
+ c
+ }
+
+ def source = io.NoSource // for now
+
+ def erasedTypes: Boolean = phase.erasedTypes
+ def debug: Boolean = base.settings.debug.value
private var _condensed: CondensedContext = null
def condensed: CondensedContext = {
@@ -115,7 +134,7 @@ object Contexts {
def fresh: FreshContext = {
val newctx = super.clone.asInstanceOf[FreshContext]
- newctx.underlying = this
+ newctx.outer = this
newctx._condensed = null
newctx
}
@@ -131,16 +150,20 @@ object Contexts {
def withRefinedPrinter(printer: Context => Printer): this.type = { this.refinedPrinter = printer; this }
def withOwner(owner: Symbol): this.type = { this.owner = owner; this }
def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
+ def withTree(tree: Tree): this.type = { this.tree = tree; this }
+ def withReporter(reporter: Reporter): this.type = { this.reporter = reporter; this }
def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this }
}
private class InitialContext(val base: ContextBase) extends FreshContext {
- underlying = NoContext
+ outer = NoContext
period = Nowhere
constraints = Map()
plainPrinter = new PlainPrinter(_)
refinedPrinter = new RefinedPrinter(_)
owner = NoSymbol
+ tree = EmptyTree
+ reporter = new ConsoleReporter
}
object NoContext extends Context {
@@ -150,7 +173,8 @@ object Contexts {
class ContextBase extends ContextState
with Transformers.TransformerBase
with Printers.PrinterBase
- with Denotations.DenotationsBase {
+ with Denotations.DenotationsBase
+ with Phases.PhasesBase {
val settings = new ScalaSettings
@@ -208,6 +232,10 @@ object Contexts {
// TypeOps state
private[core] var volatileRecursions: Int = 0
private[core] val pendingVolatiles = new mutable.HashSet[Type]
+
+ // Phases state
+ private[core] var phases = new Array[Phase](MaxPossiblePhaseId + 1)
+ private[core] var nphases = 0
}
object Context {
diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala
index b45c1ee76..af8704258 100644
--- a/src/dotty/tools/dotc/core/Decorators.scala
+++ b/src/dotty/tools/dotc/core/Decorators.scala
@@ -3,8 +3,7 @@ package core
import annotation.tailrec
import Symbols._
-
-import Contexts._, Names._
+import Contexts._, Names._, Phases._
object Decorators {
@@ -43,5 +42,10 @@ object Decorators {
loop(xs, 0)
}
}
+
+ implicit class PhaseListDecorator(val names: List[String]) extends AnyVal {
+ def containsPhase(phase: Phase) =
+ names exists (phase.name.startsWith)
+ }
}
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index efed9392d..0245928b2 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -149,6 +149,7 @@ class Definitions(implicit ctx: Context) {
def NullType: Type = NullClass.typeConstructor
def SeqType: Type = SeqClass.typeConstructor
def ArrayType: Type = ArrayClass.typeConstructor
+ def ObjectArrayType = ArrayType.appliedTo(ObjectType)
def UnitType: Type = UnitClass.typeConstructor
def BooleanType: Type = BooleanClass.typeConstructor
@@ -230,13 +231,27 @@ class Definitions(implicit ctx: Context) {
// ----- Initialization ---------------------------------------------------
+ /** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
+ lazy val syntheticCoreClasses = List(
+ AnnotationDefaultAnnot, // #2264
+ RepeatedParamClass,
+ JavaRepeatedParamClass,
+ ByNameParamClass,
+ AnyClass,
+ AnyRefAlias,
+ AnyValClass,
+ NullClass,
+ NothingClass,
+ SingletonClass,
+ EqualsPatternClass)
+
private[this] var _isInitialized = false
def isInitialized = _isInitialized
def init() =
if (!_isInitialized) {
// force initialization of every symbol that is synthesized or hijacked by the compiler
- val forced = ???
+ val forced = syntheticCoreClasses
_isInitialized = true
}
}
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 84564e7c7..b42854f69 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -141,10 +141,10 @@ object Denotations {
def isOverloaded = isInstanceOf[MultiDenotation]
/** The signature of the denotation */
- def signature: Signature
+ def signature(implicit ctx: Context): Signature
/** Resolve overloaded denotation to pick the one with the given signature */
- def atSignature(sig: Signature): SingleDenotation
+ def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation
/** The variant of this denotation that's current in the given context. */
def current(implicit ctx: Context): Denotation
@@ -158,7 +158,7 @@ object Denotations {
def orElse(that: => Denotation) = if (this.exists) this else that
/** The set of alternative single-denotations making up this denotation */
- def alts(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
+ def alternatives(implicit ctx: Context): List[SingleDenotation] =
altsWith(scala.Function.const(true))
/** The alternatives of this denotation that satisfy the predicate `p`. */
@@ -290,7 +290,7 @@ object Denotations {
if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2)
def symbol = unsupported("symbol")
def info = unsupported("info")
- def signature = unsupported("signature")
+ def signature(implicit ctx: Context) = unsupported("signature")
def firstSym(implicit ctx: Context): Symbol = denot1.firstSym orElse denot2.firstSym
def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
denot1.altsWith(p) ++ denot2.altsWith(p)
@@ -304,7 +304,7 @@ object Denotations {
}
def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean =
denot1.hasAltWith(p) || denot2.hasAltWith(p)
- def atSignature(sig: Signature): SingleDenotation =
+ def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
denot1.atSignature(sig) orElse denot2.atSignature(sig)
def validFor = denot1.validFor & denot2.validFor
def current(implicit ctx: Context): Denotation =
@@ -313,7 +313,7 @@ object Denotations {
abstract class SingleDenotation extends Denotation with DenotationSet {
override def isType = info.isInstanceOf[TypeType]
- override def signature: Signature = {
+ override def signature(implicit ctx: Context): Signature = {
def sig(tp: Type): Signature = tp match {
case tp: PolyType =>
tp.resultType match {
@@ -334,7 +334,7 @@ object Denotations {
def orElse(that: => SingleDenotation) = if (this.exists) this else that
- def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
+ def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] =
if (p(symbol)) this :: Nil else Nil
def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation =
@@ -343,7 +343,7 @@ object Denotations {
def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean =
p(symbol)
- def atSignature(sig: Signature): SingleDenotation =
+ def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
if (sig == signature) this else NoDenotation
// ------ Transformations -----------------------------------------
diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala
index 3a91b48cb..f524c8a99 100644
--- a/src/dotty/tools/dotc/core/Periods.scala
+++ b/src/dotty/tools/dotc/core/Periods.scala
@@ -11,17 +11,17 @@ abstract class Periods extends DotClass { self: Context =>
import Periods._
/** The current phase identifier */
- def phaseId = period.phaseId
+ def phaseId: Int = period.phaseId
/** The current run identifier */
- def runId = period.runId
+ def runId: Int = period.runId
/** Execute `op` at given period */
- def atPeriod[T](pd: Period)(op: Context => T) =
+ def atPeriod[T](pd: Period)(op: Context => T): T =
op(ctx.fresh.withPeriod(pd))
/** Execute `op` at given phase id */
- def atPhase[T](pid: PhaseId)(op: Context => T) =
+ def atPhase[T](pid: PhaseId)(op: Context => T): T =
op(ctx.fresh.withPhase(pid))
}
@@ -117,5 +117,5 @@ object Periods {
/** The number of bits needed to encode a phase identifier. */
final val PhaseWidth = 5
final val PhaseMask = (1 << PhaseWidth) - 1
-
+ final val MaxPossiblePhaseId = PhaseMask
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index f9b8eaa9f..02d9c9749 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -1,11 +1,91 @@
package dotty.tools.dotc
package core
+import Periods._, Contexts._
+
+trait Phases { self: Context =>
+ import Phases._
+
+ def phase: Phase = base.phases(period.phaseId)
+
+ def phasesStack: List[Phase] =
+ if (phase == this.NoPhase) Nil
+ else phase :: outersIterator.dropWhile(_.phase == phase).next.phasesStack
+
+ /** Execute `op` at given phase id */
+ def atPhase[T](phase: Phase)(op: Context => T): T =
+ atPhase(phase.id)(op)
+
+ def atPhaseNotLaterThan[T](limit: Phase)(op: Context => T): T =
+ if (!limit.exists || phase <= limit) op(this) else atPhase(limit)(op)
+
+ def atPhaseNotLaterThanTyper[T](op: Context => T): T =
+ atPhaseNotLaterThan(base.typerPhase)(op)
+}
+
object Phases {
- abstract class Phase {
- def erasedTypes: Boolean
+ trait PhasesBase { this: ContextBase =>
+
+ lazy val allPhases = phases.slice(FirstPhaseId, nphases)
+
+ val NoPhase = new Phase(initialCtx) {
+ def name = "<no phase>"
+ def run() { throw new Error("NoPhase.run") }
+ }
+/*
+ object SomePhase extends Phase {
+ def name = "<some phase>"
+ def run() { throw new Error("SomePhase.run") }
+ }
+*/
+ def phaseNamed(name: String) =
+ allPhases.find(_.name == name).getOrElse(NoPhase)
+
+ final val typerName = "typer"
+ final val refchecksName = "refchecks"
+ final val erasureName = "erasure"
+ final val flattenName = "flatten"
+
+ lazy val typerPhase = phaseNamed(typerName)
+ lazy val refchecksPhase = phaseNamed(refchecksName)
+ lazy val erasurePhase = phaseNamed(erasureName)
+ lazy val flattenPhase = phaseNamed(flattenName)
}
+ abstract class Phase(initctx: Context) {
+
+ val id: Int = initctx.nphases
+ initctx.nphases += 1
+ def name: String
+
+ def run(): Unit
+
+ def description: String = name
+
+ def checkable: Boolean = true
+
+ final def exists: Boolean = id != NoPhaseId
+
+ final def <= (that: Phase) =
+ exists && id <= that.id
+
+ final def prev(implicit ctx: Context): Phase =
+ if (id > FirstPhaseId) ctx.phases(id - 1) else initctx.NoPhase
+
+ final def next(implicit ctx: Context): Phase =
+ if (hasNext) ctx.phases(id + 1) else initctx.NoPhase
+
+ final def hasNext(implicit ctx: Context) = id + 1 < ctx.nphases
+
+ final def iterator(implicit ctx: Context) =
+ Iterator.iterate(this)(_.next) takeWhile (_.hasNext)
+
+ final def erasedTypes(implicit ctx: Context): Boolean = ctx.erasurePhase <= this
+ final def flatClasses(implicit ctx: Context): Boolean = ctx.flattenPhase <= this
+ final def refChecked (implicit ctx: Context): Boolean = ctx.refchecksPhase <= this
+
+ override def toString = name
+ }
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Positions.scala b/src/dotty/tools/dotc/core/Positions.scala
index 1d455e6f2..e16f6abe1 100644
--- a/src/dotty/tools/dotc/core/Positions.scala
+++ b/src/dotty/tools/dotc/core/Positions.scala
@@ -20,6 +20,7 @@ object Positions {
if (this == NoPosition) that
else if (that == NoPosition) this
else Position(this.start min that.start, this.end max that.end)
+ def exists = this != NoPosition
}
def Position(start: Int, end: Int, pointOffset: Int = 0): Position =
diff --git a/src/dotty/tools/dotc/core/Printers.scala b/src/dotty/tools/dotc/core/Printers.scala
index 3a9aaeb5b..b65161c64 100644
--- a/src/dotty/tools/dotc/core/Printers.scala
+++ b/src/dotty/tools/dotc/core/Printers.scala
@@ -10,6 +10,8 @@ trait Printers { this: Context =>
import Printers._
+ def printer = if (base.settings.debug.value) plainPrinter else refinedPrinter
+
private var _diagnostics: Option[StringBuilder] = _
protected def diagnostics_=(diagnostics: Option[StringBuilder]) = _diagnostics = diagnostics
@@ -203,8 +205,8 @@ object Printers {
}
case PolyParam(pt, n) =>
show(pt.paramNames(n))
- case AnnotatedType(annots, tpe) =>
- showLocal(tpe) + " " + annots.map(show).mkString(" ")
+ case AnnotatedType(annot, tpe) =>
+ showLocal(tpe) + " " + show(annot)
}
}
@@ -377,7 +379,7 @@ object Printers {
case _ => String.valueOf(const.value)
}
- def show(annot: Annotation): String = ???
+ def show(annot: Annotation): String = s"@${annot.symbol.name}" // for now
def show(syms: List[Symbol], sep: String): String =
syms map (_.showDcl) mkString sep
diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala
index ee442223d..798f21d76 100644
--- a/src/dotty/tools/dotc/core/Scopes.scala
+++ b/src/dotty/tools/dotc/core/Scopes.scala
@@ -51,7 +51,7 @@ object Scopes {
protected[Scopes] def this(base: Scope)(implicit ctx: Context) = {
this(base.lastEntry, base.size, base.nestingLevel + 1)
- ensureCapacity(MinHash)(ctx) // WTH??? it seems the implicit is not in scope for a secondary constructor call.
+ ensureCapacity(MinHash)(ctx) // WTH? it seems the implicit is not in scope for a secondary constructor call.
}
def this() = this(null, 0, 0)
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala
index 33dd14b8e..d4ead33b1 100644
--- a/src/dotty/tools/dotc/core/Substituters.scala
+++ b/src/dotty/tools/dotc/core/Substituters.scala
@@ -13,7 +13,7 @@ trait Substituters { this: Context =>
if (tp.binder eq from) tp.copy(to.asInstanceOf[tp.BT]) else tp
case tp: NamedType =>
if (tp.symbol.isStatic) tp
- else tp.derivedNamedType(subst(tp.prefix, from, to, map), tp.name)
+ else tp.derivedNamedType(subst(tp.prefix, from, to, map))
case _: ThisType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -29,7 +29,7 @@ trait Substituters { this: Context =>
val sym = tp.symbol
if (sym eq from) return to
if (sym.isStatic && !from.isStatic) tp
- else tp.derivedNamedType(subst1(tp.prefix, from, to, map), tp.name)
+ else tp.derivedNamedType(subst1(tp.prefix, from, to, map))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -47,7 +47,7 @@ trait Substituters { this: Context =>
if (sym eq from1) return to1
if (sym eq from2) return to2
if (sym.isStatic && !from1.isStatic && !from2.isStatic) tp
- else tp.derivedNamedType(subst2(tp.prefix, from1, to1, from2, to2, map), tp.name)
+ else tp.derivedNamedType(subst2(tp.prefix, from1, to1, from2, to2, map))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -70,7 +70,7 @@ trait Substituters { this: Context =>
ts = ts.tail
}
if (sym.isStatic && !existsStatic(from)) tp
- else tp.derivedNamedType(subst(tp.prefix, from, to, map), tp.name)
+ else tp.derivedNamedType(subst(tp.prefix, from, to, map))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -93,7 +93,7 @@ trait Substituters { this: Context =>
ts = ts.tail
}
if (sym.isStatic && !existsStatic(from)) tp
- else tp.derivedNamedType(substSym(tp.prefix, from, to, map), tp.name)
+ else tp.derivedNamedType(substSym(tp.prefix, from, to, map))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -109,7 +109,7 @@ trait Substituters { this: Context =>
if (clazz eq from) to else tp
case tp: NamedType =>
if (tp.symbol.isStatic) tp
- else tp.derivedNamedType(substThis(tp.prefix, from, to, map), tp.name)
+ else tp.derivedNamedType(substThis(tp.prefix, from, to, map))
case _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -125,7 +125,7 @@ trait Substituters { this: Context =>
if (rt eq from) to else tp
case tp: NamedType =>
if (tp.symbol.isStatic) tp
- else tp.derivedNamedType(substThis(tp.prefix, from, to, map), tp.name)
+ else tp.derivedNamedType(substThis(tp.prefix, from, to, map))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 67a1e1d03..830ceba1a 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -93,6 +93,9 @@ object SymDenotations {
/** Make sure this denotation is completed */
final def ensureCompleted(): Unit = info
+ /** The completer of this denotation. @pre: Denotation is not yet completed */
+ def completer: LazyType = _info.asInstanceOf[LazyType]
+
/** The privateWithin boundary, NoSymbol if no boundary is given.
*/
def privateWithin: Symbol = { ensureCompleted(); _privateWithin }
@@ -335,7 +338,7 @@ object SymDenotations {
if (!cls.exists)
fail(
s"""Access to protected $this not permitted because
- |enclosing ${ctx.enclClass.owner.showLocated} is not a subclass of
+ |enclosing ${ctx.enclTemplate.owner.showLocated} is not a subclass of
|${owner.showLocated} where target is defined""".stripMargin)
else if (!(isType || // allow accesses to types from arbitrary subclasses fixes #4737
pre.widen.typeSymbol.isSubClassOrCompanion(cls) ||
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index 85fb8037d..5b5bf0078 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -11,6 +11,7 @@ import java.io.IOException
import scala.compat.Platform.currentTime
import dotty.tools.io.{ ClassPath, AbstractFile }
import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, Positions._, Names._
+import StdNames._
import Decorators.StringDecorator
import pickling.ClassfileParser
@@ -85,7 +86,7 @@ class SymbolLoaders {
* (overridden in interactive.Global).
*/
def enterToplevelsFromSource(owner: Symbol, name: PreName, src: AbstractFile)(implicit ctx: Context) {
- ??? // !!! enterClassAndModule(owner, name, new SourcefileLoader(src))
+ enterClassAndModule(owner, name, new SourcefileLoader(src)(ctx.condensed))
}
/** The package objects of scala and scala.reflect should always
@@ -134,12 +135,44 @@ class SymbolLoaders {
for (pkg <- classpath.packages) {
enterPackage(root.symbol, pkg.name, new PackageLoader(pkg))
}
- openPackageModule(root.symbol)
+ openPackageModule(root.symbol.asClass)
}
}
}
- def openPackageModule(pkgClass: Symbol): Unit = ???
+ /** if there's a `package` member object in `pkgClass`, enter its members into it. */
+ def openPackageModule(pkgClass: ClassSymbol)(implicit ctx: Context) {
+ val pkgModule = pkgClass.info.decl(nme.PACKAGEkw).symbol
+ if (pkgModule.isModule &&
+ (pkgModule.isCompleted ||
+ !pkgModule.completer.isInstanceOf[SourcefileLoader]))
+ // println("open "+pkgModule)//DEBUG
+ openPackageModule(pkgModule, pkgClass)
+ }
+
+ def openPackageModule(container: Symbol, dest: ClassSymbol)(implicit ctx: Context) {
+ // unlink existing symbols in the package
+ for (member <- container.info.decls.iterator) {
+ if (!(member is Private) && !member.isConstructor) {
+ // todo: handle overlapping definitions in some way: mark as errors
+ // or treat as abstractions. For now the symbol in the package module takes precedence.
+ for (existing <- dest.info.decl(member.name).alternatives)
+ dest.delete(existing.symbol)
+ }
+ }
+ // enter non-private decls in the class
+ for (member <- container.info.decls.iterator) {
+ if (!(member is Private) && !member.isConstructor) {
+ dest.enter(member)
+ }
+ }
+ // enter decls of parent classes
+ for (p <- container.info.parents) {
+ if (p.symbol != defn.ObjectClass) {
+ openPackageModule(p.symbol, dest)
+ }
+ }
+ }
}
/** A lazy type that completes itself by calling parameter doComplete.
* Any linked modules/classes or module classes are also initialized.
@@ -203,41 +236,9 @@ class ClassfileLoader(val classfile: AbstractFile)(implicit val cctx: CondensedC
new ClassfileParser(classfile, classRoot, moduleRoot).run()
}
}
-/*
- class MsilFileLoader(msilFile: MsilFile) extends SymbolLoader with FlagAssigningCompleter {
- private def typ = msilFile.msilType
- private object typeParser extends clr.TypeParser {
- val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
- }
-
- protected def description = "MsilFile "+ typ.FullName + ", assembly "+ typ.Assembly.FullName
- protected def doComplete(root: Symbol) { typeParser.parse(typ, root) }
- }
-
- class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader with FlagAssigningCompleter {
- protected def description = "source file "+ srcfile.toString
- override def fromSource = true
- override def sourcefile = Some(srcfile)
- protected def doComplete(root: Symbol): Unit = global.currentRun.compileLate(srcfile)
- }
-
- object moduleClassLoader extends SymbolLoader with FlagAssigningCompleter {
- protected def description = "module class loader"
- protected def doComplete(root: Symbol) { root.sourceModule.initialize }
- }
-
- object clrTypes extends clr.CLRTypes {
- val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
- if (global.forMSIL) init()
- }
-
- /** used from classfile parser to avoid cyclies */
- var parentsLevel = 0
- var pendingLoadActions: List[() => Unit] = Nil
-}
-object SymbolLoadersStats {
- import scala.reflect.internal.TypesStats.typerNanos
- val classReadNanos = Statistics.newSubTimer ("time classfilereading", typerNanos)
+class SourcefileLoader(val srcfile: AbstractFile)(implicit val cctx: CondensedContext) extends SymbolLoader {
+ protected def description = "source file "+ srcfile.toString
+ override def sourceFileOrNull = srcfile
+ protected def doComplete(root: SymDenotation): Unit = unsupported("doComplete")
}
-*/ \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/TypedTrees.scala b/src/dotty/tools/dotc/core/TypedTrees.scala
index 49d062330..f73c0fc87 100644
--- a/src/dotty/tools/dotc/core/TypedTrees.scala
+++ b/src/dotty/tools/dotc/core/TypedTrees.scala
@@ -168,6 +168,9 @@ object TypedTrees {
def SeqLiteral(elemtpt: Tree, elems: List[Tree])(implicit ctx: Context): SeqLiteral =
Trees.SeqLiteral(elemtpt, elems).withType(defn.RepeatedParamType.appliedTo(elemtpt.tpe)).checked
+ def SeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral =
+ SeqLiteral(TypeTree(ctx.lub(elems map (_.tpe))), elems)
+
def TypeTree(tp: Type, original: Tree = EmptyTree)(implicit ctx: Context): TypeTree =
Trees.TypeTree(original).withType(tp).checked
@@ -276,7 +279,7 @@ object TypedTrees {
Trees.PackageDef(pid, stats).withType(refType(pid.symbol)).checked
def Annotated(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated =
- Trees.Annotated(annot, arg).withType(AnnotatedType(List(Annotation(annot)), arg.tpe)).checked
+ Trees.Annotated(annot, arg).withType(AnnotatedType(Annotation(annot), arg.tpe)).checked
val EmptyTree: Tree = Trees.EmptyTree[Type]
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 292f78d8e..69df1275f 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -12,7 +12,9 @@ import Contexts._
import Annotations._
import SymDenotations._
import Denotations._
-import Periods._, Trees._
+import Periods._
+import TypedTrees.tpd._, TypedTrees.TreeMapper
+import transform.Erasure._
import scala.util.hashing.{ MurmurHash3 => hashing }
import collection.mutable
@@ -41,13 +43,13 @@ object Types {
* | | +--- MethodParam
* | | +--- RefinedThis
* | | +--- NoPrefix
+ * | +- PolyParam
+ * | +- RefinedType
* | +- TypeBounds
* | +- ExprType
* | +- AnnotatedType
* |
- * +- GroundType -+- PolyParam
- * +- RefinedType
- * +- AndType
+ * +- GroundType -+- AndType
* +- OrType
* +- MethodType -----+- ImplicitMethodType
* | +- JavaMethodType
@@ -269,6 +271,15 @@ object Types {
case _ => List()
}
+ /** If this is an alias type, its alias, otherwise the type itself */
+ def dealias(implicit ctx: Context): Type = this match {
+ case tp: TypeRef =>
+ val info = tp.info
+ if (info.isAliasTypeBounds) info.dealias else this
+ case _ =>
+ this
+ }
+
/** The parameter types of a PolyType or MethodType, Empty list for others */
def paramTypess: List[List[Type]] = this match {
case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess
@@ -470,7 +481,7 @@ object Types {
* pattern is that method signatures use caching, so encapsulation
* is improved using an OO scheme).
*/
- def signature: Signature = NullSignature
+ def signature(implicit ctx: Context): Signature = NullSignature
final def baseType(base: Symbol)(implicit ctx: Context): Type = base.denot match {
case classd: ClassDenotation => classd.baseTypeOf(this)
@@ -511,10 +522,10 @@ object Types {
/** If this type equals `tycon applyToArgs args`, for some
* non-refinement type `tycon` and (possibly partial) type arguments
* `args`, return a pair consisting of `tycon` and `args`.
- * Otherwise return the type itself and `Nil`.
+ * Otherwise return the dealiased type itself and `Nil`.
*/
final def splitArgs(implicit ctx: Context): (Type, List[Type]) = {
- def recur(tp: Type, nparams: Int): (Type, List[Type]) = tp match {
+ def recur(tp: Type, nparams: Int): (Type, List[Type]) = tp.dealias match {
case tp @ RefinedType(parent, name) =>
def fail = (NoType, Nil)
if (nparams >= 0) {
@@ -538,6 +549,25 @@ object Types {
if (args.length == tycon.typeParams.length) result else (NoType, Nil)
}
+ /** If this is an encoding of an applied type, return its arguments,
+ * otherwise return Nil
+ */
+ def typeArgs(implicit ctx: Context): List[Type] = splitArgs._2
+
+ /** If this type is of the normalized form Array[...[Array[T]...]
+ * return the number of Array wrappers and T.
+ * Otherwise return 0 and the type itself
+ */
+ final def splitArray(implicit ctx: Context): (Int, Type) = {
+ def recur(n: Int, tp: Type): (Int, Type) = tp.splitArgs match {
+ case (arrayType, arg :: Nil) if arrayType == defn.ArrayType =>
+ recur(n + 1, arg)
+ case (tp, Nil) =>
+ (n, tp)
+ }
+ recur(0, this)
+ }
+
/** Turn this type into a TypeBounds RHS */
final def toRHS(tparam: Symbol)(implicit ctx: Context): TypeBounds = {
val v = tparam.variance
@@ -740,9 +770,18 @@ object Types {
override def underlying(implicit ctx: Context): Type = info
- def derivedNamedType(prefix: Type, name: Name)(implicit ctx: Context): Type =
+ def derivedNamedType(prefix: Type)(implicit ctx: Context): Type =
if (prefix eq this.prefix) this
- else NamedType(prefix, name)
+ else newLikeThis(prefix)
+
+ /** Create a NamedType of the same kind as this type, if possible,
+ * but with a new prefix. For HasFixedSym instances another such
+ * instance is only created if the symbol's owner is a base class of
+ * the new prefix. If that is not the case, we fall back to a
+ * NamedType or in the case of a TermRef, NamedType with signature.
+ */
+ protected def newLikeThis(prefix: Type)(implicit ctx: Context): Type =
+ NamedType(prefix, name)
override def computeHash = doHash(name, prefix)
}
@@ -763,17 +802,26 @@ object Types {
final class TermRefBySym(prefix: Type, val fixedSym: TermSymbol)(initctx: Context)
extends TermRef(prefix, fixedSym.name(initctx).asTermName) with HasFixedSym {
- }
-
- final class TermRefWithSignature(prefix: Type, name: TermName, override val signature: Signature) extends TermRef(prefix, name) {
- override def computeHash = doHash((name, signature), prefix)
+ override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef =
+ if (prefix.baseType(fixedSym.owner).exists) TermRef(prefix, fixedSym)
+ else TermRef(prefix, name, fixedSym.signature)
+ }
+
+ final class TermRefWithSignature(prefix: Type, name: TermName, sig: Signature) extends TermRef(prefix, name) {
+ override def signature(implicit ctx: Context) = sig
+ override def computeHash = doHash((name, sig), prefix)
override def loadDenot(implicit ctx: Context): Denotation =
- super.loadDenot.atSignature(signature)
- }
+ super.loadDenot.atSignature(sig)
+ override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRefWithSignature =
+ TermRef(prefix, name, sig)
+ }
final class TypeRefBySym(prefix: Type, val fixedSym: TypeSymbol)(initctx: Context)
extends TypeRef(prefix, fixedSym.name(initctx).asTypeName) with HasFixedSym {
- }
+ override def newLikeThis(prefix: Type)(implicit ctx: Context): TypeRef =
+ if (prefix.baseType(fixedSym.owner).exists) TypeRef(prefix, fixedSym)
+ else TypeRef(prefix, name)
+ }
final class CachedTermRef(prefix: Type, name: TermName) extends TermRef(prefix, name)
final class CachedTypeRef(prefix: Type, name: TypeName) extends TypeRef(prefix, name)
@@ -918,7 +966,8 @@ object Types {
// The reason is that most poly types are cyclic via poly params,
// and therefore two different poly types would never be equal.
- abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType {
+ abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])
+ (resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType {
override lazy val resultType = resultTypeExp(this)
def isJava = false
def isImplicit = false
@@ -928,8 +977,20 @@ object Types {
case _ => false
}
- override lazy val signature: List[TypeName] = {
- def paramSig(tp: Type): TypeName = ???
+ private[this] var _signature: Signature = _
+ private[this] var signatureRunId: Int = NoRunId
+
+ override def signature(implicit ctx: Context): Signature = {
+ if (ctx.runId != signatureRunId) {
+ _signature = computeSignature
+ signatureRunId = ctx.runId
+ }
+ _signature
+ }
+
+ private def computeSignature(implicit ctx: Context): Signature = {
+ def paramSig(tp: Type): TypeName =
+ erasure(tp).typeSymbol.asType.name
val followSig = resultType match {
case rtp: MethodType => rtp.signature
case _ => Nil
@@ -994,7 +1055,7 @@ object Types {
abstract case class ExprType(override val resultType: Type) extends CachedProxyType {
override def underlying(implicit ctx: Context): Type = resultType
- override def signature: Signature = Nil
+ override def signature(implicit ctx: Context): Signature = Nil
def derivedExprType(rt: Type)(implicit ctx: Context) =
if (rt eq resultType) this else ExprType(rt)
override def computeHash = doHash(resultType)
@@ -1012,7 +1073,7 @@ object Types {
lazy val paramBounds = paramBoundsExp(this)
override lazy val resultType = resultTypeExp(this)
- override def signature = resultType.signature
+ override def signature(implicit ctx: Context) = resultType.signature
def instantiate(argTypes: List[Type])(implicit ctx: Context): Type =
new InstPolyMap(this, argTypes) apply resultType
@@ -1109,6 +1170,10 @@ object Types {
parentsCache
}
+ def derivedClassInfo(prefix: Type, classParents: List[TypeRef], optSelfType: Type)(implicit ctx: Context) =
+ if ((prefix eq this.prefix) && (classParents eq this.classParents) && (optSelfType eq this.optSelfType)) this
+ else ClassInfo(prefix, cls, classParents, decls, optSelfType)
+
override def computeHash = doHash(cls, prefix)
}
@@ -1162,20 +1227,20 @@ object Types {
// ----- Annotated and Import types -----------------------------------------------
- case class AnnotatedType(annots: List[Annotation], tpe: Type) extends UncachedProxyType {
+ case class AnnotatedType(annot: Annotation, tpe: Type) extends UncachedProxyType {
override def underlying(implicit ctx: Context): Type = tpe
- def derivedAnnotatedType(annots1: List[Annotation], tpe1: Type) =
- if ((annots1 eq annots) && (tpe1 eq tpe)) this
- else AnnotatedType.make(annots1, tpe1)
+ def derivedAnnotatedType(annot: Annotation, tpe: Type) =
+ if ((annot eq this.annot) && (tpe eq this.tpe)) this
+ else AnnotatedType(annot, tpe)
}
object AnnotatedType {
def make(annots: List[Annotation], underlying: Type) =
if (annots.isEmpty) underlying
- else AnnotatedType(annots, underlying)
+ else (underlying /: annots)((tp, ann) => AnnotatedType(ann, tp))
}
- case class ImportType(expr: Shared[Type]) extends UncachedGroundType
+ case class ImportType(expr: Shared) extends UncachedGroundType
// Special type objects ------------------------------------------------------------
@@ -1206,7 +1271,7 @@ object Types {
/** Map this function over given type */
def mapOver(tp: Type): Type = tp match {
case tp: NamedType =>
- tp.derivedNamedType(this(tp.prefix), tp.name)
+ tp.derivedNamedType(this(tp.prefix))
case _: ThisType
| _: BoundType => tp
@@ -1235,8 +1300,8 @@ object Types {
tp.derivedTypeBounds(this(lo), this(hi))
}
- case tp @ AnnotatedType(annots, underlying) =>
- tp.derivedAnnotatedType(mapOverAnnotations(annots), this(underlying))
+ case tp @ AnnotatedType(annot, underlying) =>
+ tp.derivedAnnotatedType(mapOver(annot), this(underlying))
case _ =>
tp
@@ -1252,7 +1317,11 @@ object Types {
else newScopeWith(elems1: _*)
}
- def mapOverAnnotations(annots: List[Annotation]): List[Annotation] = ???
+ def mapOver(annot: Annotation): Annotation =
+ annot.derivedAnnotation(mapOver(annot.tree))
+
+ def mapOver(tree: Tree): Tree = new TreeMapper(this).apply(tree)
+
def andThen(f: Type => Type): TypeMap = new TypeMap {
def apply(tp: Type) = f(thisMap.apply(tp))
@@ -1285,7 +1354,7 @@ object Types {
abstract class TypeAccumulator[T] extends ((T, Type) => T) {
def apply(x: T, tp: Type): T
- def apply(x: T, annot: Annotation): T = ???
+ protected def apply(x: T, annot: Annotation): T = x // don't go into annotations
def foldOver(x: T, tp: Type): T = tp match {
case tp: NamedType =>
@@ -1312,8 +1381,8 @@ object Types {
case TypeBounds(lo, hi) =>
this(this(x, lo), hi)
- case AnnotatedType(annots, underlying) =>
- this((x /: annots)(apply), underlying)
+ case AnnotatedType(annot, underlying) =>
+ this(this(x, annot), underlying)
case _ => x
}
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index 3a1e81e2d..8e34aa0a9 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -357,18 +357,18 @@ class ClassfileParser(
val index = in.nextChar
tag match {
case STRING_TAG =>
- if (skip) None else Some(makeLiteralAnnotArg(Constant(pool.getName(index).toString)))
+ if (skip) None else Some(Literal(Constant(pool.getName(index).toString)))
case BOOL_TAG | BYTE_TAG | CHAR_TAG | SHORT_TAG | INT_TAG |
LONG_TAG | FLOAT_TAG | DOUBLE_TAG =>
- if (skip) None else Some(makeLiteralAnnotArg(pool.getConstant(index)))
+ if (skip) None else Some(Literal(pool.getConstant(index)))
case CLASS_TAG =>
- if (skip) None else Some(makeLiteralAnnotArg(Constant(pool.getType(index))))
+ if (skip) None else Some(Literal(Constant(pool.getType(index))))
case ENUM_TAG =>
val t = pool.getType(index)
val n = pool.getName(in.nextChar)
val s = t.typeSymbol.companionModule.info.decls.lookup(n)
assert(s != NoSymbol, t)
- if (skip) None else Some(makeLiteralAnnotArg(Constant(s)))
+ if (skip) None else Some(Literal(Constant(s)))
case ARRAY_TAG =>
val arr = new ArrayBuffer[Tree]()
var hasError = false
@@ -378,9 +378,9 @@ class ClassfileParser(
case None => hasError = true
}
if (hasError) None
- else if (skip) None else Some(makeArrayAnnotArg(arr.toArray))
+ else if (skip) None else Some(SeqLiteral(arr.toList))
case ANNOTATION_TAG =>
- parseAnnotation(index, skip) map makeNestedAnnotArg
+ parseAnnotation(index, skip) map (_.tree)
}
}
@@ -656,7 +656,9 @@ class ClassfileParser(
case Some(entry) =>
val outerName = entry.outerName.stripModuleSuffix
val owner = classSymbol(outerName)
- val result = cctx.beforeTyper(getMember(owner, innerName.toTypeName))
+ val result = cctx.atPhaseNotLaterThanTyper { implicit ctx =>
+ getMember(owner, innerName.toTypeName)
+ }
assert(result ne NoSymbol,
s"""failure to resolve inner class:
|externalName = $externalName,
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 7460c33fe..67e7d318f 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -548,7 +548,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleRoot: Clas
val tp = readTypeRef()
// no annotation self type is supported, so no test whether this is a symbol ref
val annots = until(end, readAnnotationRef)
- AnnotatedType(annots, tp)
+ AnnotatedType.make(annots, tp)
case _ =>
noSuchTypeTag(tag, end)
}
diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala
new file mode 100644
index 000000000..a3181a7e6
--- /dev/null
+++ b/src/dotty/tools/dotc/core/transform/Erasure.scala
@@ -0,0 +1,96 @@
+package dotty.tools.dotc
+package core
+package transform
+
+import Flags._
+import Symbols._, Types._, Contexts._
+
+object Erasure {
+
+ /** The erasure |T| of a type T. This is: !!! todo: update
+ *
+ * - For a constant type, itself.
+ * - For a refined type scala.Array+[T]:
+ * - if T is Nothing or Null, scala.Array+[Object]
+ * - otherwise, if T <: Object, scala.Array+[|T|]
+ * - otherwise, if T is a type paramter coming from Java, scala.Array+[Object].
+ * - otherwise, Object
+ * - For a typeref scala.Any, scala.AnyVal, scala.Singleon or scala.NotNull, java.lang.Object.
+ * - For a typeref scala.Unit, scala.runtime.BoxedUnit.
+ * - For a typeref P.C where C refers to a toplevel class, P.C.
+ * - For a typeref P.C where C refers to a nested class, |P|.C.
+ * - For a typeref P.C where C refers to an alias type, the erasure of C's alias.
+ * - For a typeref P.C where C refers to an abstract type, the erasure of C's upper bound.
+ * - For T1 & T2, erasure(T1) (??)
+ * - For T1 | T2, the first base class in the linearization of T which is also a base class of T2
+ * - For a method type (Fs)scala.Unit, (|Fs|)scala.Unit.
+ * - For any other method type (Fs)T, (|Fs|)|T|.
+ * - For a polymorphic type, the erasure of its result type.
+ * - For the class info type of java.lang.Object, the same type without any parents.
+ * - For a class info type of a value class, the same type without any parents.
+ * - For any other class info type with parents Ps, the same type with
+ * parents |Ps|, but with duplicate references of Object removed.
+ * - for all other types, the type itself (with any sub-components erased)
+ */
+ def erasure(tp: Type)(implicit ctx: Context): Type = tp match {
+ case ConstantType(_) =>
+ tp
+ case tp: RefinedType =>
+ val parent = tp.parent
+ if (parent.dealias.typeSymbol == defn.ArrayClass) {
+ val (n, elemtp) = tp.splitArray
+ if (elemtp <:< defn.NullType)
+ defn.ObjectArrayType
+ else if (elemtp <:< defn.ObjectType)
+ (erasure(elemtp) /: (0 until n))((erased, _) =>
+ defn.ArrayType.appliedTo(erased))
+ else if (elemtp.typeSymbol is JavaDefined)
+ defn.ObjectArrayType
+ else
+ defn.ObjectType
+ } else erasure(parent)
+ case tp: TypeRef =>
+ val sym = tp.symbol
+ if (sym == defn.AnyClass || sym == defn.AnyValClass || sym == defn.SingletonClass || sym == defn.NotNullClass)
+ defn.ObjectType
+ else if (sym == defn.UnitClass) defn.BoxedUnitClass.typeConstructor
+ // else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
+ else if (sym.isClass)
+ if (sym.owner.isPackage) tp
+ else tp.derivedNamedType(erasure(tp.prefix))
+ else
+ erasure(sym.info)
+ case NoType | NoPrefix =>
+ tp
+ case tp: TypeProxy =>
+ erasure(tp.underlying)
+ case AndType(tp1, tp2) =>
+ erasure(tp1)
+ case OrType(tp1, tp2) =>
+ var bcs1 = tp1.baseClasses
+ val bc2 = tp2.baseClasses.head
+ while (bcs1.nonEmpty && !bc2.isNonBottomSubClass(bcs1.head))
+ bcs1 = bcs1.tail
+ if (bcs1.isEmpty) defn.ObjectType
+ else erasure(bcs1.head.typeConstructor)
+ case tp: MethodType =>
+ tp.derivedMethodType(
+ tp.paramNames, tp.paramTypes.mapConserve(erasure), resultErasure(tp.resultType))
+ case tp: PolyType =>
+ erasure(tp.resultType)
+ case tp @ ClassInfo(pre, cls, classParents, decls, optSelfType) =>
+ val parents: List[TypeRef] =
+ if (cls == defn.ObjectClass || cls.isPrimitiveValueClass) Nil
+ else if (cls == defn.ArrayClass) defn.ObjectClass.typeConstructor :: Nil
+ else removeLaterObjects(classParents mapConserve (erasure(_).asInstanceOf[TypeRef]))
+ tp.derivedClassInfo(erasure(pre), parents, NoType)
+ }
+
+ def resultErasure(tp: Type)(implicit ctx: Context) =
+ if (tp.typeSymbol == defn.UnitClass) tp else erasure(tp)
+
+ def removeLaterObjects(trs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = trs match {
+ case tr :: trs1 => tr :: (trs1 filter (_.typeSymbol != defn.ObjectClass))
+ case nil => nil
+ }
+}
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
new file mode 100644
index 000000000..88fdfa386
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
@@ -0,0 +1,86 @@
+package dotty.tools
+package dotc
+package reporting
+
+import scala.collection.mutable
+import core.Positions.Position
+import core.Contexts._
+import Reporter.Severity.{Value => Severity, _}
+import java.io.{ BufferedReader, IOException, PrintWriter }
+import scala.reflect.internal.util._
+
+/**
+ * This class implements a Reporter that displays messages on a text
+ * console.
+ */
+class ConsoleReporter(
+ reader: BufferedReader = Console.in,
+ writer: PrintWriter = new PrintWriter(Console.err, true))
+ extends Reporter with UniqueMessagePositions {
+
+ /** Whether a short file name should be displayed before errors */
+ protected def shortName: Boolean = false
+
+ /** maximal number of error messages to be printed */
+ protected def ErrorLimit = 100
+
+ def formatMessage(msg: String, pos: Position)(implicit ctx: Context) = msg // for now
+
+ /** Prints the message. */
+ def printMessage(msg: String) { writer.print(msg + "\n"); writer.flush() }
+
+ /** Prints the message with the given position indication. */
+ def printMessage(msg: String, pos: Position)(implicit ctx: Context) {
+ printMessage(formatMessage(msg, pos))
+ }
+
+ def printMessage(msg: String, severity: Severity, pos: Position)(implicit ctx: Context) {
+ printMessage(label(severity) + msg, pos)
+ }
+
+ /**
+ * @param pos ...
+
+ def printSourceLine(pos: Position) {
+ printMessage(pos.lineContent.stripLineEnd)
+ printColumnMarker(pos)
+ }
+
+ /** Prints the column marker of the given position.
+ *
+ * @param pos ...
+ */
+ def printColumnMarker(pos: Position) =
+ if (pos.isDefined) { printMessage(" " * (pos.column - 1) + "^") }
+*/
+
+ /** Prints the number of errors and warnings if their are non-zero. */
+ def printSummary() {
+ if (count(WARNING) > 0) printMessage(countString(WARNING) + " found")
+ if ( count(ERROR) > 0) printMessage(countString(ERROR ) + " found")
+ }
+
+ override def report(msg: String, severity: Severity, pos: Position)(implicit ctx: Context) {
+ if (severity != ERROR || count(severity) <= ErrorLimit)
+ printMessage(msg, severity, pos)
+ if (ctx.settings.prompt.value) displayPrompt()
+ }
+
+ def displayPrompt(): Unit = {
+ writer.print("\na)bort, s)tack, r)esume: ")
+ writer.flush()
+ if (reader != null) {
+ val response = reader.read().asInstanceOf[Char].toLower
+ if (response == 'a' || response == 's') {
+ (new Exception).printStackTrace()
+ if (response == 'a')
+ sys exit 1
+
+ writer.print("\n")
+ writer.flush()
+ }
+ }
+ }
+
+ override def flush() { writer.flush() }
+}
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
new file mode 100644
index 000000000..862e665ae
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -0,0 +1,133 @@
+package dotty.tools
+package dotc
+package reporting
+
+import core.Contexts._
+import core.Positions._
+import core.Decorators.PhaseListDecorator
+import collection.mutable
+import io.{SourceFile, NoSource}
+import java.lang.System.currentTimeMillis
+
+trait Reporting { this: Context =>
+ def error(msg: String, pos: Position = NoPosition): Unit = reporter.error(msg, pos)
+ def warning(msg: String, pos: Position = NoPosition): Unit = reporter.warning(msg, pos)
+ def inform(msg: String, pos: Position = NoPosition): Unit = reporter.info(msg, pos)
+
+ def log(msg: => String)(implicit ctx: Context): Unit =
+ if (this.settings.log.value.containsPhase(phase))
+ inform(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg")
+
+ def debuglog(msg: => String)(implicit ctx: Context): Unit =
+ if (ctx.settings.debug.value) log(msg)
+
+ def informTime(msg: => String, start: Long)(implicit ctx: Context): Unit =
+ informProgress(msg + elapsed(start))
+
+ private def elapsed(start: Long) =
+ " in " + (currentTimeMillis - start) + "ms"
+
+ def informProgress(msg: => String)(implicit ctx: Context) =
+ if (ctx.settings.verbose.value) inform("[" + msg + "]")
+}
+
+object Reporter {
+ object Severity extends Enumeration {
+ val INFO, WARNING, ERROR = Value
+ }
+}
+
+/**
+ * This interface provides methods to issue information, warning and
+ * error messages.
+ */
+abstract class Reporter {
+
+ import Reporter.Severity.{Value => Severity, _}
+
+ protected def report(msg: String, severity: Severity, pos: Position)(implicit ctx: Context): Unit
+
+ protected def isHidden(severity: Severity, pos: Position)(implicit ctx: Context) = false
+
+ val count = new mutable.HashMap[Severity, Int]() {
+ override def default(key: Severity) = 0
+ }
+
+ /** Whether very long lines can be truncated. This exists so important
+ * debugging information (like printing the classpath) is not rendered
+ * invisible due to the max message length.
+ */
+ private var _truncationOK: Boolean = true
+ def truncationOK = _truncationOK
+ def withoutTruncating[T](body: => T): T = {
+ val saved = _truncationOK
+ _truncationOK = false
+ try body
+ finally _truncationOK = saved
+ }
+
+ type ErrorHandler = (String, Position, Context) => Unit
+ private var incompleteHandler: ErrorHandler = error(_, _)(_)
+ def withIncompleteHandler[T](handler: ErrorHandler)(op: => T): T = {
+ val saved = incompleteHandler
+ incompleteHandler = handler
+ try op
+ finally incompleteHandler = saved
+ }
+
+ def hasErrors = count(ERROR) > 0
+ def hasWarnings = count(WARNING) > 0
+
+ /** For sending messages that are printed only if -verbose is set */
+ def info(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit =
+ if (ctx.settings.verbose.value) info0(msg, INFO, pos)
+
+ /** For sending a message which should not be labeled as a warning/error,
+ * but also shouldn't require -verbose to be visible.
+ */
+ def echo(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit =
+ info0(msg, INFO, pos)
+
+ def warning(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit =
+ if (!ctx.settings.nowarn.value)
+ withoutTruncating(info0(msg, WARNING, pos))
+
+ def error(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit =
+ withoutTruncating(info0(msg, ERROR, pos))
+
+ def incompleteInputError(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit =
+ incompleteHandler(msg, pos, ctx)
+
+ private def info0(msg: String, severity: Severity, pos: Position)(implicit ctx: Context): Unit = {
+ if (!isHidden(severity, pos)) {
+ count(severity) += 1
+ report(msg, severity, pos)
+ }
+ }
+
+ /** Returns a string meaning "n elements". */
+ private def countElementsAsString(n: Int, elements: String): String =
+ n match {
+ case 0 => "no " + elements + "s"
+ case 1 => "one " + elements
+ case 2 => "two " + elements + "s"
+ case 3 => "three " + elements + "s"
+ case 4 => "four " + elements + "s"
+ case _ => n + " " + elements + "s"
+ }
+
+ protected def label(severity: Severity): String = severity match {
+ case INFO => ""
+ case ERROR => "error: "
+ case WARNING => "warning: "
+ }
+
+ protected def countString(severity: Severity) = {
+ assert(severity != INFO)
+ countElementsAsString(count(severity), label(severity).dropRight(2))
+ }
+
+ def flush(): Unit = {}
+
+ def reset(): Unit = count.clear()
+}
diff --git a/src/dotty/tools/dotc/reporting/StoreReporter.scala b/src/dotty/tools/dotc/reporting/StoreReporter.scala
new file mode 100644
index 000000000..5b9553509
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/StoreReporter.scala
@@ -0,0 +1,28 @@
+package dotty.tools
+package dotc
+package reporting
+
+import core.Contexts.Context
+import scala.collection.mutable
+import core.Positions.Position
+import Reporter.Severity.{Value => Severity}
+
+/**
+ * This class implements a Reporter that stores all messages
+ */
+class StoreReporter extends Reporter {
+
+ class Info(val msg: String, val severity: Severity, val pos: Position) {
+ override def toString() = "pos: " + pos + " " + msg + " " + severity
+ }
+ val infos = new mutable.LinkedHashSet[Info]
+
+ protected def report(msg: String, severity: Severity, pos: Position)(implicit ctx: Context): Unit = {
+ infos += new Info(msg, severity, pos)
+ }
+
+ override def reset() {
+ super.reset()
+ infos.clear()
+ }
+}
diff --git a/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala b/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
new file mode 100644
index 000000000..5df999aab
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
@@ -0,0 +1,35 @@
+package dotty.tools
+package dotc
+package reporting
+
+import scala.collection.mutable
+import core.Positions.Position
+import Reporter.Severity.{Value => Severity}
+import io.SourceFile
+import core.Contexts.Context
+
+/**
+ * This trait implements `isHidden` do that multiple messages per position
+ * are suppressed, unless they are of increasing severity.
+ */
+trait UniqueMessagePositions extends Reporter {
+
+ private val positions =
+ new mutable.HashMap[(SourceFile, Int), Severity]
+
+ /** Logs a position and returns true if it was already logged.
+ * @note Two positions are considered identical for logging if they have the same point.
+ */
+ override def isHidden(severity: Severity, pos: Position)(implicit ctx: Context): Boolean =
+ pos.exists && {
+ positions get (ctx.source, pos.point) match {
+ case Some(level) if level >= severity => true
+ case _ => positions((ctx.source, pos.point)) = severity; false
+ }
+ }
+
+ override def reset(): Unit = {
+ super.reset()
+ positions.clear()
+ }
+}
diff --git a/src/dotty/tools/io/package.scala b/src/dotty/tools/io/package.scala
index 2543c38d2..584819c58 100644
--- a/src/dotty/tools/io/package.scala
+++ b/src/dotty/tools/io/package.scala
@@ -14,6 +14,8 @@ package object io {
// Forwarders from scala.reflect.io
type AbstractFile = scala.reflect.io.AbstractFile
val AbstractFile = scala.reflect.io.AbstractFile
+ type SourceFile = AbstractFile // for now
+ val NoSource = scala.reflect.io.NoAbstractFile // for now
type Directory = scala.reflect.io.Directory
val Directory = scala.reflect.io.Directory
type File = scala.reflect.io.File