aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-04-27 21:24:55 +0200
committerMartin Odersky <odersky@gmail.com>2015-04-28 12:07:28 +0200
commit12f2ee7042c8f44a81afa54bdf261d4cd2a31b9c (patch)
treee46becdab2b8b1ec91a218e6f5091688f10b7e48
parentdad799912e80377310d6f2408a78344dc2112d8b (diff)
downloaddotty-12f2ee7042c8f44a81afa54bdf261d4cd2a31b9c.tar.gz
dotty-12f2ee7042c8f44a81afa54bdf261d4cd2a31b9c.tar.bz2
dotty-12f2ee7042c8f44a81afa54bdf261d4cd2a31b9c.zip
Compiler for embedded TASTY info.
`FromTasty` is a main module which compiles TASTY info instead of sources.
-rw-r--r--src/dotty/tools/dotc/Compiler.scala8
-rw-r--r--src/dotty/tools/dotc/FromTasty.scala90
-rw-r--r--src/dotty/tools/dotc/Run.scala30
3 files changed, 112 insertions, 16 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 1657adbbb..6787e3a2d 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -8,7 +8,7 @@ import Symbols._
import Scopes._
import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks}
import reporting.ConsoleReporter
-import dotty.tools.dotc.core.Phases.Phase
+import Phases.Phase
import dotty.tools.dotc.transform._
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
@@ -101,9 +101,13 @@ class Compiler {
(start.setRunInfo(new RunInfo(start)) /: defn.RootImports)(addImport)
}
- def newRun(implicit ctx: Context): Run = {
+ def reset()(implicit ctx: Context): Unit = {
ctx.base.reset()
ctx.runInfo.clear()
+ }
+
+ def newRun(implicit ctx: Context): Run = {
+ reset()
new Run(this)(rootContext)
}
}
diff --git a/src/dotty/tools/dotc/FromTasty.scala b/src/dotty/tools/dotc/FromTasty.scala
new file mode 100644
index 000000000..844f5fe76
--- /dev/null
+++ b/src/dotty/tools/dotc/FromTasty.scala
@@ -0,0 +1,90 @@
+/* dotc
+ * Copyright 2005-2015 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package dotty.tools
+package dotc
+
+import core._
+import Contexts._
+import Symbols._
+import SymDenotations._
+import typer.FrontEnd
+import Phases.Phase
+import util._
+import Decorators._
+import dotty.tools.dotc.transform.Pickler
+import pickling.DottyUnpickler
+
+object FromTasty extends Driver {
+ override def newCompiler(): Compiler = new TASTYCompiler
+
+ class TASTYCompiler extends Compiler {
+
+ override def phases: List[List[Phase]] = {
+ val backendPhases = super.phases.dropWhile {
+ case List(_: Pickler) => false
+ case _ => true
+ }.tail
+ List(new ReadTastyTreesFromClasses) :: backendPhases
+ }
+
+ override def newRun(implicit ctx: Context): Run = {
+ reset()
+ new TASTYRun(this)(rootContext)
+ }
+ }
+
+ class TASTYRun(comp: Compiler)(implicit ctx: Context) extends Run(comp) {
+ override def compile(classNames: List[String]) = {
+ units = classNames.map(new TASTYCompilationUnit(_))
+ compileUnits()
+ }
+ }
+
+ class TASTYCompilationUnit(val className: String) extends CompilationUnit(NoSource) {
+ override def toString = s"class file $className"
+ }
+
+ class ReadTastyTreesFromClasses extends FrontEnd {
+ override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] =
+ units.map(readTASTY)
+
+ def readTASTY(unit: CompilationUnit)(implicit ctx: Context): CompilationUnit = unit match {
+ case unit: TASTYCompilationUnit =>
+ val className = unit.className.toTypeName
+ val clsd =
+ if (className.contains('.')) ctx.base.staticRef(className)
+ else defn.EmptyPackageClass.info.decl(className)
+ def cannotUnpickle(reason: String) = {
+ ctx.error(s"class $className cannot be unpickled because $reason")
+ unit
+ }
+ clsd match {
+ case clsd: ClassDenotation =>
+ clsd.infoOrCompleter match {
+ case info: ClassfileLoader =>
+ info.load(clsd) match {
+ case Some(unpickler: DottyUnpickler) =>
+ val (List(unpickled), sources) = unpickler.body(readPositions = false)
+ val unit1 = sources.get(unpickled) match {
+ case Some(source) => new CompilationUnit(source)
+ case _ => unit
+ }
+ unit1.tpdTree = unpickled
+ unit1.embeddedSources = sources - unpickled
+ unit1
+ case _ =>
+ cannotUnpickle(s"it does not have a TASTY attribute")
+ }
+ case info =>
+ cannotUnpickle(s"its info of type ${info.getClass} is not a ClassfileLoader")
+ }
+ case _ =>
+ println(defn.EmptyPackageClass.info.decls)
+ ctx.error(s"class not found: $className")
+ unit
+ }
+ }
+ }
+}
diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala
index af9c878f0..a008214c9 100644
--- a/src/dotty/tools/dotc/Run.scala
+++ b/src/dotty/tools/dotc/Run.scala
@@ -38,23 +38,25 @@ class Run(comp: Compiler)(implicit ctx: Context) {
* or we need to assmeble phases on each run, and take -Yskip, -Ystop into
* account. I think the latter would be preferable.
*/
- def compileSources(sources: List[SourceFile]) = Stats.monitorHeartBeat {
+ def compileSources(sources: List[SourceFile]) =
if (sources forall (_.exists)) {
- val phases = ctx.squashPhases(ctx.phasePlan,
- ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, ctx.settings.YstopAfter.value, ctx.settings.Ycheck.value)
- ctx.usePhases(phases)
units = sources map (new CompilationUnit(_))
- for (phase <- ctx.allPhases)
- if (!ctx.reporter.hasErrors) {
- if (ctx.settings.verbose.value) println(s"[$phase]")
- units = phase.runOn(units)
- def foreachUnit(op: Context => Unit)(implicit ctx: Context): Unit =
- for (unit <- units) op(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
- if (ctx.settings.Xprint.value.containsPhase(phase))
- foreachUnit(printTree)
-
- }
+ compileUnits()
}
+
+ protected def compileUnits() = Stats.monitorHeartBeat {
+ val phases = ctx.squashPhases(ctx.phasePlan,
+ ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, ctx.settings.YstopAfter.value, ctx.settings.Ycheck.value)
+ ctx.usePhases(phases)
+ for (phase <- ctx.allPhases)
+ if (!ctx.reporter.hasErrors) {
+ if (ctx.settings.verbose.value) println(s"[$phase]")
+ units = phase.runOn(units)
+ def foreachUnit(op: Context => Unit)(implicit ctx: Context): Unit =
+ for (unit <- units) op(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
+ if (ctx.settings.Xprint.value.containsPhase(phase))
+ foreachUnit(printTree)
+ }
}
private def printTree(ctx: Context) = {