Skip to content

Separate parsing into its own Phase #13173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 6, 2021

Conversation

adampauls
Copy link
Contributor

@adampauls adampauls commented Jul 27, 2021

First-time contributor. This is a resurrection of #5613. I've left a few inline comments about any confusion I had along the way.
Motivations:

  • Reuse phase infrastructure (e.g. -Ystop-after:parser)
  • Make it easier to replace the parser (useful in the REPL for example)

@adampauls adampauls marked this pull request as draft July 27, 2021 22:45
@@ -64,7 +66,6 @@ object Phases {
YCheckAfter: List[String])(using Context): List[Phase] = {
val fusedPhases = ListBuffer[Phase]()
var prevPhases: Set[String] = Set.empty
val YCheckAll = YCheckAfter.contains("all")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was redundant because containsPhase already checks for "all"

@@ -106,7 +107,7 @@ object Phases {
phase
}
fusedPhases += phaseToAdd
val shouldAddYCheck = YCheckAfter.containsPhase(phaseToAdd) || YCheckAll
val shouldAddYCheck = filteredPhases(i).exists(_.isCheckable) && YCheckAfter.containsPhase(phaseToAdd)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for isCheckable.

@@ -402,9 +407,17 @@ object Phases {
final def iterator: Iterator[Phase] =
Iterator.iterate(this)(_.next) takeWhile (_.hasNext)

final def monitor(doing: String)(body: => Unit)(using Context): Unit =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved up from FrontEnd

@@ -573,7 +573,7 @@ object SymDenotations {
case _ =>
// Otherwise, no completion is necessary, see the preconditions of `markAbsent()`.
(myInfo `eq` NoType)
|| is(Invisible) && !ctx.isAfterTyper
|| is(Invisible) && ctx.isTyper
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is the intent of this line.

@@ -113,7 +115,7 @@ class Pickler extends Phase {
val ctx2 = ctx.fresh.setSetting(ctx.settings.YreadComments, true)
testUnpickler(
using ctx2
.setPeriod(Period(ctx.runId + 1, FirstPhaseId))
.setPeriod(Period(ctx.runId + 1, ctx.base.typerPhase.id))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed to fix the pickling tests. I don't understand why.

@adampauls adampauls changed the title [WIP] Separate parsing into its own Phase Separate parsing into its own Phase Jul 31, 2021
@adampauls adampauls marked this pull request as ready for review July 31, 2021 02:16
@@ -164,3 +164,10 @@ The test suite will create a new file if it detects any difference, which can be
original expect file, or if the user wants to globally replace all expect files for semanticdb they can use
`scala3-compiler-bootstrapped/test:runMain dotty.tools.dotc.semanticdb.updateExpect`, and compare the changes via version
control.

## Troubleshooting
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrote up some advice I got from gitter.

@smarter
Copy link
Member

smarter commented Aug 2, 2021

This is a resurrection #5613.

Cool, /cc @allanrenucci

@adampauls adampauls force-pushed the wip_separate_parser_phase branch from d68d3f3 to adc8f44 Compare August 2, 2021 18:26
@adampauls
Copy link
Contributor Author

adampauls commented Aug 2, 2021

I rebased so there are only two commits. I fixed a test failure. There's a compilation error that seems to be present on master

[error] -- [E007] Type Mismatch Error: /Users/adpauls/sm/git/dotty/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala:258:97
[error] 258 |            ParametersList(paramList.params.map(mkParameter(_, memberInfo = memberInfo.paramLists(index))), paramListModifier(paramList.params))

@griggt
Copy link
Contributor

griggt commented Aug 2, 2021

[error] -- [E008] Not Found Error: /__w/dotty/dotty/community-build/community-projects/akka/plugins/serialversion-remover-plugin/src/main/scala/akka/Plugin.scala:14:30 
[error] 14 |import dotty.tools.dotc.typer.FrontEnd
[error]    |                              ^^^^^^^^
[error]    |                value FrontEnd is not a member of dotty.tools.dotc.typer

There is an open ticket upstream to remove this compiler plugin: akka/akka#30245

@adampauls adampauls force-pushed the wip_separate_parser_phase branch from adc8f44 to 024b0ad Compare August 2, 2021 20:14
val name: String = "typer"
}

@deprecated(message = "FrontEnd has been split into TyperPhase and Parser. Refer to one or the other.")
object FrontEnd {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little sketchy, but should silence the error in the community build.

@adampauls
Copy link
Contributor Author

adampauls commented Aug 2, 2021

Also, /cc @biboudis

Copy link
Member

@dwijnand dwijnand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm no expert, but the diff seems reasonable to me. Left some non-major comments, questions and suggestions.

unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors)
}
// Run regardless of parsing errors
override def isRunnable(implicit ctx: Context): Boolean = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong, no? Then again no checkfile has failed so perhaps I'm wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I lifted that from the original PR. Without it, at least dotty.tools.dotc.CompilationTests fail.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, even in case of errors in parsing, we run the typer phase, this is particularly useful for IDEs since it means the presentation compiler is usable even when your code doesn't typecheck.

Copy link
Member

@dwijnand dwijnand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I'm not sure if Nico's just putting names to PRs or if he wants Guilliaume to sign off on merging this.

@adampauls
Copy link
Contributor Author

Thanks for the quick review!

@adampauls
Copy link
Contributor Author

I'll hold off until merging until @smarter has approved.

@adampauls adampauls requested a review from smarter August 4, 2021 01:45
@adampauls
Copy link
Contributor Author

Should I continue to wait or just go ahead and merge?

@smarter
Copy link
Member

smarter commented Aug 5, 2021

I should be able to review this tomorrow.

Copy link
Member

@smarter smarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM.

@@ -97,7 +97,8 @@ phases. The current list of phases is specified in class [Compiler] as follows:

/** Phases dealing with the frontend up to trees ready for TASTY pickling */
protected def frontendPhases: List[List[Phase]] =
List(new FrontEnd) :: // Compiler frontend: scanner, parser, namer, typer
List(new Parser) :: // scanner, parser, namer, typer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
List(new Parser) :: // scanner, parser, namer, typer
List(new Parser) :: // scanner, parser

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks

Comment on lines 80 to 81
// TODO without this test, dotty.tools.repl.ScriptedTests fails. Not sure why.
if (this.start > Periods.FirstPhaseId)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using this to indirectly check if we're in the REPL, I suggest defining class TyperPhase(val addRootImports: Boolean = true) and setting the parameter to false in ReplCompiler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@smarter smarter assigned adampauls and unassigned smarter Aug 6, 2021
@adampauls adampauls force-pushed the wip_separate_parser_phase branch from 87456bb to bd08f7e Compare August 6, 2021 16:36
@fommil
Copy link

fommil commented Feb 3, 2022

@smarter does this mean we can have pre-typer plugins now? 😬 As per https://contributors.scala-lang.org/t/pre-typer-syntactic-plugins-in-scala-3/5565

@smarter
Copy link
Member

smarter commented Feb 3, 2022

No, pre-typer plugin are still intentionally restricted to research plugins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants