Skip to content

Transform/erasure #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 29, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import Scopes._
import typer.{FrontEnd, Typer, Mode, ImportInfo}
import reporting.ConsoleReporter
import dotty.tools.dotc.core.Phases.Phase
import dotty.tools.dotc.transform.{UncurryTreeTransform, LazyValsCreateCompanionObjects, LazyValTranformContext}
import dotty.tools.dotc.transform._
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
import dotty.tools.dotc.core.Denotations.SingleDenotation
import dotty.tools.dotc.transform.TreeTransforms.Separator

class Compiler {

def phases: List[List[Phase]] = List(
List(new FrontEnd), List(new LazyValsCreateCompanionObjects),
//force separataion between lazyVals and LVCreateCO
List(new LazyValTranformContext().transformer, new UncurryTreeTransform)
)
def phases: List[List[Phase]] =
List(
List(new FrontEnd),
List(new LazyValsCreateCompanionObjects), //force separataion between lazyVals and LVCreateCO
List(new LazyValTranformContext().transformer, new TypeTestsCasts),
List(new Erasure),
List(new UncurryTreeTransform)
)

var runId = 1
def nextRunId = {
Expand Down
22 changes: 19 additions & 3 deletions src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dotty.tools
package dotc

import core._
import Contexts._, Periods._, Symbols._
import Contexts._, Periods._, Symbols._, Phases._, Decorators._
import io.PlainFile
import util.{SourceFile, NoSource, Stats, SimpleMap}
import reporting.Reporter
Expand Down Expand Up @@ -30,13 +30,29 @@ class Run(comp: Compiler)(implicit ctx: Context) {
def compileSources(sources: List[SourceFile]) = Stats.monitorHeartBeat {
if (sources forall (_.exists)) {
units = sources map (new CompilationUnit(_))
for (phase <- ctx.allPhases.init) {
if (!ctx.reporter.hasErrors)
def stoppedBefore(phase: Phase) =
ctx.settings.YstopBefore.value.containsPhase(phase) ||
ctx.settings.YstopAfter.value.containsPhase(phase.prev)
val phasesToRun = ctx.allPhases.init
.takeWhile(!stoppedBefore(_))
.filterNot(ctx.settings.Yskip.value.containsPhase(_))
for (phase <- phasesToRun) {
if (!ctx.reporter.hasErrors) {
phase.runOn(units)
if (ctx.settings.Xprint.value.containsPhase(phase))
for (unit <- units)
printTree(ctx.fresh.setPhase(phase).setCompilationUnit(unit))
}
}
}
}

private def printTree(implicit ctx: Context) = {
val unit = ctx.compilationUnit
println(s"result of $unit after ${ctx.phase}:")
println(unit.tpdTree.show)
}

def compile(sourceCode: String): Unit = {
val virtualFile = new VirtualFile(sourceCode) // use source code as name as it's used for equals
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8")) // buffering is still advised by javadoc
Expand Down
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ object Trees {
trait DefTree[-T >: Untyped] extends DenotingTree[T] {
type ThisTree[-T >: Untyped] <: DefTree[T]
override def isDef = true
def namedType = tpe.asInstanceOf[NamedType]
}

/** Tree defines a new symbol and carries modifiers.
Expand Down
41 changes: 39 additions & 2 deletions src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package ast
import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import CheckTrees._, Denotations._
import CheckTrees._, Denotations._, Decorators._
import config.Printers._

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

def Select(qualifier: Tree, sym: Symbol)(implicit ctx: Context): Select =
untpd.Select(qualifier, sym.name).withType(qualifier.tpe select sym)

def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context) =
untpd.SelectWithSig(qualifier, name, sig)
.withType(TermRef.withSig(qualifier.tpe, name.asTermName, sig))
Expand All @@ -46,6 +49,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def Apply(fn: Tree, args: List[Tree])(implicit ctx: Context): Apply =
ta.assignType(untpd.Apply(fn, args), fn, args)

def ensureApplied(fn: Tree)(implicit ctx: Context): Tree =
if (fn.tpe.widen.isParameterless) fn else Apply(fn, Nil)

def TypeApply(fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
ta.assignType(untpd.TypeApply(fn, args), fn, args)

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

def SyntheticValDef(name: TermName, rhs: Tree)(implicit ctx: Context): ValDef =
ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe, coord = rhs.pos), rhs)

def DefDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef =
ta.assignType(DefDef(sym, Function.const(rhs) _), sym)

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

def ref(sym: Symbol)(implicit ctx: Context): tpd.NameTree =
def ref(sym: Symbol)(implicit ctx: Context): NameTree =
ref(NamedType(sym.owner.thisType, sym.name, sym.denot))

def singleton(tp: Type)(implicit ctx: Context): Tree = tp match {
case tp: TermRef => ref(tp)
case ThisType(cls) => This(cls)
case SuperType(qual, _) => singleton(qual)
case ConstantType(value) => Literal(value)
}

// ------ Creating typed equivalents of trees that exist only in untyped form -------

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

// convert a numeric with a toXXX method
def numericConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = {
val mname = ("to" + numericCls.name).toTermName
val conversion = tree.tpe member mname
assert(conversion.symbol.exists, s"$tree => $numericCls")
ensureApplied(Select(tree, conversion.symbol.termRef))
}

def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context) = {
if (isIdempotentExpr(tree)) within(tree)
else {
val vdef = SyntheticValDef(ctx.freshName("ev$").toTermName, tree)
Block(vdef :: Nil, within(Ident(vdef.namedType)))
}
}

def runtimeCall(name: TermName, args: List[Tree])(implicit ctx: Context): Tree = ???

def mkAnd(tree1: Tree, tree2: Tree)(implicit ctx: Context) =
Apply(Select(tree1, defn.Boolean_and), tree2 :: Nil)

// ensure that constructors are fully applied?
// ensure that normal methods are fully applied?

Expand Down
3 changes: 3 additions & 0 deletions src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ object Config {
* Disadvantage: It might hide inconsistencies, so while debugging it's better to turn it off
*/
final val newMatch = false

/** The recursion depth for showing a summarized string */
final val summarizeDepth = 2
}
8 changes: 4 additions & 4 deletions src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ class ScalaSettings extends Settings.SettingGroup {
val XshowtreesStringified = BooleanSetting("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.")
val Yshowsyms = BooleanSetting("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
val Yshowsymkinds = BooleanSetting("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
val skip = PhasesSetting("-Yskip", "Skip")
val Yskip = PhasesSetting("-Yskip", "Skip")
val Ygenjavap = StringSetting("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "")
val Ydumpclasses = StringSetting("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
val Ynosqueeze = BooleanSetting("-Yno-squeeze", "Disable creation of compact code in matching.")
val stopAfter = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
val stopBefore = PhasesSetting("-Ystop-before", "Stop before")
val YstopAfter = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
val YstopBefore = PhasesSetting("-Ystop-before", "Stop before", "erasure") // stop before erasure as long as we have not debugged it fully
val refinementMethodDispatch = ChoiceSetting("-Ystruct-dispatch", "policy", "structural method dispatch policy", List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache")
val Yrangepos = BooleanSetting("-Yrangepos", "Use range positions for syntax trees.")
val Ybuilderdebug = ChoiceSetting("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
Expand All @@ -144,7 +144,7 @@ class ScalaSettings extends Settings.SettingGroup {
val YshowSuppressedErrors = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally supressed.")
val Yheartbeat = BooleanSetting("-Yheartbeat", "show heartbeat stack trace of compiler operations.")
val Yprintpos = BooleanSetting("-Yprintpos", "show tree positions")
def stop = stopAfter
def stop = YstopAfter

/** Area-specific debug output.
*/
Expand Down
38 changes: 34 additions & 4 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ class Definitions {

lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc)
lazy val BooleanClass = valueClassSymbol("scala.Boolean", BoxedBooleanClass, java.lang.Boolean.TYPE, BooleanEnc)

lazy val Boolean_and = BooleanClass.requiredMethod(nme.ZAND)

lazy val ByteClass = valueClassSymbol("scala.Byte", BoxedByteClass, java.lang.Byte.TYPE, ByteEnc)
lazy val ShortClass = valueClassSymbol("scala.Short", BoxedShortClass, java.lang.Short.TYPE, ShortEnc)
lazy val CharClass = valueClassSymbol("scala.Char", BoxedCharClass, java.lang.Character.TYPE, CharEnc)
Expand All @@ -179,6 +182,9 @@ class Definitions {
lazy val DoubleClass = valueClassSymbol("scala.Double", BoxedDoubleClass, java.lang.Double.TYPE, DoubleEnc)

lazy val BoxedUnitClass = ctx.requiredClass("scala.runtime.BoxedUnit")

lazy val BoxedUnit_UNIT = BoxedUnitClass.linkedClass.requiredValue("UNIT")

lazy val BoxedBooleanClass = ctx.requiredClass("java.lang.Boolean")
lazy val BoxedByteClass = ctx.requiredClass("java.lang.Byte")
lazy val BoxedShortClass = ctx.requiredClass("java.lang.Short")
Expand All @@ -192,7 +198,7 @@ class Definitions {
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType)

lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, SeqType)
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS, Covariant, ArrayType)
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS, Covariant, ArrayClass.typeRef)

// fundamental classes
lazy val StringClass = ctx.requiredClass("java.lang.String")
Expand Down Expand Up @@ -250,8 +256,7 @@ class Definitions {
def NothingType: Type = NothingClass.typeRef
def NullType: Type = NullClass.typeRef
def SeqType: Type = SeqClass.typeRef
def ArrayType: Type = ArrayClass.typeRef
def ObjectArrayType = ArrayType.appliedTo(ObjectType)
def ObjectArrayType = ArrayType(ObjectType)

def UnitType: Type = UnitClass.typeRef
def BooleanType: Type = BooleanClass.typeRef
Expand Down Expand Up @@ -298,6 +303,29 @@ class Definitions {
}
}

object ArrayType {
def apply(elem: Type) =
ArrayClass.typeRef.appliedTo(elem :: Nil)
def unapply(tp: Type) = tp.dealias match {
case at: RefinedType if (at isRef ArrayClass) && at.argInfos.length == 1 => Some(at.argInfos.head)
case _ => None
}
}

object MultiArrayType {
def apply(elem: Type, ndims: Int): Type =
if (ndims == 0) elem else ArrayType(apply(elem, ndims - 1))
def unapply(tp: Type): Option[(Type, Int)] = tp match {
case ArrayType(elemtp) =>
elemtp match {
case MultiArrayType(finalElemTp, n) => Some(finalElemTp, n + 1)
case _ => Some(elemtp, 1)
}
case _ =>
None
}
}

// ----- Symbol sets ---------------------------------------------------

lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0)
Expand Down Expand Up @@ -390,7 +418,7 @@ class Definitions {
hkTraitOfArity.getOrElseUpdate(vcs, createTrait)
}

// ----- Value class machinery ------------------------------------------
// ----- primitive value class machinery ------------------------------------------

lazy val ScalaValueClasses: collection.Set[Symbol] = Set(
UnitClass,
Expand All @@ -403,6 +431,8 @@ class Definitions {
FloatClass,
DoubleClass)

lazy val ScalaBoxedClasses = ScalaValueClasses map boxedClass

private[this] val _boxedClass = mutable.Map[Symbol, Symbol]()
private[this] val _unboxedClass = mutable.Map[Symbol, Symbol]()

Expand Down
8 changes: 8 additions & 0 deletions src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ object NameOps {
name.drop(tpnme.HK_TRAIT_PREFIX.length).toList.map(varianceOfSuffix)
}

/** The name of the generic runtime operation corresponding to an array operation */
def genericArrayOp: TermName = name match {
case nme.apply => nme.array_apply
case nme.length => nme.array_length
case nme.update => nme.array_update
case nme.clone_ => nme.array_clone
}

/** If name length exceeds allowable limit, replace part of it by hash */
def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/Phases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ object Phases {
* The list should never contain NoPhase.
* if squashing is enabled, phases in same subgroup will be squashed to single phase.
*/
def usePhases(phasess: List[List[Phase]], squash: Boolean = false) = {
def usePhases(phasess: List[List[Phase]], squash: Boolean = true) = {
phases = (NoPhase :: phasess.flatten ::: new TerminalPhase :: Nil).toArray
nextDenotTransformerId = new Array[Int](phases.length)
denotTransformers = new Array[DenotTransformer](phases.length)
Expand Down
8 changes: 4 additions & 4 deletions src/dotty/tools/dotc/core/Signature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ case class Signature private (paramsSig: List[TypeName], resSig: TypeName) {
/** Construct a signature by prepending the signature names of the given `params`
* to the parameter part of this signature.
*/
def ++:(params: List[Type])(implicit ctx: Context) =
Signature((params map sigName) ++ paramsSig, resSig)
def prepend(params: List[Type], isJava: Boolean)(implicit ctx: Context) =
Signature((params.map(sigName(_, isJava))) ++ paramsSig, resSig)

}

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

/** The signature of a method with no parameters and result type `resultType`. */
def apply(resultType: Type)(implicit ctx: Context): Signature =
apply(Nil, sigName(resultType))
def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature =
apply(Nil, sigName(resultType, isJava))
}
4 changes: 4 additions & 0 deletions src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,10 @@ object SymDenotations {
val cname = if (this is ImplClass) nme.IMPLCLASS_CONSTRUCTOR else nme.CONSTRUCTOR
decls.denotsNamed(cname).first.symbol
}

def underlyingOfValueClass: Type = ???

def valueClassUnbox: Symbol = ???
}

/** The denotation of a package class.
Expand Down
5 changes: 5 additions & 0 deletions src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ object Symbols {
/** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */
def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol

/** Is this symbol a user-defined value class? */
final def isDerivedValueClass(implicit ctx: Context): Boolean =
false && // value classes are not supported yet
isClass && denot.derivesFrom(defn.AnyValClass) && !isPrimitiveValueClass

/** Is symbol a primitive value class? */
def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains this

Expand Down
17 changes: 0 additions & 17 deletions src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -298,23 +298,6 @@ class TypeApplications(val self: Type) extends AnyVal {
def elemType(implicit ctx: Context): Type =
firstBaseArgInfo(defn.SeqClass) orElse firstBaseArgInfo(defn.ArrayClass)

/** If this type is of the normalized form Array[...[Array[T]...]
* return the number of Array wrappers and T.
* Otherwise return 0 and the type itself
*/
final def splitArray(implicit ctx: Context): (Int, Type) = {
def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match {
case RefinedType(tycon, _) if tycon isRef defn.ArrayClass =>
tp.argInfos match {
case arg :: Nil => recur(n + 1, arg)
case _ => (n, tp)
}
case _ =>
(n, tp)
}
recur(0, self)
}

/** Given a type alias
*
* type T[boundSyms] = p.C[targs]
Expand Down
Loading