@@ -45,8 +45,7 @@ class Semantic {
4545 * of the heap, we may handle it in a simple way.
4646 */
4747 case class ThisRef (klass : ClassSymbol )(val fields : mutable.Map [Symbol , Value ]) extends Value {
48- def updateField (field : Symbol , value : Value ): Unit =
49- fields(field) = value
48+ var allFieldsInitialized : Boolean = false
5049 }
5150
5251 /** An object with all fields initialized but reaches objects under initialization
@@ -99,11 +98,8 @@ class Semantic {
9998
10099 def + (error : Error ): Result = this .copy(errors = this .errors :+ error)
101100
102- def ensureHot (msg : String , source : Tree )(using Trace ): Result =
103- if value == Hot then this
104- else
105- // TODO: define a new error
106- this + PromoteCold (source, trace)
101+ def ensureHot (msg : String , source : Tree )(using Context , Trace ): Result =
102+ this ++ value.promote(msg, source)
107103
108104 def select (f : Symbol , source : Tree )(using Context , Trace ): Result =
109105 value.select(f, source) ++ errors
@@ -270,6 +266,67 @@ class Semantic {
270266 }
271267 end extension
272268
269+ extension (value : Value )
270+ def canDirectlyPromote (using Context ): Boolean =
271+ value match
272+ case Hot => true
273+ case Cold => false
274+
275+ case warm : Warm =>
276+ warm.outer.canDirectlyPromote
277+
278+ case thisRef : ThisRef =>
279+ thisRef.allFieldsInitialized || {
280+ // If we have all fields initialized, then we can promote This to hot.
281+ thisRef.allFieldsInitialized = thisRef.klass.appliedRef.fields.forall { denot =>
282+ val sym = denot.symbol
283+ sym.isOneOf(Flags .Lazy | Flags .Deferred ) || thisRef.fields.contains(sym)
284+ }
285+ thisRef.allFieldsInitialized
286+ }
287+
288+ case fun : Fun => false
289+
290+ case RefSet (refs) =>
291+ refs.forall(_.canDirectlyPromote)
292+
293+ end canDirectlyPromote
294+
295+ /** Promotion of values to hot */
296+ def promote (msg : String , source : Tree )(using Context , Trace ): List [Error ] =
297+ value match
298+ case Hot => Nil
299+
300+ case Cold => PromoteCold (source, trace) :: Nil
301+
302+ case thisRef : ThisRef =>
303+ if thisRef.canDirectlyPromote then Nil
304+ else PromoteThis (source, trace) :: Nil
305+
306+ case warm : Warm =>
307+ if warm.outer.canDirectlyPromote then Nil
308+ else PromoteWarm (source, trace) :: Nil
309+
310+ case Fun (body, thisV, klass) =>
311+ val res = eval(body, thisV, klass)
312+ val errors2 = res.value.promote(msg, source)
313+ if (res.errors.nonEmpty || errors2.nonEmpty)
314+ UnsafePromotion (source, trace, res.errors ++ errors2) :: Nil
315+ else
316+ Nil
317+
318+ case RefSet (refs) =>
319+ refs.flatMap(_.promote(msg, source))
320+ end extension
321+
322+ extension (ref : ThisRef | Warm )
323+ def updateField (field : Symbol , value : Value ): Unit =
324+ ref match
325+ case thisRef : ThisRef => thisRef.fields(field) = value
326+ case warm : Warm => // ignore
327+ end extension
328+
329+
273330// ----- Semantic definition --------------------------------
274331
275332 /** Evaluate an expression with the given value for `this` in a given class `klass`
0 commit comments