-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add expression compiler #22597
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
Add expression compiler #22597
Conversation
37985f6 to
839713b
Compare
|
Looks like the tests are not compiling due to usage of newer JDK API? |
I need to configure sbt-jdi-tools to enable JDI on JDK 8. |
55e7262 to
df7f853
Compare
d60954c to
b207244
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review of the tests and testing infrastructure so far (everything except the actual compiler/src/ things).
sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSCompilationTests.scala
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here's the rest.
11e4259 to
587896a
Compare
debugMode allows to connect to runner processes with JDI
Each time we disconnect the debugger, the child process opens a new port that we must read to connect a new debugger
We use ParallelTesting.cleanup instead
587896a to
9fcf8f1
Compare
| val errorWithNewPos = new Diagnostic.Error(error.msg, newPos) | ||
| reportError(stripColor(messageAndPos(errorWithNewPos))) | ||
| case _ => | ||
| // TODO report the warnings in the expression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we report warnings? Maybe let's add a follow up issue later if this really necessary, but I would say it's not.
| override def phaseName: String = InsertExpression.name | ||
| override def isCheckable: Boolean = false | ||
|
|
||
| // TODO move reflection methods (callMethod, getField, etc) to scala3-library |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's maybe create an issue?
This PR migrates the expression compiler from scalacenter/scala-debug-adapter to the scala3 repository. This change was agreed upon a few months ago during a core meeting to simplify the release process. By doing so, we eliminate the need to release parts of scalacenter/scala-debug-adapter during each Scala 3 release.
The
ExpressionCompilerandExpressionCompilerBridgeare now parts of the main compiler module. This integration streamlines usage for external tools like sbt, Metals, Bloop, IJ Scala plugin. They can now rely on the compiler JAR directly without needing to download additional artifacts.The expression compiler
The expression compiler extends the main compiler with 3 phases:
InsertExpression:
def evaluate: Anymethod.ExtractExpression:
Typer, the pickler phases,ExtensionMethodsandElimByName.LambdaLiftto prevent interference: the expression itself can change how lambdas are lifted. Notably it can contains lambda that needs to be lifted to the expression class.ResolveReflectEval:
reflectEvalcalls into actual reflective calls based onReflectEvalStrategymetadata.Usage of the expression compiler
The expression compiler powers the debug console in Metals and the IJ Scala plugin, enabling evaluation of arbitrary Scala expressions at runtime (even macros). The expression compiler produce class files that can be loaded the running Scala program, to compute the evaluation output.
The
ExpressionCompilerBridgecan be invoked by reflection with the following parameters:outputDir: Path: Directory where compiled classes are writtenclassPath: String: Classpath used during compilationoptions: Array[String]: Compiler optionssourceFile: Path: Source file where the expression is evaluatedconfig: ExpressionCompilerConfig:packageName: Package name of the current evaluation frameoutputClassName: String: Name of the main generated class, to be loaded by the debuggeebreakpointLine: Int: Line number where the expression is evaluatedexpression: String: Expression to compilelocalVariables: Set[String]: Set of visible local variables (used for checking evaluation of captured variables)errorReporter: Consumer[String]: Callback for reporting errorsThe
ExpressionCompilerConfigis designed as a factory class to allow binary-compatible evolution across versions, enabling cross-compatibility between different debugger and compiler versions.The debug tests
A significant part of this PR is the migration of ScalaEvaluationTests, notably the integration with the vulpix test infrastructure:
dotty.tools.vulpix.RunnerOrchestration:debugModeto start runners with JVM debugging optionsdebugMainmethod to connect a debugger, start a main method and execute the debug stepsdotty.tools.debug.Debugger: a lightweight implementation of a JVM debuggerdotty.tools.debug.ExpressionEvaluator: to compile and evaluate expressions insidedotty.tools.debug.Debuggerdotty.tools.debug.DebugStepAssert: to describe a debug scenario as a series of steps (break,step,nextandeval)dotty.tools.debug.DebugTeststest class:tests/debug.checkfile as a series ofDebugStepAssertdebugMain, and executes the debug stepsI migrated all relevant tests from ScalaEvaluationTests to
tests/debugfolder. Thanks to Vulpix parallel execution, the 47 debug tests now complete in approximately 30-40 seconds.