@@ -11,6 +11,7 @@ import NameKinds.OuterSelectName
11
11
import NameKinds .SuperAccessorName
12
12
13
13
import ast .tpd .*
14
+ import util .SourcePosition
14
15
import config .Printers .init as printer
15
16
import reporting .StoreReporter
16
17
import reporting .trace as log
@@ -122,30 +123,34 @@ object Objects:
122
123
/**
123
124
* Rerepsents values that are instances of the specified class.
124
125
*
126
+ * For immutable classes (classes without mutable fields, non-transitive), the parameter regions
127
+ * is always empty and `owner` is `NoSymbol`.
128
+ *
125
129
* Note that the 2nd parameter block does not take part in the definition of equality.
126
130
*/
127
- case class OfClass private (klass : ClassSymbol , outer : Value , ctor : Symbol , args : List [Value ], env : Env .Data )
128
- (valsMap : mutable.Map [Symbol , Value ], varsMap : mutable.Map [Symbol , Heap .Addr ], outersMap : mutable.Map [ClassSymbol , Value ])
131
+ case class OfClass private (
132
+ klass : ClassSymbol , outer : Value , ctor : Symbol , args : List [Value ], env : Env .Data ,
133
+ regions : Regions .Data , owner : Symbol )(
134
+ valsMap : mutable.Map [Symbol , Value ], varsMap : mutable.Map [Symbol , Heap .Addr ], outersMap : mutable.Map [ClassSymbol , Value ])
129
135
extends Ref (valsMap, varsMap, outersMap):
130
136
def widenedCopy (outer : Value , args : List [Value ], env : Env .Data ): OfClass =
131
- new OfClass (klass, outer, ctor, args, env)(this .valsMap, this .varsMap, outersMap)
137
+ new OfClass (klass, outer, ctor, args, env, regions, owner )(this .valsMap, this .varsMap, outersMap)
132
138
133
139
def show (using Context ) =
134
140
val valFields = vals.map(_.show + " -> " + _.show)
135
141
" OfClass(" + klass.show + " , outer = " + outer + " , args = " + args.map(_.show) + " , vals = " + valFields + " )"
136
142
137
143
object OfClass :
138
144
def apply (
139
- klass : ClassSymbol , outer : Value , ctor : Symbol , args : List [Value ], env : Env .Data )(
145
+ klass : ClassSymbol , outer : Value , ctor : Symbol , args : List [Value ], env : Env .Data , regions : Regions . Data , owner : Symbol )(
140
146
using Context
141
147
): OfClass =
142
- val instance = new OfClass (klass, outer, ctor, args, env)(
148
+ val instance = new OfClass (klass, outer, ctor, args, env, regions, owner )(
143
149
valsMap = mutable.Map .empty, varsMap = mutable.Map .empty, outersMap = mutable.Map .empty
144
150
)
145
151
instance.initOuter(klass, outer)
146
152
instance
147
153
148
-
149
154
/**
150
155
* Rerepsents arrays.
151
156
*
@@ -468,9 +473,20 @@ object Objects:
468
473
result.value
469
474
end Cache
470
475
476
+ /**
477
+ * Region context for mutable states
478
+ *
479
+ * By default, the region context is empty.
480
+ */
481
+ object Regions :
482
+ opaque type Data = List [SourcePosition ]
483
+ val empty : Data = Nil
484
+ def extend (pos : SourcePosition )(using data : Data ): Data = pos :: data
485
+ def exists (pos : SourcePosition )(using data : Data ): Data = data.indexOf(pos) >= 0
486
+
471
487
inline def cache (using c : Cache .Data ): Cache .Data = c
472
488
473
- type Contextual [T ] = (Context , State .Data , Env .Data , Cache .Data , Heap .MutableData , Trace ) ?=> T
489
+ type Contextual [T ] = (Context , State .Data , Env .Data , Cache .Data , Heap .MutableData , Regions . Data , Trace ) ?=> T
474
490
475
491
// --------------------------- domain operations -----------------------------
476
492
@@ -499,7 +515,7 @@ object Objects:
499
515
if height == 0 then Cold
500
516
else Fun (code, thisV.widen(height), klass, env.widen(height))
501
517
502
- case ref @ OfClass (klass, outer, init , args, env) =>
518
+ case ref @ OfClass (klass, outer, _ , args, env, _, _ ) =>
503
519
if height == 0 then
504
520
Cold
505
521
else
@@ -731,7 +747,11 @@ object Objects:
731
747
// klass.enclosingMethod returns its primary constructor
732
748
Env .resolveEnv(klass.owner.enclosingMethod, outer, summon[Env .Data ]).getOrElse(Cold -> Env .NoEnv )
733
749
734
- val instance = OfClass (klass, outerWidened, ctor, args.map(_.value), envWidened)
750
+ // Immutable objects do not care about owners and context
751
+ val owner = if isMutable(klass) then State .currentObject else NoSymbol
752
+ val regions = if isMutable(klass) then summon[Regions .Data ] else Regions .empty
753
+
754
+ val instance = OfClass (klass, outerWidened, ctor, args.map(_.value), envWidened, regions, owner)
735
755
callConstructor(instance, ctor, args)
736
756
instance
737
757
0 commit comments