aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-05 12:05:49 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-05 12:05:49 +0100
commitc2f101a33ea7f89681d6b74731bbcff948e7e6da (patch)
tree52a67e7ea6001944ac2216c6e55e9dad9fe0b42f /src/dotty/tools
parent8bb6ccae5c4f3ec91877fcfe032902f92aa5d2b4 (diff)
downloaddotty-c2f101a33ea7f89681d6b74731bbcff948e7e6da.tar.gz
dotty-c2f101a33ea7f89681d6b74731bbcff948e7e6da.tar.bz2
dotty-c2f101a33ea7f89681d6b74731bbcff948e7e6da.zip
Changes to Desugar and Namer.
In particular: Changed the scheme to represent the types of setter parameters.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala52
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala35
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala21
4 files changed, 74 insertions, 40 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 1b7f4edc8..84e321158 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -20,19 +20,44 @@ object desugar {
private type VarInfo = (NameTree, Tree)
+ /** var x: Int = expr
+ * ==>
+ * def x: Int = expr
+ * def x_=($1: like (var x: Int = expr)): Unit = ()
+ */
def valDef(vdef: ValDef)(implicit ctx: Context): Tree = {
val ValDef(mods, name, tpt, rhs) = vdef
- if (!ctx.owner.isClass || (mods is Private) || !(mods is Mutable)) vdef
- else {
- val setterParam = makeSyntheticParameter(tpt = TypeTree(vdef))
+ def setterNeeded =
+ (mods is Mutable) && ctx.owner.isClass && (!(mods is Private) || (ctx.owner is Trait))
+ if (setterNeeded) {
+ // todo: copy of vdef as getter needed?
+ // val getter = ValDef(mods, name, tpt, rhs) withPos vdef.pos ?
+ // right now vdef maps via expandedTree to a thicket which concerns itself.
+ // I don't see a problem with that but if there is one we can avoid it by making a copy here.
+ val setterParam = makeSyntheticParameter(tpt = TypeTree())
val setterRhs = if (vdef.rhs.isEmpty) EmptyTree else unitLiteral
val setter = cpy.DefDef(vdef,
mods | Accessor, name.setterName, Nil, (setterParam :: Nil) :: Nil,
TypeTree(defn.UnitType), setterRhs) // rhs gets filled in later, when field is generated and getter has parameters
Thicket(vdef, setter)
}
+ else vdef
}
+ /** Expand context bounds to evidence params. E.g.,
+ *
+ * def f[T >: L <: H : B](params)
+ * ==>
+ * def f[T >: L <: H](params)(implicit evidence$0: B[T])
+ *
+ * Expand default arguments to default getters. E.g,
+ *
+ * def f(x: Int = 1)(y: String = x + "m") = ...
+ * ==>
+ * def f(x: Int)(y: String) = ...
+ * def f$default$1 = 1
+ * def f$default$2(x: Int) = x + "m"
+ */
def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = {
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = meth
val epbuf = new ListBuffer[ValDef]
@@ -62,14 +87,20 @@ object desugar {
cpy.DefDef(meth, mods, name, tparams1, vparamss1, tpt, rhs)
}
+ /** The first n parameters in a possibly curried list of parameter sections */
def take(vparamss: List[List[ValDef]], n: Int): List[List[ValDef]] = vparamss match {
case vparams :: vparamss1 =>
val len = vparams.length
- if (len <= n) vparams :: take(vparamss1, n - len) else Nil
+ if (n == 0) Nil
+ else if (n < len) (vparams take n) :: Nil
+ else vparams :: take(vparamss1, n - len)
case _ =>
Nil
}
+ def normalizedVparamss = vparamss map (_ map (vparam =>
+ cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, EmptyTree)))
+
def defaultGetters(vparamss: List[List[ValDef]], n: Int = 0): List[DefDef] = vparamss match {
case (vparam :: vparams) :: vparamss1 =>
def defaultGetter: DefDef =
@@ -77,7 +108,7 @@ object desugar {
mods = vparam.mods & AccessFlags,
name = meth.name.defaultGetterName(n + 1),
tparams = meth.tparams,
- vparamss = take(meth.vparamss, n),
+ vparamss = take(normalizedVparamss, n),
tpt = TypeTree(),
rhs = vparam.rhs)
val rest = defaultGetters(vparams :: vparamss1, n + 1)
@@ -92,13 +123,18 @@ object desugar {
if (defGetters.isEmpty) meth1
else {
val mods1 = meth1.mods | DefaultParameterized
- val vparamss1 = vparamss map (_ map (vparam =>
- cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, EmptyTree)))
- val meth2 = cpy.DefDef(meth1, mods1, meth1.name, meth1.tparams, vparamss1, meth1.tpt, meth1.rhs)
+ val meth2 = cpy.DefDef(meth1, meth1.mods | DefaultParameterized,
+ meth1.name, meth1.tparams, normalizedVparamss, meth1.tpt, meth1.rhs)
Thicket(meth2 :: defGetters)
}
}
+ /** Fill in empty type bounds with Nothing/Any. Expand private local type parameters as follows:
+ *
+ * class C[T]
+ * ==>
+ * class C { type C$T; type T = C$T }
+ */
def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = {
val TypeDef(mods, name, rhs) = tdef
val rhs1 = rhs match {
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index abea42c1d..546a3e027 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -212,11 +212,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case SeqLiteral(elems) =>
"[" ~ toTextGlobal(elems, ",") ~ "]"
case TypeTree(orig) =>
- if (tree.hasType) toText(tree.typeOpt)
- else orig match {
- case orig: ValDef => "like(" ~ toText(orig) ~ ")"
- case _ => toText(orig)
- }
+ if (tree.hasType) toText(tree.typeOpt) else toText(orig)
case SingletonTypeTree(ref) =>
toTextLocal(ref) ~ ".type"
case SelectFromTypeTree(qual, name) =>
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 66d238614..bcdb4a43f 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -18,6 +18,11 @@ import language.implicitConversions
trait NamerContextOps { this: Context =>
+ /** Enter symbol into current class, if current class is owner of current context,
+ * or into current scope, if not. Should always be called instead of scope.enter
+ * in order to make sure that updates to class members are reflected in
+ * finger prints.
+ */
def enter(sym: Symbol): Symbol = {
ctx.owner match {
case cls: ClassSymbol => cls.enter(sym)
@@ -26,6 +31,7 @@ trait NamerContextOps { this: Context =>
sym
}
+ /** The denotation with the given name in current context */
def denotNamed(name: Name): Denotation =
if (owner.isClass)
if (outer.owner == owner)
@@ -35,12 +41,15 @@ trait NamerContextOps { this: Context =>
else
scope.denotsNamed(name).toDenot(NoPrefix)
- def effectiveScope =
+ /** Either the current scope, or, if the current context owner is a class,
+ * the declarations of the current class.
+ */
+ def effectiveScope: Scope =
if (owner != null && owner.isClass) owner.asClass.decls
else scope
}
-/** This class attaches creates symbols from definitions and imports and gives them
+/** This class creates symbols from definitions and imports and gives them
* lazy types.
*
* Timeline:
@@ -64,7 +73,6 @@ class Namer { typer: Typer =>
import untpd._
-
/** A partial map from unexpanded member and pattern defs and to their expansions.
* Populated during enterSyms, emptied during typer.
*/
@@ -186,7 +194,7 @@ class Namer { typer: Typer =>
sym
}
- /** All PackageClassInfoTypes come from here. */
+ /** Create package if it does not yet exist. */
private def createPackageSymbol(pid: RefTree)(implicit ctx: Context): Symbol = {
val pkgOwner = pid match {
case Ident(_) => if (ctx.owner eq defn.EmptyPackageClass) defn.RootClass else ctx.owner
@@ -242,12 +250,6 @@ class Namer { typer: Typer =>
/** Create top-level symbols for statements and enter them into symbol table */
def index(stats: List[Tree])(implicit ctx: Context): Context = {
- @tailrec def traverse(stats: List[Tree])(implicit ctx: Context): Context = stats match {
- case stat :: stats1 =>
- traverse(stats1)(index(stat))
- case nil =>
- ctx
- }
/** Merge the definitions of a synthetic companion generated by a case class
* and the real companion, if both exist.
@@ -270,7 +272,7 @@ class Namer { typer: Typer =>
}
}
- val result = traverse(stats)
+ val result = (ctx /: stats) ((ctx, stat) => index(stat)(ctx))
mergeCompanionDefs()
result
}
@@ -377,9 +379,16 @@ class Namer { typer: Typer =>
lazy val schema = paramFn(WildcardType)
val site = sym.owner.thisType
val inherited = {
- // TODO: Look only at member of supertype instead?
- if (sym.owner.isTerm) NoType
+ if ((sym is Param) && sym.owner.isSetter) { // fill in type from getter result type
+ val getterCtx = ctx.outersIterator
+ .dropWhile(_.owner != sym.owner)
+ .dropWhile(_.owner == sym.owner)
+ .next
+ getterCtx.denotNamed(sym.owner.asTerm.name.setterToGetter).info.widenExpr
+ }
+ else if (sym.owner.isTerm) NoType
else
+ // TODO: Look only at member of supertype instead?
((NoType: Type) /: sym.owner.info.baseClasses.tail) { (tp, cls) =>
val itpe = cls.info
.nonPrivateDecl(sym.name)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 6f5739396..fd97c2c22 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -619,18 +619,10 @@ class Typer extends Namer with Applications with Implicits {
}
def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = track("typedTypeTree") {
- val (original1, ownType) = tree.original match {
- case untpd.EmptyTree =>
- assert(isFullyDefined(pt, ForceDegree.none))
- (EmptyTree, pt)
- case original: ValDef =>
- val meth = original.symbol // ??? was: symbolOfTree(original) TODO: come back to this
- assert(meth.exists, meth)
- (EmptyTree, meth.info)
- case original =>
- val original1 = typed(original)
- (original1, original1.tpe)
- }
+ val original1 = typed(tree.original)
+ val ownType =
+ if (tree.original.isEmpty) { assert(isFullyDefined(pt, ForceDegree.none)); pt }
+ else original1.tpe
cpy.TypeTree(tree, original1) withType ownType
}
@@ -1011,9 +1003,10 @@ class Typer extends Namer with Applications with Implicits {
noMatches
}
case alts =>
+ def all = if (altDenots.length == 2) "both" else "all"
errorTree(tree,
- i"""Ambiguous overload. The ${err.overloadedAltsStr(altDenots take 2)}
- |both match $expectedStr""".stripMargin)
+ i"""Ambiguous overload. The ${err.overloadedAltsStr(altDenots)}
+ |$all match $expectedStr""".stripMargin)
}
}