Skip to content

Commit 5d9feef

Browse files
committed
Merge pull request #101 from dotty-staging/transform/erasure
Transform/erasure
2 parents a926843 + d26d189 commit 5d9feef

28 files changed

+834
-181
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,22 @@ import Scopes._
99
import typer.{FrontEnd, Typer, Mode, ImportInfo}
1010
import reporting.ConsoleReporter
1111
import dotty.tools.dotc.core.Phases.Phase
12-
import dotty.tools.dotc.transform.{UncurryTreeTransform, LazyValsCreateCompanionObjects, LazyValTranformContext}
12+
import dotty.tools.dotc.transform._
1313
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
1414
import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer
1515
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
1616
import dotty.tools.dotc.core.Denotations.SingleDenotation
17-
import dotty.tools.dotc.transform.TreeTransforms.Separator
1817

1918
class Compiler {
2019

21-
def phases: List[List[Phase]] = List(
22-
List(new FrontEnd), List(new LazyValsCreateCompanionObjects),
23-
//force separataion between lazyVals and LVCreateCO
24-
List(new LazyValTranformContext().transformer, new UncurryTreeTransform)
25-
)
20+
def phases: List[List[Phase]] =
21+
List(
22+
List(new FrontEnd),
23+
List(new LazyValsCreateCompanionObjects), //force separataion between lazyVals and LVCreateCO
24+
List(new LazyValTranformContext().transformer, new TypeTestsCasts),
25+
List(new Erasure),
26+
List(new UncurryTreeTransform)
27+
)
2628

2729
var runId = 1
2830
def nextRunId = {

src/dotty/tools/dotc/Run.scala

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33

44
import core._
5-
import Contexts._, Periods._, Symbols._
5+
import Contexts._, Periods._, Symbols._, Phases._, Decorators._
66
import io.PlainFile
77
import util.{SourceFile, NoSource, Stats, SimpleMap}
88
import reporting.Reporter
@@ -30,13 +30,29 @@ class Run(comp: Compiler)(implicit ctx: Context) {
3030
def compileSources(sources: List[SourceFile]) = Stats.monitorHeartBeat {
3131
if (sources forall (_.exists)) {
3232
units = sources map (new CompilationUnit(_))
33-
for (phase <- ctx.allPhases.init) {
34-
if (!ctx.reporter.hasErrors)
33+
def stoppedBefore(phase: Phase) =
34+
ctx.settings.YstopBefore.value.containsPhase(phase) ||
35+
ctx.settings.YstopAfter.value.containsPhase(phase.prev)
36+
val phasesToRun = ctx.allPhases.init
37+
.takeWhile(!stoppedBefore(_))
38+
.filterNot(ctx.settings.Yskip.value.containsPhase(_))
39+
for (phase <- phasesToRun) {
40+
if (!ctx.reporter.hasErrors) {
3541
phase.runOn(units)
42+
if (ctx.settings.Xprint.value.containsPhase(phase))
43+
for (unit <- units)
44+
printTree(ctx.fresh.setPhase(phase).setCompilationUnit(unit))
45+
}
3646
}
3747
}
3848
}
3949

50+
private def printTree(implicit ctx: Context) = {
51+
val unit = ctx.compilationUnit
52+
println(s"result of $unit after ${ctx.phase}:")
53+
println(unit.tpdTree.show)
54+
}
55+
4056
def compile(sourceCode: String): Unit = {
4157
val virtualFile = new VirtualFile(sourceCode) // use source code as name as it's used for equals
4258
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8")) // buffering is still advised by javadoc

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ object Trees {
384384
trait DefTree[-T >: Untyped] extends DenotingTree[T] {
385385
type ThisTree[-T >: Untyped] <: DefTree[T]
386386
override def isDef = true
387+
def namedType = tpe.asInstanceOf[NamedType]
387388
}
388389

389390
/** Tree defines a new symbol and carries modifiers.

src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package ast
55
import core._
66
import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
77
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
8-
import CheckTrees._, Denotations._
8+
import CheckTrees._, Denotations._, Decorators._
99
import config.Printers._
1010

1111
/** Some creators for typed trees */
@@ -27,6 +27,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
2727
def Select(qualifier: Tree, tp: NamedType)(implicit ctx: Context): Select =
2828
untpd.Select(qualifier, tp.name).withType(tp)
2929

30+
def Select(qualifier: Tree, sym: Symbol)(implicit ctx: Context): Select =
31+
untpd.Select(qualifier, sym.name).withType(qualifier.tpe select sym)
32+
3033
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context) =
3134
untpd.SelectWithSig(qualifier, name, sig)
3235
.withType(TermRef.withSig(qualifier.tpe, name.asTermName, sig))
@@ -46,6 +49,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
4649
def Apply(fn: Tree, args: List[Tree])(implicit ctx: Context): Apply =
4750
ta.assignType(untpd.Apply(fn, args), fn, args)
4851

52+
def ensureApplied(fn: Tree)(implicit ctx: Context): Tree =
53+
if (fn.tpe.widen.isParameterless) fn else Apply(fn, Nil)
54+
4955
def TypeApply(fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
5056
ta.assignType(untpd.TypeApply(fn, args), fn, args)
5157

@@ -165,6 +171,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
165171
def ValDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): ValDef =
166172
ta.assignType(untpd.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs), sym)
167173

174+
def SyntheticValDef(name: TermName, rhs: Tree)(implicit ctx: Context): ValDef =
175+
ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe, coord = rhs.pos), rhs)
176+
168177
def DefDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef =
169178
ta.assignType(DefDef(sym, Function.const(rhs) _), sym)
170179

@@ -234,9 +243,16 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
234243
case pre => SelectFromTypeTree(TypeTree(pre), tp)
235244
} // no checks necessary
236245

237-
def ref(sym: Symbol)(implicit ctx: Context): tpd.NameTree =
246+
def ref(sym: Symbol)(implicit ctx: Context): NameTree =
238247
ref(NamedType(sym.owner.thisType, sym.name, sym.denot))
239248

249+
def singleton(tp: Type)(implicit ctx: Context): Tree = tp match {
250+
case tp: TermRef => ref(tp)
251+
case ThisType(cls) => This(cls)
252+
case SuperType(qual, _) => singleton(qual)
253+
case ConstantType(value) => Literal(value)
254+
}
255+
240256
// ------ Creating typed equivalents of trees that exist only in untyped form -------
241257

242258
/** new C(args) */
@@ -383,6 +399,27 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
383399
ownerMap andThen (from zip to).toMap)
384400
}
385401

402+
// convert a numeric with a toXXX method
403+
def numericConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = {
404+
val mname = ("to" + numericCls.name).toTermName
405+
val conversion = tree.tpe member mname
406+
assert(conversion.symbol.exists, s"$tree => $numericCls")
407+
ensureApplied(Select(tree, conversion.symbol.termRef))
408+
}
409+
410+
def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context) = {
411+
if (isIdempotentExpr(tree)) within(tree)
412+
else {
413+
val vdef = SyntheticValDef(ctx.freshName("ev$").toTermName, tree)
414+
Block(vdef :: Nil, within(Ident(vdef.namedType)))
415+
}
416+
}
417+
418+
def runtimeCall(name: TermName, args: List[Tree])(implicit ctx: Context): Tree = ???
419+
420+
def mkAnd(tree1: Tree, tree2: Tree)(implicit ctx: Context) =
421+
Apply(Select(tree1, defn.Boolean_and), tree2 :: Nil)
422+
386423
// ensure that constructors are fully applied?
387424
// ensure that normal methods are fully applied?
388425

src/dotty/tools/dotc/config/Config.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ object Config {
2727
* Disadvantage: It might hide inconsistencies, so while debugging it's better to turn it off
2828
*/
2929
final val newMatch = false
30+
31+
/** The recursion depth for showing a summarized string */
32+
final val summarizeDepth = 2
3033
}

src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ class ScalaSettings extends Settings.SettingGroup {
125125
val XshowtreesStringified = BooleanSetting("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.")
126126
val Yshowsyms = BooleanSetting("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
127127
val Yshowsymkinds = BooleanSetting("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
128-
val skip = PhasesSetting("-Yskip", "Skip")
128+
val Yskip = PhasesSetting("-Yskip", "Skip")
129129
val Ygenjavap = StringSetting("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "")
130130
val Ydumpclasses = StringSetting("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
131131
val Ynosqueeze = BooleanSetting("-Yno-squeeze", "Disable creation of compact code in matching.")
132-
val stopAfter = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
133-
val stopBefore = PhasesSetting("-Ystop-before", "Stop before")
132+
val YstopAfter = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
133+
val YstopBefore = PhasesSetting("-Ystop-before", "Stop before", "erasure") // stop before erasure as long as we have not debugged it fully
134134
val refinementMethodDispatch = ChoiceSetting("-Ystruct-dispatch", "policy", "structural method dispatch policy", List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache")
135135
val Yrangepos = BooleanSetting("-Yrangepos", "Use range positions for syntax trees.")
136136
val Ybuilderdebug = ChoiceSetting("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
@@ -144,7 +144,7 @@ class ScalaSettings extends Settings.SettingGroup {
144144
val YshowSuppressedErrors = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally supressed.")
145145
val Yheartbeat = BooleanSetting("-Yheartbeat", "show heartbeat stack trace of compiler operations.")
146146
val Yprintpos = BooleanSetting("-Yprintpos", "show tree positions")
147-
def stop = stopAfter
147+
def stop = YstopAfter
148148

149149
/** Area-specific debug output.
150150
*/

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class Definitions {
170170

171171
lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc)
172172
lazy val BooleanClass = valueClassSymbol("scala.Boolean", BoxedBooleanClass, java.lang.Boolean.TYPE, BooleanEnc)
173+
174+
lazy val Boolean_and = BooleanClass.requiredMethod(nme.ZAND)
175+
173176
lazy val ByteClass = valueClassSymbol("scala.Byte", BoxedByteClass, java.lang.Byte.TYPE, ByteEnc)
174177
lazy val ShortClass = valueClassSymbol("scala.Short", BoxedShortClass, java.lang.Short.TYPE, ShortEnc)
175178
lazy val CharClass = valueClassSymbol("scala.Char", BoxedCharClass, java.lang.Character.TYPE, CharEnc)
@@ -179,6 +182,9 @@ class Definitions {
179182
lazy val DoubleClass = valueClassSymbol("scala.Double", BoxedDoubleClass, java.lang.Double.TYPE, DoubleEnc)
180183

181184
lazy val BoxedUnitClass = ctx.requiredClass("scala.runtime.BoxedUnit")
185+
186+
lazy val BoxedUnit_UNIT = BoxedUnitClass.linkedClass.requiredValue("UNIT")
187+
182188
lazy val BoxedBooleanClass = ctx.requiredClass("java.lang.Boolean")
183189
lazy val BoxedByteClass = ctx.requiredClass("java.lang.Byte")
184190
lazy val BoxedShortClass = ctx.requiredClass("java.lang.Short")
@@ -192,7 +198,7 @@ class Definitions {
192198
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType)
193199

194200
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, SeqType)
195-
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS, Covariant, ArrayType)
201+
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS, Covariant, ArrayClass.typeRef)
196202

197203
// fundamental classes
198204
lazy val StringClass = ctx.requiredClass("java.lang.String")
@@ -250,8 +256,7 @@ class Definitions {
250256
def NothingType: Type = NothingClass.typeRef
251257
def NullType: Type = NullClass.typeRef
252258
def SeqType: Type = SeqClass.typeRef
253-
def ArrayType: Type = ArrayClass.typeRef
254-
def ObjectArrayType = ArrayType.appliedTo(ObjectType)
259+
def ObjectArrayType = ArrayType(ObjectType)
255260

256261
def UnitType: Type = UnitClass.typeRef
257262
def BooleanType: Type = BooleanClass.typeRef
@@ -298,6 +303,29 @@ class Definitions {
298303
}
299304
}
300305

306+
object ArrayType {
307+
def apply(elem: Type) =
308+
ArrayClass.typeRef.appliedTo(elem :: Nil)
309+
def unapply(tp: Type) = tp.dealias match {
310+
case at: RefinedType if (at isRef ArrayClass) && at.argInfos.length == 1 => Some(at.argInfos.head)
311+
case _ => None
312+
}
313+
}
314+
315+
object MultiArrayType {
316+
def apply(elem: Type, ndims: Int): Type =
317+
if (ndims == 0) elem else ArrayType(apply(elem, ndims - 1))
318+
def unapply(tp: Type): Option[(Type, Int)] = tp match {
319+
case ArrayType(elemtp) =>
320+
elemtp match {
321+
case MultiArrayType(finalElemTp, n) => Some(finalElemTp, n + 1)
322+
case _ => Some(elemtp, 1)
323+
}
324+
case _ =>
325+
None
326+
}
327+
}
328+
301329
// ----- Symbol sets ---------------------------------------------------
302330

303331
lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0)
@@ -390,7 +418,7 @@ class Definitions {
390418
hkTraitOfArity.getOrElseUpdate(vcs, createTrait)
391419
}
392420

393-
// ----- Value class machinery ------------------------------------------
421+
// ----- primitive value class machinery ------------------------------------------
394422

395423
lazy val ScalaValueClasses: collection.Set[Symbol] = Set(
396424
UnitClass,
@@ -403,6 +431,8 @@ class Definitions {
403431
FloatClass,
404432
DoubleClass)
405433

434+
lazy val ScalaBoxedClasses = ScalaValueClasses map boxedClass
435+
406436
private[this] val _boxedClass = mutable.Map[Symbol, Symbol]()
407437
private[this] val _unboxedClass = mutable.Map[Symbol, Symbol]()
408438

src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ object NameOps {
181181
name.drop(tpnme.HK_TRAIT_PREFIX.length).toList.map(varianceOfSuffix)
182182
}
183183

184+
/** The name of the generic runtime operation corresponding to an array operation */
185+
def genericArrayOp: TermName = name match {
186+
case nme.apply => nme.array_apply
187+
case nme.length => nme.array_length
188+
case nme.update => nme.array_update
189+
case nme.clone_ => nme.array_clone
190+
}
191+
184192
/** If name length exceeds allowable limit, replace part of it by hash */
185193
def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
186194
}

src/dotty/tools/dotc/core/Phases.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ object Phases {
7272
* The list should never contain NoPhase.
7373
* if squashing is enabled, phases in same subgroup will be squashed to single phase.
7474
*/
75-
def usePhases(phasess: List[List[Phase]], squash: Boolean = false) = {
75+
def usePhases(phasess: List[List[Phase]], squash: Boolean = true) = {
7676
phases = (NoPhase :: phasess.flatten ::: new TerminalPhase :: Nil).toArray
7777
nextDenotTransformerId = new Array[Int](phases.length)
7878
denotTransformers = new Array[DenotTransformer](phases.length)

src/dotty/tools/dotc/core/Signature.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ case class Signature private (paramsSig: List[TypeName], resSig: TypeName) {
3838
/** Construct a signature by prepending the signature names of the given `params`
3939
* to the parameter part of this signature.
4040
*/
41-
def ++:(params: List[Type])(implicit ctx: Context) =
42-
Signature((params map sigName) ++ paramsSig, resSig)
41+
def prepend(params: List[Type], isJava: Boolean)(implicit ctx: Context) =
42+
Signature((params.map(sigName(_, isJava))) ++ paramsSig, resSig)
4343

4444
}
4545

@@ -51,6 +51,6 @@ object Signature {
5151
val NotAMethod = Signature(List(), EmptyTypeName)
5252

5353
/** The signature of a method with no parameters and result type `resultType`. */
54-
def apply(resultType: Type)(implicit ctx: Context): Signature =
55-
apply(Nil, sigName(resultType))
54+
def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature =
55+
apply(Nil, sigName(resultType, isJava))
5656
}

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,10 @@ object SymDenotations {
12141214
val cname = if (this is ImplClass) nme.IMPLCLASS_CONSTRUCTOR else nme.CONSTRUCTOR
12151215
decls.denotsNamed(cname).first.symbol
12161216
}
1217+
1218+
def underlyingOfValueClass: Type = ???
1219+
1220+
def valueClassUnbox: Symbol = ???
12171221
}
12181222

12191223
/** The denotation of a package class.

src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,11 @@ object Symbols {
379379
/** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */
380380
def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol
381381

382+
/** Is this symbol a user-defined value class? */
383+
final def isDerivedValueClass(implicit ctx: Context): Boolean =
384+
false && // value classes are not supported yet
385+
isClass && denot.derivesFrom(defn.AnyValClass) && !isPrimitiveValueClass
386+
382387
/** Is symbol a primitive value class? */
383388
def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains this
384389

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -298,23 +298,6 @@ class TypeApplications(val self: Type) extends AnyVal {
298298
def elemType(implicit ctx: Context): Type =
299299
firstBaseArgInfo(defn.SeqClass) orElse firstBaseArgInfo(defn.ArrayClass)
300300

301-
/** If this type is of the normalized form Array[...[Array[T]...]
302-
* return the number of Array wrappers and T.
303-
* Otherwise return 0 and the type itself
304-
*/
305-
final def splitArray(implicit ctx: Context): (Int, Type) = {
306-
def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match {
307-
case RefinedType(tycon, _) if tycon isRef defn.ArrayClass =>
308-
tp.argInfos match {
309-
case arg :: Nil => recur(n + 1, arg)
310-
case _ => (n, tp)
311-
}
312-
case _ =>
313-
(n, tp)
314-
}
315-
recur(0, self)
316-
}
317-
318301
/** Given a type alias
319302
*
320303
* type T[boundSyms] = p.C[targs]

0 commit comments

Comments
 (0)