@@ -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
@@ -699,7 +700,8 @@ class Objects {
699
700
700
701
val paramsMap = tpl.constr.termParamss.flatten.map(vdef => vdef.name -> vdef.symbol).toMap
701
702
702
- def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree ): Unit =
703
+ type Handler = (() => Unit ) => Unit
704
+ def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree , handler : Handler ): Unit =
703
705
val cls = tref.classSymbol.asClass
704
706
// update outer for super class
705
707
val res = outerValue(tref, thisV, klass, source)
@@ -708,53 +710,57 @@ class Objects {
708
710
709
711
// follow constructor
710
712
if cls.hasSource then
711
- use(trace.add(source)) {
712
- val res2 = thisV.call(ctor, args, superType = NoType , source)
713
- errorBuffer ++= res2.errors
713
+ handler { () =>
714
+ use(trace.add(source)) {
715
+ val res2 = thisV.call(ctor, args, superType = NoType , source)
716
+ errorBuffer ++= res2.errors
717
+ }
714
718
}
719
+ else
720
+ handler { () => () }
715
721
716
722
// parents
717
- def initParent (parent : Tree ) = parent match {
723
+ def initParent (parent : Tree , handler : Handler ) = parent match {
718
724
case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
719
725
eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
720
726
val resArgs = evalArgs(argss.flatten, thisV, klass)
721
727
val argsValues = resArgs.map(_.value)
722
728
val argsErrors = resArgs.flatMap(_.errors)
723
729
724
730
errorBuffer ++= argsErrors
725
- superCall(tref, ctor, argsValues, tree)
731
+ superCall(tref, ctor, argsValues, tree, handler )
726
732
727
733
case tree @ NewExpr (tref, New (tpt), ctor, argss) => // extends A(args)
728
734
val resArgs = evalArgs(argss.flatten, thisV, klass)
729
735
val argsValues = resArgs.map(_.value)
730
736
val argsErrors = resArgs.flatMap(_.errors)
731
737
732
738
errorBuffer ++= argsErrors
733
- superCall(tref, ctor, argsValues, tree)
739
+ superCall(tref, ctor, argsValues, tree, handler )
734
740
735
741
case _ => // extends A or extends A[T]
736
742
val tref = typeRefOf(parent.tpe)
737
- superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent)
743
+ superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent, handler )
738
744
}
739
745
740
746
// see spec 5.1 about "Template Evaluation".
741
747
// https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
742
748
if ! klass.is(Flags .Trait ) then
749
+ // outers are set first
750
+ val tasks = new mutable.ArrayBuffer [() => Unit ]
751
+ val handler : Handler = task => tasks.append(task)
752
+
743
753
// 1. first init parent class recursively
744
754
// 2. initialize traits according to linearization order
745
755
val superParent = tpl.parents.head
746
756
val superCls = superParent.tpe.classSymbol.asClass
747
- initParent(superParent)
748
-
749
- // Access to the object possible after this point
750
- if klass.isStaticOwner then
751
- thisV.updateField(klass, thisV)
757
+ initParent(superParent, handler)
752
758
753
759
val parents = tpl.parents.tail
754
760
val mixins = klass.baseClasses.tail.takeWhile(_ != superCls)
755
761
mixins.reverse.foreach { mixin =>
756
762
parents.find(_.tpe.classSymbol == mixin) match
757
- case Some (parent) => initParent(parent)
763
+ case Some (parent) => initParent(parent, handler )
758
764
case None =>
759
765
// According to the language spec, if the mixin trait requires
760
766
// arguments, then the class must provide arguments to it explicitly
@@ -765,9 +771,21 @@ class Objects {
765
771
// term arguments to B. That can only be done in a concrete class.
766
772
val tref = typeRefOf(klass.typeRef.baseType(mixin).typeConstructor)
767
773
val ctor = tref.classSymbol.primaryConstructor
768
- if ctor.exists then superCall(tref, ctor, Nil , superParent)
774
+ if ctor.exists then superCall(tref, ctor, Nil , superParent, handler )
769
775
}
770
776
777
+ // initialize super classes after outers are set
778
+ // 1. first call super class constructor
779
+ // 2. make the object accessible
780
+ // 3. call mixin initializations
781
+ tasks.head()
782
+
783
+ // Access to the object possible after this point
784
+ if klass.isStaticOwner then
785
+ thisV.updateField(klass, thisV)
786
+
787
+ tasks.tail.foreach(task => task())
788
+
771
789
772
790
// class body
773
791
tpl.body.foreach {
0 commit comments