@@ -565,9 +565,6 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
565
565
}
566
566
}
567
567
568
- // Constant typed vals are not memoized.
569
- def memoizeValue (sym : Symbol ) = ! sym.info.resultType.isInstanceOf [ConstantType ]
570
-
571
568
/** Triage definitions and statements in this template into the following categories.
572
569
* The primary constructor is treated separately, as it is assembled in part from these pieces.
573
570
*
@@ -577,84 +574,109 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
577
574
* - `constrStats`: statements that go into the constructor after and including the superclass constructor call
578
575
* - `classInitStats`: statements that go into the class initializer
579
576
*/
580
- def triageStats = {
581
- val defBuf, auxConstructorBuf, constrPrefixBuf, constrStatBuf, classInitStatBuf = new mutable.ListBuffer [Tree ]
582
-
583
- // The early initialized field definitions of the class (these are the class members)
584
- val presupers = treeInfo.preSuperFields(stats)
585
-
586
- // generate code to copy pre-initialized fields
587
- for (stat <- primaryConstrBody.stats) {
588
- constrStatBuf += stat
589
- stat match {
590
- case ValDef (mods, name, _, _) if mods.hasFlag(PRESUPER ) =>
591
- // stat is the constructor-local definition of the field value
592
- val fields = presupers filter (_.getterName == name)
593
- assert(fields.length == 1 , s " expected exactly one field by name $name in $presupers of $clazz's early initializers " )
594
- val to = fields.head.symbol
595
-
596
- if (memoizeValue(to)) constrStatBuf += mkAssign(to, Ident (stat.symbol))
597
- case _ =>
577
+ class Triage {
578
+ private val defBuf, auxConstructorBuf, constrPrefixBuf, constrStatBuf, classInitStatBuf = new mutable.ListBuffer [Tree ]
579
+
580
+ triage()
581
+
582
+ val defs = defBuf.toList
583
+ val auxConstructors = auxConstructorBuf.toList
584
+ val constructorPrefix = constrPrefixBuf.toList
585
+ val constructorStats = constrStatBuf.toList
586
+ val classInitStats = classInitStatBuf.toList
587
+
588
+ private def triage () = {
589
+ // Constant typed vals are not memoized.
590
+ def memoizeValue (sym : Symbol ) = ! sym.info.resultType.isInstanceOf [ConstantType ]
591
+
592
+ // The early initialized field definitions of the class (these are the class members)
593
+ val presupers = treeInfo.preSuperFields(stats)
594
+
595
+ // generate code to copy pre-initialized fields
596
+ for (stat <- primaryConstrBody.stats) {
597
+ constrStatBuf += stat
598
+ stat match {
599
+ case ValDef (mods, name, _, _) if mods.hasFlag(PRESUPER ) => // TODO trait presupers
600
+ // stat is the constructor-local definition of the field value
601
+ val fields = presupers filter (_.getterName == name)
602
+ assert(fields.length == 1 , s " expected exactly one field by name $name in $presupers of $clazz's early initializers " )
603
+ val to = fields.head.symbol
604
+
605
+ if (memoizeValue(to)) constrStatBuf += mkAssign(to, Ident (stat.symbol))
606
+ case _ =>
607
+ }
598
608
}
599
- }
600
609
601
- for (stat <- stats) {
602
- val statSym = stat.symbol
603
-
604
- // Move the RHS of a ValDef to the appropriate part of the ctor.
605
- // If the val is an early initialized or a parameter accessor,
606
- // it goes before the superclass constructor call, otherwise it goes after.
607
- // A lazy val's effect is not moved to the constructor, as it is delayed.
608
- // Returns `true` when a `ValDef` is needed.
609
- def moveEffectToCtor (mods : Modifiers , rhs : Tree , assignSym : Symbol ): Unit = {
610
- val initializingRhs =
611
- if ((assignSym eq NoSymbol ) || statSym.isLazy) EmptyTree // not memoized, or effect delayed (for lazy val)
612
- else if (! mods.hasStaticFlag) intoConstructor(statSym, primaryConstr.symbol)(rhs)
613
- else rhs
614
-
615
- if (initializingRhs ne EmptyTree ) {
616
- val initPhase =
617
- if (mods hasFlag STATIC ) classInitStatBuf
618
- else if (mods hasFlag PRESUPER | PARAMACCESSOR ) constrPrefixBuf
619
- else constrStatBuf
620
-
621
- initPhase += mkAssign(assignSym, initializingRhs)
610
+ val primaryConstrSym = primaryConstr.symbol
611
+
612
+ for (stat <- stats) {
613
+ val statSym = stat.symbol
614
+
615
+ // Move the RHS of a ValDef to the appropriate part of the ctor.
616
+ // If the val is an early initialized or a parameter accessor,
617
+ // it goes before the superclass constructor call, otherwise it goes after.
618
+ // A lazy val's effect is not moved to the constructor, as it is delayed.
619
+ // Returns `true` when a `ValDef` is needed.
620
+ def moveEffectToCtor (mods : Modifiers , rhs : Tree , assignSym : Symbol ): Unit = {
621
+ val initializingRhs =
622
+ if ((assignSym eq NoSymbol ) || statSym.isLazy) EmptyTree // not memoized, or effect delayed (for lazy val)
623
+ else if (! mods.hasStaticFlag) intoConstructor(statSym, primaryConstrSym)(rhs)
624
+ else rhs
625
+
626
+ if (initializingRhs ne EmptyTree ) {
627
+ val initPhase =
628
+ if (mods hasFlag STATIC ) classInitStatBuf
629
+ else if (mods hasFlag PRESUPER | PARAMACCESSOR ) constrPrefixBuf
630
+ else constrStatBuf
631
+
632
+ initPhase += mkAssign(assignSym, initializingRhs)
633
+ }
622
634
}
623
- }
624
635
625
- stat match {
626
- // recurse on class definition, store in defBuf
627
- case _ : ClassDef if ! stat.symbol.isInterface => defBuf += new ConstructorTransformer (unit).transform(stat)
628
-
629
- // Triage methods -- they all end up in the template --
630
- // regular ones go to `defBuf`, secondary contructors go to `auxConstructorBuf`.
631
- // The primary constructor is dealt with separately (we're massaging it here).
632
- case _ : DefDef if statSym.isPrimaryConstructor || statSym.isMixinConstructor => ()
633
- case _ : DefDef if statSym.isConstructor => auxConstructorBuf += stat
634
- case _ : DefDef => defBuf += stat
635
-
636
- // If a val needs a field, an empty valdef goes into the template.
637
- // Except for lazy and ConstantTyped vals, the field is initialized by an assignment in:
638
- // - the class initializer (static),
639
- // - the constructor, before the super call (early initialized or a parameter accessor),
640
- // - the constructor, after the super call (regular val).
641
- case ValDef (mods, _, _, rhs) =>
642
- if (rhs ne EmptyTree ) {
643
- val emitField = memoizeValue(statSym)
644
- moveEffectToCtor(mods, rhs, if (emitField) statSym else NoSymbol )
645
- if (emitField) defBuf += deriveValDef(stat)(_ => EmptyTree )
646
- } else defBuf += stat
647
-
648
- // all other statements go into the constructor
649
- case _ => constrStatBuf += intoConstructor(impl.symbol, primaryConstr.symbol)(stat)
636
+ stat match {
637
+ // recurse on class definition, store in defBuf
638
+ case _ : ClassDef if ! statSym.isInterface =>
639
+ defBuf += new ConstructorTransformer (unit).transform(stat)
640
+
641
+ // primary constructor is already tracked as `primaryConstr`
642
+ // non-primary constructors go to auxConstructorBuf
643
+ // mixin constructors are suppressed (!?!?)
644
+ case _ : DefDef if statSym.isConstructor =>
645
+ if ((statSym ne primaryConstrSym) && ! statSym.isMixinConstructor) auxConstructorBuf += stat
646
+
647
+ // If a val needs a field, an empty valdef goes into the template.
648
+ // Except for lazy and ConstantTyped vals, the field is initialized by an assignment in:
649
+ // - the class initializer (static),
650
+ // - the constructor, before the super call (early initialized or a parameter accessor),
651
+ // - the constructor, after the super call (regular val).
652
+ case vd : ValDef =>
653
+ if (vd.rhs eq EmptyTree ) { defBuf += vd }
654
+ else {
655
+ val emitField = memoizeValue(statSym)
656
+
657
+ val assignSym = if (! emitField) NoSymbol else statSym
658
+ moveEffectToCtor(vd.mods, vd.rhs, assignSym)
659
+
660
+ if (emitField) defBuf += deriveValDef(stat)(_ => EmptyTree )
661
+ }
662
+
663
+ case dd : DefDef =>
664
+ def traitMemoizedFieldAccessor = clazz.isTrait && statSym.isAccessor && memoizeValue(statSym.accessed)
665
+
666
+ if ((dd.rhs eq EmptyTree ) || ! traitMemoizedFieldAccessor) { defBuf += dd }
667
+ else defBuf += deriveDefDef(stat)(_ => EmptyTree )
668
+
669
+
670
+ // all other statements go into the constructor
671
+ case _ =>
672
+ constrStatBuf += intoConstructor(impl.symbol, primaryConstrSym)(stat)
673
+ }
650
674
}
651
675
}
652
-
653
- (defBuf.toList, auxConstructorBuf.toList, constrPrefixBuf.toList, constrStatBuf.toList, classInitStatBuf.toList)
654
676
}
655
677
656
678
def transformed = {
657
- val (defs, auxConstructors, constructorPrefix, constructorStats, classInitStats) = triageStats
679
+ val triage = new Triage ; import triage . _
658
680
659
681
// omit unused outers
660
682
val omittableAccessor : Set [Symbol ] =
0 commit comments