aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-07 18:14:29 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-07 18:14:29 +0100
commit377eb3318cdacd2dfb91d56be3649431ec1155f0 (patch)
tree058530f166821fdc58df3ba9833006c9da3d481c /src/dotty/tools
parente74b6316b93993e3c798bd9df45d83fc0665c52e (diff)
downloaddotty-377eb3318cdacd2dfb91d56be3649431ec1155f0.tar.gz
dotty-377eb3318cdacd2dfb91d56be3649431ec1155f0.tar.bz2
dotty-377eb3318cdacd2dfb91d56be3649431ec1155f0.zip
Fixes for desugarings of case classes.
Also: Standardized on selectorName; Translate $init$ to <init> when unpickling.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala61
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala3
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala11
4 files changed, 50 insertions, 27 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 7904a9388..86e584f6b 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -18,6 +18,7 @@ object desugar {
import untpd._
+ /** Info of a variable in a pattern: The named tree and its type */
private type VarInfo = (NameTree, Tree)
/** var x: Int = expr
@@ -210,7 +211,7 @@ object desugar {
val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true)))
val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(caseParams.length)))
val productElemMeths = for (i <- 0 until caseParams.length) yield
- syntheticProperty(("_" + (i + 1)).toTermName, Select(This(EmptyTypeName), caseParams(i).name))
+ syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeName), caseParams(i).name))
val copyMeths =
if (mods is Abstract) Nil
else {
@@ -225,10 +226,18 @@ object desugar {
else Nil
def anyRef = ref(defn.AnyRefAlias.typeRef)
- def parentConstr(tpt: Tree) = Select(New(tpt), nme.CONSTRUCTOR)
+ def productConstr = {
+ val tycon = ref(defn.ProductNClass(vparamss.head.length).typeRef)
+ val targs = vparamss.head map (_.tpt)
+ New(AppliedTypeTree(tycon, targs), Nil)
+ }
// The desugared parents: AnyRef, in case parents are Nil.
- val parents1 = if (parents.isEmpty) parentConstr(anyRef) :: Nil else parents
+ // Case classes also get a ProductN parent
+ val parents1 = {
+ val parents0 = if (mods is Case) parents :+ productConstr else parents
+ if (parents0.isEmpty) New(anyRef, Nil) :: Nil else parents0
+ }
// The thicket which is the desugared version of the companion object
// synthetic object C extends parentTpt { defs }
@@ -236,7 +245,7 @@ object desugar {
moduleDef(
ModuleDef(
Modifiers(Synthetic), name.toTermName,
- Template(emptyConstructor, parentConstr(parentTpt) :: Nil, EmptyValDef, defs))).toList
+ Template(emptyConstructor, New(parentTpt, Nil) :: Nil, EmptyValDef, defs))).toList
// The companion object defifinitions, if a companion is needed, Nil otherwise.
// companion definitions include:
@@ -308,29 +317,21 @@ object desugar {
Thicket(modul, classDef(cls))
}
+ /** val p1, ..., pN: T = E
+ * ==>
+ * makePatDef[[val p1: T1 = E]]; ...; makePatDef[[val pN: TN = E]]
+ */
def patDef(pdef: PatDef)(implicit ctx: Context): Tree = {
val PatDef(mods, pats, tpt, rhs) = pdef
val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt))
flatTree(pats1 map (makePatDef(mods, _, rhs)))
}
- def defTree(tree: Tree)(implicit ctx: Context): Tree = tree match {
- case tree: ValDef => valDef(tree)
- case tree: TypeDef => if (tree.isClassDef) classDef(tree) else typeDef(tree)
- case tree: DefDef => defDef(tree)
- case tree: ModuleDef => moduleDef(tree)
- case tree: PatDef => patDef(tree)
- }
-
- def block(tree: Block)(implicit ctx: Context): Block = tree.expr match {
- case EmptyTree =>
- cpy.Block(tree, tree.stats,
- unitLiteral withPos (if (tree.stats.isEmpty) tree.pos else tree.pos.endPos))
- case _ =>
- tree
- }
-
- /** In case there is exactly one variable x_1 in pattern
+ /** If `pat` is a variable pattern,
+ *
+ * val/var p = e
+ *
+ * Otherwise, in case there is exactly one variable x_1 in pattern
* val/var p = e ==> val/var x_1 = (e: @unchecked) match (case p => (x_1))
*
* in case there are zero or more than one variables in pattern
@@ -357,7 +358,7 @@ object desugar {
val tmpName = ctx.freshName().toTermName
val patMods = Modifiers(PrivateLocal | Synthetic | (mods.flags & Lazy))
val firstDef = ValDef(patMods, tmpName, TypeTree(), matchExpr)
- def selector(n: Int) = Select(Ident(tmpName), ("_" + n).toTermName)
+ def selector(n: Int) = Select(Ident(tmpName), nme.selectorName(n))
val restDefs =
for (((named, tpt), n) <- vars.zipWithIndex)
yield derivedValDef(mods, named, tpt, selector(n))
@@ -365,6 +366,22 @@ object desugar {
}
}
+ def defTree(tree: Tree)(implicit ctx: Context): Tree = tree match {
+ case tree: ValDef => valDef(tree)
+ case tree: TypeDef => if (tree.isClassDef) classDef(tree) else typeDef(tree)
+ case tree: DefDef => defDef(tree)
+ case tree: ModuleDef => moduleDef(tree)
+ case tree: PatDef => patDef(tree)
+ }
+
+ def block(tree: Block)(implicit ctx: Context): Block = tree.expr match {
+ case EmptyTree =>
+ cpy.Block(tree, tree.stats,
+ unitLiteral withPos (if (tree.stats.isEmpty) tree.pos else tree.pos.endPos))
+ case _ =>
+ tree
+ }
+
/** Make closure corresponding to function params => body */
def makeClosure(params: List[ValDef], body: Tree) =
Block(
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 50e5b518b..03e9f3bfc 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -628,6 +628,8 @@ object StdNames {
LOCALDUMMY_PREFIX ++ clazz.name ++ ">"
def newBitmapName(bitmapPrefix: TermName, n: Int): TermName = bitmapPrefix ++ n.toString
+
+ def selectorName(n: Int): TermName = "_" + (n + 1)
}
class ScalaTypeNames extends ScalaNames[TypeName] {
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 21bdbcce9..88dbca4f7 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -407,7 +407,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
owner.setFlag(DefaultParameterized)
}
- val name = name0.adjustIfModuleClass(flags)
+ val name1 = name0.adjustIfModuleClass(flags)
+ val name = if (name1 == nme.IMPLCLASS_CONSTRUCTOR) nme.CONSTRUCTOR else name1
def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) && !(flags is ModuleClass)
def isModuleClassRoot = (name == moduleClassRoot.name) && (owner == moduleClassRoot.owner) && (flags is Module)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 3de835736..023e7c2b5 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -564,7 +564,7 @@ trait Applications extends Compatibility { self: Typer =>
}
def productSelectors(tp: Type): List[Type] = {
- val sels = for (n <- Iterator.from(1)) yield extractorMemberType(tp, ("_" + n).toTermName)
+ val sels = for (n <- Iterator.from(0)) yield extractorMemberType(tp, nme.selectorName(n))
sels.takeWhile(_.exists).toList
}
def seqSelector = defn.RepeatedParamType.appliedTo(unapplyResult.elemType :: Nil)
@@ -572,9 +572,12 @@ trait Applications extends Compatibility { self: Typer =>
if (tp derivesFrom defn.ProductClass) productSelectors(tp) else tp :: Nil
def getTp = extractorMemberType(unapplyResult, nme.get)
- if ((extractorMemberType(unapplyResult, nme.isDefined) isRef defn.BooleanClass) &&
- getTp.exists) getSelectors(getTp)
- else if (unapplyResult derivesFrom defn.SeqClass) seqSelector :: Nil
+ // println(s"unapply $unapplyResult ${extractorMemberType(unapplyResult, nme.isDefined)}")
+ if (extractorMemberType(unapplyResult, nme.isDefined) isRef defn.BooleanClass) {
+ if (getTp.exists) return getSelectors(getTp)
+ else if (unapplyResult derivesFrom defn.ProductClass) return productSelectors(unapplyResult)
+ }
+ if (unapplyResult derivesFrom defn.SeqClass) seqSelector :: Nil
else if (unapplyResult isRef defn.BooleanClass) Nil
else {
ctx.error(s"${unapplyResult.show} is not a valid result type of an unapply method of an extractor", tree.pos)