@@ -59,6 +59,7 @@ object Semantic {
5959 def isHot = this == Hot
6060 def isCold = this == Cold
6161 def isWarm = this .isInstanceOf [Warm ]
62+ def isThisRef = this .isInstanceOf [ThisRef ]
6263 }
6364
6465 /** A transitively initialized object */
@@ -104,9 +105,6 @@ object Semantic {
104105 def ensureObjectExistsAndPopulated (): Contextual [this .type ] =
105106 if cache.containsObject(this ) then this
106107 else this .ensureFresh().populateParams()
107-
108- def ensureObjectFreshAndPopulated (): Contextual [this .type ] =
109- this .ensureFresh().populateParams()
110108 }
111109
112110 /** A function value */
@@ -328,25 +326,37 @@ object Semantic {
328326
329327 /** Prepare cache for the next iteration
330328 *
331- * 1. Reset changed flag
329+ * 1. Reset changed flag.
332330 *
333- * 2. Reset current cache (last cache already synced in `assume`)
331+ * 2. Reset current cache (last cache already synced in `assume`).
334332 *
335333 * 3. Revert heap if instable.
336334 *
337335 */
338- def prepareForNextIteration (isStable : Boolean )(using State , Context ) =
339- if isStable then
340- this .commitToStableCache()
341- this .heapStable = this .heap
342- // If the current iteration is not stable, we need to use `last` for the next iteration,
343- // which already contains the updated value from the current iteration.
344- this .last = mutable.Map .empty
345-
336+ def prepareForNextIteration ()(using Context ) =
346337 this .changed = false
347338 this .current = mutable.Map .empty
348339 this .heap = this .heapStable
349340
341+ /** Prepare for checking next class
342+ *
343+ * 1. Reset changed flag.
344+ *
345+ * 2. Commit current cache to stable cache if not changed.
346+ *
347+ * 3. Update stable heap if not changed.
348+ *
349+ * 4. Reset last cache.
350+ */
351+ def prepareForNextClass ()(using Context ) =
352+ if this .changed then
353+ this .changed = false
354+ else
355+ this .commitToStableCache()
356+ this .heapStable = this .heap
357+
358+ this .last = mutable.Map .empty
359+
350360 def updateObject (ref : Ref , obj : Objekt ) =
351361 assert(! this .heapStable.contains(ref))
352362 this .heap = this .heap.updated(ref, obj)
@@ -395,17 +405,10 @@ object Semantic {
395405 value.instantiate(klass, ctor, args, source) ++ errors
396406 }
397407
398- // ----- State --------------------------------------------
399- /** Global state of the checker */
400- class State (val cache : Cache , val workList : WorkList )
401-
402- given (using s : State ): Cache = s.cache
403- given (using s : State ): WorkList = s.workList
404-
405- inline def state (using s : State ) = s
408+ // ----- Checker State -----------------------------------
406409
407410 /** The state that threads through the interpreter */
408- type Contextual [T ] = (Env , Context , Trace , Promoted , State ) ?=> T
411+ type Contextual [T ] = (Env , Context , Trace , Promoted , Cache ) ?=> T
409412
410413// ----- Error Handling -----------------------------------
411414
@@ -917,64 +920,62 @@ object Semantic {
917920 cls == defn.ObjectClass
918921
919922// ----- Work list ---------------------------------------------------
920- case class Task (value : ThisRef )( val trace : Trace )
923+ case class Task (value : ThisRef )
921924
922925 class WorkList private [Semantic ]() {
923926 private var pendingTasks : List [Task ] = Nil
924- private var checkedTasks : Set [Task ] = Set .empty
925927
926928 def addTask (task : Task ): Unit =
927- if ! checkedTasks .contains(task) then pendingTasks = task :: pendingTasks
929+ if ! pendingTasks .contains(task) then pendingTasks = task :: pendingTasks
928930
929931 /** Process the worklist until done */
930- @ tailrec
931- final def work ()(using State , Context ): Unit =
932- pendingTasks match
933- case task :: rest =>
934- checkedTasks = checkedTasks + task
935-
936- task.value.ensureFresh()
937- val res = doTask(task)
938- res.errors.foreach(_.issue)
939-
940- if cache.hasChanged && res.errors.isEmpty then
941- cache.prepareForNextIteration(isStable = false )
942- else
943- cache.prepareForNextIteration(isStable = true )
944- pendingTasks = rest
945-
946- work()
947- case _ =>
932+ final def work ()(using Cache , Context ): Unit =
933+ for task <- pendingTasks
934+ do doTask(task)
948935
949936 /** Check an individual class
950937 *
951938 * This method should only be called from the work list scheduler.
952939 */
953- private def doTask (task : Task )(using State , Context ): Result = log(" checking " + task) {
940+ private def doTask (task : Task )(using Cache , Context ): Unit = log(" checking " + task) {
954941 val thisRef = task.value
955942 val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
956943
957944 val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot ).toMap
958945
959946 given Promoted = Promoted .empty
960- given Trace = task.trace
947+ given Trace = Trace .empty
961948 given Env = Env (paramValues)
962949
963- eval(tpl, thisRef, thisRef.klass)
950+ @ tailrec
951+ def iterate (): Unit = {
952+ thisRef.ensureFresh()
953+ val res = eval(tpl, thisRef, thisRef.klass)
954+ res.errors.foreach(_.issue)
955+
956+ if cache.hasChanged && res.errors.isEmpty then
957+ // code to prepare cache and heap for next iteration
958+ cache.prepareForNextIteration()
959+ iterate()
960+ else
961+ cache.prepareForNextClass()
962+ }
963+
964+ iterate()
964965 }
965966 }
966967 inline def workList (using wl : WorkList ): WorkList = wl
967968
968969// ----- API --------------------------------
969970
970971 /** Add a checking task to the work list */
971- def addTask (thisRef : ThisRef )(using WorkList , Trace ) = workList.addTask(Task (thisRef)(trace ))
972+ def addTask (thisRef : ThisRef )(using WorkList ) = workList.addTask(Task (thisRef))
972973
973974 /** Perform check on the work list until it becomes empty
974975 *
975976 * Should only be called once from the checker.
976977 */
977- def check ()(using State , Context ) = workList.work()
978+ def check ()(using Cache , WorkList , Context ) = workList.work()
978979
979980 /** Perform actions with initial checking state.
980981 *
@@ -984,9 +985,8 @@ object Semantic {
984985 * Semantic.check()
985986 * }
986987 */
987- def withInitialState [T ](work : State ?=> T ): T = {
988- val initialState = State (new Cache , new WorkList )
989- work(using initialState)
988+ def withInitialState [T ](work : (Cache , WorkList ) ?=> T ): T = {
989+ work(using new Cache , new WorkList )
990990 }
991991
992992// ----- Semantic definition --------------------------------
@@ -1412,7 +1412,7 @@ object Semantic {
14121412 var fieldsChanged = true
14131413
14141414 // class body
1415- if ! thisV.isWarm || ! thisV.asInstanceOf [Warm ].isPopulatingParams then tpl.body.foreach {
1415+ if thisV.isThisRef || ! thisV.asInstanceOf [Warm ].isPopulatingParams then tpl.body.foreach {
14161416 case vdef : ValDef if ! vdef.symbol.is(Flags .Lazy ) && ! vdef.rhs.isEmpty =>
14171417 given Env = Env .empty
14181418 val res = eval(vdef.rhs, thisV, klass)
@@ -1423,7 +1423,7 @@ object Semantic {
14231423 case _ : MemberDef =>
14241424
14251425 case tree =>
1426- if fieldsChanged && ! thisV.isWarm then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
1426+ if fieldsChanged && thisV.isThisRef then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
14271427 fieldsChanged = false
14281428
14291429 given Env = Env .empty
0 commit comments