@@ -49,7 +49,7 @@ class Objects {
49
49
case class ObjectRef (klass : ClassSymbol ) extends Addr
50
50
51
51
/** An ClassAbs of class */
52
- case class ClassAbs (klass : ClassSymbol ) extends Addr
52
+ case class ClassAbs (klass : ClassSymbol , outer : Value ) extends Addr
53
53
54
54
/** A function value */
55
55
case class Fun (expr : Tree , thisV : Value , klass : ClassSymbol ) extends Value
@@ -68,7 +68,7 @@ class Objects {
68
68
*
69
69
* Note: Object is NOT a value.
70
70
*/
71
- case class Objekt (klass : ClassSymbol , fields : mutable.Map [Symbol , Value ])
71
+ case class Objekt (klass : ClassSymbol , fields : mutable.Map [Symbol , Value ], outers : mutable. Map [ Symbol , Value ] )
72
72
73
73
/** Abstract heap stores abstract objects
74
74
*
@@ -93,7 +93,8 @@ class Objects {
93
93
def updateField (field : Symbol , value : Value ): Contextual [Unit ] =
94
94
heap(ref).fields(field) = value
95
95
96
- def updateOuter (klass : ClassSymbol , value : Value ): Contextual [Unit ] = ()
96
+ def updateOuter (klass : ClassSymbol , value : Value ): Contextual [Unit ] =
97
+ heap(ref).outers(klass) = value
97
98
end extension
98
99
}
99
100
type Heap = Heap .Heap
@@ -192,6 +193,11 @@ class Objects {
192
193
case (RefSet (refs), b) => RefSet (b :: refs)
193
194
case (a, b) => RefSet (a :: b :: Nil )
194
195
196
+ def widen (using Context ): Value = a.match
197
+ case RefSet (refs) => refs.map(_.widen).join
198
+ case ClassAbs (klass, outer : ClassAbs ) => ClassAbs (klass, TypeAbs (outer.klass.typeRef))
199
+ case _ => a
200
+
195
201
extension (values : Seq [Value ])
196
202
def join : Value =
197
203
if values.isEmpty then Bottom
@@ -227,7 +233,7 @@ class Objects {
227
233
eval(rhs, addr, target.owner.asClass, cacheResult = true )
228
234
else
229
235
given Trace = trace1
230
- val obj = if heap.contains(addr) then heap(addr) else Objekt (addr.klass, mutable.Map .empty)
236
+ val obj = if heap.contains(addr) then heap(addr) else Objekt (addr.klass, mutable.Map .empty, mutable. Map .empty )
231
237
if obj.fields.contains(target) then
232
238
Result (obj.fields(target), Nil )
233
239
else if target.is(Flags .ParamAccessor ) then
@@ -318,14 +324,15 @@ class Objects {
318
324
319
325
case Bottom | _ : TypeAbs | _ : ClassAbs | _ : ObjectRef =>
320
326
given Trace = trace1
327
+ val outer = value.widen
321
328
val addr =
322
329
if klass.isStaticObjectRef then
323
330
ObjectRef (klass)
324
331
else
325
- ClassAbs (klass)
332
+ ClassAbs (klass, outer )
326
333
327
334
if ! heap.contains(addr) then
328
- val obj = Objekt (klass, fields = mutable.Map .empty)
335
+ val obj = Objekt (klass, fields = mutable.Map .empty, outers = mutable. Map (klass -> outer) )
329
336
heap.update(addr, obj)
330
337
331
338
val res = addr.call(ctor, args, superType = NoType , source)
@@ -658,7 +665,26 @@ class Objects {
658
665
val res = Result (ObjectRef (target.moduleClass.asClass), Nil )
659
666
if target == klass || elideObjectAccess then res
660
667
else res.ensureAccess(klass, source)
661
- else Result (TypeAbs (target.typeRef), Nil )
668
+ else
669
+ thisV match
670
+ case Bottom => Result (Bottom , Nil )
671
+ case addr : Addr =>
672
+ val obj = heap(addr)
673
+ val outerCls = klass.owner.enclosingClass.asClass
674
+ if ! obj.outers.contains(klass) then
675
+ val error = PromoteError (" outer not yet initialized, target = " + target + " , klass = " + klass, source, trace.toVector)
676
+ report.error(error.show + error.stacktrace, source)
677
+ Result (Bottom , Nil )
678
+ else
679
+ resolveThis(target, obj.outers(klass), outerCls, source)
680
+ case RefSet (refs) =>
681
+ val ress = refs.map(ref => resolveThis(target, ref, klass, source))
682
+ Result (ress.map(_.value).join, ress.flatMap(_.errors))
683
+ case fun : Fun =>
684
+ report.warning(" unexpected thisV = " + thisV + " , target = " + target.show + " , klass = " + klass.show, source.srcPos)
685
+ Result (TypeAbs (defn.AnyType ), Nil )
686
+ case TypeAbs (tp) =>
687
+ Result (TypeAbs (target.info), Nil )
662
688
}
663
689
664
690
/** Compute the outer value that correspond to `tref.prefix` */
0 commit comments