Skip to content

Commit

Permalink
Show Option, Map, Period, Atoms
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Feb 12, 2024
1 parent c529a48 commit 206b28d
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 17 deletions.
37 changes: 34 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Periods.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package dotty.tools.dotc.core
package dotty.tools
package dotc
package core

import Contexts.*
import Phases.unfusedPhases
import printing.*, Texts.*

object Periods {

Expand Down Expand Up @@ -35,7 +38,7 @@ object Periods {
*
* // Dmitry: sign == 0 isn't actually always true, in some cases phaseId == -1 is used for shifts, that easily creates code < 0
*/
class Period(val code: Int) extends AnyVal {
class Period(val code: Int) extends AnyVal with Showable {

/** The run identifier of this period. */
def runId: RunId = code >>> (PhaseWidth * 2)
Expand Down Expand Up @@ -97,7 +100,24 @@ object Periods {
this.firstPhaseId min that.firstPhaseId,
this.lastPhaseId max that.lastPhaseId)

override def toString: String = s"Period($firstPhaseId..$lastPhaseId, run = $runId)"
def toText(p: Printer): Text = inContext(p.printerContext)(this match
case Nowhere => "Nowhere"
case InitialPeriod => "InitialPeriod"
case InvalidPeriod => "InvalidPeriod"
case Period(NoRunId, 0, PhaseMask) => s"Period(NoRunId.all)"
case Period(runId, 0, PhaseMask) => s"Period($runId.all)"
case Period(runId, p1, pn) if p1 == pn => s"Period($runId.$p1(${ctx.base.phases(p1)}))"
case Period(runId, p1, pn) => s"Period($runId.$p1(${ctx.base.phases(p1)})-$pn(${ctx.base.phases(pn)}))"
)

override def toString: String = this match
case Nowhere => "Nowhere"
case InitialPeriod => "InitialPeriod"
case InvalidPeriod => "InvalidPeriod"
case Period(NoRunId, 0, PhaseMask) => s"Period(NoRunId.all)"
case Period(runId, 0, PhaseMask) => s"Period($runId.all)"
case Period(runId, p1, pn) if p1 == pn => s"Period($runId.$p1)"
case Period(runId, p1, pn) => s"Period($runId.$p1-$pn)"

def ==(that: Period): Boolean = this.code == that.code
def !=(that: Period): Boolean = this.code != that.code
Expand All @@ -116,6 +136,17 @@ object Periods {
/** The interval consisting of all periods of given run id */
def allInRun(rid: RunId): Period =
apply(rid, 0, PhaseMask)

def unapply(p: Period): Extractor = new Extractor(p.code)

final class Extractor(private val code: Int) extends AnyVal {
private def p = new Period(code)
def isEmpty: false = false
def get: this.type = this
def _1 = p.runId
def _2 = p.firstPhaseId
def _3 = p.lastPhaseId
}
}

inline val NowhereCode = 0
Expand Down
45 changes: 31 additions & 14 deletions compiler/src/dotty/tools/dotc/printing/Formatting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ object Formatting {
object Shown:
given [A: Show]: Conversion[A, Shown] = Show[A].show(_)

extension (s: Shown)
def runCtxShow(using Context): Shown = s match
case cs: CtxShow => cs.run
case _ => s

def toStr(x: Shown)(using Context): String = x match
case seq: Seq[?] => seq.map(toStr).mkString("[", ", ", "]")
case res => res.tryToShow

sealed abstract class Show[-T]:
/** Show a value T by returning a "shown" result. */
def show(x: T): Shown

trait CtxShow:
def run(using Context): Shown

extension (s: Shown)
def ctxShow(using Context): Shown = s match
case cs: CtxShow => cs.run
case _ => s
import Shown.runCtxShow

/** The base implementation, passing the argument to StringFormatter which will try to `.show` it. */
object ShowAny extends Show[Any]:
Expand All @@ -55,15 +61,21 @@ object Formatting {
inline def apply[A](using inline z: Show[A]): Show[A] = z

given [X: Show]: Show[Seq[X]] with
def show(x: Seq[X]) = new CtxShow:
def run(using Context) = x.map(show1)
def show(x: Seq[X]) = CtxShow(x.map(toStr))

given [H: Show, T <: Tuple: Show]: Show[H *: T] with
def show(x: H *: T) = new CtxShow:
def run(using Context) = show1(x.head) *: Show[T].show(x.tail).ctxShow.asInstanceOf[Tuple]
def show(x: H *: T) = CtxShow(toStr(x.head) *: toShown(x.tail).asInstanceOf[Tuple])

given [X: Show]: Show[X | Null] with
def show(x: X | Null) = if x == null then "null" else Show[X].show(x.nn)
def show(x: X | Null) = if x == null then "null" else CtxShow(toStr(x.nn))

given [X: Show]: Show[Option[X]] with
def show(x: Option[X]) = x match
case Some(x) => CtxShow("Some(" + toStr(x) + ")")
case _ => "None"

given [K: Show, V: Show]: Show[Map[X, Y]] with
def show(x: Map[K, V]) = CtxShow(x.map((k, v) => toStr(k) + " => " + toStr(v)))

given Show[FlagSet] with
def show(x: FlagSet) = x.flagsString
Expand All @@ -81,6 +93,11 @@ object Formatting {
case ast.TreeInfo.IdempotentPath => "PurityLevel.IdempotentPath"
case _ => s"PurityLevel(${x.x})"

given Show[Atoms] with
def show(x: Atoms) = x match
case Atoms.Unknown => "Unknown"
case Atoms.Range(lo, hi) => CtxShow("Range(" + toStr(lo.toList) + ", " + toStr(hi.toList) + ")")

given Show[Showable] = ShowAny
given Show[Shown] = ShowAny
given Show[Int] = ShowAny
Expand All @@ -92,6 +109,7 @@ object Formatting {
given Show[Throwable] = ShowAny
given Show[StringBuffer] = ShowAny
given Show[CompilationUnit] = ShowAny
given Show[Periods.Period] = ShowAny
given Show[Phases.Phase] = ShowAny
given Show[TyperState] = ShowAny
given Show[config.ScalaVersion] = ShowAny
Expand All @@ -102,10 +120,9 @@ object Formatting {
given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny
given Show[typer.ForceDegree.Value] = ShowAny

private def show1[A: Show](x: A)(using Context) = show2(Show[A].show(x).ctxShow)
private def show2(x: Shown)(using Context): String = x match
case seq: Seq[?] => seq.map(show2).mkString("[", ", ", "]")
case res => res.tryToShow
private inline def CtxShow(inline x: Context ?=> Shown) = new CtxShow { def run(using Context) = x(using ctx) }
private def toStr[A: Show](x: A)(using Context): String = Shown.toStr(toShown(x))
private def toShown[A: Show](x: A)(using Context): Shown = Show[A].show(x).runCtxShow
end Show
end ShownDef
export ShownDef.{ Show, Shown }
Expand All @@ -122,7 +139,7 @@ object Formatting {
class StringFormatter(protected val sc: StringContext) {
protected def showArg(arg: Any)(using Context): String = arg.tryToShow

private def treatArg(arg: Shown, suffix: String)(using Context): (String, String) = arg.ctxShow match {
private def treatArg(arg: Shown, suffix: String)(using Context): (String, String) = arg.runCtxShow match {
case arg: Seq[?] if suffix.indexOf('%') == 0 && suffix.indexOf('%', 1) != -1 =>
val end = suffix.indexOf('%', 1)
val sep = StringContext.processEscapes(suffix.substring(1, end))
Expand Down

0 comments on commit 206b28d

Please sign in to comment.