@@ -105,11 +105,46 @@ class Semantic {
105
105
*
106
106
* This is only one object we need to care about, hence it's just `Objekt`.
107
107
*/
108
- type Heap = mutable.Map [Addr , Objekt ]
108
+ object Heap {
109
+ opaque type Heap = mutable.Map [Addr , Objekt ]
110
+
111
+ /** Note: don't use `val` to avoid incorrect sharing */
112
+ def empty : Heap = mutable.Map .empty
113
+
114
+ extension (heap : Heap )
115
+ def apply (addr : Addr ): Objekt = heap(addr)
116
+ def add (addr : Addr , obj : Objekt ): Unit = heap(addr) = obj
117
+ end extension
118
+
119
+ extension (ref : Addr )
120
+ def updateField (field : Symbol , value : Value ): Contextual [Unit ] =
121
+ heap(ref).fields(field) = value
122
+
123
+ def updateOuter (klass : ClassSymbol , value : Value ): Contextual [Unit ] =
124
+ heap(ref).outers(klass) = value
125
+ end extension
126
+ }
127
+ type Heap = Heap .Heap
128
+
129
+ import Heap ._
109
130
def heap (using h : Heap ): Heap = h
110
131
111
- /** Values that have been safely promoted */
112
- type Promoted = mutable.Set [Value ]
132
+ object Promoted {
133
+ /** Values that have been safely promoted */
134
+ opaque type Promoted = mutable.Set [Value ]
135
+
136
+ /** Note: don't use `val` to avoid incorrect sharing */
137
+ def empty : Promoted = mutable.Set .empty
138
+
139
+ extension (promoted : Promoted )
140
+ def contains (value : Value ): Boolean = promoted.contains(value)
141
+ def add (value : Value ): Unit = promoted += value
142
+ def remove (value : Value ): Unit = promoted -= value
143
+ end extension
144
+ }
145
+ type Promoted = Promoted .Promoted
146
+
147
+ import Promoted ._
113
148
def promoted (using p : Promoted ): Promoted = p
114
149
115
150
/** Interpreter configuration
@@ -171,11 +206,21 @@ class Semantic {
171
206
type Contextual [T ] = (Heap , Context , Trace , Promoted ) ?=> T
172
207
173
208
// ----- Error Handling -----------------------------------
174
- type Trace = Vector [Tree ]
175
- def trace (using t : Trace ): Trace = t
176
209
177
- extension (trace : Trace )
178
- def add (node : Tree ): Trace = trace :+ node
210
+ object Trace {
211
+ opaque type Trace = Vector [Tree ]
212
+
213
+ val empty : Trace = Vector .empty
214
+
215
+ extension (trace : Trace )
216
+ def add (node : Tree ): Trace = trace :+ node
217
+ def toVector : Vector [Tree ] = trace
218
+ }
219
+
220
+ type Trace = Trace .Trace
221
+
222
+ import Trace ._
223
+ def trace (using t : Trace ): Trace = t
179
224
180
225
// ----- Operations on domains -----------------------------
181
226
extension (a : Value )
@@ -209,7 +254,7 @@ class Semantic {
209
254
Result (Hot , Errors .empty)
210
255
211
256
case Cold =>
212
- val error = AccessCold (field, source, trace)
257
+ val error = AccessCold (field, source, trace.toVector )
213
258
Result (Hot , error :: Nil )
214
259
215
260
case addr : Addr =>
@@ -225,10 +270,10 @@ class Semantic {
225
270
val rhs = target.defTree.asInstanceOf [ValOrDefDef ].rhs
226
271
eval(rhs, addr, target.owner.asClass, cacheResult = true )
227
272
else
228
- val error = CallUnknown (field, source, trace)
273
+ val error = CallUnknown (field, source, trace.toVector )
229
274
Result (Hot , error :: Nil )
230
275
else
231
- val error = AccessNonInit (target, trace.add(source))
276
+ val error = AccessNonInit (target, trace.add(source).toVector )
232
277
Result (Hot , error :: Nil )
233
278
234
279
case _ : Fun =>
@@ -247,7 +292,7 @@ class Semantic {
247
292
Result (Hot , Errors .empty)
248
293
249
294
case Cold =>
250
- val error = CallCold (meth, source, trace)
295
+ val error = CallCold (meth, source, trace.toVector )
251
296
Result (Hot , error :: Nil )
252
297
253
298
case addr : Addr =>
@@ -270,7 +315,7 @@ class Semantic {
270
315
else if addr.canIgnoreMethodCall(target) then
271
316
Result (Hot , Nil )
272
317
else
273
- val error = CallUnknown (target, source, trace)
318
+ val error = CallUnknown (target, source, trace.toVector )
274
319
Result (Hot , error :: Nil )
275
320
else
276
321
val obj = heap(addr)
@@ -298,7 +343,7 @@ class Semantic {
298
343
Result (Hot , Errors .empty)
299
344
300
345
case Cold =>
301
- val error = CallCold (ctor, source, trace)
346
+ val error = CallCold (ctor, source, trace.toVector )
302
347
Result (Hot , error :: Nil )
303
348
304
349
case thisRef : ThisRef =>
@@ -324,14 +369,6 @@ class Semantic {
324
369
}
325
370
end extension
326
371
327
- extension (ref : Addr )
328
- def updateField (field : Symbol , value : Value ): Contextual [Unit ] =
329
- heap(ref).fields(field) = value
330
-
331
- def updateOuter (klass : ClassSymbol , value : Value ): Contextual [Unit ] =
332
- heap(ref).outers(klass) = value
333
- end extension
334
-
335
372
// ----- Promotion ----------------------------------------------------
336
373
337
374
extension (value : Value )
@@ -349,7 +386,7 @@ class Semantic {
349
386
350
387
case warm : Warm =>
351
388
warm.outer.canPromoteExtrinsic && {
352
- promoted += warm
389
+ promoted.add( warm)
353
390
true
354
391
}
355
392
@@ -361,13 +398,13 @@ class Semantic {
361
398
val sym = denot.symbol
362
399
sym.isOneOf(Flags .Lazy | Flags .Deferred ) || obj.fields.contains(sym)
363
400
}
364
- if allFieldsInitialized then promoted += thisRef
401
+ if allFieldsInitialized then promoted.add( thisRef)
365
402
allFieldsInitialized
366
403
}
367
404
368
405
case fun : Fun =>
369
406
fun.thisV.canPromoteExtrinsic && {
370
- promoted += fun
407
+ promoted.add( fun)
371
408
true
372
409
}
373
410
@@ -381,20 +418,20 @@ class Semantic {
381
418
value match
382
419
case Hot => Nil
383
420
384
- case Cold => PromoteError (msg, source, trace) :: Nil
421
+ case Cold => PromoteError (msg, source, trace.toVector ) :: Nil
385
422
386
423
case thisRef : ThisRef =>
387
424
if promoted.contains(thisRef) then Nil
388
425
else if thisRef.canPromoteExtrinsic then Nil
389
- else PromoteError (msg, source, trace) :: Nil
426
+ else PromoteError (msg, source, trace.toVector ) :: Nil
390
427
391
428
case warm : Warm =>
392
429
if promoted.contains(warm) then Nil
393
430
else if warm.canPromoteExtrinsic then Nil
394
431
else {
395
- promoted += warm
432
+ promoted.add( warm)
396
433
val errors = warm.tryPromote(msg, source)
397
- if errors.nonEmpty then promoted -= warm
434
+ if errors.nonEmpty then promoted.remove( warm)
398
435
errors
399
436
}
400
437
@@ -404,9 +441,9 @@ class Semantic {
404
441
val res = eval(body, thisV, klass)
405
442
val errors2 = res.value.promote(msg, source)
406
443
if (res.errors.nonEmpty || errors2.nonEmpty)
407
- UnsafePromotion (msg, source, trace, res.errors ++ errors2) :: Nil
444
+ UnsafePromotion (msg, source, trace.toVector , res.errors ++ errors2) :: Nil
408
445
else
409
- promoted += fun
446
+ promoted.add( fun)
410
447
Nil
411
448
412
449
case RefSet (refs) =>
@@ -434,7 +471,7 @@ class Semantic {
434
471
def tryPromote (msg : String , source : Tree ): Contextual [List [Error ]] = log(" promote " + warm.show, printer) {
435
472
val classRef = warm.klass.appliedRef
436
473
if classRef.memberClasses.nonEmpty then
437
- return PromoteError (msg, source, trace) :: Nil
474
+ return PromoteError (msg, source, trace.toVector ) :: Nil
438
475
439
476
val fields = classRef.fields
440
477
val methods = classRef.membersBasedOnFlags(Flags .Method , Flags .Deferred | Flags .Accessor )
@@ -465,7 +502,7 @@ class Semantic {
465
502
}
466
503
467
504
if buffer.isEmpty then Nil
468
- else UnsafePromotion (msg, source, trace, buffer.toList) :: Nil
505
+ else UnsafePromotion (msg, source, trace.toVector , buffer.toList) :: Nil
469
506
}
470
507
471
508
end extension
0 commit comments