summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-01-17 16:37:27 +0000
committerMartin Odersky <odersky@gmail.com>2008-01-17 16:37:27 +0000
commit76c06b4661b70e934530a0debad34a5766ee43e9 (patch)
tree4abb85699a2d663681a9ca31fb7ccff45b80746f /src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
parente5ca1a3906ae29c1d6db5de333932bbfc189cedc (diff)
downloadscala-76c06b4661b70e934530a0debad34a5766ee43e9.tar.gz
scala-76c06b4661b70e934530a0debad34a5766ee43e9.tar.bz2
scala-76c06b4661b70e934530a0debad34a5766ee43e9.zip
build target is now 1.5
case classes now generate objects not factory methods. some small cleanups for type inference
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Unapplies.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala88
1 files changed, 87 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 98c6935953..c0be7a9454 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -6,6 +6,8 @@
package scala.tools.nsc.typechecker
+import symtab.Flags._
+
/*
* @author Martin Odersky
* @version 1.0
@@ -14,6 +16,7 @@ trait Unapplies { self: Analyzer =>
import global._
import definitions._
+ import posAssigner.atPos
/** returns type list for return type of the extraction */
def unapplyTypeList(ufn: Symbol, ufntpe: Type) = {
@@ -79,7 +82,6 @@ trait Unapplies { self: Analyzer =>
else
productType({val es = elems; if(useWildCards) elems map { x => WildcardType} else elems})
*/
-
def unapplyReturnTypeExpected(argsLength: Int) = argsLength match {
case 0 => BooleanClass.tpe
case 1 => optionType(WildcardType)
@@ -92,4 +94,88 @@ trait Unapplies { self: Analyzer =>
if (unapp == NoSymbol) unapp = tp.member(nme.unapplySeq)
unapp
}
+
+ private def copyUntyped[T <: Tree](tree: T): T = {
+ val tree1 = tree.duplicate
+ UnTyper.traverse(tree1)
+ tree1
+ }
+
+ private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = {
+ val tycon = gen.mkAttributedRef(cdef.symbol)
+ if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map (x => Ident(x.name)))
+ }
+
+ private def constrParams(cdef: ClassDef): List[List[ValDef]] = {
+ val constr = treeInfo.firstConstructor(cdef.impl.body)
+ (constr: @unchecked) match {
+ case DefDef(_, _, _, vparamss, _, _) => vparamss map (_ map copyUntyped[ValDef])
+ }
+ }
+
+ /** The return value of an unapply method of a case class C[Ts]
+ * @param param The name of the parameter of the unapply method, assumed to be of type C[Ts]
+ * @param caseclazz The case class C[Ts]
+ */
+ private def caseClassUnapplyReturnValue(param: Name, caseclazz: Symbol) = {
+ def caseFieldAccessorValue(selector: Symbol) = Select(Ident(param), selector)
+ val accessors = caseclazz.caseFieldAccessors
+ if (accessors.isEmpty) Literal(true)
+ else if (accessors.tail.isEmpty) caseFieldAccessorValue(accessors.head)
+ else Apply(gen.scalaDot(newTermName( "Tuple" + accessors.length)), accessors map caseFieldAccessorValue)
+ }
+
+ /** The module corresponding to a case class; without any member definitions
+ */
+ def caseModuleDef(cdef: ClassDef): ModuleDef = atPos(cdef.pos) {
+ var parents = List(gen.scalaScalaObjectConstr)
+ if (cdef.tparams.isEmpty && constrParams(cdef).length == 1)
+ parents = gen.scalaFunctionConstr(constrParams(cdef).head map (_.tpt),
+ Ident(cdef.name)) :: parents
+ ModuleDef(
+ Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin),
+ cdef.name.toTermName,
+ Template(parents, emptyValDef, Modifiers(0), List(), List(List()), List()))
+ }
+
+ /** The apply method corresponding to a case class
+ */
+ def caseModuleApplyMeth(cdef: ClassDef): DefDef = {
+ val tparams = cdef.tparams map copyUntyped[TypeDef]
+ def paramToArg(param: ValDef) = {
+ val id = Ident(param.name)
+ val RP = nme.REPEATED_PARAM_CLASS_NAME.toTypeName
+ param.tpt match {
+ case AppliedTypeTree(Select(_, RP), _) => Typed(id, Ident(nme.WILDCARD_STAR.toTypeName))
+ case _ =>id
+ }
+ }
+ val cparams = constrParams(cdef)
+ atPos(cdef.pos) {
+ DefDef(
+ Modifiers(SYNTHETIC | CASE),
+ nme.apply,
+ tparams,
+ cparams,
+ classType(cdef, tparams),
+ New(classType(cdef, tparams), cparams map (_ map paramToArg)))
+ }
+ }
+
+ /** The unapply method corresponding to a case class
+ */
+ def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = {
+ val tparams = cdef.tparams map copyUntyped[TypeDef]
+ val unapplyParamName = newTermName("x$0")
+ atPos(cdef.pos) {
+ DefDef(
+ Modifiers(SYNTHETIC | CASE),
+ nme.unapply,
+ tparams,
+ List(List(ValDef(Modifiers(PARAM | SYNTHETIC), unapplyParamName,
+ classType(cdef, tparams), EmptyTree))),
+ TypeTree(),
+ caseClassUnapplyReturnValue(unapplyParamName, cdef.symbol))
+ }
+ }
}