From d7de71e9d31dae56b5afc62e3777fa03112ee1e1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Dec 2010 05:53:25 +0000 Subject: delayed init now supported --- .../scala/tools/nsc/symtab/Definitions.scala | 8 +- src/compiler/scala/tools/nsc/symtab/StdNames.scala | 3 + src/compiler/scala/tools/nsc/symtab/Symbols.scala | 10 +++ .../scala/tools/nsc/transform/Constructors.scala | 90 +++++++++++++++++++++- src/library/scala/package.scala | 23 ++++++ src/library/scala/reflect/generic/StdNames.scala | 2 +- 6 files changed, 130 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index da4b5a83da..db757a66f5 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -169,7 +169,13 @@ trait Definitions extends reflect.generic.StandardDefinitions { def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements) // classes with special meanings - lazy val NotNullClass = getClass("scala.NotNull") + lazy val NotNullClass = getClass("scala.NotNull") + lazy val DelayedInitClass = getClass("scala.DelayedInit") + def delayedInitMethod = getMember(DelayedInitClass, nme.delayedInit) + // a dummy value that communicates that a delayedInit call is compiler-generated + // from phase UnCurry to phase Constructors + def delayedInitArgVal = EmptyPackageClass.newValue(NoPosition, nme.delayedInitArg) + .setInfo(UnitClass.tpe) lazy val TypeConstraintClass = getClass("scala.TypeConstraint") lazy val SingletonClass = newClass(ScalaPackageClass, nme.Singleton, anyparam) setFlag (ABSTRACT | TRAIT | FINAL) lazy val SerializableClass = getClass("scala.Serializable") diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index 64dc254f28..e3a23b2b43 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -12,6 +12,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers { self: SymbolTable => object nme extends StandardNames with NameMangling { + /** Translate a String into a list of simple TypeNames and TermNames. * In all segments before the last, type/term is determined by whether * the following separator char is '.' or '#'. In the last segment, @@ -222,6 +223,8 @@ trait StdNames extends reflect.generic.StdNames with NameManglers { val identity = newTermName("identity") val conforms = newTermName("conforms") val copy = newTermName("copy") + val delayedInit = newTermName("delayedInit") + val delayedInitArg = newTermName("delayedInit$body") val dottype = newTermName(".type") val drop = newTermName("drop") val elem = newTermName("elem") diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 824d047d6b..31992c5d0b 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -523,6 +523,10 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable => isClass && (isAnonymousClass || isRefinementClass || isLocal || !owner.isPackageClass && owner.isLocalClass) +/* code for fixing nested objects + override final def isModuleClass: Boolean = + super.isModuleClass && !isExpandedModuleClass +*/ /** Is this class or type defined as a structural refinement type? */ final def isStructuralRefinement: Boolean = @@ -1451,7 +1455,13 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable => if (isType) name = name.toTypeName } } +/* code for fixing nested objects + def expandModuleClassName() { + name = newTypeName(name.toString + "$") + } + def isExpandedModuleClass: Boolean = name(name.length - 1) == '$' +*/ def sourceFile: AbstractFile = (if (isModule) moduleClass else toplevelClass).sourceFile diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index ed479763e5..091e10c170 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -155,7 +155,8 @@ abstract class Constructors extends Transform with ast.TreeDSL { // The list of statements that go into constructor after superclass constructor call val constrStatBuf = new ListBuffer[Tree] - // The list of statements that go into constructor before superclass constructor call + // The list of statements that go into constructor before and including the + // superclass constructor call val constrPrefixBuf = new ListBuffer[Tree] // The early initialized field definitions of the class (these are the class members) @@ -163,14 +164,14 @@ abstract class Constructors extends Transform with ast.TreeDSL { // generate code to copy pre-initialized fields for (stat <- constrBody.stats) { - constrStatBuf += stat + constrPrefixBuf += stat stat match { case ValDef(mods, name, _, _) if (mods hasFlag PRESUPER) => // stat is the constructor-local definition of the field value val fields = presupers filter ( vdef => nme.localToGetter(vdef.name) == name) assert(fields.length == 1) - constrStatBuf += mkAssign(fields.head.symbol, Ident(stat.symbol)) + constrPrefixBuf += mkAssign(fields.head.symbol, Ident(stat.symbol)) case _ => } } @@ -404,12 +405,87 @@ abstract class Constructors extends Transform with ast.TreeDSL { } else stats0 } + def isInitDef(stat: Tree) = stat match { + case dd: DefDef => dd.symbol == delayedInitMethod + case _ => false + } + + def delayedInitClosure(stats: List[Tree]) = + localTyper.typed { + atPos(impl.pos) { + val closureClass = clazz.newClass(impl.pos, nme.delayedInitArg.toTypeName) + .setFlag(SYNTHETIC | FINAL) + val closureParents = List(AbstractFunctionClass(0).tpe, ScalaObjectClass.tpe) + closureClass.setInfo(new ClassInfoType(closureParents, new Scope, closureClass)) + + val outerField = clazz.newValue(impl.pos, nme.OUTER) + .setFlag(PRIVATE | LOCAL) + .setInfo(clazz.tpe) + + val applyMethod = closureClass.newMethod(impl.pos, nme.apply) + .setFlag(FINAL) + .setInfo(MethodType(List(), ObjectClass.tpe)) + + closureClass.info.decls enter outerField + closureClass.info.decls enter applyMethod + + val outerFieldDef = ValDef(outerField) + + val changeOwner = new ChangeOwnerTraverser(impl.symbol, applyMethod) + val constrStatTransformer = new Transformer { + override def transform(tree: Tree): Tree = tree match { + case This(`clazz`) => + localTyper.typed { + atPos(tree.pos) { + Select(This(closureClass), outerField) + } + } + case _ => + changeOwner traverse tree + tree + } + } + + def applyMethodStats = constrStatTransformer.transformTrees(stats) + + val applyMethodDef = DefDef( + sym = applyMethod, + vparamss = List(List()), + rhs = Block(applyMethodStats, gen.mkAttributedRef(BoxedUnit_UNIT))) + + util.trace("delayedInit: ") { ClassDef( + sym = closureClass, + constrMods = Modifiers(0), + vparamss = List(List(outerFieldDef)), + argss = List(List()), + body = List(outerFieldDef, applyMethodDef), + superPos = impl.pos) + }} + } + + def delayedInitCall(closure: Tree) = + localTyper.typed { + atPos(impl.pos) { + Apply( + Select(This(clazz), delayedInitMethod), + List(New(TypeTree(closure.symbol.tpe), List(List(This(clazz)))))) + } + } + + val needsDelayedInit = + false && (clazz isSubClass DelayedInitClass) && !(defBuf exists isInitDef) && constrStatBuf.nonEmpty + + var constrStats = constrStatBuf.toList + if (needsDelayedInit) { + constrStats = List(delayedInitCall(delayedInitClosure(constrStats))) + } + // Assemble final constructor defBuf += treeCopy.DefDef( constr, constr.mods, constr.name, constr.tparams, constr.vparamss, constr.tpt, treeCopy.Block( constrBody, - paramInits ::: constrPrefixBuf.toList ::: guardSpecializedInitializer(constrStatBuf.toList), + paramInits ::: constrPrefixBuf.toList ::: guardSpecializedInitializer(constrStats), constrBody.expr)); // Followed by any auxiliary constructors @@ -424,6 +500,12 @@ abstract class Constructors extends Transform with ast.TreeDSL { defBuf.toList filter (stat => mustbeKept(stat.symbol))) } // transformClassTemplate + def hasDelayedInit(clazz: Symbol) = false && + (clazz isSubClass DelayedInitClass) && + (clazz.info.decls lookup nme.delayedInit) == NoSymbol + + def delayedInitCall(stats: List[Tree]): Tree = null + override def transform(tree: Tree): Tree = tree match { case ClassDef(mods, name, tparams, impl) if !tree.symbol.isInterface => diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index 86efe7c379..a6b974b4d3 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -102,6 +102,23 @@ package object scala { type PartialOrdering[T] = scala.math.PartialOrdering[T] type PartiallyOrdered[T] = scala.math.PartiallyOrdered[T] + // Annotations which we might move to annotation.* +/* + type SerialVersionUID = annotation.SerialVersionUID + type cloneable = annotation.cloneable + type deprecated = annotation.deprecated + type deprecatedName = annotation.deprecatedName + type inline = annotation.inline + type native = annotation.native + type noinline = noannotation.inline + type remote = annotation.remote + type serializable = annotation.serializable + type specialized = annotation.specialized + type transient = annotation.transient + type throws = annotation.throws + type unchecked = annotation.unchecked.unchecked + type volatile = annotation.volatile + */ @deprecated("Use Tuple1(x) to create a 1-tuple.") def Tuple[A1](x1: A1) = Tuple1(x1) @deprecated("Use ((x1, x2, ...)) syntax to create Tuples") @@ -160,4 +177,10 @@ package object scala { @deprecated("use IndexedSeq instead") type RandomAccessSeq[+A] = scala.collection.IndexedSeq[A] @deprecated("use IndexedSeq instead") val RandomAccessSeq = scala.collection.IndexedSeq +/* the following classes should be moved to annotation and the aliases should be enabled + @deprecated("use annotation.Annotation instead") type Annotation = annotation.Annotation + @deprecated("use annotation.ClassfileAnnotation instead") type ClassfileAnnotation = annotation.Annotation + @deprecated("use annotation.StaticAnnotation instead") type StaticAnnotation = annotation.Annotation + @deprecated("use annotation.TypeConstraint instead") type TypeConstraint = annotation.TypeConstraint +*/ } diff --git a/src/library/scala/reflect/generic/StdNames.scala b/src/library/scala/reflect/generic/StdNames.scala index f6f89c9100..7d2e0fde6a 100755 --- a/src/library/scala/reflect/generic/StdNames.scala +++ b/src/library/scala/reflect/generic/StdNames.scala @@ -30,6 +30,6 @@ trait StdNames { self: Universe => newTermName(base.fullName('$') + separator + name) def moduleVarName(name: Name): Name = - newTermName(name.toString() + MODULE_SUFFIX) + newTermName(name.toString + MODULE_SUFFIX) } } -- cgit v1.2.3