Skip to content

Commit fb3390e

Browse files
committed
Show Option, Map, Period, Atoms
1 parent 11c4595 commit fb3390e

File tree

2 files changed

+66
-18
lines changed

2 files changed

+66
-18
lines changed

compiler/src/dotty/tools/dotc/core/Periods.scala

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
package dotty.tools.dotc.core
1+
package dotty.tools
2+
package dotc
3+
package core
24

35
import Contexts.*
46
import Phases.unfusedPhases
7+
import printing.*, Texts.*
58

69
object Periods {
710

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

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

100-
override def toString: String = s"Period($firstPhaseId..$lastPhaseId, run = $runId)"
103+
def toText(p: Printer): Text = inContext(p.printerContext)(this match
104+
case Nowhere => "Nowhere"
105+
case InitialPeriod => "InitialPeriod"
106+
case InvalidPeriod => "InvalidPeriod"
107+
case Period(NoRunId, 0, PhaseMask) => s"Period(NoRunId.all)"
108+
case Period(runId, 0, PhaseMask) => s"Period($runId.all)"
109+
case Period(runId, p1, pn) if p1 == pn => s"Period($runId.$p1(${ctx.base.phases(p1)}))"
110+
case Period(runId, p1, pn) => s"Period($runId.$p1(${ctx.base.phases(p1)})-$pn(${ctx.base.phases(pn)}))"
111+
)
112+
113+
override def toString: String = this match
114+
case Nowhere => "Nowhere"
115+
case InitialPeriod => "InitialPeriod"
116+
case InvalidPeriod => "InvalidPeriod"
117+
case Period(NoRunId, 0, PhaseMask) => s"Period(NoRunId.all)"
118+
case Period(runId, 0, PhaseMask) => s"Period($runId.all)"
119+
case Period(runId, p1, pn) if p1 == pn => s"Period($runId.$p1)"
120+
case Period(runId, p1, pn) => s"Period($runId.$p1-$pn)"
101121

102122
def ==(that: Period): Boolean = this.code == that.code
103123
def !=(that: Period): Boolean = this.code != that.code
@@ -116,6 +136,17 @@ object Periods {
116136
/** The interval consisting of all periods of given run id */
117137
def allInRun(rid: RunId): Period =
118138
apply(rid, 0, PhaseMask)
139+
140+
def unapply(p: Period): Extractor = new Extractor(p.code)
141+
142+
final class Extractor(private val code: Int) extends AnyVal {
143+
private def p = new Period(code)
144+
def isEmpty: false = false
145+
def get: this.type = this
146+
def _1 = p.runId
147+
def _2 = p.firstPhaseId
148+
def _3 = p.lastPhaseId
149+
}
119150
}
120151

121152
inline val NowhereCode = 0

compiler/src/dotty/tools/dotc/printing/Formatting.scala

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,23 @@ object Formatting {
2424
object Shown:
2525
given [A: Show]: Conversion[A, Shown] = Show[A].show(_)
2626

27+
extension (s: Shown)
28+
def runCtxShow(using Context): Shown = s match
29+
case cs: CtxShow => cs.run
30+
case _ => s
31+
32+
def toStr(x: Shown)(using Context): String = x match
33+
case seq: Seq[?] => seq.map(toStr).mkString("[", ", ", "]")
34+
case res => res.tryToShow
35+
2736
sealed abstract class Show[-T]:
2837
/** Show a value T by returning a "shown" result. */
2938
def show(x: T): Shown
3039

3140
trait CtxShow:
3241
def run(using Context): Shown
3342

34-
extension (s: Shown)
35-
def ctxShow(using Context): Shown = s match
36-
case cs: CtxShow => cs.run
37-
case _ => s
43+
import Shown.runCtxShow
3844

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

5763
given [X: Show]: Show[Seq[X]] with
58-
def show(x: Seq[X]) = new CtxShow:
59-
def run(using Context) = x.map(show1)
64+
def show(x: Seq[X]) = CtxShow(x.map(toStr))
6065

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

6569
given [X: Show]: Show[X | Null] with
66-
def show(x: X | Null) = if x == null then "null" else Show[X].show(x.nn)
70+
def show(x: X | Null) = if x == null then "null" else CtxShow(toStr(x.nn))
71+
72+
given [X: Show]: Show[Option[X]] with
73+
def show(x: Option[X]) = x match
74+
case Some(x) => CtxShow("Some(" + toStr(x) + ")")
75+
case _ => "None"
76+
77+
given [K: Show, V: Show]: Show[Map[K, V]] with
78+
def show(x: Map[K, V]) = CtxShow(x.map((k, v) => toStr(k) + " => " + toStr(v)))
6779

6880
given Show[FlagSet] with
6981
def show(x: FlagSet) = x.flagsString
@@ -79,7 +91,12 @@ object Formatting {
7991
case ast.TreeInfo.Impure => "PurityLevel.Impure"
8092
case ast.TreeInfo.PurePath => "PurityLevel.PurePath"
8193
case ast.TreeInfo.IdempotentPath => "PurityLevel.IdempotentPath"
82-
case _ => s"PurityLevel(${x.x})"
94+
case _ => s"PurityLevel(${x.x.toBinaryString})"
95+
96+
given Show[Atoms] with
97+
def show(x: Atoms) = x match
98+
case Atoms.Unknown => "Unknown"
99+
case Atoms.Range(lo, hi) => CtxShow("Range(" + toStr(lo.toList) + ", " + toStr(hi.toList) + ")")
83100

84101
given Show[Showable] = ShowAny
85102
given Show[Shown] = ShowAny
@@ -92,6 +109,7 @@ object Formatting {
92109
given Show[Throwable] = ShowAny
93110
given Show[StringBuffer] = ShowAny
94111
given Show[CompilationUnit] = ShowAny
112+
given Show[Periods.Period] = ShowAny
95113
given Show[Phases.Phase] = ShowAny
96114
given Show[TyperState] = ShowAny
97115
given Show[config.ScalaVersion] = ShowAny
@@ -102,10 +120,9 @@ object Formatting {
102120
given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny
103121
given Show[typer.ForceDegree.Value] = ShowAny
104122

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

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

0 commit comments

Comments
 (0)