aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/Run.scala
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-02 11:08:28 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch)
treea8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/Run.scala
parent6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff)
downloaddotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/Run.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/Run.scala138
1 files changed, 138 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala
new file mode 100644
index 000000000..0f652ff0b
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/Run.scala
@@ -0,0 +1,138 @@
+package dotty.tools
+package dotc
+
+import core._
+import Contexts._
+import Periods._
+import Symbols._
+import Phases._
+import Decorators._
+import dotty.tools.dotc.transform.TreeTransforms.TreeTransformer
+import io.PlainFile
+import scala.io.Codec
+import util._
+import reporting.Reporter
+import transform.TreeChecker
+import rewrite.Rewrites
+import java.io.{BufferedWriter, OutputStreamWriter}
+
+import scala.annotation.tailrec
+import scala.reflect.io.VirtualFile
+import scala.util.control.NonFatal
+
+/** A compiler run. Exports various methods to compile source files */
+class Run(comp: Compiler)(implicit ctx: Context) {
+
+ assert(comp.phases.last.last.id <= Periods.MaxPossiblePhaseId)
+ assert(ctx.runId <= Periods.MaxPossibleRunId)
+
+ var units: List[CompilationUnit] = _
+
+ def getSource(fileName: String): SourceFile = {
+ val f = new PlainFile(fileName)
+ if (f.isDirectory) {
+ ctx.error(s"expected file, received directory '$fileName'")
+ NoSource
+ } else if (f.exists) {
+ val encoding = ctx.settings.encoding.value
+ new SourceFile(f, Codec(encoding))
+ } else {
+ ctx.error(s"not found: $fileName")
+ NoSource
+ }
+ }
+
+ def compile(fileNames: List[String]): Unit = try {
+ val sources = fileNames map getSource
+ compileSources(sources)
+ } catch {
+ case NonFatal(ex) =>
+ ctx.echo(i"exception occurred while compiling $units%, %")
+ throw ex
+ }
+
+ /** TODO: There's a fundamental design problem here: We assemble phases using `squash`
+ * when we first build the compiler. But we modify them with -Yskip, -Ystop
+ * on each run. That modification needs to either transform the tree structure,
+ * or we need to assemble phases on each run, and take -Yskip, -Ystop into
+ * account. I think the latter would be preferable.
+ */
+ def compileSources(sources: List[SourceFile]) =
+ if (sources forall (_.exists)) {
+ units = sources map (new CompilationUnit(_))
+ compileUnits()
+ }
+
+ protected def compileUnits() = Stats.monitorHeartBeat {
+ ctx.checkSingleThreaded()
+ 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)
+ var lastPrintedTree: PrintedTree = NoPrintedTree
+ for (phase <- ctx.allPhases)
+ if (!ctx.reporter.hasErrors) {
+ val start = System.currentTimeMillis
+ units = phase.runOn(units)
+ if (ctx.settings.Xprint.value.containsPhase(phase)) {
+ for (unit <- units) {
+ lastPrintedTree =
+ printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
+ }
+ }
+ ctx.informTime(s"$phase ", start)
+ }
+ if (!ctx.reporter.hasErrors) Rewrites.writeBack()
+ for (unit <- units)
+ Stats.record("retained typed trees at end", unit.tpdTree.treeSize)
+ Stats.record("total trees at end", ast.Trees.ntrees)
+ }
+
+ private sealed trait PrintedTree
+ private final case class SomePrintedTree(phase: String, tree: String) extends PrintedTree
+ private object NoPrintedTree extends PrintedTree
+
+ private def printTree(last: PrintedTree)(implicit ctx: Context): PrintedTree = {
+ val unit = ctx.compilationUnit
+ val prevPhase = ctx.phase.prev // can be a mini-phase
+ val squashedPhase = ctx.squashed(prevPhase)
+ val treeString = unit.tpdTree.show
+
+ ctx.echo(s"result of $unit after $squashedPhase:")
+
+ last match {
+ case SomePrintedTree(phase, lastTreeSting) if lastTreeSting != treeString =>
+ val msg =
+ if (!ctx.settings.XprintDiff.value && !ctx.settings.XprintDiffDel.value) treeString
+ else DiffUtil.mkColoredCodeDiff(treeString, lastTreeSting, ctx.settings.XprintDiffDel.value)
+ ctx.echo(msg)
+ SomePrintedTree(squashedPhase.toString, treeString)
+
+ case SomePrintedTree(phase, lastTreeSting) =>
+ ctx.echo(" Unchanged since " + phase)
+ last
+
+ case NoPrintedTree =>
+ ctx.echo(treeString)
+ SomePrintedTree(squashedPhase.toString, treeString)
+ }
+ }
+
+ def compile(sourceCode: String): Unit = {
+ val virtualFile = new VirtualFile(sourceCode) // use source code as name as it's used for equals
+ val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8")) // buffering is still advised by javadoc
+ writer.write(sourceCode)
+ writer.close()
+ compileSources(List(new SourceFile(virtualFile, Codec.UTF8)))
+ }
+
+ /** The context created for this run */
+ def runContext = ctx
+
+ /** Print summary; return # of errors encountered */
+ def printSummary(): Reporter = {
+ ctx.runInfo.printMaxConstraint()
+ val r = ctx.reporter
+ r.printSummary
+ r
+ }
+}