@@ -7,46 +7,28 @@ import config.Config
77import config .Printers
88import core .Mode
99
10- /** Exposes the {{{ trace("question") { op } }}} syntax.
11- *
12- * Traced operations will print indented messages if enabled.
13- * Tracing depends on [[Config.tracingEnabled ]] and [[dotty.tools.dotc.config.ScalaSettings.Ylog ]].
14- * Tracing can be forced by replacing [[trace ]] with [[trace.force ]] (see below).
15- */
16- object trace extends TraceSyntax {
17- final val isForced = false
18-
19- /** Forces a particular trace to be printed out regardless of tracing being enabled. */
20- object force extends TraceSyntax {
21- final val isForced = true
22- }
23- }
24-
25- abstract class TraceSyntax {
26- val isForced : Boolean
10+ /** This module is carefully optimized to give zero overhead if Config.tracingEnabled
11+ * is false. The `trace` operation is called in various hotspots, so every tiny bit
12+ * of overhead is unacceptable: boxing, closures, additional method calls are all out.
13+ */
14+ object trace :
2715
2816 inline def onDebug [TD ](inline question : String )(inline op : TD )(using Context ): TD =
2917 conditionally(ctx.settings.YdebugTrace .value, question, false )(op)
3018
31- inline def conditionally [TC ](inline cond : Boolean , inline question : String , inline show : Boolean )(op : => TC )(using Context ): TC =
32- inline if (isForced || Config .tracingEnabled) {
33- if (cond) apply[TC ](question, Printers .default, show)(op)
34- else op
35- }
19+ inline def conditionally [TC ](inline cond : Boolean , inline question : String , inline show : Boolean )(inline op : TC )(using Context ): TC =
20+ if Config .tracingEnabled then
21+ apply(question, if cond then Printers .default else Printers .noPrinter, show)(op)
3622 else op
3723
38- inline def apply [T ](inline question : String , inline printer : Printers .Printer , inline showOp : Any => String )(op : => T )(using Context ): T =
39- inline if (isForced || Config .tracingEnabled) {
40- if (! isForced && printer.eq(config.Printers .noPrinter)) op
41- else doTrace[T ](question, printer, showOp)(op)
42- }
24+ inline def apply [T ](inline question : String , inline printer : Printers .Printer , inline showOp : Any => String )(inline op : T )(using Context ): T =
25+ if Config .tracingEnabled then
26+ doTrace[T ](question, printer, showOp)(op)
4327 else op
4428
45- inline def apply [T ](inline question : String , inline printer : Printers .Printer , inline show : Boolean )(op : => T )(using Context ): T =
46- inline if (isForced || Config .tracingEnabled) {
47- if (! isForced && printer.eq(config.Printers .noPrinter)) op
48- else doTrace[T ](question, printer, if (show) showShowable(_) else alwaysToString)(op)
49- }
29+ inline def apply [T ](inline question : String , inline printer : Printers .Printer , inline show : Boolean )(inline op : T )(using Context ): T =
30+ if Config .tracingEnabled then
31+ doTrace[T ](question, printer, if show then showShowable(_) else alwaysToString)(op)
5032 else op
5133
5234 inline def apply [T ](inline question : String , inline printer : Printers .Printer )(inline op : T )(using Context ): T =
@@ -56,55 +38,41 @@ abstract class TraceSyntax {
5638 apply[T ](question, Printers .default, show)(op)
5739
5840 inline def apply [T ](inline question : String )(inline op : T )(using Context ): T =
59- apply[T ](question, Printers .default, false )(op)
41+ apply[T ](question, false )(op)
6042
61- private def showShowable (x : Any )(using Context ) = x match {
43+ private def showShowable (x : Any )(using Context ) = x match
6244 case x : printing.Showable => x.show
6345 case _ => String .valueOf(x)
64- }
6546
6647 private val alwaysToString = (x : Any ) => String .valueOf(x)
6748
6849 private def doTrace [T ](question : => String ,
6950 printer : Printers .Printer = Printers .default,
7051 showOp : Any => String = alwaysToString)
71- (op : => T )(using Context ): T = {
72- // Avoid evaluating question multiple time, since each evaluation
73- // may cause some extra logging output.
74- lazy val q : String = question
75- apply[T ](s " ==> $q? " , (res : Any ) => s " <== $q = ${showOp(res)}" )(op)
76- }
77-
78- def apply [T ](leading : => String , trailing : Any => String )(op : => T )(using Context ): T = {
79- val log : String => Unit = if (isForced) Console .println else {
80- var logctx = ctx
81- while (logctx.reporter.isInstanceOf [StoreReporter ]) logctx = logctx.outer
82- report.log(_)(using logctx)
83- }
84- doApply(leading, trailing, log)(op)
85- }
86-
87- def doApply [T ](leading : => String , trailing : Any => String , log : String => Unit )(op : => T )(using Context ): T =
88- if (ctx.mode.is(Mode .Printing )) op
89- else {
52+ (op : => T )(using Context ): T =
53+ if ctx.mode.is(Mode .Printing ) || (printer eq Printers .noPrinter) then op
54+ else
55+ // Avoid evaluating question multiple time, since each evaluation
56+ // may cause some extra logging output.
57+ val q = question
58+ val leading = s " ==> $q? "
59+ val trailing = (res : Any ) => s " <== $q = ${showOp(res)}"
9060 var finalized = false
61+ var logctx = ctx
62+ while logctx.reporter.isInstanceOf [StoreReporter ] do logctx = logctx.outer
63+ def margin = ctx.base.indentTab * ctx.base.indent
9164 def finalize (result : Any , note : String ) =
92- if ( ! finalized) {
65+ if ! finalized then
9366 ctx.base.indent -= 1
94- log(s " ${ctx.base.indentTab * ctx.base.indent} ${trailing(result)}$note" )
67+ report. log(s " $margin ${trailing(result)}$note" )
9568 finalized = true
96- }
97- try {
98- log(s " ${ctx.base.indentTab * ctx.base.indent}$leading" )
69+ try
70+ report.log(s " $margin$leading" )
9971 ctx.base.indent += 1
10072 val res = op
10173 finalize(res, " " )
10274 res
103- }
104- catch {
105- case ex : Throwable =>
106- finalize(" <missing>" , s " (with exception $ex) " )
107- throw ex
108- }
109- }
110- }
75+ catch case ex : Throwable =>
76+ finalize(" <missing>" , s " (with exception $ex) " )
77+ throw ex
78+ end trace
0 commit comments