@@ -135,12 +135,13 @@ class Objects {
135
135
def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [Value ], source : Tree ): Contextual [Result ] =
136
136
value.instantiate(klass, ctor, args, source) ++ errors
137
137
138
- def ensureAccess (klass : ClassSymbol , source : Tree ): Contextual [Result ] =
138
+ def ensureAccess (klass : ClassSymbol , source : Tree ): Contextual [Result ] = log( " ensure access " + value.show, printer) {
139
139
value match
140
140
case obj : ObjectRef =>
141
141
if obj.klass == klass then this
142
142
else obj.access(source) ++ errors
143
143
case _ => this
144
+ }
144
145
}
145
146
146
147
/** The state that threads through the interpreter */
@@ -233,7 +234,7 @@ class Objects {
233
234
eval(rhs, addr, target.owner.asClass, cacheResult = true )
234
235
else
235
236
given Trace = trace1
236
- val obj = if heap.contains (addr) then heap(addr) else Objekt (addr.klass, mutable. Map .empty, mutable. Map .empty )
237
+ val obj = heap(addr)
237
238
if obj.fields.contains(target) then
238
239
Result (obj.fields(target), Nil )
239
240
else if target.is(Flags .ParamAccessor ) then
@@ -658,7 +659,7 @@ class Objects {
658
659
}
659
660
660
661
/** Resolve C.this that appear in `klass` */
661
- def resolveThis (target : ClassSymbol , thisV : Value , klass : ClassSymbol , source : Tree , elideObjectAccess : Boolean = false ): Contextual [Result ] = log(" resolving " + target.show + " , this = " + thisV.show + " in " + klass.show, printer, res => res.asInstanceOf [Value ].show) {
662
+ def resolveThis (target : ClassSymbol , thisV : Value , klass : ClassSymbol , source : Tree , elideObjectAccess : Boolean = false ): Contextual [Result ] = log(" resolving " + target.show + " , this = " + thisV.show + " in " + klass.show, printer, res => res.asInstanceOf [Result ].show) {
662
663
if target == klass then Result (thisV, Nil )
663
664
else if target.is(Flags .Package ) then Result (Bottom , Nil )
664
665
else if target.isStaticObjectRef then
@@ -704,7 +705,8 @@ class Objects {
704
705
705
706
val paramsMap = tpl.constr.termParamss.flatten.map(vdef => vdef.name -> vdef.symbol).toMap
706
707
707
- def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree ): Unit =
708
+ type Handler = (() => Unit ) => Unit
709
+ def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree , handler : Handler ): Unit =
708
710
val cls = tref.classSymbol.asClass
709
711
// update outer for super class
710
712
val res = outerValue(tref, thisV, klass, source)
@@ -713,53 +715,57 @@ class Objects {
713
715
714
716
// follow constructor
715
717
if cls.hasSource then
716
- use(trace.add(source)) {
717
- val res2 = thisV.call(ctor, args, superType = NoType , source)
718
- errorBuffer ++= res2.errors
718
+ handler { () =>
719
+ use(trace.add(source)) {
720
+ val res2 = thisV.call(ctor, args, superType = NoType , source)
721
+ errorBuffer ++= res2.errors
722
+ }
719
723
}
724
+ else
725
+ handler { () => () }
720
726
721
727
// parents
722
- def initParent (parent : Tree ) = parent match {
728
+ def initParent (parent : Tree , handler : Handler ) = parent match {
723
729
case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
724
730
eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
725
731
val resArgs = evalArgs(argss.flatten, thisV, klass)
726
732
val argsValues = resArgs.map(_.value)
727
733
val argsErrors = resArgs.flatMap(_.errors)
728
734
729
735
errorBuffer ++= argsErrors
730
- superCall(tref, ctor, argsValues, tree)
736
+ superCall(tref, ctor, argsValues, tree, handler )
731
737
732
738
case tree @ NewExpr (tref, New (tpt), ctor, argss) => // extends A(args)
733
739
val resArgs = evalArgs(argss.flatten, thisV, klass)
734
740
val argsValues = resArgs.map(_.value)
735
741
val argsErrors = resArgs.flatMap(_.errors)
736
742
737
743
errorBuffer ++= argsErrors
738
- superCall(tref, ctor, argsValues, tree)
744
+ superCall(tref, ctor, argsValues, tree, handler )
739
745
740
746
case _ => // extends A or extends A[T]
741
747
val tref = typeRefOf(parent.tpe)
742
- superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent)
748
+ superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent, handler )
743
749
}
744
750
745
751
// see spec 5.1 about "Template Evaluation".
746
752
// https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
747
753
if ! klass.is(Flags .Trait ) then
754
+ // outers are set first
755
+ val tasks = new mutable.ArrayBuffer [() => Unit ]
756
+ val handler : Handler = task => tasks.append(task)
757
+
748
758
// 1. first init parent class recursively
749
759
// 2. initialize traits according to linearization order
750
760
val superParent = tpl.parents.head
751
761
val superCls = superParent.tpe.classSymbol.asClass
752
- initParent(superParent)
753
-
754
- // Access to the object possible after this point
755
- if klass.isStaticOwner then
756
- thisV.updateField(klass, thisV)
762
+ initParent(superParent, handler)
757
763
758
764
val parents = tpl.parents.tail
759
765
val mixins = klass.baseClasses.tail.takeWhile(_ != superCls)
760
766
mixins.reverse.foreach { mixin =>
761
767
parents.find(_.tpe.classSymbol == mixin) match
762
- case Some (parent) => initParent(parent)
768
+ case Some (parent) => initParent(parent, handler )
763
769
case None =>
764
770
// According to the language spec, if the mixin trait requires
765
771
// arguments, then the class must provide arguments to it explicitly
@@ -770,9 +776,21 @@ class Objects {
770
776
// term arguments to B. That can only be done in a concrete class.
771
777
val tref = typeRefOf(klass.typeRef.baseType(mixin).typeConstructor)
772
778
val ctor = tref.classSymbol.primaryConstructor
773
- if ctor.exists then superCall(tref, ctor, Nil , superParent)
779
+ if ctor.exists then superCall(tref, ctor, Nil , superParent, handler )
774
780
}
775
781
782
+ // initialize super classes after outers are set
783
+ // 1. first call super class constructor
784
+ // 2. make the object accessible
785
+ // 3. call mixin initializations
786
+ tasks.head()
787
+
788
+ // Access to the object possible after this point
789
+ if klass.isStaticOwner then
790
+ thisV.updateField(klass, thisV)
791
+
792
+ tasks.tail.foreach(task => task())
793
+
776
794
777
795
// class body
778
796
tpl.body.foreach {
0 commit comments