Skip to content

Create dotc -decompiler #3485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ object CompilationUnit {
/** Make a compilation unit for top class `clsd` with the contends of the `unpickled` */
def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = {
assert(!unpickled.isEmpty, unpickled)
val unit1 = new CompilationUnit(new SourceFile(clsd.symbol.sourceFile, Seq()))
val unit1 = new CompilationUnit(new SourceFile(clsd.symbol.associatedFile, Seq()))
unit1.tpdTree = unpickled
if (forceTrees)
force.traverse(unit1.tpdTree)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dotty.tools.dotc
package decompiler

import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.core.Phases.Phase

/** Phase that prints the trees in all loaded compilation units.
*
* @author Nicolas Stucki
*/
class DecompilationPrinter extends Phase {

override def phaseName: String = "decompilationPrinter"

override def run(implicit ctx: Context): Unit = {
val unit = ctx.compilationUnit

val pageWidth = ctx.settings.pageWidth.value

val doubleLine = "=" * pageWidth
val line = "-" * pageWidth

println(doubleLine)
println(unit.source)
println(line)

println(unit.tpdTree.show)
println(line)
}
}
21 changes: 21 additions & 0 deletions compiler/src/dotty/tools/dotc/decompiler/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dotty.tools.dotc.decompiler

import dotty.tools.dotc
import dotty.tools.dotc.core.Contexts._

/** Main class of the `dotc -decompiler` decompiler.
*
* @author Nicolas Stucki
*/
object Main extends dotc.Driver {
override protected def newCompiler(implicit ctx: Context): dotc.Compiler = {
assert(ctx.settings.fromTasty.value)
new TASTYDecompiler
}

override def setup(args0: Array[String], rootCtx: Context): (List[String], Context) = {
var args = args0.filter(a => a != "-decompile")
args = if (args.contains("-from-tasty")) args else "-from-tasty" +: args
super.setup(args, rootCtx)
}
}
16 changes: 16 additions & 0 deletions compiler/src/dotty/tools/dotc/decompiler/TASTYDecompiler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dotty.tools.dotc.decompiler

import dotty.tools.dotc.fromtasty._
import dotty.tools.dotc.core.Phases.Phase

/** Compiler from tasty to user readable high text representation
* of the compiled scala code.
*
* @author Nicolas Stucki
*/
class TASTYDecompiler extends TASTYCompiler {
override def phases: List[List[Phase]] = List(
List(new ReadTastyTreesFromClasses), // Load classes from tasty
List(new DecompilationPrinter) // Print all loaded classes
)
}
2 changes: 2 additions & 0 deletions dist/bin/dotc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ default_java_opts="-Xmx768m -Xms768m"
bootcp=true

CompilerMain=dotty.tools.dotc.Main
DecompilerMain=dotty.tools.dotc.decompiler.Main
ReplMain=dotty.tools.repl.Main

PROG_NAME=$CompilerMain
Expand Down Expand Up @@ -82,6 +83,7 @@ case "$1" in
-Oshort) addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" && shift ;;
-repl) PROG_NAME="$ReplMain" && shift ;;
-compile) PROG_NAME="$CompilerMain" && shift ;;
-decompile) PROG_NAME="$DecompilerMain" && shift ;;
-run) PROG_NAME="$ReplMain" && shift ;;
-bootcp) bootcp=true && shift ;;
-nobootcp) unset bootcp && shift ;;
Expand Down
17 changes: 12 additions & 5 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ object Build {
lazy val dotr =
inputKey[Unit]("run compiled binary using the correct classpath, or the user supplied classpath")


// Compiles the documentation and static site
lazy val genDocs = taskKey[Unit]("run dottydoc to generate static documentation site")

Expand Down Expand Up @@ -523,8 +524,8 @@ object Build {
}
},
run := dotc.evaluated,
dotc := runCompilerMain(false).evaluated,
repl := runCompilerMain(true).evaluated,
dotc := runCompilerMain().evaluated,
repl := runCompilerMain(repl = true).evaluated,

// enable verbose exception messages for JUnit
testOptions in Test += Tests.Argument(
Expand Down Expand Up @@ -618,16 +619,22 @@ object Build {
}
)

def runCompilerMain(repl: Boolean) = Def.inputTaskDyn {
def runCompilerMain(repl: Boolean = false) = Def.inputTaskDyn {
val dottyLib = packageAll.value("dotty-library")
val args0: List[String] = spaceDelimited("<arg>").parsed.toList
val args = args0.filter(arg => arg != "-repl")
val decompile = args0.contains("-decompile")
val args = args0.filter(arg => arg != "-repl" || arg != "-decompile")

val main =
if (repl) "dotty.tools.repl.Main"
else if (decompile) "dotty.tools.dotc.decompiler.Main"
else "dotty.tools.dotc.Main"

val fullArgs = main :: insertClasspathInArgs(args, dottyLib)
val extraClasspath =
if (decompile && !args.contains("-classpath")) dottyLib + ":."
else dottyLib

val fullArgs = main :: insertClasspathInArgs(args, extraClasspath)

(runMain in Compile).toTask(fullArgs.mkString(" ", " ", ""))
}
Expand Down
4 changes: 2 additions & 2 deletions project/scripts/sbtBootstrappedTests
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
./project/scripts/sbt dist-bootstrapped/pack

# check that `dotc` compiles and `dotr` runs it
echo "testing sbt dotc and dotr"
echo "testing ./bin/dotc and ./bin/dotr"
mkdir out/scriptedtest0
./bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest0
# FIXME #3477
Expand All @@ -21,7 +21,7 @@ mkdir out/scriptedtest0


# check that `dotc` compiles and `dotr` runs it
echo "testing sbt dotc -from-tasty and dotr -classpath"
echo "testing ./bin/dotc -from-tasty and dotr -classpath"
mkdir out/scriptedtest1
mkdir out/scriptedtest2
./bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest1/
Expand Down
19 changes: 16 additions & 3 deletions project/scripts/sbtTests
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cat sbtdotr1.out
if grep -e "dotr test ok" sbtdotr1.out; then
echo "output ok"
else
echo "failed output check"
exit -1
fi

Expand All @@ -23,13 +24,25 @@ cat sbtdotr2.out
if grep -e "dotr test ok" sbtdotr2.out; then
echo "output ok"
else
echo "failed output check"
exit -1
fi

# check that `sbt dotc -decompile` runs
echo "testing sbt dotc -decompile"
./project/scripts/sbt ";dotc -decompile -code -color:never -classpath out/scriptedtest1 dotrtest.Test" > sbtdotc3.out
cat sbtdotc3.out
if grep -e "def main(args: Array\[String\]): Unit =" sbtdotc3.out; then
echo "output ok"
else
echo "failed output check"
exit -1
fi
echo "testing sbt dotr with no -classpath"

./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala; dotr dotrtest.Test" > sbtdotp1.out
cat sbtdotp1.out
if grep -e "dotr test ok" sbtdotp1.out; then
./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala; dotr dotrtest.Test" > sbtdotr3.out
cat sbtdotr3.out
if grep -e "dotr test ok" sbtdotr3.out; then
echo "output ok"
else
exit -1
Expand Down