Skip to content

Commit 4b75d3c

Browse files
authored
Merge pull request #3691 from dotty-staging/print-lambdas
Create DecompilerPrinter and ReplPrinter
2 parents e6babac + a5f967e commit 4b75d3c

22 files changed

+492
-245
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,5 @@ compiler/test/debug/Gen.jar
7171
compiler/before-pickling.txt
7272
compiler/after-pickling.txt
7373
*.dotty-ide-version
74+
75+
*.decompiled.out
Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package dotty.tools.dotc
22
package decompiler
33

4+
import java.io.{OutputStream, PrintStream}
5+
46
import dotty.tools.dotc.core.Contexts._
57
import dotty.tools.dotc.core.Phases.Phase
68
import dotty.tools.dotc.core.tasty.TastyPrinter
9+
import dotty.tools.dotc.printing.DecompilerPrinter
10+
import dotty.tools.io.{File, Path}
711

812
/** Phase that prints the trees in all loaded compilation units.
913
*
@@ -14,23 +18,41 @@ class DecompilationPrinter extends Phase {
1418
override def phaseName: String = "decompilationPrinter"
1519

1620
override def run(implicit ctx: Context): Unit = {
17-
val unit = ctx.compilationUnit
21+
val outputDir = ctx.settings.outputDir.value
22+
if (outputDir == ".") printToOutput(System.out)
23+
else {
24+
var os: OutputStream = null
25+
var ps: PrintStream = null
26+
try {
27+
os = File(outputDir + ".decompiled").outputStream()
28+
ps = new PrintStream(os)
29+
printToOutput(ps)
30+
} finally {
31+
if (os ne null) os.close()
32+
if (ps ne null) ps.close()
33+
}
34+
}
35+
}
1836

37+
private def printToOutput(out: PrintStream)(implicit ctx: Context): Unit = {
38+
val unit = ctx.compilationUnit
1939
val pageWidth = ctx.settings.pageWidth.value
20-
40+
val printLines = ctx.settings.printLines.value
2141
val doubleLine = "=" * pageWidth
2242
val line = "-" * pageWidth
2343

24-
println(doubleLine)
25-
println(unit.source)
26-
println(line)
44+
out.println(doubleLine)
45+
out.println(unit.source)
46+
out.println(line)
47+
48+
val printer = new DecompilerPrinter(ctx)
2749

28-
println(unit.tpdTree.show)
29-
println(line)
50+
out.println(printer.toText(unit.tpdTree).mkString(pageWidth, printLines))
51+
out.println(line)
3052

3153
if (ctx.settings.printTasty.value) {
3254
new TastyPrinter(unit.pickled.head._2).printContents()
33-
println(line)
55+
out.println(line)
3456
}
3557
}
3658
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package dotty.tools.dotc.printing
2+
3+
import dotty.tools.dotc.ast.Trees.{Closure, DefDef, Untyped, ValDef}
4+
import dotty.tools.dotc.ast.untpd.{PackageDef, Template, TypeDef}
5+
import dotty.tools.dotc.ast.{Trees, untpd}
6+
import dotty.tools.dotc.printing.Texts._
7+
import dotty.tools.dotc.core.Contexts._
8+
import dotty.tools.dotc.core.Flags._
9+
import dotty.tools.dotc.core.Symbols._
10+
11+
import scala.language.implicitConversions
12+
13+
class DecompilerPrinter(_ctx: Context) extends RefinedPrinter(_ctx) {
14+
15+
override protected def filterModTextAnnots(annots: List[untpd.Tree]): List[untpd.Tree] =
16+
annots.filter(_.tpe != defn.SourceFileAnnotType)
17+
18+
override protected def blockText[T >: Untyped](trees: List[Trees.Tree[T]]): Text = {
19+
super.blockText(trees.filterNot(_.isInstanceOf[Closure[_]]))
20+
}
21+
22+
override protected def packageDefText(tree: PackageDef): Text = {
23+
val stats = tree.stats.filter {
24+
case vdef: ValDef[_] => !vdef.symbol.is(Module)
25+
case _ => true
26+
}
27+
val statsText = stats match {
28+
case (pdef: PackageDef) :: Nil => toText(pdef)
29+
case _ => toTextGlobal(stats, "\n")
30+
}
31+
val bodyText =
32+
if (currentPrecedence == TopLevelPrec) "\n" ~ statsText else " {" ~ statsText ~ "}"
33+
keywordStr("package ") ~ toTextPackageId(tree.pid) ~ bodyText
34+
}
35+
36+
override protected def templateText(tree: TypeDef, impl: Template): Text = {
37+
val decl =
38+
if (!tree.mods.is(Module)) modText(tree.mods, keywordStr(if ((tree).mods is Trait) "trait" else "class"))
39+
else modText(tree.mods &~ (Final | Module), keywordStr("object"))
40+
decl ~~ typeText(nameIdText(tree)) ~ withEnclosingDef(tree) { toTextTemplate(impl) } ~ ""
41+
}
42+
43+
override protected def defDefToText[T >: Untyped](tree: DefDef[T]): Text = {
44+
import untpd.{modsDeco => _, _}
45+
dclTextOr(tree) {
46+
val printLambda = tree.symbol.isAnonymousFunction
47+
val prefix = modText(tree.mods, keywordStr("def")) ~~ valDefText(nameIdText(tree)) provided (!printLambda)
48+
withEnclosingDef(tree) {
49+
addVparamssText(prefix ~ tparamsText(tree.tparams), tree.vparamss) ~ optAscription(tree.tpt).provided(!printLambda) ~
50+
optText(tree.rhs)((if (printLambda) " => " else " = ") ~ _)
51+
}
52+
}
53+
}
54+
}

0 commit comments

Comments
 (0)