diff options
author | Martin Odersky <odersky@gmail.com> | 2013-12-07 18:14:29 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-12-07 18:14:29 +0100 |
commit | 377eb3318cdacd2dfb91d56be3649431ec1155f0 (patch) | |
tree | 058530f166821fdc58df3ba9833006c9da3d481c /src/dotty/tools | |
parent | e74b6316b93993e3c798bd9df45d83fc0665c52e (diff) | |
download | dotty-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.scala | 61 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 11 |
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) |