summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2007-11-15 15:07:48 +0000
committerIulian Dragos <jaguarul@gmail.com>2007-11-15 15:07:48 +0000
commit8fc8fb71ac8df99e06c0c64986d6b4922d902d16 (patch)
treef6ab00b047dc57d8d03f5192865e9d3026d1706f /src/compiler
parentac791fa286be5496dc1f54c8bfaa46ece48b0ddd (diff)
downloadscala-8fc8fb71ac8df99e06c0c64986d6b4922d902d16.tar.gz
scala-8fc8fb71ac8df99e06c0c64986d6b4922d902d16.tar.bz2
scala-8fc8fb71ac8df99e06c0c64986d6b4922d902d16.zip
Fixed ticket #206
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala30
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala34
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala12
3 files changed, 57 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index 74fa713430..eeddb24124 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -69,7 +69,10 @@ abstract class LazyVals extends Transform {
* {
* l$ = <rhs>
* l$
- * }
+ * } or
+ * <rhs> when the lazy value has type Unit (for which there is no field
+ * to cache it's value.
+ *
* The result will be a tree of the form
* {
* if ((bitmap$n & MASK) == 0) {
@@ -79,19 +82,36 @@ abstract class LazyVals extends Transform {
* l$
* }
* where bitmap$n is an int value acting as a bitmap of initialized values. It is
- * the 'n' is (offset / 32), the MASK is (1 << (offset % 32)).
+ * the 'n' is (offset / 32), the MASK is (1 << (offset % 32)). If the value has type
+ * unit, no field is used to chache the value, so the resulting code is:
+ * {
+ * if ((bitmap$n & MASK) == 0) {
+ * <rhs>;
+ * bitmap$n = bimap$n | MASK
+ * }
+ * ()
+ * }
*/
private def mkLazyDef(meth: Symbol, tree: Tree, offset: Int): Tree = {
val bitmapSym = getBitmapFor(meth, offset)
- val Block(List(assignment), res) = tree
val mask = Literal(Constant(1 << (offset % FLAGS_PER_WORD)))
- val result =
+
+ val (block, res) = tree match {
+ case Block(List(assignment), res) =>
+ (Block(List(assignment, mkSetFlag(bitmapSym, mask)), Literal(Constant(()))), res)
+ case rhs =>
+ assert(meth.tpe.finalResultType.typeSymbol == definitions.UnitClass)
+ (Block(List(rhs, mkSetFlag(bitmapSym, mask)), Literal(Constant(()))), Literal(()))
+ }
+
+ val result = atPos(tree.pos) {
If(Apply(
Select(
Apply(Select(Ident(bitmapSym), Int_And),
List(mask)),
Int_==),
- List(Literal(Constant(0)))), Block(List(assignment, mkSetFlag(bitmapSym, mask)), Literal(Constant(()))), EmptyTree)
+ List(Literal(Constant(0)))), block, EmptyTree)
+ }
typed(Block(List(result), res))
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 15197d3f9f..a73b2f1662 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -240,6 +240,10 @@ abstract class Mixin extends InfoTransform {
case MethodType(List(), ConstantType(_)) =>
// member is a constant; only getter is needed
;
+ case MethodType(List(), TypeRef(_, tpeSym, _))
+ if member.hasFlag(LAZY) && tpeSym == definitions.UnitClass =>
+ // member is a lazy value of type unit. No field needed
+ ;
case _ =>
// otherwise mixin a field as well
addMember(clazz,
@@ -533,7 +537,7 @@ abstract class Mixin extends InfoTransform {
* where bitmap$n is an int value acting as a bitmap of initialized values. It is
* the 'n' is (offset / 32), the MASK is (1 << (offset % 32)).
*/
- def mkLazyDef(clazz: Symbol, init: Tree, fieldSym: Symbol, offset: Int): Tree = {
+ def mkLazyDef(clazz: Symbol, init: Tree, retVal: Tree, offset: Int): Tree = {
/** Return the bitmap field for 'offset', create one if not inheriting it already. */
def bitmapFor(offset: Int): Symbol = {
@@ -571,17 +575,21 @@ abstract class Mixin extends InfoTransform {
Literal(Constant(()))),
EmptyTree)),
EmptyTree)
- localTyper.typed(Block(List(result), Select(This(clazz), fieldSym)))
+ localTyper.typed(atPos(init.pos)(Block(List(result), retVal)))
}
/** Complete lazy field accessors. Applies only to classes, for it's own (non inherited) lazy fields. */
def lazifyOwnFields(clazz: Symbol, stats: List[Tree]): List[Tree] = {
- var offset = clazz.info.findMember(nme.ANYNAME, METHOD, LAZY, false).alternatives.filter(_.owner != clazz).length
+ var offset = clazz.info.findMember(nme.ANYNAME, 0, METHOD | LAZY, false).alternatives.filter(_.owner != clazz).length
val stats1 = for (stat <- stats; sym = stat.symbol) yield stat match {
case DefDef(mods, name, tp, vp, tpt, rhs)
if sym.hasFlag(LAZY) && rhs != EmptyTree && !clazz.isImplClass =>
- val Block(List(assignment), res) = rhs
- val rhs1 = mkLazyDef(clazz, assignment, res.symbol, offset)
+ val rhs1 = if (sym.tpe.resultType.typeSymbol == definitions.UnitClass)
+ mkLazyDef(clazz, rhs, Literal(()), offset)
+ else {
+ val Block(List(assignment), res) = rhs
+ mkLazyDef(clazz, assignment, Select(This(clazz), res.symbol), offset)
+ }
offset += 1
copy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)
case _ => stat
@@ -591,7 +599,7 @@ abstract class Mixin extends InfoTransform {
// the number of inherited lazy fields that are not mixed in
- offset = (clazz.info.findMember(nme.ANYNAME, METHOD, LAZY, false)
+ offset = (clazz.info.findMember(nme.ANYNAME, 0, METHOD | LAZY, false)
.alternatives filter { f => f.owner != clazz || !f.hasFlag(MIXEDIN)}).length
// begin addNewDefs
var stats1 = lazifyOwnFields(clazz, stats)
@@ -613,11 +621,15 @@ abstract class Mixin extends InfoTransform {
case _ =>
// if it is a mixed-in lazy value, complete the accessor
if (sym.hasFlag(LAZY) && sym.isGetter) {
- val assign =
- Assign(Select(This(sym.accessed.owner), sym.accessed) /*gen.mkAttributedRef(sym.accessed)*/,
- Apply(staticRef(initializer(sym)), gen.mkAttributedThis(clazz) :: Nil))
-
- val rhs1 = mkLazyDef(clazz, assign, sym.accessed, offset)
+ val rhs1 = if (sym.tpe.resultType.typeSymbol == definitions.UnitClass)
+ mkLazyDef(clazz, Apply(staticRef(initializer(sym)), List(gen.mkAttributedThis(clazz))), Literal(()), offset)
+ else {
+ val assign = atPos(sym.pos) {
+ Assign(Select(This(sym.accessed.owner), sym.accessed) /*gen.mkAttributedRef(sym.accessed)*/,
+ Apply(staticRef(initializer(sym)), gen.mkAttributedThis(clazz) :: Nil))
+ }
+ mkLazyDef(clazz, assign, Select(This(clazz), sym.accessed), offset)
+ }
offset += 1
rhs1
} else
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index ffecaf5a39..1eae1b9389 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -587,7 +587,8 @@ abstract class RefChecks extends InfoTransform {
}
/** Implements lazy value accessors:
- * - for lazy fields inside traits, the rhs is the initializer itself
+ * - for lazy values of type Unit and all lazy fields inside traits,
+ * the rhs is the initializer itself
* - for all other lazy values z the accessor is a block of this form:
* { z = <rhs>; z } where z can be an identifier or a field.
*/
@@ -666,17 +667,22 @@ abstract class RefChecks extends InfoTransform {
if (tree.symbol.hasFlag(LAZY)) {
assert(tree.symbol.isTerm, tree.symbol)
val vsym = tree.symbol
+ val hasUnitType = (tree.symbol.tpe.typeSymbol == definitions.UnitClass)
val lazyDefSym = vsym.lazyAccessor
assert(lazyDefSym != NoSymbol, vsym)
val ownerTransformer = new ChangeOwnerTraverser(vsym, lazyDefSym)
val lazyDef = atPos(tree.pos)(
DefDef(lazyDefSym, vparamss => ownerTransformer(
- if (tree.symbol.owner.isTrait) rhs // for traits, this is further tranformed in mixins
+ if (tree.symbol.owner.isTrait // for traits, this is further tranformed in mixins
+ || hasUnitType) rhs
else Block(List(
Assign(gen.mkAttributedRef(vsym), rhs)),
gen.mkAttributedRef(vsym)))))
log("Made lazy def: " + lazyDef)
- typed(ValDef(vsym, EmptyTree)) :: typed(lazyDef) :: Nil
+ if (hasUnitType)
+ typed(lazyDef) :: Nil
+ else
+ typed(ValDef(vsym, EmptyTree)) :: typed(lazyDef) :: Nil
} else {
if (tree.symbol.isLocal && index <= currentLevel.maxindex && !tree.symbol.hasFlag(LAZY)) {
if (settings.debug.value) Console.println(currentLevel.refsym);