From 669b9594a7783b9440773053f466cc489dbad5e7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 13 Mar 2016 19:41:46 +0100 Subject: [PATCH 01/12] First of a series of compiler design documents --- docs/dotc-internals/periods.md | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/dotc-internals/periods.md diff --git a/docs/dotc-internals/periods.md b/docs/dotc-internals/periods.md new file mode 100644 index 000000000000..2385fd00b6f0 --- /dev/null +++ b/docs/dotc-internals/periods.md @@ -0,0 +1,52 @@ +# Dotc's concept of time + +Conceptually, the `dotc` copmpiler's job is to maintain views of +various artifacts associated with source code at all points in time. +But what is *time* for `dotc`? In fact, it is a combination of +compiler runs and compiler phases. + +The *hours* of the compiler's clocks are measured in compiler +[runs](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Run.scala). Every +run creates a new hour, which follows all the compiler runs (hours) that +happened before. `dotc` is designed to be used as an incremental +compiler that can support incremental builds, as well as interactions +in an IDE and a REPL. This means that new runs can occur quite +frequently. At the extreme, every keystroke in an editor or REPL can +potentially launch a new compiler run, so potentially an "hour" of +compiler time might take only a fraction of a second in real time. + +The *minutes* of the compiler's clocks are measured in phases. At every +compiler run, the compiler cycles through a number of +[phases](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Phases.scala). +There are currently about 60 phases per run, so the minutes/hours +analogy works out roughly. After every phase the view the compiler has +of the world changes: trees are transformed, types are gradually simplified +from Scala types to JVM types, definitions are rearranged, and so on. + +Many pieces in the information compiler are time-dependent. For +instance, a Scala symbol representing a definition has a type, but +that type will usually change as one goes from the higher-level Scala +view of things to the lower-level JVM view. There are different ways +to deal with this. Many compilers change the type of a symbol +destructively according to the "current phase". Another, more +functional approach might be to have different symbols representing +the same definition at different phases, which each symbol carrying a +different immutable type. `dotc` employs yet another scheme, which is +inspired by functional reactive programming (FRP): Symbols carry not a +single type, but a function from compiler phase to type. So the type +of a symbol is a time-indexed function, where time ranges over +compiler phases. + +Typically, the definition of a symbol or other quantity remains stable +for a number of phases. This leads us to the concept of a +[period](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Periods.scala). +Conceptually, period is an interval of some given phases in a given +compiler run. Periods are conceptually represented by three pieces of +information + + - the ID of the current run, + - the ID of the phase starting the period + - the number of phases in the period + +All three pieces of information are encoded in a value class over a 32 bit integer. + From 4687dd390cf8e854291bb95a6f9d427b383d6a6f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 13 Mar 2016 20:48:23 +0100 Subject: [PATCH 02/12] Add more material to periods.md --- docs/dotc-internals/periods.md | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/dotc-internals/periods.md b/docs/dotc-internals/periods.md index 2385fd00b6f0..d229f4fce047 100644 --- a/docs/dotc-internals/periods.md +++ b/docs/dotc-internals/periods.md @@ -1,6 +1,6 @@ # Dotc's concept of time -Conceptually, the `dotc` copmpiler's job is to maintain views of +Conceptually, the `dotc` compiler's job is to maintain views of various artifacts associated with source code at all points in time. But what is *time* for `dotc`? In fact, it is a combination of compiler runs and compiler phases. @@ -18,6 +18,7 @@ compiler time might take only a fraction of a second in real time. The *minutes* of the compiler's clocks are measured in phases. At every compiler run, the compiler cycles through a number of [phases](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Phases.scala). +The list of phases is defined in the [Compiler]object There are currently about 60 phases per run, so the minutes/hours analogy works out roughly. After every phase the view the compiler has of the world changes: trees are transformed, types are gradually simplified @@ -49,4 +50,41 @@ information - the number of phases in the period All three pieces of information are encoded in a value class over a 32 bit integer. +Here's the API for class `Period`: + class Period(val code: Int) extends AnyVal { + def runId: RunId // The run identifier of this period. + def firstPhaseId // The first phase of this period + def lastPhaseId: PhaseId = // The last phase of this period + def phaseId: PhaseId // The phase identifier of this single-phase period. + + def containsPhaseId(id: PhaseId): Boolean + def contains(that: Period): Boolean + def overlaps(that: Period): Boolean + + def & (that: Period): Period + def | (that: Period): Period + } + +We can access the parts of a period using `runId`, `firstPhaseId`, +`lastPhaseId`, or using `phaseId` for periods consisting only of a +single phase. They return `RunId` or `PhaseId` values, which are +aliases of `Int`. `containsPhaseId`, `contains` and `overlaps` test +whether a period contains a phase or a period as a sub-interval, or +whether the interval overlaps with another period. Finally, `&` and +`|` produce the intersection and the union of two period intervals +(the union operation `|` takes as `runId` the `runId` of its left +operand, as periods spanning different `runId`s cannot be constructed. + +Periods are constructed using two `apply` methods: + + object Period { + + /** The single-phase period consisting of given run id and phase id */ + def apply(rid: RunId, pid: PhaseId): Period } + + /** The period consisting of given run id, and lo/hi phase ids */ + def apply(rid: RunId, loPid: PhaseId, hiPid: PhaseId): Period + } + +As a sentinel value there's `Nowhere`, a period that is empty. From f9632aeb3c52314bccdb32e5cde655e0b82f85ad Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 13 Mar 2016 20:49:49 +0100 Subject: [PATCH 03/12] Fix typo --- docs/dotc-internals/periods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dotc-internals/periods.md b/docs/dotc-internals/periods.md index d229f4fce047..fd1abec977cd 100644 --- a/docs/dotc-internals/periods.md +++ b/docs/dotc-internals/periods.md @@ -55,7 +55,7 @@ Here's the API for class `Period`: class Period(val code: Int) extends AnyVal { def runId: RunId // The run identifier of this period. def firstPhaseId // The first phase of this period - def lastPhaseId: PhaseId = // The last phase of this period + def lastPhaseId: PhaseId // The last phase of this period def phaseId: PhaseId // The phase identifier of this single-phase period. def containsPhaseId(id: PhaseId): Boolean From 646ef5c321ec1c62ed03bfa24bed0438bbfcc937 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 13 Mar 2016 20:51:26 +0100 Subject: [PATCH 04/12] fix typo --- docs/dotc-internals/periods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dotc-internals/periods.md b/docs/dotc-internals/periods.md index fd1abec977cd..0d90252a008e 100644 --- a/docs/dotc-internals/periods.md +++ b/docs/dotc-internals/periods.md @@ -54,7 +54,7 @@ Here's the API for class `Period`: class Period(val code: Int) extends AnyVal { def runId: RunId // The run identifier of this period. - def firstPhaseId // The first phase of this period + def firstPhaseId: PhaseId // The first phase of this period def lastPhaseId: PhaseId // The last phase of this period def phaseId: PhaseId // The phase identifier of this single-phase period. From 32dcb8bb3a3eebf405e049f73ec4f153eb1f5b24 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 13 Mar 2016 20:52:59 +0100 Subject: [PATCH 05/12] add syntax highlighting --- docs/dotc-internals/periods.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/dotc-internals/periods.md b/docs/dotc-internals/periods.md index 0d90252a008e..a616ba8a84d7 100644 --- a/docs/dotc-internals/periods.md +++ b/docs/dotc-internals/periods.md @@ -52,6 +52,7 @@ information All three pieces of information are encoded in a value class over a 32 bit integer. Here's the API for class `Period`: +```scala class Period(val code: Int) extends AnyVal { def runId: RunId // The run identifier of this period. def firstPhaseId: PhaseId // The first phase of this period @@ -65,6 +66,7 @@ Here's the API for class `Period`: def & (that: Period): Period def | (that: Period): Period } +``` We can access the parts of a period using `runId`, `firstPhaseId`, `lastPhaseId`, or using `phaseId` for periods consisting only of a @@ -78,6 +80,7 @@ operand, as periods spanning different `runId`s cannot be constructed. Periods are constructed using two `apply` methods: +```scala object Period { /** The single-phase period consisting of given run id and phase id */ @@ -86,5 +89,6 @@ Periods are constructed using two `apply` methods: /** The period consisting of given run id, and lo/hi phase ids */ def apply(rid: RunId, loPid: PhaseId, hiPid: PhaseId): Period } +``` As a sentinel value there's `Nowhere`, a period that is empty. From b2d1e87059a097809285803c3ec123ec36d4a4aa Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 14 Mar 2016 14:52:02 +0100 Subject: [PATCH 06/12] Move Mode to core Mode is used from a lot of low-level code, does not just reflect Typer info. So it makes more sense top to place it in the core package. --- src/dotty/tools/dotc/Compiler.scala | 2 +- src/dotty/tools/dotc/ast/Desugar.scala | 1 - src/dotty/tools/dotc/ast/tpd.scala | 1 - src/dotty/tools/dotc/core/Annotations.scala | 1 - src/dotty/tools/dotc/core/Contexts.scala | 2 +- src/dotty/tools/dotc/core/Decorators.scala | 1 - src/dotty/tools/dotc/core/Denotations.scala | 1 - src/dotty/tools/dotc/{typer => core}/Mode.scala | 5 ++--- src/dotty/tools/dotc/core/SymDenotations.scala | 1 - src/dotty/tools/dotc/core/TypeApplications.scala | 1 - src/dotty/tools/dotc/core/TypeComparer.scala | 1 - src/dotty/tools/dotc/core/TypeErasure.scala | 1 - src/dotty/tools/dotc/core/Types.scala | 3 +-- src/dotty/tools/dotc/core/classfile/ClassfileParser.scala | 1 - src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 1 - .../tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 1 - src/dotty/tools/dotc/printing/PlainPrinter.scala | 1 - src/dotty/tools/dotc/reporting/Reporter.scala | 2 +- src/dotty/tools/dotc/transform/Erasure.scala | 2 +- src/dotty/tools/dotc/transform/LazyVals.scala | 1 - src/dotty/tools/dotc/transform/PatternMatcher.scala | 2 +- src/dotty/tools/dotc/transform/RestoreScopes.scala | 1 - src/dotty/tools/dotc/transform/TreeChecker.scala | 1 + src/dotty/tools/dotc/transform/TreeTransform.scala | 2 +- test/test/DeSugarTest.scala | 2 +- test/test/showTree.scala | 2 +- 26 files changed, 12 insertions(+), 28 deletions(-) rename src/dotty/tools/dotc/{typer => core}/Mode.scala (97%) diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index fe16243bbbe6..13c98a8fef1c 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -7,7 +7,7 @@ import Periods._ import Symbols._ import Types._ import Scopes._ -import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks} +import typer.{FrontEnd, Typer, ImportInfo, RefChecks} import reporting.{Reporter, ConsoleReporter} import Phases.Phase import transform._ diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 2ab33a1200b2..719f3d0360a6 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -9,7 +9,6 @@ import Decorators._ import language.higherKinds import collection.mutable.ListBuffer import config.Printers._ -import typer.Mode object desugar { diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index a6d97478b027..8d21953ae564 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -10,7 +10,6 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Symbols._ import Denotations._, Decorators._, DenotTransformers._ import config.Printers._ -import typer.Mode import collection.mutable import typer.ErrorReporting._ diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 2b27b5e01ca2..dc4897233d89 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -5,7 +5,6 @@ import Symbols._, Types._, util.Positions._, Contexts._, Constants._, ast.tpd._ import config.ScalaVersion import StdNames._ import dotty.tools.dotc.ast.{tpd, untpd} -import dotty.tools.dotc.typer.ProtoTypes.FunProtoTyped object Annotations { diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index fd0cff94e157..a0bb03e505b5 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -18,7 +18,7 @@ import util.Positions._ import ast.Trees._ import ast.untpd import util.{FreshNameCreator, SimpleMap, SourceFile, NoSource} -import typer._ +import typer.{Implicits, ImplicitRunInfo, ImportInfo, NamerContextOps, SearchHistory, TypeAssigner, Typer} import Implicits.ContextualImplicits import config.Settings._ import config.Config diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index 60c019bce733..7d108a45923f 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -7,7 +7,6 @@ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer, printi import util.Positions.Position, util.SourcePosition import collection.mutable.ListBuffer import dotty.tools.dotc.transform.TreeTransforms._ -import typer.Mode import scala.language.implicitConversions /** This object provides useful implicit decorators for types defined elsewhere */ diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index b52c1120195e..218fb8561943 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -18,7 +18,6 @@ import printing.Texts._ import printing.Printer import io.AbstractFile import config.Config -import typer.Mode import util.common._ import collection.mutable.ListBuffer import Decorators.SymbolIteratorDecorator diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/core/Mode.scala similarity index 97% rename from src/dotty/tools/dotc/typer/Mode.scala rename to src/dotty/tools/dotc/core/Mode.scala index 55d44ad7a45c..5b3dbc872c1c 100644 --- a/src/dotty/tools/dotc/typer/Mode.scala +++ b/src/dotty/tools/dotc/core/Mode.scala @@ -1,7 +1,6 @@ -package dotty.tools.dotc.typer - -import collection.mutable +package dotty.tools.dotc.core +/** A collection of mode bits that are part of a context */ case class Mode(val bits: Int) extends AnyVal { import Mode._ def | (that: Mode) = Mode(bits | that.bits) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index a83e7726af0d..28932b69161e 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -13,7 +13,6 @@ import Decorators.SymbolIteratorDecorator import ast._ import annotation.tailrec import CheckRealizable._ -import typer.Mode import util.SimpleMap import util.Stats import config.Config diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 8f8a7dbdda6a..26ffefec4ced 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -12,7 +12,6 @@ import Names._ import NameOps._ import Flags._ import StdNames.tpnme -import typer.Mode import util.Positions.Position import config.Printers._ import collection.mutable diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 4e7a4a75db70..c846737b63cd 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3,7 +3,6 @@ package dotc package core import Types._, Contexts._, Symbols._, Flags._, Names._, NameOps._, Denotations._ -import typer.Mode import Decorators._ import StdNames.{nme, tpnme} import collection.mutable diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 26cac4f728a5..a7d825131e7e 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -6,7 +6,6 @@ import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Decorators. import Uniques.unique import dotc.transform.ExplicitOuter._ import dotc.transform.ValueClasses._ -import typer.Mode import util.DotClass /** Erased types are: diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 3801f191449e..5dfe3a4f15dd 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -31,7 +31,6 @@ import config.Config import config.Printers._ import annotation.tailrec import Flags.FlagSet -import typer.Mode import language.implicitConversions import scala.util.hashing.{ MurmurHash3 => hashing } @@ -3446,7 +3445,7 @@ object Types { object CyclicReference { def apply(denot: SymDenotation)(implicit ctx: Context): CyclicReference = { val ex = new CyclicReference(denot) - if (!(ctx.mode is typer.Mode.CheckCyclic)) { + if (!(ctx.mode is Mode.CheckCyclic)) { cyclicErrors.println(ex.getMessage) for (elem <- ex.getStackTrace take 200) cyclicErrors.println(elem.toString) diff --git a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 25558a79a690..f7a69aa53f28 100644 --- a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -12,7 +12,6 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch import typer.Checking.checkNonCyclic -import typer.Mode import io.AbstractFile import scala.util.control.NonFatal diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index eb33691841f0..b547862b4083 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -13,7 +13,6 @@ import TastyUnpickler._, TastyBuffer._, PositionPickler._ import scala.annotation.{tailrec, switch} import scala.collection.mutable.ListBuffer import scala.collection.{ mutable, immutable } -import typer.Mode import config.Printers.pickling /** Unpickler for typed trees diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 2831de3e01b3..e4c8d7d13eec 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -17,7 +17,6 @@ import printing.Printer import io.AbstractFile import util.common._ import typer.Checking.checkNonCyclic -import typer.Mode import PickleBuffer._ import scala.reflect.internal.pickling.PickleFormat._ import Decorators._ diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index 6d026dde741b..3fb220afe701 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -8,7 +8,6 @@ import StdNames.{nme, tpnme} import ast.Trees._, ast._ import java.lang.Integer.toOctalString import config.Config.summarizeDepth -import typer.Mode import scala.annotation.switch class PlainPrinter(_ctx: Context) extends Printer { diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index 8236f93ef719..44defa6b1593 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -10,7 +10,7 @@ import collection.mutable import config.Settings.Setting import config.Printers import java.lang.System.currentTimeMillis -import typer.Mode +import core.Mode import interfaces.Diagnostic.{ERROR, WARNING, INFO} object Reporter { diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 8d890902e805..b4beaab8833a 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -25,7 +25,7 @@ import dotty.tools.dotc.core.Flags import ValueClasses._ import TypeUtils._ import ExplicitOuter._ -import typer.Mode +import core.Mode class Erasure extends Phase with DenotTransformer { thisTransformer => diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index fc02e68cc979..e42c7bae9ece 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -3,7 +3,6 @@ package transform import dotty.tools.dotc.core.Annotations.Annotation import dotty.tools.dotc.core.Phases.NeedsCompanions -import dotty.tools.dotc.typer.Mode import scala.collection.mutable import core._ diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala index a7f654780053..35e772cd1a92 100644 --- a/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -21,7 +21,7 @@ import ast.Trees._ import Applications._ import TypeApplications._ import SymUtils._, core.NameOps._ -import typer.Mode +import core.Mode import dotty.tools.dotc.util.Positions.Position import dotty.tools.dotc.core.Decorators._ diff --git a/src/dotty/tools/dotc/transform/RestoreScopes.scala b/src/dotty/tools/dotc/transform/RestoreScopes.scala index 41da05691d38..8b9d2be0d021 100644 --- a/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -11,7 +11,6 @@ import TreeTransforms.MiniPhaseTransform import SymDenotations._ import ast.Trees._ import NameOps._ -import typer.Mode import TreeTransforms.TransformerInfo import StdNames._ diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index a260963e917a..dadaf52e2b85 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -15,6 +15,7 @@ import core.StdNames._ import core.Decorators._ import core.TypeErasure.isErasedType import core.Phases.Phase +import core.Mode import typer._ import typer.ErrorReporting._ import reporting.ThrowingReporter diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala index 7fe00338832b..67bd2f16049e 100644 --- a/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -11,7 +11,7 @@ import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Flags.PackageVal -import dotty.tools.dotc.typer.Mode +import dotty.tools.dotc.core.Mode import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.util.DotClass diff --git a/test/test/DeSugarTest.scala b/test/test/DeSugarTest.scala index 77aa293d53a3..1365f3222f38 100644 --- a/test/test/DeSugarTest.scala +++ b/test/test/DeSugarTest.scala @@ -9,7 +9,7 @@ import dotty.tools.dotc._ import ast.Trees._ import ast.desugar import ast.desugar._ -import typer.Mode +import core.Mode import Contexts.Context import scala.collection.mutable.ListBuffer diff --git a/test/test/showTree.scala b/test/test/showTree.scala index 2c3316ac9ce5..8d5a5ad7c5f3 100644 --- a/test/test/showTree.scala +++ b/test/test/showTree.scala @@ -3,7 +3,7 @@ import dotty.tools.dotc._ import ast.Trees._ import ast.desugar import ast.desugar._ -import typer.Mode +import core.Mode object showTree extends DeSugarTest { From a73a1d9f17d0de945262fbf1c61aa68b105a02d1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 15 Mar 2016 11:21:56 +0100 Subject: [PATCH 07/12] Document phases Give a one-line explanation what each phase does in Compiler. --- src/dotty/tools/dotc/Compiler.scala | 97 ++++++++++--------- .../tools/dotc/transform/ElimStaticThis.scala | 2 +- src/dotty/tools/dotc/transform/GetClass.scala | 3 +- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 13c98a8fef1c..62507d11afb5 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -38,54 +38,55 @@ class Compiler { */ def phases: List[List[Phase]] = List( - List(new FrontEnd), - List(new PostTyper), - List(new Pickler), - List(new FirstTransform, - new CheckReentrant), - List(new RefChecks, - new CheckStatic, - new ElimRepeated, - new NormalizeFlags, - new ExtensionMethods, - new ExpandSAMs, - new TailRec, - new LiftTry, - new ClassOf), - List(new PatternMatcher, - new ExplicitOuter, - new ExplicitSelf, - new CrossCastAnd, - new Splitter), - List(new VCInlineMethods, - new SeqLiterals, - new InterceptedMethods, - new Getters, - new ElimByName, - new AugmentScala2Traits, - new ResolveSuper), - List(new Erasure), - List(new ElimErasedValueType, - new VCElideAllocations, - new Mixin, - new LazyVals, - new Memoize, - new LinkScala2ImplClasses, - new NonLocalReturns, - new CapturedVars, // capturedVars has a transformUnit: no phases should introduce local mutable vars here - new Constructors, // constructors changes decls in transformTemplate, no InfoTransformers should be added after it - new FunctionalInterfaces, - new GetClass), // getClass transformation should be applied to specialized methods - List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here - new ElimStaticThis, - new Flatten, - // new DropEmptyCompanions, - new RestoreScopes), - List(new ExpandPrivate, - new CollectEntryPoints, - new LabelDefs), - List(new GenSJSIR), - List(new GenBCode) + List(new FrontEnd), // Compiler frontend: scanner, parser, namer, typer + List(new PostTyper), // Additional checks and cleanups after type checking + List(new Pickler), // Generate TASTY info + List(new FirstTransform, // Some transformations to put trees into a canonical form + new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars + List(new RefChecks, // Various checks mostly related to abstract members and overriding + new CheckStatic, // Check restrictions that apply to @static members + new ElimRepeated, // Rewrite vararg parameters and arguments + new NormalizeFlags, // Rewrite some definition flags + new ExtensionMethods, // Expand methods of value classes with extension methods + new ExpandSAMs, // Expand single abstract method closures to anonymous classes + new TailRec, // Rewrite tail recursion to loops + new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods + new ClassOf), // Expand `Predef.classOf` calls. + List(new PatternMatcher, // Compile pattern matches + new ExplicitOuter, // Add accessors to outer classes from nested ones. + new ExplicitSelf, // Make references to non-trivial self types explicit as casts + new CrossCastAnd, // Normalize selections involving intersection types. + new Splitter), // Expand selections involving union types into conditionals + List(new VCInlineMethods, // Inlines calls to value class methods + new SeqLiterals, // Express vararg arguments as arrays + new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods + new Getters, // Replace non-private vals and vars with getter defs (fields are added later) + new ElimByName, // Expand by-name parameters and arguments + new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings + new ResolveSuper), // Implement super accessors and add forwarders to trait methods + List(new Erasure), // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements. + List(new ElimErasedValueType, // Expand erased value types to their underlying implmementation types + new VCElideAllocations, // Peep-hole optimization to eliminate unnecessary value class allocations + new Mixin, // Expand trait fields and trait initializers + new LazyVals, // Expand lazy vals + new Memoize, // Add private fields to getters and setters + new LinkScala2ImplClasses, // Forward calls to the implementation classes of traits defined by Scala 2.11 + new NonLocalReturns, // Expand non-local returns + new CapturedVars, // Represent vars captured by closures as heap objects + new Constructors, // Collect initialization code in primary constructors + // Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it + new FunctionalInterfaces,// Rewrites closures to implement @specialized types of Functions. + new GetClass), // Rewrites getClass calls on primitive types. + List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments + // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here + new ElimStaticThis, // Replace `this` references to static objects by global identifiers + new Flatten, // Lift all inner classes to package scope + new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group + List(new ExpandPrivate, // Widen private definitions accessed from nested classes + new CollectEntryPoints, // Find classes with main methods + new LabelDefs), // Converts calls to labels to jumps + List(new GenSJSIR), // Generate .js code + List(new GenBCode) // Generate JVM bytecode ) var runId = 1 diff --git a/src/dotty/tools/dotc/transform/ElimStaticThis.scala b/src/dotty/tools/dotc/transform/ElimStaticThis.scala index 7df29b0b079a..70a610188540 100644 --- a/src/dotty/tools/dotc/transform/ElimStaticThis.scala +++ b/src/dotty/tools/dotc/transform/ElimStaticThis.scala @@ -10,7 +10,7 @@ import dotty.tools.dotc.core.SymDenotations.SymDenotation import TreeTransforms.{MiniPhaseTransform, TransformerInfo} import dotty.tools.dotc.core.Types.{ThisType, TermRef} -/** Replace This references to module classes in static methods by global identifiers to the +/** Replace This references to module classes in static methods by global identifiers to the * corresponding modules. */ class ElimStaticThis extends MiniPhaseTransform { diff --git a/src/dotty/tools/dotc/transform/GetClass.scala b/src/dotty/tools/dotc/transform/GetClass.scala index f25fd6f64128..6a9a5fda2019 100644 --- a/src/dotty/tools/dotc/transform/GetClass.scala +++ b/src/dotty/tools/dotc/transform/GetClass.scala @@ -20,7 +20,8 @@ class GetClass extends MiniPhaseTransform { override def phaseName: String = "getClass" - override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure]) + // getClass transformation should be applied to specialized methods + override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure], classOf[FunctionalInterfaces]) override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = { import ast.Trees._ From 5ab9e4d025b14760cdeacb7aafd44d920729f538 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 15 Mar 2016 11:22:53 +0100 Subject: [PATCH 08/12] New article: dotc's overall structure --- docs/dotc-internals/overall-structure.md | 165 +++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/dotc-internals/overall-structure.md diff --git a/docs/dotc-internals/overall-structure.md b/docs/dotc-internals/overall-structure.md new file mode 100644 index 000000000000..d5828ea13572 --- /dev/null +++ b/docs/dotc-internals/overall-structure.md @@ -0,0 +1,165 @@ +# Dotc's Overall Structure + +The compiler code is found in package `dotty.tools`. It spans the +following three sub-packages: + + backend Compiler backends (currently for JVM and JS) + dotc The main compiler + io Helper modules for file access and classpath handling. + +The `dotc` package contains some main classes that can be run as separate +programs. The most important one is class `Main`. `Main` inherits from `Driver` which +contains the highest level functions for starting a compiler and processing some sources +`Driver` in turn is based on two other high-level classes, `Compiler` and `Run`. + +## Package Structure + +Most functionality of `dotc` is implemented in subpackages of `dotc`. Here's a list of sub-packages +and their focus. + + ast Abstract syntax trees, + config Compiler configuration, settings, platform specific definitions. + core Core data structures and operations, with specific subpackages for: + + core.classfile Reading of Java classfiles into core data structures + core.tasty Reading and writing of TASTY files to/from core data structures + core.unpickleScala2 Reading of Scala2 symbol information into core data structures + + parsing Scanner and parser + printing Pretty-printing trees, types and other data + repl The interactive REPL + reporting Reporting of error messages, warnings and other info. + rewrite Helpers for rewriting Scala 2's constructs into dotty's. + transform Miniphases and helpers for tree transformations. + typer Type-checking and other frontend phases + util General purpose utility classes and modules. + +## Contexts + +`dotc` has almost no global state (the only significant bit of global state is the name table, +which is used to hash strings into unique names). Instead, all essential bits of information that +can vary over a compiler run are collected in a [Context](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Context.scala). Most methods in `dotc` take a Context value as an implicit parameter. + +Contexts give a convenient way to customize values in some part of the +call-graph. To run, e.g. some compiler function `f` at a given +phase `phase`, we invoke `f` with an explicit context parameter, like +this + + f(/*normal args*/)(ctx.withPhase(phase)) + +This assumes that `f` is defined in way most compiler functions are: + + def f(/*normal parameters*/)(implicit ctx: Context) ... + +Compiler code follows the convention that all implicit `Context` +parameters are named `ctx`. This is important to avoid implicit +ambiguities in the case where nested methods contain each a Context +parameters. The common name ensures then that the implicit parameters +properly shadow each other. + +Sometimes we want to make sure that implicit contexts are not captured +in closures or other long-lived objects, be it because we want to +enforce that nested methods each get their own implicit context, or +because we want to avoid a space leak in the case where a closure can +survive several compiler runs. A typical case is a completer for a +symbol representing an external class, which produces the attributes +of the symbol on demand, and which might never be invoked. In that +case we follow the convention that any context parameter is explicit, +not implicit, so we can track where it is used, and that it has a name +different from `ctx`. Commonly used is `ictx` for "initialization +context". + +With these two conventions is has turned out that the use of implicit +contexts as an dependency injection and bulk parameterization device +worked exceptionally well. There were not very many bugs related to +passing the wrong context by accident. + +## Compiler Phases + +Seen from a temporal perspective, the `dotc` compiler consists of a list of phases. +The current list of phases is specified in class [Compiler] as follows: + +```scala + def phases: List[List[Phase]] = List( + List(new FrontEnd), // Compiler frontend: scanner, parser, namer, typer + List(new PostTyper), // Additional checks and cleanups after type checking + List(new Pickler), // Generate TASTY info + List(new FirstTransform, // Some transformations to put trees into a canonical form + new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars + List(new RefChecks, // Various checks mostly related to abstract members and overriding + new CheckStatic, // Check restrictions that apply to @static members + new ElimRepeated, // Rewrite vararg parameters and arguments + new NormalizeFlags, // Rewrite some definition flags + new ExtensionMethods, // Expand methods of value classes with extension methods + new ExpandSAMs, // Expand single abstract method closures to anonymous classes + new TailRec, // Rewrite tail recursion to loops + new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods + new ClassOf), // Expand `Predef.classOf` calls. + List(new PatternMatcher, // Compile pattern matches + new ExplicitOuter, // Add accessors to outer classes from nested ones. + new ExplicitSelf, // Make references to non-trivial self types explicit as casts + new CrossCastAnd, // Normalize selections involving intersection types. + new Splitter), // Expand selections involving union types into conditionals + List(new VCInlineMethods, // Inlines calls to value class methods + new SeqLiterals, // Express vararg arguments as arrays + new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods + new Getters, // Replace non-private vals and vars with getter defs (fields are added later) + new ElimByName, // Expand by-name parameters and arguments + new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings + new ResolveSuper), // Implement super accessors and add forwarders to trait methods + List(new Erasure), // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements. + List(new ElimErasedValueType, // Expand erased value types to their underlying implementation types + new VCElideAllocations, // Peep-hole optimization to eliminate unnecessary value class allocations + new Mixin, // Expand trait fields and trait initializers + new LazyVals, // Expand lazy vals + new Memoize, // Add private fields to getters and setters + new LinkScala2ImplClasses, // Forward calls to the implementation classes of traits defined by Scala 2.11 + new NonLocalReturns, // Expand non-local returns + new CapturedVars, // Represent vars captured by closures as heap objects + new Constructors, // Collect initialization code in primary constructors + // Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it + new FunctionalInterfaces,// Rewrites closures to implement @specialized types of Functions. + new GetClass), // Rewrites getClass calls on primitive types. + List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments + // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here + new ElimStaticThis, // Replace `this` references to static objects by global identifiers + new Flatten, // Lift all inner classes to package scope + new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group + List(new ExpandPrivate, // Widen private definitions accessed from nested classes + new CollectEntryPoints, // Find classes with main methods + new LabelDefs), // Converts calls to labels to jumps + List(new GenSJSIR), // Generate .js code + List(new GenBCode) // Generate JVM bytecode + ) +``` + +Note that phases are grouped, so the `phases` value is a +`List[List[Phase]]`. The idea is that all phases in a group are be +*fused* into a single tree traversal. That way, phases can be kept +small (most phases perform a single function) without requiring an +excessive number of tree traversals (which are costly, because they +have generally bad cache locality). + +Phases fall into 4 categories: + + - Frontend phases: `Frontend`, `PostTyper` and `Pickler`. `FrontEnd` parses the source programs and generates + untyped abstract syntax trees, which are then typechecked and transformed into typed abstract syntax trees. + `PostTyper` performs checks and cleanups that require a fully typed program. In particular, it + + - creates super accessors representing `super` calls in traits + - creates implementations of synthetic (compiler-implemented) methods + - avoids storing parameters passed unchanged from subclass to superclass in duplicate fields. + + Finally `Pickler` serializes the typed syntax trees produced by the frontend as TASTY data structures. + + - High-level transformations: All phases from `FirstTransform` to `Erasure`. Most of these phases transform + syntax trees, expanding high-level constructs to more primitive ones. The last phase in the group, `Erasure` + translates all types into types supported directly by the JVM. To do this, it performs another type checking + pass, but using the rules of the JVM's type system instead of Scala's. + + - Low-level transformations: All phases from `ElimErasedValueType` to `LabelDefs`. These + further transform trees until they are just a structured version of Java bytecode. + + - Code generators: These map the transformed trees to Java classfiles or Javascript files. + + From 1c48c1f8a0ff8f94652a98992d13fa47207a79d4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 15 Mar 2016 11:34:21 +0100 Subject: [PATCH 09/12] Add links --- docs/dotc-internals/overall-structure.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/dotc-internals/overall-structure.md b/docs/dotc-internals/overall-structure.md index d5828ea13572..93c97090f7c0 100644 --- a/docs/dotc-internals/overall-structure.md +++ b/docs/dotc-internals/overall-structure.md @@ -1,16 +1,22 @@ # Dotc's Overall Structure -The compiler code is found in package `dotty.tools`. It spans the +The compiler code is found in package [dotty.tools](https://github.com/lampepfl/dotty/tree/master/src/dotty/tools). It spans the following three sub-packages: backend Compiler backends (currently for JVM and JS) dotc The main compiler io Helper modules for file access and classpath handling. -The `dotc` package contains some main classes that can be run as separate -programs. The most important one is class `Main`. `Main` inherits from `Driver` which -contains the highest level functions for starting a compiler and processing some sources -`Driver` in turn is based on two other high-level classes, `Compiler` and `Run`. +The [dotc](https://github.com/lampepfl/dotty/tree/master/src/dotty/tools/dotc) +package contains some main classes that can be run as separate +programs. The most important one is class +[Main](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Main.scala). +`Main` inherits from +[Driver](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Driver.scala) which +contains the highest level functions for starting a compiler and processing some sources. +`Driver` in turn is based on two other high-level classes, +[Compiler](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Compiler.scala) and +[Run](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Run.scala). ## Package Structure @@ -38,7 +44,9 @@ and their focus. `dotc` has almost no global state (the only significant bit of global state is the name table, which is used to hash strings into unique names). Instead, all essential bits of information that -can vary over a compiler run are collected in a [Context](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Context.scala). Most methods in `dotc` take a Context value as an implicit parameter. +can vary over a compiler run are collected in a +[Context](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Contexts.scala). +Most methods in `dotc` take a Context value as an implicit parameter. Contexts give a convenient way to customize values in some part of the call-graph. To run, e.g. some compiler function `f` at a given From 4ab16677e1ccc469fe17b313dc48fd8427418fc7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 15 Mar 2016 11:43:00 +0100 Subject: [PATCH 10/12] Better documentation of main classes --- src/dotty/tools/dotc/Bench.scala | 4 ++++ src/dotty/tools/dotc/Compiler.scala | 3 +++ src/dotty/tools/dotc/Main.scala | 3 +-- src/dotty/tools/dotc/Resident.scala | 4 +++- src/dotty/tools/dotc/Run.scala | 1 + 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/Bench.scala b/src/dotty/tools/dotc/Bench.scala index 2fc38d78c640..56b6dabbe4ca 100644 --- a/src/dotty/tools/dotc/Bench.scala +++ b/src/dotty/tools/dotc/Bench.scala @@ -8,6 +8,10 @@ package dotc import core.Contexts.Context import reporting.Reporter +/** A main class for running compiler benchmarks. Can instantiate a given + * number of compilers and run each (sequentially) a given number of times + * on the same sources. + */ object Bench extends Driver { @sharable private var numRuns = 1 diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 62507d11afb5..fe48ac30e12f 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -18,6 +18,9 @@ import core.Denotations.SingleDenotation import dotty.tools.backend.jvm.{LabelDefs, GenBCode} import dotty.tools.backend.sjs.GenSJSIR +/** The central class of the dotc compiler. The job of a compiler is to create + * runs, which process given `phases` in a given `rootContext`. + */ class Compiler { /** Meta-ordering constraint: diff --git a/src/dotty/tools/dotc/Main.scala b/src/dotty/tools/dotc/Main.scala index 6c473d8bbb44..a6844fbbc4c0 100644 --- a/src/dotty/tools/dotc/Main.scala +++ b/src/dotty/tools/dotc/Main.scala @@ -3,8 +3,7 @@ package dotc import core.Contexts.Context -/* To do: - */ +/** Main class of the `dotc` batch compiler. */ object Main extends Driver { override def newCompiler(implicit ctx: Context): Compiler = new Compiler } diff --git a/src/dotty/tools/dotc/Resident.scala b/src/dotty/tools/dotc/Resident.scala index e1b62e4d0e29..56f6684d0964 100644 --- a/src/dotty/tools/dotc/Resident.scala +++ b/src/dotty/tools/dotc/Resident.scala @@ -6,7 +6,9 @@ import reporting.Reporter import java.io.EOFException import scala.annotation.tailrec -/** A compiler which stays resident between runs. +/** A compiler which stays resident between runs. This is more of a PoC than + * something that's expected to be used often + * * Usage: * * > scala dotty.tools.dotc.Resident diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala index ee808323ae5e..7a0e555e4084 100644 --- a/src/dotty/tools/dotc/Run.scala +++ b/src/dotty/tools/dotc/Run.scala @@ -13,6 +13,7 @@ import java.io.{BufferedWriter, OutputStreamWriter} import scala.reflect.io.VirtualFile import scala.util.control.NonFatal +/** A compiler run. Exports various methods to compile source files */ class Run(comp: Compiler)(implicit ctx: Context) { assert(comp.phases.last.last.id <= Periods.MaxPossiblePhaseId) From 492791f6940f472b9c4b12cf5dca178437d8b9d5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 15 Mar 2016 11:52:23 +0100 Subject: [PATCH 11/12] Polishing --- docs/dotc-internals/overall-structure.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/dotc-internals/overall-structure.md b/docs/dotc-internals/overall-structure.md index 93c97090f7c0..a80c35b4c7cb 100644 --- a/docs/dotc-internals/overall-structure.md +++ b/docs/dotc-internals/overall-structure.md @@ -55,7 +55,7 @@ this f(/*normal args*/)(ctx.withPhase(phase)) -This assumes that `f` is defined in way most compiler functions are: +This assumes that `f` is defined in the way most compiler functions are: def f(/*normal parameters*/)(implicit ctx: Context) ... @@ -77,15 +77,16 @@ not implicit, so we can track where it is used, and that it has a name different from `ctx`. Commonly used is `ictx` for "initialization context". -With these two conventions is has turned out that the use of implicit -contexts as an dependency injection and bulk parameterization device -worked exceptionally well. There were not very many bugs related to -passing the wrong context by accident. +With these two conventions in place, it has turned out that implicit +contexts work amazingly well as a device for dependency injection and +bulk parameterization. There is of course always the danger that +an unexpected implicit will be passed, but in practice this has not turned out to +be much of a problem. ## Compiler Phases Seen from a temporal perspective, the `dotc` compiler consists of a list of phases. -The current list of phases is specified in class [Compiler] as follows: +The current list of phases is specified in class [Compiler](https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Compiler.scala) as follows: ```scala def phases: List[List[Phase]] = List( @@ -141,14 +142,14 @@ The current list of phases is specified in class [Compiler] as follows: ) ``` -Note that phases are grouped, so the `phases` value is a -`List[List[Phase]]`. The idea is that all phases in a group are be +Note that phases are grouped, so the `phases` method is of type +`List[List[Phase]]`. The idea is that all phases in a group are *fused* into a single tree traversal. That way, phases can be kept small (most phases perform a single function) without requiring an excessive number of tree traversals (which are costly, because they have generally bad cache locality). -Phases fall into 4 categories: +Phases fall into four categories: - Frontend phases: `Frontend`, `PostTyper` and `Pickler`. `FrontEnd` parses the source programs and generates untyped abstract syntax trees, which are then typechecked and transformed into typed abstract syntax trees. @@ -166,7 +167,7 @@ Phases fall into 4 categories: pass, but using the rules of the JVM's type system instead of Scala's. - Low-level transformations: All phases from `ElimErasedValueType` to `LabelDefs`. These - further transform trees until they are just a structured version of Java bytecode. + further transform trees until they are essentially a structured version of Java bytecode. - Code generators: These map the transformed trees to Java classfiles or Javascript files. From 98a69cae13db04741e99a7abd45f9e2a9845e5f7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 18 Mar 2016 11:53:06 +0100 Subject: [PATCH 12/12] Drop Mode.scala from tasty_typer test File was moved, it's no longer in package typer. --- test/dotc/tests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 084f13a90635..51b8b3dc5d93 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -280,7 +280,7 @@ class tests extends CompilerTest { @Test def tasty_typer = compileList("tasty_typer", List( "Applications.scala", "Checking.scala", "ConstFold.scala", "ErrorReporting.scala", "EtaExpansion.scala", "FrontEnd.scala", "Implicits.scala", "ImportInfo.scala", - "Inferencing.scala", "Mode.scala", "ProtoTypes.scala", "ReTyper.scala", "RefChecks.scala", + "Inferencing.scala", "ProtoTypes.scala", "ReTyper.scala", "RefChecks.scala", "TypeAssigner.scala", "Typer.scala", "VarianceChecker.scala", "Variances.scala" ) map (typerDir + _), testPickling)