Skip to content

Commit 374c30f

Browse files
allanrenucciAllan Renucci
authored and
Allan Renucci
committed
Extract parser into its own phase
1 parent 11acdd9 commit 374c30f

File tree

9 files changed

+64
-69
lines changed

9 files changed

+64
-69
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import transform._
99
import dotty.tools.backend.jvm.{CollectSuperCalls, GenBCode}
1010
import dotty.tools.backend.sjs
1111
import dotty.tools.dotc.transform.localopt.StringInterpolatorOpt
12+
import dotty.tools.dotc.parsing.Parsing
1213

1314
/** The central class of the dotc compiler. The job of a compiler is to create
1415
* runs, which process given `phases` in a given `rootContext`.
@@ -36,6 +37,7 @@ class Compiler {
3637

3738
/** Phases dealing with the frontend up to trees ready for TASTY pickling */
3839
protected def frontendPhases: List[List[Phase]] =
40+
List(new Parsing) ::
3941
List(new FrontEnd) :: // Compiler frontend: scanner, parser, namer, typer
4042
List(new YCheckPositions) :: // YCheck positions
4143
List(new Staging) :: // Check PCP, heal quoted types and expand macros

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
155155
Stats.trackTime(s"$phase ms ") {
156156
val start = System.currentTimeMillis
157157
val profileBefore = profiler.beforePhase(phase)
158-
units = phase.runOn(units)
158+
units = phase.runOn(units)(ctx.fresh.setPhase(phase.start))
159159
profiler.afterPhase(phase, profileBefore)
160160
if (ctx.settings.Xprint.value.containsPhase(phase)) {
161161
for (unit <- units) {
@@ -217,7 +217,10 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
217217
val unit = ctx.compilationUnit
218218
val prevPhase = ctx.phase.prev // can be a mini-phase
219219
val squashedPhase = ctx.base.squashed(prevPhase)
220-
val treeString = unit.tpdTree.show(ctx.withProperty(XprintMode, Some(())))
220+
val tree =
221+
if (ctx.isAfterTyper) unit.tpdTree
222+
else unit.untpdTree
223+
val treeString = tree.show(ctx.withProperty(XprintMode, Some(())))
221224

222225
ctx.echo(s"result of $unit after $squashedPhase:")
223226

compiler/src/dotty/tools/dotc/core/Phases.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Denotations._
1010
import Decorators._
1111
import config.Printers.config
1212
import scala.collection.mutable.ListBuffer
13+
import scala.util.control.NonFatal
1314
import dotty.tools.dotc.transform.MegaPhase._
1415
import dotty.tools.dotc.transform._
1516
import Periods._
@@ -312,7 +313,7 @@ object Phases {
312313
/** @pre `isRunnable` returns true */
313314
def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] =
314315
units.map { unit =>
315-
val unitCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit)
316+
val unitCtx = ctx.fresh.setCompilationUnit(unit)
316317
run(unitCtx)
317318
unitCtx.compilationUnit
318319
}
@@ -327,7 +328,7 @@ object Phases {
327328
def checkPostCondition(tree: tpd.Tree)(implicit ctx: Context): Unit = ()
328329

329330
/** Is this phase the standard typerphase? True for FrontEnd, but
330-
* not for other first phases (such as FromTasty). The predicate
331+
* not for other first phases (such as ReadTasty). The predicate
331332
* is tested in some places that perform checks and corrections. It's
332333
* different from isAfterTyper (and cheaper to test).
333334
*/
@@ -412,6 +413,14 @@ object Phases {
412413
final def iterator: Iterator[Phase] =
413414
Iterator.iterate(this)(_.next) takeWhile (_.hasNext)
414415

416+
final def monitor(doing: String)(body: => Unit)(implicit ctx: Context): Unit =
417+
try body
418+
catch {
419+
case NonFatal(ex) =>
420+
ctx.echo(s"exception occurred while $doing ${ctx.compilationUnit}")
421+
throw ex
422+
}
423+
415424
override def toString: String = phaseName
416425
}
417426

compiler/src/dotty/tools/dotc/interactive/InteractiveCompiler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ package interactive
55
import core._
66
import Phases._
77
import typer._
8+
import parsing.Parsing
89

910
class InteractiveCompiler extends Compiler {
1011
// TODO: Figure out what phases should be run in IDEs
1112
// More phases increase latency but allow us to report more errors.
1213
// This could be improved by reporting errors back to the IDE
1314
// after each phase group instead of waiting for the pipeline to finish.
1415
override def phases: List[List[Phase]] = List(
16+
List(new Parsing),
1517
List(new FrontEnd),
1618
List(new transform.SetRootTree),
1719
List(new transform.CookComments)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dotty.tools.dotc.parsing
2+
3+
import dotty.tools.dotc.config.Config
4+
import dotty.tools.dotc.core.Contexts.Context
5+
import dotty.tools.dotc.core.Phases.Phase
6+
import dotty.tools.dotc.parsing.JavaParsers.JavaParser
7+
import dotty.tools.dotc.parsing.Parsers.Parser
8+
9+
class Parsing extends Phase {
10+
11+
override def phaseName: String = "parsing"
12+
13+
// We run TreeChecker only after type checking
14+
override def isCheckable: Boolean = false
15+
16+
override def isRunnable(implicit ctx: Context): Boolean =
17+
!ctx.settings.fromTasty.value
18+
19+
override def run(implicit ctx: Context): Unit = monitor("parsing") {
20+
val unit = ctx.compilationUnit
21+
unit.untpdTree =
22+
if (unit.isJava) new JavaParser(unit.source).parse()
23+
else new Parser(unit.source).parse()
24+
25+
if (Config.checkPositions)
26+
unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors)
27+
}
28+
}

compiler/src/dotty/tools/dotc/typer/FrontEnd.scala

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@ import core._
66
import Phases._
77
import Contexts._
88
import Symbols._
9-
import dotty.tools.dotc.parsing.JavaParsers.JavaParser
10-
import parsing.Parsers.Parser
119
import config.Config
1210
import config.Printers.{typr, default}
1311
import util.Stats._
1412
import util.{ SourcePosition, NoSourcePosition }
1513
import scala.util.control.NonFatal
16-
import ast.Trees._
14+
import ast.{tpd, Trees}
15+
import Trees._
1716

1817
class FrontEnd extends Phase {
18+
import tpd._
1919

2020
override def phaseName: String = FrontEnd.name
2121
override def isTyper: Boolean = true
22-
import ast.tpd
22+
23+
// Run regardless of parsing errors
24+
override def isRunnable(implicit ctx: Context): Boolean = true
2325

2426
override def allowsImplicitSearch: Boolean = true
2527

@@ -37,48 +39,21 @@ class FrontEnd extends Phase {
3739
def stillToBeEntered(name: String): Boolean =
3840
remaining.exists(_.compilationUnit.toString.endsWith(name + ".scala"))
3941

40-
def monitor(doing: String)(body: => Unit)(implicit ctx: Context): Unit =
41-
try body
42-
catch {
43-
case NonFatal(ex) =>
44-
ctx.echo(s"exception occurred while $doing ${ctx.compilationUnit}")
45-
throw ex
46-
}
47-
48-
def parse(implicit ctx: Context): Unit = monitor("parsing") {
49-
val unit = ctx.compilationUnit
50-
51-
unit.untpdTree =
52-
if (unit.isJava) new JavaParser(unit.source).parse()
53-
else {
54-
val p = new Parser(unit.source)
55-
val tree = p.parse()
56-
if (p.firstXmlPos.exists && !firstXmlPos.exists)
57-
firstXmlPos = p.firstXmlPos
58-
tree
59-
}
60-
61-
val printer = if (ctx.settings.Xprint.value.contains("parser")) default else typr
62-
printer.println("parsed:\n" + unit.untpdTree.show)
63-
if (Config.checkPositions)
64-
unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors)
65-
}
66-
67-
def enterSyms(implicit ctx: Context): Unit = monitor("indexing") {
42+
private def enterSyms(implicit ctx: Context): Unit = monitor("indexing") {
6843
val unit = ctx.compilationUnit
6944
ctx.typer.index(unit.untpdTree)
7045
typr.println("entered: " + unit.source)
7146
}
7247

73-
def typeCheck(implicit ctx: Context): Unit = monitor("typechecking") {
48+
private def typeCheck(implicit ctx: Context): Unit = monitor("typechecking") {
7449
val unit = ctx.compilationUnit
7550
unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
7651
typr.println("typed: " + unit.source)
7752
record("retained untyped trees", unit.untpdTree.treeSize)
7853
record("retained typed trees after typer", unit.tpdTree.treeSize)
7954
}
8055

81-
private def firstTopLevelDef(trees: List[tpd.Tree])(implicit ctx: Context): Symbol = trees match {
56+
private def firstTopLevelDef(trees: List[Tree])(implicit ctx: Context): Symbol = trees match {
8257
case PackageDef(_, defs) :: _ => firstTopLevelDef(defs)
8358
case Import(_, _, _) :: defs => firstTopLevelDef(defs)
8459
case (tree @ TypeDef(_, _)) :: _ => tree.symbol
@@ -93,8 +68,8 @@ class FrontEnd extends Phase {
9368
ctx.inform(s"compiling ${unit.source}")
9469
ctx.fresh.setCompilationUnit(unit)
9570
}
96-
unitContexts foreach (parse(_))
97-
record("parsedTrees", ast.Trees.ntrees)
71+
72+
record("parsedTrees", Trees.ntrees)
9873
remaining = unitContexts
9974
while (remaining.nonEmpty) {
10075
enterSyms(remaining.head)
@@ -107,7 +82,7 @@ class FrontEnd extends Phase {
10782
firstXmlPos)
10883

10984
unitContexts.foreach(typeCheck(_))
110-
record("total trees after typer", ast.Trees.ntrees)
85+
record("total trees after typer", Trees.ntrees)
11186
unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper)
11287
}
11388

compiler/src/dotty/tools/repl/ReplCompiler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import dotty.tools.dotc.core.StdNames._
1313
import dotty.tools.dotc.core.Symbols._
1414
import dotty.tools.dotc.reporting.diagnostic.messages
1515
import dotty.tools.dotc.transform.{PostTyper, Staging}
16-
import dotty.tools.dotc.typer.ImportInfo
16+
import dotty.tools.dotc.typer.{FrontEnd, ImportInfo}
1717
import dotty.tools.dotc.util.Spans._
1818
import dotty.tools.dotc.util.{ParsedComment, SourceFile}
1919
import dotty.tools.dotc.{CompilationUnit, Compiler, Run}
@@ -32,7 +32,7 @@ import scala.collection.mutable
3232
class ReplCompiler extends Compiler {
3333

3434
override protected def frontendPhases: List[List[Phase]] = List(
35-
List(new REPLFrontEnd),
35+
List(new FrontEnd),
3636
List(new CollectTopLevelImports),
3737
List(new Staging),
3838
List(new PostTyper)

compiler/src/dotty/tools/repl/ReplFrontEnd.scala

Lines changed: 0 additions & 26 deletions
This file was deleted.

doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import dotc.typer.FrontEnd
1111

1212
import dotty.tools.dotc.fromtasty.{ReadTasty, TASTYRun}
1313
import dotty.tools.dotc.transform.CookComments
14+
import dotty.tools.dotc.parsing.Parsing
1415

1516
/** Custom Compiler with phases for the documentation tool
1617
*
@@ -53,6 +54,7 @@ class DocCompiler extends Compiler {
5354
}
5455

5556
override def phases: List[List[Phase]] = List(
57+
List(new Parsing),
5658
List(new DocFrontEnd),
5759
List(new ReadTasty),
5860
List(new CookComments),

0 commit comments

Comments
 (0)