@@ -176,13 +176,13 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
176176 if local != null then
177177 op(using ctx)(local)
178178
179- def doBeginUnit (unit : CompilationUnit )(using Context ): Unit =
179+ def doBeginUnit ()(using Context ): Unit =
180180 trackProgress : progress =>
181- progress.informUnitStarting(unit )
181+ progress.informUnitStarting(ctx.compilationUnit )
182182
183183 def doAdvanceUnit ()(using Context ): Unit =
184184 trackProgress : progress =>
185- progress.unitc += 1 // trace that we completed a unit in the current phase
185+ progress.unitc += 1 // trace that we completed a unit in the current (sub) phase
186186 progress.refreshProgress()
187187
188188 def doAdvanceLate ()(using Context ): Unit =
@@ -196,14 +196,23 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
196196
197197 private def doAdvancePhase (currentPhase : Phase , wasRan : Boolean )(using Context ): Unit =
198198 trackProgress : progress =>
199- progress.unitc = 0 // reset unit count in current phase
200- progress.seen += 1 // trace that we've seen a phase
199+ progress.unitc = 0 // reset unit count in current (sub)phase
200+ progress.subtraversalc = 0 // reset subphase index to initial
201+ progress.seen += 1 // trace that we've seen a (sub)phase
201202 if wasRan then
202- // add an extra traversal now that we completed a phase
203+ // add an extra traversal now that we completed a (sub) phase
203204 progress.traversalc += 1
204205 else
205- // no phase was ran, remove a traversal from expected total
206- progress.runnablePhases -= 1
206+ // no subphases were ran, remove traversals from expected total
207+ progress.totalTraversals -= currentPhase.traversals
208+
209+ private def doAdvanceSubPhase ()(using Context ): Unit =
210+ trackProgress : progress =>
211+ progress.unitc = 0 // reset unit count in current (sub)phase
212+ progress.seen += 1 // trace that we've seen a (sub)phase
213+ progress.traversalc += 1 // add an extra traversal now that we completed a (sub)phase
214+ progress.subtraversalc += 1 // record that we've seen a subphase
215+ progress.tickSubphase()
207216
208217 /** Will be set to true if any of the compiled compilation units contains
209218 * a pureFunctions language import.
@@ -318,7 +327,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
318327 unfusedPhases.foreach(_.initContext(runCtx))
319328 val fusedPhases = runCtx.base.allPhases
320329 runCtx.withProgressCallback: cb =>
321- _progress = Progress (cb, this , fusedPhases.length )
330+ _progress = Progress (cb, this , fusedPhases.map(_.traversals).sum )
322331 runPhases(allPhases = fusedPhases)(using runCtx)
323332 if (! ctx.reporter.hasErrors)
324333 Rewrites .writeBack()
@@ -451,31 +460,52 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
451460
452461object Run {
453462
454- /** Computes the next MegaPhase for the given phase.*/
455- def nextMegaPhase (phase : Phase )(using Context ): Phase = phase.megaPhase.next.megaPhase
463+ class SubPhases (val phase : Phase ):
464+ require(phase.exists)
465+
466+ val all = IArray .from(phase.subPhases.map(sub => s " ${phase.phaseName} ( $sub) " ))
467+
468+ def next (using Context ): Option [SubPhases ] =
469+ val next0 = phase.megaPhase.next.megaPhase
470+ if next0.exists then Some (SubPhases (next0))
471+ else None
456472
457- private class Progress (cb : ProgressCallback , private val run : Run , val initialPhases : Int ):
458- private [Run ] var runnablePhases : Int = initialPhases // track how many phases we expect to run
459- private [Run ] var unitc : Int = 0 // current unit count in the current phase
473+ def subPhase (index : Int ) =
474+ if index < all.size then all(index)
475+ else phase.phaseName
476+
477+ private class Progress (cb : ProgressCallback , private val run : Run , val initialTraversals : Int ):
478+ private [Run ] var totalTraversals : Int = initialTraversals // track how many phases we expect to run
479+ private [Run ] var unitc : Int = 0 // current unit count in the current (sub)phase
460480 private [Run ] var latec : Int = 0 // current late unit count
461481 private [Run ] var traversalc : Int = 0 // completed traversals over all files
482+ private [Run ] var subtraversalc : Int = 0 // completed subphases in the current phase
462483 private [Run ] var seen : Int = 0 // how many phases we've seen so far
463484
464485 private var currPhase : Phase = uninitialized // initialized by enterPhase
486+ private var subPhases : SubPhases = uninitialized // initialized by enterPhase
465487 private var currPhaseName : String = uninitialized // initialized by enterPhase
466488 private var nextPhaseName : String = uninitialized // initialized by enterPhase
467489
468- private def phaseNameFor (phase : Phase ): String =
469- if phase.exists then phase.phaseName
470- else " <end>"
471-
490+ /** Enter into a new real phase, setting the current and next (sub)phases */
472491 private [Run ] def enterPhase (newPhase : Phase )(using Context ): Unit =
473492 if newPhase ne currPhase then
474493 currPhase = newPhase
475- currPhaseName = phaseNameFor(newPhase)
476- nextPhaseName = phaseNameFor(Run .nextMegaPhase(newPhase))
477- if seen > 0 then
478- refreshProgress()
494+ subPhases = SubPhases (newPhase)
495+ tickSubphase()
496+
497+ /** Compute the current (sub)phase name and next (sub)phase name */
498+ private [Run ] def tickSubphase ()(using Context ): Unit =
499+ val index = subtraversalc
500+ val s = subPhases
501+ currPhaseName = s.subPhase(index)
502+ nextPhaseName =
503+ if index + 1 < s.all.size then s.subPhase(index + 1 )
504+ else s.next match
505+ case None => " <end>"
506+ case Some (next0) => next0.subPhase(0 )
507+ if seen > 0 then
508+ refreshProgress()
479509
480510
481511 /** Counts the number of completed full traversals over files, plus the number of units in the current phase */
@@ -487,26 +517,35 @@ object Run {
487517 * - the number of late compilations
488518 */
489519 private def totalProgress ()(using Context ): Int =
490- runnablePhases * run.files.size + run.lateFiles.size
520+ totalTraversals * run.files.size + run.lateFiles.size
491521
492522 private def requireInitialized (): Unit =
493523 require((currPhase : Phase | Null ) != null , " enterPhase was not called" )
494524
525+ /** trace that we are beginning a unit in the current (sub)phase */
495526 private [Run ] def informUnitStarting (unit : CompilationUnit )(using Context ): Unit =
496527 requireInitialized()
497528 cb.informUnitStarting(currPhaseName, unit)
498529
530+ /** trace the current progress out of the total, in the current (sub)phase, reporting the next (sub)phase */
499531 private [Run ] def refreshProgress ()(using Context ): Unit =
500532 requireInitialized()
501533 cb.progress(currentProgress(), totalProgress(), currPhaseName, nextPhaseName)
502534
503535 extension (run : Run | Null )
504- def beginUnit (unit : CompilationUnit )(using Context ): Unit =
505- if run != null then run.doBeginUnit(unit)
506536
537+ /** record that the current phase has begun for the compilation unit of the current Context */
538+ def beginUnit ()(using Context ): Unit =
539+ if run != null then run.doBeginUnit()
540+
541+ /** advance the unit count and record progress in the current phase */
507542 def advanceUnit ()(using Context ): Unit =
508543 if run != null then run.doAdvanceUnit()
509544
545+ def advanceSubPhase ()(using Context ): Unit =
546+ if run != null then run.doAdvanceSubPhase()
547+
548+ /** advance the late count and record progress in the current phase */
510549 def advanceLate ()(using Context ): Unit =
511550 if run != null then run.doAdvanceLate()
512551
0 commit comments