The Scala 3 compiler (Dotty) providing advanced type inference, metaprogramming capabilities, and enhanced performance for modern Scala development
Framework for creating compiler plugins that extend the Scala 3 compilation pipeline with custom phases, transformations, and analysis capabilities.
Base trait defining the interface for all compiler plugins with metadata and lifecycle methods.
/**
* Base trait for all compiler plugins
* Defines the plugin interface and metadata requirements
*/
sealed trait Plugin {
/**
* Unique name identifying this plugin
* Used for plugin registration and dependency resolution
* @return String identifier for the plugin
*/
def name: String
/**
* Human-readable description of the plugin's functionality
* @return String describing what the plugin does
*/
def description: String
/**
* Optional help text describing plugin-specific options
* @return Option containing help text for plugin options, or None
*/
def optionsHelp: Option[String]
}Standard plugin type that inserts phases into the normal compilation pipeline without modifying the overall phase plan.
/**
* Standard plugin that inserts phases into normal compilation pipeline
* Suitable for most plugin use cases that add transformation or analysis phases
*/
trait StandardPlugin extends Plugin {
/**
* Initialize plugin and return list of phases to insert into compilation pipeline
* Called once during compiler initialization with plugin-specific options
* @param options List of options passed to this plugin
* @param ctx Compilation context for initialization
* @return List of PluginPhase instances to add to the compilation pipeline
*/
def initialize(options: List[String])(using Context): List[PluginPhase]
}Usage Example:
import dotty.tools.dotc.plugins.{StandardPlugin, PluginPhase}
import dotty.tools.dotc.core.Contexts.Context
class MyPlugin extends StandardPlugin {
val name = "my-plugin"
val description = "Custom transformation plugin"
override def initialize(options: List[String])(using Context): List[PluginPhase] = {
List(new MyTransformPhase)
}
}
class MyTransformPhase extends PluginPhase {
val phaseName = "my-transform"
override def transformTree(tree: Tree)(using Context): Tree = {
// Custom tree transformation logic
tree
}
}Research plugin type that can completely customize the compilation pipeline by modifying the phase plan.
/**
* Research plugin that can customize the compilation pipeline freely
* Allows complete control over phase ordering and structure
* Use with caution as it can significantly modify compilation behavior
*/
trait ResearchPlugin extends Plugin {
/**
* Customize the compilation phase plan
* Called during compiler initialization to allow complete pipeline modification
* @param options List of options passed to this plugin
* @param plan Current phase plan as nested list of phases
* @param ctx Compilation context for initialization
* @return Modified phase plan with custom phase organization
*/
def init(options: List[String], plan: List[List[Phase]])(using Context): List[List[Phase]]
}Usage Example:
import dotty.tools.dotc.plugins.ResearchPlugin
import dotty.tools.dotc.core.Phases.Phase
class MyResearchPlugin extends ResearchPlugin {
val name = "research-plugin"
val description = "Experimental compilation pipeline modification"
override def init(options: List[String], plan: List[List[Phase]])(using Context): List[List[Phase]] = {
// Insert custom phases at specific positions
val customPhases = List(List(new MyAnalysisPhase))
plan.take(2) ++ customPhases ++ plan.drop(2)
}
}Base class for plugin phases that integrate into the compilation pipeline.
/**
* Base class for plugin phases
* Extends MiniPhase to provide efficient transformation capabilities
*/
abstract class PluginPhase extends MiniPhase {
/**
* Name of this phase for identification and logging
* @return String name of the phase
*/
def phaseName: String
/**
* Set of phase names this phase must run before
* Used for phase ordering constraints
* @return Set of phase names that must run after this phase
*/
def runsBefore: Set[String] = Set.empty
/**
* Set of phase names this phase must run after
* Used for phase ordering constraints
* @return Set of phase names that must run before this phase
*/
def runsAfter: Set[String] = Set.empty
/**
* Transform a tree node during compilation
* Override this method to implement custom transformations
* @param tree Tree node to transform
* @param ctx Compilation context
* @return Transformed tree node
*/
def transformTree(tree: Tree)(using Context): Tree = tree
/**
* Check if this phase is enabled for the given compilation unit
* @param unit Compilation unit being processed
* @param ctx Compilation context
* @return True if phase should run on this unit
*/
def isEnabled(unit: CompilationUnit)(using Context): Boolean = true
}Usage Example:
import dotty.tools.dotc.plugins.PluginPhase
import dotty.tools.dotc.ast.Trees._
import dotty.tools.dotc.core.Contexts.Context
class LoggingPhase extends PluginPhase {
val phaseName = "logging"
override val runsAfter = Set("typer")
override val runsBefore = Set("pickler")
override def transformTree(tree: Tree)(using Context): Tree = {
tree match {
case DefDef(name, _, _, _) =>
println(s"Found method definition: $name")
tree
case ClassDef(name, _, _) =>
println(s"Found class definition: $name")
tree
case _ => tree
}
}
}Base framework for creating efficient transformation phases that operate on individual tree nodes.
/**
* Base class for mini-phases that provide efficient tree transformations
* Mini-phases are combined into mega-phases for optimal performance
*/
abstract class MiniPhase extends Phase {
/**
* Transform a tree node
* @param tree Tree to transform
* @param ctx Compilation context
* @return Transformed tree
*/
def transformTree(tree: Tree)(using Context): Tree = tree
/**
* Transform a definition (class, method, value, etc.)
* @param tree Definition tree to transform
* @param ctx Compilation context
* @return Transformed definition tree
*/
def transformDef(tree: Tree)(using Context): Tree = transformTree(tree)
/**
* Transform an expression
* @param tree Expression tree to transform
* @param ctx Compilation context
* @return Transformed expression tree
*/
def transformExpr(tree: Tree)(using Context): Tree = transformTree(tree)
}Plugins are discovered through the Java ServiceLoader mechanism or explicit registration.
// META-INF/services/dotty.tools.dotc.plugins.Plugin file content:
// com.example.MyPlugin
class MyPlugin extends StandardPlugin {
val name = "my-plugin"
val description = "Example plugin"
def initialize(options: List[String])(using Context): List[PluginPhase] = {
List(new MyPhase)
}
}// Registering plugins programmatically
val driver = new Driver {
override def newCompiler(using Context) = {
val compiler = super.newCompiler
// Plugin registration logic
compiler
}
}/**
* Base class for all compilation phases
*/
abstract class Phase {
def phaseName: String
def run(using Context): Unit
def isRunnable(using Context): Boolean = true
}/**
* Abstract syntax tree node
* Base class for all AST elements in the Scala 3 compiler
*/
abstract class Tree[T] {
def pos: Position
def symbol: Symbol
def tpe: Type
}/**
* Compilation context containing settings, symbols, and phase information
*/
abstract class Context {
def settings: Settings
def definitions: Definitions
def phase: Phase
}Install with Tessl CLI
npx tessl i tessl/maven-org-scala-lang--scala3-compiler-3