@@ -3,71 +3,64 @@ layout: doc-page
3
3
title : " Changes in Compiler Plugins"
4
4
---
5
5
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 ` :
8
8
9
- - No more support for analyzer plugins
9
+ - No support for analyzer plugins
10
10
- Added support for research plugins
11
11
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.
15
15
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.
23
21
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
25
23
_ standard plugins_ in Dotty. In terms of features, they are similar to
26
24
Scalac plugins, despite minor changes in the API.
27
25
28
- ## Artifact Interface
26
+ ## Using Compiler Plugins
29
27
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:
32
29
33
30
``` shell
34
31
dotc -Xplugin:pluginA.jar -Xplugin:pluginB.jar Test.scala
35
32
```
36
33
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:
41
37
42
- ```
38
+ ``` properties
43
39
pluginClass =dividezero.DivideZero
44
40
```
45
41
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.
54
43
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.
56
46
57
- ## Standard Plugin
47
+ ## Writing a Standard Compiler Plugin
58
48
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.
60
51
61
- ``` Scala
52
+ ``` scala
62
53
package dividezero
63
54
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 }
71
64
72
65
class DivideZero extends StandardPlugin {
73
66
val name : String = " divideZero"
@@ -77,44 +70,45 @@ class DivideZero extends StandardPlugin {
77
70
}
78
71
79
72
class DivideZeroPhase extends PluginPhase {
73
+ import tpd ._
74
+
80
75
val phaseName = " divideZero"
81
76
82
77
override val runsAfter = Set (Pickler .name)
83
78
override val runsBefore = Set (LinkAll .name)
84
79
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
+ }
87
88
tree
88
89
}
89
90
}
90
91
```
91
92
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.
96
96
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.
103
101
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 ` .
107
103
108
- ## Research Plugin
104
+ ## Writing a Research Compiler Plugin
109
105
110
- Research plugins extend the trait ` ResearchPlugin ` as the following code shows:
106
+ Here is a template for research plugins.
111
107
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
118
112
119
113
class DummyResearchPlugin extends ResearchPlugin {
120
114
val name : String = " dummy"
@@ -125,13 +119,11 @@ class DummyResearchPlugin extends ResearchPlugin {
125
119
}
126
120
```
127
121
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.
135
126
136
127
137
128
[ 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