Skip to content

Commit c495b83

Browse files
committed
Polishing
1 parent 19d3c16 commit c495b83

File tree

1 file changed

+63
-71
lines changed

1 file changed

+63
-71
lines changed

docs/docs/reference/changed/compiler-plugins.md

Lines changed: 63 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,71 +3,64 @@ layout: doc-page
33
title: "Changes in Compiler Plugins"
44
---
55

6-
Compiler plugins are supported by Dotty since 0.9. Compared to Scalac, there are
7-
two notable changes:
6+
Compiler plugins are supported by Dotty since 0.9. There are two notable changes
7+
compared to `scalac`:
88

9-
- No more support for analyzer plugins
9+
- No support for analyzer plugins
1010
- Added support for research plugins
1111

12-
[Analyzer plugins][1] in Scalac are executed during type checking to change the
13-
normal type checking. This is a nice feature for doing research, but for
14-
production usage, a predictable and consistent type checker is more important.
12+
[Analyzer plugins][1] in `scalac` run during type checking and may influence
13+
normal type checking. This is a very powerful feature but for production usages,
14+
a predictable and consistent type checker is more important.
1515

16-
For experiments and researches that rely on analyzer plugins in Scalac,
17-
_research plugin_ can be used for the same purpose in Dotty. Research plugins
18-
are more powerful than Scalac analyzer plugins as they enable plugin authors to
19-
customize the whole compiler pipeline. That means, you can easily use your
20-
customized typer to replace the standard typer, or roll your own parser for
21-
your domain-specific language. Research plugins are only enabled for nightly or
22-
snaphot releases of Dotty.
16+
For experimentation and research, Dotty introduces _research plugin_. Research plugins
17+
are more powerful than `scalac` analyzer plugins as they let plugin authors customize
18+
the whole compiler pipeline. One can easily replace the standard typer by a custom one or
19+
roll its own parser for domain-specific language. However, research plugins are only
20+
enabled for nightly or snaphot releases of Dotty.
2321

24-
The common plugins that add new phases to the compiler pipeline are called
22+
Common plugins that add new phases to the compiler pipeline are called
2523
_standard plugins_ in Dotty. In terms of features, they are similar to
2624
Scalac plugins, despite minor changes in the API.
2725

28-
## Artifact Interface
26+
## Using Compiler Plugins
2927

30-
Both research plugins and standard plugins share the same command line options
31-
as Scalac plugins. You may integrate a plugin in the Dotty compiler as follows:
28+
Both standard and research plugins can be used with `dotc` by adding the `-Xplugin:` option:
3229

3330
```shell
3431
dotc -Xplugin:pluginA.jar -Xplugin:pluginB.jar Test.scala
3532
```
3633

37-
The compiler will examine the jar provided, and look for a property file
38-
`plugin.properties` in the root directory of the jar. The property file
39-
specifies the fully qualified plugin class name. The format of a property file
40-
looks like the following:
34+
The compiler will examine the jar provided, and look for a property file named
35+
`plugin.properties` in the root directory of the jar. The property file specifies
36+
the fully qualified plugin class name. The format of a property file is as follow:
4137

42-
```
38+
```properties
4339
pluginClass=dividezero.DivideZero
4440
```
4541

46-
The above is a change from Scalac, which depends on an XML file
47-
`scalac-plugin.xml`.
48-
49-
Starting from 1.1.5, SBT also supports Dotty compiler plugins:
50-
51-
```Scala
52-
addCompilerPlugin("org.divbyzero" % "divbyzero" % "1.0")
53-
```
42+
This is different from `scalac` plugins that required a `scalac-plugin.xml` file.
5443

55-
With the code above, SBT will prepare the correct options to the compiler.
44+
Starting from 1.1.5, `sbt` also supports Dotty compiler plugins. Please refer to the
45+
`sbt` [documentation][2] for more information.
5646

57-
## Standard Plugin
47+
## Writing a Standard Compiler Plugin
5848

59-
The following code example shows the template for a standard plugin:
49+
Here is the source code for a simple compiler plugin that reports integer divisions by
50+
zero as errors.
6051

61-
```Scala
52+
```scala
6253
package dividezero
6354

64-
import dotty.tools.dotc._
65-
import core._
66-
import Contexts.Context
67-
import plugins._
68-
import Phases.Phase
69-
import ast.tpd
70-
import transform.{LinkAll, Pickler}
55+
import dotty.tools.dotc.ast.Trees._
56+
import dotty.tools.dotc.ast.tpd
57+
import dotty.tools.dotc.core.Constants.Constant
58+
import dotty.tools.dotc.core.Contexts.Context
59+
import dotty.tools.dotc.core.Decorators._
60+
import dotty.tools.dotc.core.StdNames._
61+
import dotty.tools.dotc.core.Symbols._
62+
import dotty.tools.dotc.plugins.{PluginPhase, StandardPlugin}
63+
import dotty.tools.dotc.transform.{LinkAll, Pickler}
7164

7265
class DivideZero extends StandardPlugin {
7366
val name: String = "divideZero"
@@ -77,44 +70,45 @@ class DivideZero extends StandardPlugin {
7770
}
7871

7972
class DivideZeroPhase extends PluginPhase {
73+
import tpd._
74+
8075
val phaseName = "divideZero"
8176

8277
override val runsAfter = Set(Pickler.name)
8378
override val runsBefore = Set(LinkAll.name)
8479

85-
override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = {
86-
// check whether divide by zero here
80+
override def transformApply(tree: Apply)(implicit ctx: Context): Tree = {
81+
tree match {
82+
case Apply(Select(rcvr, nme.DIV), List(Literal(Constant(0))))
83+
if rcvr.tpe <:< defn.IntType =>
84+
ctx.error("dividing by zero", tree.pos)
85+
case _ =>
86+
()
87+
}
8788
tree
8889
}
8990
}
9091
```
9192

92-
As you can see from the code above, the plugin main class `DivideZero`
93-
extends the trait `StandardPlugin`. It implements the method `init` which
94-
takes the options for the plugin and return a list of `PluginPhase`s to be
95-
inserted into the compilation pipeline.
93+
The plugin main class (`DivideZero`) must extends the `StandardPlugin` trait
94+
and implement the method `init` that takes the plugin's options as argument
95+
and return a list of `PluginPhase`s to be inserted into the compilation pipeline.
9696

97-
The plugin `DivideZero` only adds one compiler phase, `DivideZeroPhase`,
98-
to the compiler pipeline. The compiler phase has to extend the trait
99-
`PluginPhase`. It also needs to tell the compiler the place where it wants to be
100-
in the pipeline by specifying `runsAfter` and `runsBefore` relative to standard
101-
compiler phases. Finally, it can transform the trees of interest by overriding
102-
methods like `transformXXX`.
97+
Our plugin adds one compiler phase to the pipeline. A compiler phase must extend
98+
the `PluginPhase` trait. In order to specify when the phase is executed, we also
99+
need to specify a `runsBefore` and `runsAfter` constraints that are list of phase
100+
names.
103101

104-
Usually a compiler plugin requires significant compiler knowledge in order to
105-
maintain invariants of the compiler. It is a good practice to enable
106-
the compiler option `-Ycheck:all` in the test set of your plugin.
102+
We can now transform trees by by overriding methods like `transformXXX`.
107103

108-
## Research Plugin
104+
## Writing a Research Compiler Plugin
109105

110-
Research plugins extend the trait `ResearchPlugin` as the following code shows:
106+
Here is a template for research plugins.
111107

112-
```Scala
113-
import dotty.tools.dotc._
114-
import core._
115-
import Contexts.Context
116-
import plugins._
117-
import Phases.Phase
108+
```scala
109+
import dotty.tools.dotc.core.Contexts.Context
110+
import dotty.tools.dotc.core.Phases.Phase
111+
import dotty.tools.dotc.plugins.ResearchPlugin
118112

119113
class DummyResearchPlugin extends ResearchPlugin {
120114
val name: String = "dummy"
@@ -125,13 +119,11 @@ class DummyResearchPlugin extends ResearchPlugin {
125119
}
126120
```
127121

128-
Research plugins also define a method `init`, but the signature is different.
129-
Research plugins receive options for the plugin and the whole compiler pipeline as parameters.
130-
Usually, the `init` method replaces some standard phase of the compiler pipeline
131-
with a custom phase, e.g. use a custom frontend. Finally, `init` returns the
132-
updated compiler pipeline.
133-
134-
Note that research plugins are only enabled for nightly or snaphot release of Dotty.
122+
A research plugins must extend the `ResearchPlugin` trait and implements the
123+
method `init` that takes the plugin's options as argument as well as the list of
124+
default compiler phases. We can return an updated version of this list that may
125+
replace, remove or add any phases to the pipeline.
135126

136127

137128
[1]: https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
129+
[2]: https://www.scala-sbt.org/1.x/docs/Compiler-Plugins.html

0 commit comments

Comments
 (0)