diff options
author | Martin Odersky <odersky@gmail.com> | 2015-04-27 21:24:55 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-04-28 12:07:28 +0200 |
commit | 12f2ee7042c8f44a81afa54bdf261d4cd2a31b9c (patch) | |
tree | e46becdab2b8b1ec91a218e6f5091688f10b7e48 | |
parent | dad799912e80377310d6f2408a78344dc2112d8b (diff) | |
download | dotty-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.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/FromTasty.scala | 90 | ||||
-rw-r--r-- | src/dotty/tools/dotc/Run.scala | 30 |
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) = { |