Commit 8a99f9f
authored
Add expression compiler (#22597)
This PR migrates the expression compiler from
[scalacenter/scala-debug-adapter](https://github.com/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](https://github.com/scalacenter/scala-debug-adapter)
during each Scala 3 release.
The `ExpressionCompiler` and `ExpressionCompilerBridge` are 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**:
- Just after parsing
- Parses and inserts the expression in the original source tree.
- Inserts the expression class, with a placeholder `def evaluate: Any`
method.
**ExtractExpression**:
- After `Typer`, the pickler phases, `ExtensionMethods` and
`ElimByName`.
- Extracts the expression before `LambdaLift` to 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.
- Replaces references to local variables and inaccessible members with
magic calls to reflectEval, annotated with ReflectEvalStrategy
attachments.
**ResolveReflectEval**:
- At the end of the transform phases
- Transforms `reflectEval` calls into actual reflective calls based on
`ReflectEvalStrategy` metadata.
## 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 `ExpressionCompilerBridge` can be invoked by reflection with the
following parameters:
- `outputDir: Path`: Directory where compiled classes are written
- `classPath: String`: Classpath used during compilation
- `options: Array[String]`: Compiler options
- `sourceFile: Path`: Source file where the expression is evaluated
- `config: ExpressionCompilerConfig`:
- `packageName`: Package name of the current evaluation frame
- `outputClassName: String`: Name of the main generated class, to be
loaded by the debuggee
- `breakpointLine: Int`: Line number where the expression is evaluated
- `expression: String`: Expression to compile
- `localVariables: Set[String]`: Set of visible local variables (used
for checking evaluation of captured variables)
- `errorReporter: Consumer[String]`: Callback for reporting errors
The `ExpressionCompilerConfig` is 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](https://github.com/scalacenter/scala-debug-adapter/blob/main/modules/tests/src/test/scala/ch/epfl/scala/debugadapter/ScalaEvaluationTests.scala),
notably the integration with the vulpix test infrastructure:
- In `dotty.tools.vulpix.RunnerOrchestration`:
- added the `debugMode` to start runners with JVM debugging options
- added the `debugMain` method to connect a debugger, start a main
method and execute the debug steps
- Added `dotty.tools.debug.Debugger`: a lightweight implementation of a
JVM debugger
- Added `dotty.tools.debug.ExpressionEvaluator`: to compile and evaluate
expressions inside `dotty.tools.debug.Debugger`
- Added `dotty.tools.debug.DebugStepAssert`: to describe a debug
scenario as a series of steps (`break`, `step`, `next` and `eval`)
- Added `dotty.tools.debug.DebugTests` test class:
- it reads all Scala files and folders from `tests/debug`
- for each Scala file, it parses its associated `.check` file as a
series of `DebugStepAssert`
- for each Scala file, it compiles it, runs it with `debugMain`, and
executes the debug steps
I migrated all relevant tests from
[ScalaEvaluationTests](https://github.com/scalacenter/scala-debug-adapter/blob/main/modules/tests/src/test/scala/ch/epfl/scala/debugadapter/ScalaEvaluationTests.scala)
to `tests/debug` folder. Thanks to Vulpix parallel execution, the 47
debug tests now complete in approximately 30-40 seconds.File tree
125 files changed
+3575
-473
lines changed- compiler
- src/dotty/tools/debug
- test
- debug
- dotty/tools
- debug
- dotc/coverage
- vulpix
- docs/_docs/contributing
- debugging
- project
- sjs-compiler-tests/test/scala/dotty/tools/dotc
- tasty/test/dotty/tools/tasty
- tests
- debug-custom-args
- debug
- eval-java-protected-members
- eval-macro
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
125 files changed
+3575
-473
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
66 | 65 | | |
67 | 66 | | |
68 | 67 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
Lines changed: 38 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
Lines changed: 65 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
0 commit comments