Skip to content

Commit bf6d805

Browse files
committed
Merge pull request #662 from dotty-staging/add/resident-compiler
Add/resident compiler
2 parents 68b4e6c + 840aa93 commit bf6d805

File tree

10 files changed

+104
-72
lines changed

10 files changed

+104
-72
lines changed

src/dotty/tools/dotc/Bench.scala

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,7 @@ package dotc
88
import core.Contexts.Context
99
import reporting.Reporter
1010

11-
/* To do:
12-
* - simplify hk types
13-
* - have a second look at normalization (leave at method types if pt is method type?)
14-
* - Don't open package objects from class files if they are present in source
15-
* - Revise the way classes are inherited - when not followed by [...] or (...),
16-
* assume the unparameterized type and forward type parameters as we do now for the synthetic head class.
17-
*/
1811
object Bench extends Driver {
19-
def resident(compiler: Compiler): Reporter = unsupported("resident") /*loop { line =>
20-
val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError))
21-
compiler.reporter.reset()
22-
new compiler.Run() compile command.files
23-
}*/
2412

2513
private var numRuns = 1
2614

@@ -29,29 +17,25 @@ object Bench extends Driver {
2917
private def ntimes(n: Int)(op: => Reporter): Reporter =
3018
(emptyReporter /: (0 until n)) ((_, _) => op)
3119

32-
override def doCompile(compiler: Compiler, fileNames: List[String], reporter: Option[Reporter] = None)
33-
(implicit ctx: Context): Reporter =
34-
if (new config.Settings.Setting.SettingDecorator[Boolean](ctx.base.settings.resident).value(ctx))
35-
resident(compiler)
36-
else
37-
ntimes(numRuns) {
38-
val start = System.nanoTime()
39-
val r = super.doCompile(compiler, fileNames, reporter)
40-
ctx.println(s"time elapsed: ${(System.nanoTime - start) / 1000000}ms")
41-
r
42-
}
20+
override def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter =
21+
ntimes(numRuns) {
22+
val start = System.nanoTime()
23+
val r = super.doCompile(compiler, fileNames)
24+
println(s"time elapsed: ${(System.nanoTime - start) / 1000000}ms")
25+
r
26+
}
4327

4428
def extractNumArg(args: Array[String], name: String, default: Int = 1): (Int, Array[String]) = {
4529
val pos = args indexOf name
4630
if (pos < 0) (default, args)
4731
else (args(pos + 1).toInt, (args take pos) ++ (args drop (pos + 2)))
4832
}
4933

50-
override def process(args: Array[String], rootCtx: Context, reporter: Option[Reporter] = None): Reporter = {
34+
override def process(args: Array[String], rootCtx: Context): Reporter = {
5135
val (numCompilers, args1) = extractNumArg(args, "#compilers")
5236
val (numRuns, args2) = extractNumArg(args1, "#runs")
5337
this.numRuns = numRuns
54-
ntimes(numCompilers)(super.process(args2, rootCtx, reporter))
38+
ntimes(numCompilers)(super.process(args2, rootCtx))
5539
}
5640
}
5741

src/dotty/tools/dotc/Compiler.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Periods._
77
import Symbols._
88
import Scopes._
99
import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks}
10-
import reporting.{ConsoleReporter, Reporter}
10+
import reporting.{Reporter, ConsoleReporter}
1111
import Phases.Phase
1212
import dotty.tools.dotc.transform._
1313
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
@@ -94,7 +94,7 @@ class Compiler {
9494
* for type checking.
9595
* imports For each element of RootImports, an import context
9696
*/
97-
def rootContext(implicit ctx: Context, r: Option[Reporter] = None): Context = {
97+
def rootContext(implicit ctx: Context): Context = {
9898
ctx.definitions.init(ctx)
9999
ctx.setPhasePlan(phases)
100100
val rootScope = new MutableScope
@@ -106,20 +106,22 @@ class Compiler {
106106
.setOwner(defn.RootClass)
107107
.setTyper(new Typer)
108108
.setMode(Mode.ImplicitsEnabled)
109-
.setTyperState(new MutableTyperState(ctx.typerState, r.getOrElse(new ConsoleReporter()(ctx)), isCommittable = true))
109+
.setTyperState(new MutableTyperState(ctx.typerState, rootReporter(ctx), isCommittable = true))
110110
ctx.definitions.init(start) // set context of definitions to start
111111
def addImport(ctx: Context, symf: () => Symbol) =
112112
ctx.fresh.setImportInfo(ImportInfo.rootImport(symf)(ctx))
113113
(start.setRunInfo(new RunInfo(start)) /: defn.RootImportFns)(addImport)
114114
}
115115

116+
protected def rootReporter(implicit ctx: Context): Reporter = new ConsoleReporter()(ctx)
117+
116118
def reset()(implicit ctx: Context): Unit = {
117119
ctx.base.reset()
118120
ctx.runInfo.clear()
119121
}
120122

121-
def newRun(implicit ctx: Context, r: Option[Reporter] = None): Run = {
123+
def newRun(implicit ctx: Context): Run = {
122124
reset()
123-
new Run(this)(rootContext(ctx, r))
125+
new Run(this)(rootContext)
124126
}
125127
}

src/dotty/tools/dotc/Driver.scala

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,40 @@ import scala.util.control.NonFatal
88

99
abstract class Driver extends DotClass {
1010

11-
val prompt = "\ndotc>"
11+
val prompt = "\ndotc> "
1212

1313
protected def newCompiler(): Compiler
1414

1515
protected def emptyReporter: Reporter = new StoreReporter
1616

17-
protected def doCompile(compiler: Compiler, fileNames: List[String], reporter: Option[Reporter] = None)
18-
(implicit ctx: Context): Reporter =
19-
if (fileNames.nonEmpty) {
20-
val run = compiler.newRun(ctx, reporter)
21-
run.compile(fileNames)
22-
run.printSummary()
23-
} else emptyReporter
17+
protected def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter =
18+
if (fileNames.nonEmpty)
19+
try {
20+
val run = compiler.newRun
21+
run.compile(fileNames)
22+
run.printSummary()
23+
}
24+
catch {
25+
case ex: FatalError =>
26+
ctx.error(ex.getMessage) // signals that we should fail compilation.
27+
ctx.typerState.reporter
28+
}
29+
else emptyReporter
2430

2531
protected def initCtx = (new ContextBase).initialCtx
2632

27-
def process(args: Array[String], rootCtx: Context, reporter: Option[Reporter] = None): Reporter = {
33+
protected def sourcesRequired = true
34+
35+
def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
2836
val summary = CompilerCommand.distill(args)(rootCtx)
2937
implicit val ctx: Context = initCtx.fresh.setSettings(summary.sstate)
30-
val fileNames = CompilerCommand.checkUsage(summary)
31-
try {
32-
doCompile(newCompiler(), fileNames, reporter)
33-
} catch {
34-
case ex: FatalError =>
35-
ctx.error(ex.getMessage) // signals that we should fail compilation.
36-
ctx.typerState.reporter
37-
}
38+
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
39+
(fileNames, ctx)
40+
}
41+
42+
def process(args: Array[String], rootCtx: Context): Reporter = {
43+
val (fileNames, ctx) = setup(args, rootCtx)
44+
doCompile(newCompiler(), fileNames)(ctx)
3845
}
3946

4047
def main(args: Array[String]): Unit =

src/dotty/tools/dotc/FromTasty.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ object FromTasty extends Driver {
4242
List(new ReadTastyTreesFromClasses) :: backendPhases
4343
}
4444

45-
override def newRun(implicit ctx: Context, reporter: Option[Reporter] = None): Run = {
45+
override def newRun(implicit ctx: Context): Run = {
4646
reset()
4747
new TASTYRun(this)(rootContext)
4848
}

src/dotty/tools/dotc/Main.scala

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
/* NSC -- new Scala compiler
2-
* Copyright 2005-2013 LAMP/EPFL
3-
* @author Martin Odersky
4-
*/
51
package dotty.tools
62
package dotc
73

@@ -11,18 +7,5 @@ import reporting.Reporter
117
/* To do:
128
*/
139
object Main extends Driver {
14-
def resident(compiler: Compiler): Reporter = unsupported("resident") /*loop { line =>
15-
val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError))
16-
compiler.reporter.reset()
17-
new compiler.Run() compile command.files
18-
}*/
19-
2010
override def newCompiler(): Compiler = new Compiler
21-
22-
override def doCompile(compiler: Compiler, fileNames: List[String], reporter: Option[Reporter] = None)(implicit ctx: Context): Reporter = {
23-
if (new config.Settings.Setting.SettingDecorator[Boolean](ctx.base.settings.resident).value(ctx))
24-
resident(compiler)
25-
else
26-
super.doCompile(compiler, fileNames, reporter)
27-
}
2811
}

src/dotty/tools/dotc/Resident.scala

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package dotty.tools
2+
package dotc
3+
4+
import core.Contexts.Context
5+
import reporting.Reporter
6+
import java.io.EOFException
7+
import scala.annotation.tailrec
8+
9+
/** A compiler which stays resident between runs.
10+
* Usage:
11+
*
12+
* > scala dotty.tools.dotc.Resident <options> <initial files>
13+
*
14+
* dotc> "more options and files to compile"
15+
*
16+
* ...
17+
*
18+
* dotc> :reset // reset all options to the ones passed on the command line
19+
*
20+
* ...
21+
*
22+
* dotc> :q // quit
23+
*/
24+
object Resident extends Driver {
25+
26+
object residentCompiler extends Compiler
27+
28+
override def newCompiler(): Compiler = ???
29+
30+
override def sourcesRequired = false
31+
32+
private val quit = ":q"
33+
private val reset = ":reset"
34+
35+
private def getLine() = {
36+
Console.print(prompt)
37+
try scala.io.StdIn.readLine() catch { case _: EOFException => quit }
38+
}
39+
40+
final override def process(args: Array[String], rootCtx: Context): Reporter = {
41+
@tailrec def loop(args: Array[String], prevCtx: Context): Reporter = {
42+
var (fileNames, ctx) = setup(args, prevCtx)
43+
doCompile(residentCompiler, fileNames)(ctx)
44+
var nextCtx = ctx
45+
var line = getLine()
46+
while (line == reset) {
47+
nextCtx = rootCtx
48+
line = getLine()
49+
}
50+
if (line.startsWith(quit)) ctx.typerState.reporter
51+
else loop(line split "\\s+", nextCtx)
52+
}
53+
loop(args, rootCtx)
54+
}
55+
}

src/dotty/tools/dotc/config/CompilerCommand.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ object CompilerCommand extends DotClass {
6060
* are already applied in context.
6161
* @return The list of files to compile.
6262
*/
63-
def checkUsage(summary: ArgsSummary)(implicit ctx: Context): List[String] = {
63+
def checkUsage(summary: ArgsSummary, sourcesRequired: Boolean)(implicit ctx: Context): List[String] = {
6464
val settings = ctx.settings
6565

6666
/** Creates a help message for a subset of options based on cond */
@@ -121,8 +121,7 @@ object CompilerCommand extends DotClass {
121121
ctx.println(infoMessage)
122122
Nil
123123
} else {
124-
if (summary.arguments.isEmpty && !settings.resident.value)
125-
ctx.println(usageMessage)
124+
if (sourcesRequired && summary.arguments.isEmpty) ctx.println(usageMessage)
126125
summary.arguments
127126
}
128127
}

src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ class ScalaSettings extends Settings.SettingGroup {
8181
val Xprintpos = BooleanSetting("-Xprint-pos", "Print tree positions, as offsets.")
8282
val printtypes = BooleanSetting("-Xprint-types", "Print tree types (debugging option).")
8383
val prompt = BooleanSetting("-Xprompt", "Display a prompt after each error (debugging option).")
84-
val resident = BooleanSetting("-Xresident", "Compiler stays resident: read source filenames from standard input.")
8584
val script = StringSetting("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "")
8685
val mainClass = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "")
8786
val Xshowcls = StringSetting("-Xshow-class", "class", "Show internal representation of class.", "")

src/dotty/tools/dotc/reporting/ThrowingReporter.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import collection.mutable
77
import Reporter._
88

99
/**
10-
* This class implements a Reporter that stores all messages
10+
* This class implements a Reporter that throws all errors and sends warnings and other
11+
* info to the underlying reporter.
1112
*/
1213
class ThrowingReporter(reportInfo: Reporter) extends Reporter {
1314
protected def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match {

test/dotty/partest/DPDirectCompiler.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ class DPDirectCompiler(runner: DPTestRunner) extends nest.DirectCompiler(runner)
2323
}
2424

2525
try {
26-
val processor = if (opts0.exists(_.startsWith("#"))) dotty.tools.dotc.Bench else dotty.tools.dotc.Main
26+
val processor =
27+
if (opts0.exists(_.startsWith("#"))) dotty.tools.dotc.Bench else dotty.tools.dotc.Main
2728
val clogger = new ConsoleReporter(writer = clogWriter)(ctx)
28-
val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, ctx, Some(clogger))
29+
val logCtx = ctx.fresh.setTyperState(ctx.typerState.withReporter(clogger))
30+
val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, logCtx)
2931
if (!reporter.hasErrors) runner.genPass()
3032
else {
3133
reporter.printSummary(ctx)

0 commit comments

Comments
 (0)