From b47c487c4933f7f35eccb98534fb969935719326 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 3 Nov 2017 17:08:53 +0100 Subject: [PATCH 01/14] Add sbt dotr instuctions for repl --- project/Build.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 0e28abc47f51..356171441964 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -504,15 +504,17 @@ object Build { val args: Seq[String] = spaceDelimited("").parsed val java: String = Process("which" :: "java" :: Nil).!! val attList = (dependencyClasspath in Runtime).value - val _ = packageAll.value + val _ = packageAll.value val scalaLib = attList .map(_.data.getAbsolutePath) .find(_.contains("scala-library")) .toList.mkString(":") - if (java == "") + if (args.isEmpty) { + println("Couldn't run `dotr` without args. Use `repl` to run the repl or add args to run the dotty application") + } else if (java == "") { println("Couldn't find java executable on path, please install java to a default location") - else if (scalaLib == "") { + } else if (scalaLib == "") { println("Couldn't find scala-library on classpath, please run using script in bin dir instead") } else { val dottyLib = packageAll.value("dotty-library") From ec084ec282d6b96428bb8444c887fc8f9ca335d4 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 3 Nov 2017 17:09:27 +0100 Subject: [PATCH 02/14] Factor sbt dotr/repl common init code --- project/Build.scala | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 356171441964..72449bd475b1 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -521,34 +521,9 @@ object Build { s"""$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}""".! } }, - run := Def.inputTaskDyn { - val dottyLib = packageAll.value("dotty-library") - val args: Seq[String] = spaceDelimited("").parsed - - val fullArgs = args.span(_ != "-classpath") match { - case (beforeCp, "-classpath" :: cp :: rest) => beforeCp ++ List("-classpath", cp + ":" + dottyLib) ++ rest - case (beforeCp, _) => beforeCp ++ List("-classpath", dottyLib) - } - - (runMain in Compile).toTask( - s" dotty.tools.dotc.Main " + fullArgs.mkString(" ") - ) - }.evaluated, - dotc := run.evaluated, - - repl := Def.inputTaskDyn { - val dottyLib = packageAll.value("dotty-library") - val args: Seq[String] = spaceDelimited("").parsed - - val fullArgs = args.span(_ != "-classpath") match { - case (beforeCp, "-classpath" :: cp :: rest) => beforeCp ++ List("-classpath", cp + ":" + dottyLib) ++ rest - case (beforeCp, _) => beforeCp ++ List("-classpath", dottyLib) - } - - (runMain in Compile).toTask( - s" dotty.tools.repl.Main " + fullArgs.mkString(" ") - ) - }.evaluated, + run := dotc.evaluated, + dotc := dotDynTask("dotty.tools.dotc.Main").evaluated, + repl := dotDynTask("dotty.tools.repl.Main").evaluated, // enable verbose exception messages for JUnit testOptions in Test += Tests.Argument( @@ -642,6 +617,20 @@ object Build { } ) + def dotDynTask(main: String) = Def.inputTaskDyn { + val dottyLib = packageAll.value("dotty-library") + val args: Seq[String] = spaceDelimited("").parsed + + val fullArgs = main +: { + args.span(_ != "-classpath") match { + case (beforeCp, "-classpath" :: cp :: rest) => beforeCp ++ List("-classpath", cp + ":" + dottyLib) ++ rest + case (beforeCp, _) => beforeCp ++ List("-classpath", dottyLib) + } + } + + (runMain in Compile).toTask(fullArgs.mkString(" ", " ", "")) + } + lazy val nonBootstrapedDottyCompilerSettings = commonDottyCompilerSettings ++ Seq( // Disable scaladoc generation, it's way too slow and we'll replace it // by dottydoc anyway. We still publish an empty -javadoc.jar to make From 5aaed798f1ae940dd2b34cbadeedb4fc26b05f7b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 3 Nov 2017 17:10:11 +0100 Subject: [PATCH 03/14] Add simple regression tests for sbt dotc/dotr --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index eb340cae3d24..4eb8d539353e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -25,7 +25,7 @@ pipeline: image: lampepfl/dotty:2017-10-20 commands: - cp -R . /tmp/1/ && cd /tmp/1/ - - ./project/scripts/sbt ";compile ;testAll ;dotty-bench/jmh:run 1 1 tests/pos/alias.scala" + - ./project/scripts/sbt ";compile ;testAll ;dotty-bench/jmh:run 1 1 tests/pos/alias.scala; ;dotc tests/run/arraycopy.scala ;dotr Test" test_bootstrapped: group: test From 660cb40d5f53a01bda6bb129a4b38112ceb4d2bc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 3 Nov 2017 17:28:11 +0100 Subject: [PATCH 04/14] Improve implementation of sbt dotc --- project/Build.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 72449bd475b1..31bcee369428 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -619,13 +619,12 @@ object Build { def dotDynTask(main: String) = Def.inputTaskDyn { val dottyLib = packageAll.value("dotty-library") - val args: Seq[String] = spaceDelimited("").parsed + val args: List[String] = spaceDelimited("").parsed.toList - val fullArgs = main +: { - args.span(_ != "-classpath") match { - case (beforeCp, "-classpath" :: cp :: rest) => beforeCp ++ List("-classpath", cp + ":" + dottyLib) ++ rest - case (beforeCp, _) => beforeCp ++ List("-classpath", dottyLib) - } + val fullArgs = main :: { + val (beforeCp, fromCp) = args.span(_ != "-classpath") + val classpath = fromCp.drop(1).headOption.fold(dottyLib)(_ + ":" + dottyLib) + beforeCp ::: "-classpath" :: classpath :: fromCp.drop(2) } (runMain in Compile).toTask(fullArgs.mkString(" ", " ", "")) From 47ae1cf8f4afa04f10eb821c6e33e0ad49cb30e3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 7 Nov 2017 11:59:26 +0100 Subject: [PATCH 05/14] Rename sbt dotc/repl abstraction to runCompilerMain --- project/Build.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 31bcee369428..4d165a3eefd9 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -518,12 +518,12 @@ object Build { println("Couldn't find scala-library on classpath, please run using script in bin dir instead") } else { val dottyLib = packageAll.value("dotty-library") - s"""$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}""".! + s"$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}".! } }, run := dotc.evaluated, - dotc := dotDynTask("dotty.tools.dotc.Main").evaluated, - repl := dotDynTask("dotty.tools.repl.Main").evaluated, + dotc := runCompilerMain("dotty.tools.dotc.Main").evaluated, + repl := runCompilerMain("dotty.tools.repl.Main").evaluated, // enable verbose exception messages for JUnit testOptions in Test += Tests.Argument( @@ -617,7 +617,7 @@ object Build { } ) - def dotDynTask(main: String) = Def.inputTaskDyn { + def runCompilerMain(main: String) = Def.inputTaskDyn { val dottyLib = packageAll.value("dotty-library") val args: List[String] = spaceDelimited("").parsed.toList From 20c72f4e383fcb9ff8d155dc98785711cd431297 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 7 Nov 2017 13:10:03 +0100 Subject: [PATCH 06/14] Move sbt tests to scripted tests --- .drone.yml | 6 ++++-- project/scripts/sbtBootstrappedTests | 4 ++++ project/scripts/sbtTests | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100755 project/scripts/sbtBootstrappedTests create mode 100755 project/scripts/sbtTests diff --git a/.drone.yml b/.drone.yml index 4eb8d539353e..bf0f60506a29 100644 --- a/.drone.yml +++ b/.drone.yml @@ -25,14 +25,16 @@ pipeline: image: lampepfl/dotty:2017-10-20 commands: - cp -R . /tmp/1/ && cd /tmp/1/ - - ./project/scripts/sbt ";compile ;testAll ;dotty-bench/jmh:run 1 1 tests/pos/alias.scala; ;dotc tests/run/arraycopy.scala ;dotr Test" + - ./project/scripts/sbt ";compile ;testAll" + - ./project/scripts/sbtTests test_bootstrapped: group: test image: lampepfl/dotty:2017-10-20 commands: - cp -R . /tmp/2/ && cd /tmp/2/ - - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/testAll ;dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" + - ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/testAll" + - ./project/scripts/sbtBootstrappedTests test_optimised: group: test diff --git a/project/scripts/sbtBootstrappedTests b/project/scripts/sbtBootstrappedTests new file mode 100755 index 000000000000..a16a129c3e3b --- /dev/null +++ b/project/scripts/sbtBootstrappedTests @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# check that benchmarks can run +./project/scripts/sbt "dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" diff --git a/project/scripts/sbtTests b/project/scripts/sbtTests new file mode 100755 index 000000000000..e2fe686b394e --- /dev/null +++ b/project/scripts/sbtTests @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# check that benchmarks can run +./project/scripts/sbt "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" + +# check that `dotc` compiles and `dotr` runs it +./project/scripts/sbt ";dotc tests/run/arraycopy.scala ;dotr Test" From e133b9e59270674d55f7f02e14f6b83f703c19ba Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 7 Nov 2017 13:52:20 +0100 Subject: [PATCH 07/14] Check sbt dotr output --- project/scripts/sbtTests | 8 +++++++- tests/pos/sbtDotrTest.scala | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/pos/sbtDotrTest.scala diff --git a/project/scripts/sbtTests b/project/scripts/sbtTests index e2fe686b394e..dd8729391778 100755 --- a/project/scripts/sbtTests +++ b/project/scripts/sbtTests @@ -4,4 +4,10 @@ ./project/scripts/sbt "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" # check that `dotc` compiles and `dotr` runs it -./project/scripts/sbt ";dotc tests/run/arraycopy.scala ;dotr Test" +echo "testing sbt dotc and dotr" +./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala ;dotr dotrtest.Test" > sbtdotr.out +if grep -e "dotr test ok" sbtdotr.out; then + echo "output ok" +else + exit -1 +fi diff --git a/tests/pos/sbtDotrTest.scala b/tests/pos/sbtDotrTest.scala new file mode 100644 index 000000000000..b7e525886292 --- /dev/null +++ b/tests/pos/sbtDotrTest.scala @@ -0,0 +1,7 @@ +package dotrtest + +object Test { + def main(args: Array[String]): Unit = { + println("dotr test ok") + } +} From 26cdb57c9b39027460b65dad4da655c575176604 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 12 Nov 2017 15:22:05 +0100 Subject: [PATCH 08/14] Fix dotr -tasty --- dist/bin/dotc | 2 +- project/Build.scala | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/dist/bin/dotc b/dist/bin/dotc index 3eb596fa15d7..8d70cce6b1b6 100755 --- a/dist/bin/dotc +++ b/dist/bin/dotc @@ -82,7 +82,7 @@ case "$1" in # Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 -Oshort) addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" && shift ;; -repl) PROG_NAME="$ReplMain" && shift ;; - -tasty) PROG_NAME="$FromTasty" && shift ;; + -tasty) addScala "-Yretain-trees" && PROG_NAME="$FromTasty" && shift ;; -compile) PROG_NAME="$CompilerMain" && shift ;; -run) PROG_NAME="$ReplMain" && shift ;; -bootcp) bootcp=true && shift ;; diff --git a/project/Build.scala b/project/Build.scala index 4d165a3eefd9..fdd417462bff 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -522,8 +522,8 @@ object Build { } }, run := dotc.evaluated, - dotc := runCompilerMain("dotty.tools.dotc.Main").evaluated, - repl := runCompilerMain("dotty.tools.repl.Main").evaluated, + dotc := runCompilerMain(Nil).evaluated, + repl := runCompilerMain(List("-repl")).evaluated, // enable verbose exception messages for JUnit testOptions in Test += Tests.Argument( @@ -617,11 +617,24 @@ object Build { } ) - def runCompilerMain(main: String) = Def.inputTaskDyn { + def runCompilerMain(otherArgs: List[String]) = Def.inputTaskDyn { val dottyLib = packageAll.value("dotty-library") - val args: List[String] = spaceDelimited("").parsed.toList + val args0: List[String] = spaceDelimited("").parsed.toList ++ otherArgs + val args = args0.filter(arg => arg != "-tasty" && arg != "-repl") - val fullArgs = main :: { + val repl = args0.contains("-repl") + val tasty = args0.contains("-tasty") + + val main = + if (repl) "dotty.tools.repl.Main" + else if (tasty) "dotty.tools.dotc.FromTasty" + else "dotty.tools.dotc.Main" + + val extraArgs = + if (tasty && !args.contains("-Yretain-trees")) List("-Yretain-trees") + else Nil + + val fullArgs = main :: extraArgs ::: { val (beforeCp, fromCp) = args.span(_ != "-classpath") val classpath = fromCp.drop(1).headOption.fold(dottyLib)(_ + ":" + dottyLib) beforeCp ::: "-classpath" :: classpath :: fromCp.drop(2) From 106b15d42cd1beb1ce2d7b1662110316d5765496 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 12 Nov 2017 15:42:09 +0100 Subject: [PATCH 09/14] Fix sbt dotr with -classpath --- project/Build.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index fdd417462bff..9f37bb9c8e4a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -501,7 +501,7 @@ object Build { // Override run to be able to run compiled classfiles dotr := { - val args: Seq[String] = spaceDelimited("").parsed + val args: List[String] = spaceDelimited("").parsed.toList val java: String = Process("which" :: "java" :: Nil).!! val attList = (dependencyClasspath in Runtime).value val _ = packageAll.value @@ -518,7 +518,8 @@ object Build { println("Couldn't find scala-library on classpath, please run using script in bin dir instead") } else { val dottyLib = packageAll.value("dotty-library") - s"$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}".! + val fullArgs = insertClasspathInArgs(args, s".:$dottyLib:$scalaLib") + s"$java ${fullArgs.mkString(" ")}".! } }, run := dotc.evaluated, @@ -634,15 +635,17 @@ object Build { if (tasty && !args.contains("-Yretain-trees")) List("-Yretain-trees") else Nil - val fullArgs = main :: extraArgs ::: { - val (beforeCp, fromCp) = args.span(_ != "-classpath") - val classpath = fromCp.drop(1).headOption.fold(dottyLib)(_ + ":" + dottyLib) - beforeCp ::: "-classpath" :: classpath :: fromCp.drop(2) - } + val fullArgs = main :: extraArgs ::: insertClasspathInArgs(args, dottyLib) (runMain in Compile).toTask(fullArgs.mkString(" ", " ", "")) } + def insertClasspathInArgs(args: List[String], cp: String): List[String] = { + val (beforeCp, fromCp) = args.span(_ != "-classpath") + val classpath = fromCp.drop(1).headOption.fold(cp)(_ + ":" + cp) + beforeCp ::: "-classpath" :: classpath :: fromCp.drop(2) + } + lazy val nonBootstrapedDottyCompilerSettings = commonDottyCompilerSettings ++ Seq( // Disable scaladoc generation, it's way too slow and we'll replace it // by dottydoc anyway. We still publish an empty -javadoc.jar to make From 6889d443220a16cb8642de946a40c8dad6a9d815 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 12 Nov 2017 15:43:02 +0100 Subject: [PATCH 10/14] Add regression test for `dotc -tasty` and `dotr -classpath` --- project/scripts/sbtTests | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/project/scripts/sbtTests b/project/scripts/sbtTests index dd8729391778..d10f784428c9 100755 --- a/project/scripts/sbtTests +++ b/project/scripts/sbtTests @@ -5,8 +5,20 @@ # check that `dotc` compiles and `dotr` runs it echo "testing sbt dotc and dotr" -./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala ;dotr dotrtest.Test" > sbtdotr.out -if grep -e "dotr test ok" sbtdotr.out; then +mkdir out/scriptedtest0 +./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest0 ;dotr -classpath out/scriptedtest0 dotrtest.Test" > sbtdotr1.out +if grep -e "dotr test ok" sbtdotr1.out; then + echo "output ok" +else + exit -1 +fi + +# check that `dotc` compiles and `dotr` runs it +echo "testing sbt dotc -tasty and dotr -classpath" +mkdir out/scriptedtest1 +mkdir out/scriptedtest2 +./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest1/; dotc -tasty -classpath out/scriptedtest1/ -d out/scriptedtest2/ dotrtest.Test; dotr -classpath out/scriptedtest2/ dotrtest.Test" > sbtdotr2.out +if grep -e "dotr test ok" sbtdotr2.out; then echo "output ok" else exit -1 From 178402e3e0d5f9cbfc62a8deb800074b55df441f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 14 Nov 2017 08:45:20 +0100 Subject: [PATCH 11/14] Extract inner classes from FromTasty --- compiler/src/dotty/tools/dotc/FromTasty.scala | 97 +------------------ .../fromtasty/ReadTastyTreesFromClasses.scala | 66 +++++++++++++ .../dotc/fromtasty/TASTYCompilationUnit.scala | 8 ++ .../tools/dotc/fromtasty/TASTYCompiler.scala | 24 +++++ .../dotty/tools/dotc/fromtasty/TASTYRun.scala | 12 +++ 5 files changed, 113 insertions(+), 94 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala create mode 100644 compiler/src/dotty/tools/dotc/fromtasty/TASTYCompilationUnit.scala create mode 100644 compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala create mode 100644 compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala diff --git a/compiler/src/dotty/tools/dotc/FromTasty.scala b/compiler/src/dotty/tools/dotc/FromTasty.scala index a9114826b86d..8b88ed1ab719 100644 --- a/compiler/src/dotty/tools/dotc/FromTasty.scala +++ b/compiler/src/dotty/tools/dotc/FromTasty.scala @@ -2,22 +2,10 @@ * Copyright 2005-2015 LAMP/EPFL * @author Martin Odersky */ -package dotty.tools -package dotc +package dotty.tools.dotc -import core._ -import Contexts._ -import Symbols._ -import SymDenotations._ -import typer.FrontEnd -import Phases.Phase -import util._ -import Decorators._ -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core._ -import dotty.tools.dotc.core.Names._ -import dotty.tools.dotc.core.NameOps._ -import dotty.tools.dotc.transform.Pickler +import dotty.tools.dotc.core.Contexts._ +import dotty.tools.dotc.fromtasty.TASTYCompiler /** Compiler for TASTY files. * Usage: @@ -32,83 +20,4 @@ import dotty.tools.dotc.transform.Pickler */ object FromTasty extends Driver { override def newCompiler(implicit ctx: Context): Compiler = new TASTYCompiler - - class TASTYCompiler extends Compiler { - - override def phases: List[List[Phase]] = { - val backendPhases = super.phases.dropWhile { - case List(_: Pickler) => false - case _ => true - }.tail - List(new ReadTastyTreesFromClasses) :: backendPhases - } - - override def newRun(implicit ctx: Context): Run = { - reset() - new TASTYRun(this, ctx) - } - } - - class TASTYRun(comp: Compiler, ictx: Context) extends Run(comp, ictx) { - override def compile(classNames: List[String]) = { - units = classNames.map(new TASTYCompilationUnit(_)) - compileUnits() - } - } - - class TASTYCompilationUnit(val className: String) extends CompilationUnit(NoSource) { - override def toString = s"class file $className" - } - - class ReadTastyTreesFromClasses extends FrontEnd { - - override def isTyper = false - - override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = - units.flatMap(readTASTY) - - def readTASTY(unit: CompilationUnit)(implicit ctx: Context): Option[CompilationUnit] = unit match { - case unit: TASTYCompilationUnit => - assert(ctx.settings.YretainTrees.value) - val className = unit.className.toTypeName - def compilationUnit(className: TypeName): Option[CompilationUnit] = { - tree(className).flatMap { case (clsd, unpickled) => - if (unpickled.isEmpty) None - else Some(CompilationUnit.mkCompilationUnit(clsd, unpickled, forceTrees = true)) - } - } - // The TASTY section in a/b/C.class may either contain a class a.b.C, an object a.b.C, or both. - // We first try to load the class and fallback to loading the object if the class doesn't exist. - // Note that if both the class and the object are present, then loading the class will also load - // the object, this is why we use orElse here, otherwise we could load the object twice and - // create ambiguities! - compilationUnit(className).orElse(compilationUnit(className.moduleClassName)) - } - - private def tree(className: TypeName)(implicit ctx: Context): Option[(ClassDenotation, tpd.Tree)] = { - val clsd = ctx.base.staticRef(className) - ctx.base.staticRef(className) match { - case clsd: ClassDenotation => - def cannotUnpickle(reason: String) = - ctx.error(s"class $className cannot be unpickled because $reason") - def tryToLoad = clsd.infoOrCompleter match { - case info: ClassfileLoader => - info.load(clsd) - Option(clsd.symbol.asClass.tree).orElse { - cannotUnpickle(s"its class file ${info.classfile} does not have a TASTY attribute") - None - } - - case info => - cannotUnpickle(s"its info of type ${info.getClass} is not a ClassfileLoader") - None - } - Option(clsd.symbol.asClass.tree).orElse(tryToLoad).map(tree => (clsd, tree)) - - case _ => - ctx.error(s"class not found: $className") - None - } - } - } } diff --git a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala new file mode 100644 index 000000000000..d212a9dd7d3f --- /dev/null +++ b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala @@ -0,0 +1,66 @@ +package dotty.tools +package dotc +package fromtasty + +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.Names._ +import dotty.tools.dotc.core.NameOps._ +import dotty.tools.dotc.core.SymDenotations.ClassDenotation +import dotty.tools.dotc.core._ +import dotty.tools.dotc.typer.FrontEnd + +class ReadTastyTreesFromClasses extends FrontEnd { + + override def isTyper = false + + override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = + units.flatMap(readTASTY) + + def readTASTY(unit: CompilationUnit)(implicit ctx: Context): Option[CompilationUnit] = unit match { + case unit: TASTYCompilationUnit => + assert(ctx.settings.YretainTrees.value) + val className = unit.className.toTypeName + def compilationUnit(className: TypeName): Option[CompilationUnit] = { + tree(className).flatMap { + case (clsd, unpickled) => + if (unpickled.isEmpty) None + else Some(CompilationUnit.mkCompilationUnit(clsd, unpickled, forceTrees = true)) + + } + } + // The TASTY section in a/b/C.class may either contain a class a.b.C, an object a.b.C, or both. + // We first try to load the class and fallback to loading the object if the class doesn't exist. + // Note that if both the class and the object are present, then loading the class will also load + // the object, this is why we use orElse here, otherwise we could load the object twice and + // create ambiguities! + compilationUnit(className).orElse(compilationUnit(className.moduleClassName)) + } + + private def tree(className: TypeName)(implicit ctx: Context): Option[(ClassDenotation, tpd.Tree)] = { + val clsd = ctx.base.staticRef(className) + ctx.base.staticRef(className) match { + case clsd: ClassDenotation => + def cannotUnpickle(reason: String) = + ctx.error(s"class $className cannot be unpickled because $reason") + def tryToLoad = clsd.infoOrCompleter match { + case info: ClassfileLoader => + info.load(clsd) + Option(clsd.symbol.asClass.tree).orElse { + cannotUnpickle(s"its class file ${info.classfile} does not have a TASTY attribute") + None + } + + case info => + cannotUnpickle(s"its info of type ${info.getClass} is not a ClassfileLoader") + None + } + Option(clsd.symbol.asClass.tree).orElse(tryToLoad).map(tree => (clsd, tree)) + + case _ => + ctx.error(s"class not found: $className") + None + } + } +} diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompilationUnit.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompilationUnit.scala new file mode 100644 index 000000000000..1e7360a8662c --- /dev/null +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompilationUnit.scala @@ -0,0 +1,8 @@ +package dotty.tools.dotc.fromtasty + +import dotty.tools.dotc.CompilationUnit +import dotty.tools.dotc.util.NoSource + +class TASTYCompilationUnit(val className: String) extends CompilationUnit(NoSource) { + override def toString = s"class file $className" +} diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala new file mode 100644 index 000000000000..80184d05317b --- /dev/null +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala @@ -0,0 +1,24 @@ +package dotty.tools +package dotc +package fromtasty + +import core._ +import Contexts._ +import Phases.Phase +import dotty.tools.dotc.transform.Pickler + +class TASTYCompiler extends Compiler { + + override def phases: List[List[Phase]] = { + val backendPhases = super.phases.dropWhile { + case List(_: Pickler) => false + case _ => true + }.tail + List(new ReadTastyTreesFromClasses) :: backendPhases + } + + override def newRun(implicit ctx: Context): Run = { + reset() + new TASTYRun(this, ctx) + } +} diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala new file mode 100644 index 000000000000..9b360ea1056f --- /dev/null +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala @@ -0,0 +1,12 @@ +package dotty.tools +package dotc +package fromtasty + +import core.Contexts._ + +class TASTYRun(comp: Compiler, ictx: Context) extends Run(comp, ictx) { + override def compile(classNames: List[String]) = { + units = classNames.map(new TASTYCompilationUnit(_)) + compileUnits() + } +} From fdbab4837096eb870b1410bcd1c09265b8455b4f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 14 Nov 2017 09:13:15 +0100 Subject: [PATCH 12/14] Make -tasty a ScalaSettings flag and remove FromTasty --- compiler/src/dotty/tools/dotc/Driver.scala | 5 +++- compiler/src/dotty/tools/dotc/FromTasty.scala | 23 ------------------- compiler/src/dotty/tools/dotc/Main.scala | 2 -- .../tools/dotc/config/ScalaSettings.scala | 1 + .../dotty/tools/vulpix/ParallelTesting.scala | 6 +++-- dist/bin/dotc | 3 +-- project/Build.scala | 12 ++++------ 7 files changed, 15 insertions(+), 37 deletions(-) delete mode 100644 compiler/src/dotty/tools/dotc/FromTasty.scala diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 8e2c1910dcd6..349147dc81a9 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -6,6 +6,7 @@ import core.Contexts.{Context, ContextBase} import util.DotClass import reporting._ import scala.util.control.NonFatal +import fromtasty.TASTYCompiler /** Run the Dotty compiler. * @@ -15,7 +16,9 @@ import scala.util.control.NonFatal */ class Driver extends DotClass { - protected def newCompiler(implicit ctx: Context): Compiler = new Compiler + protected def newCompiler(implicit ctx: Context): Compiler = + if (ctx.settings.tasty.value) new TASTYCompiler + else new Compiler protected def emptyReporter: Reporter = new StoreReporter(null) diff --git a/compiler/src/dotty/tools/dotc/FromTasty.scala b/compiler/src/dotty/tools/dotc/FromTasty.scala deleted file mode 100644 index 8b88ed1ab719..000000000000 --- a/compiler/src/dotty/tools/dotc/FromTasty.scala +++ /dev/null @@ -1,23 +0,0 @@ -/* dotc - * Copyright 2005-2015 LAMP/EPFL - * @author Martin Odersky - */ -package dotty.tools.dotc - -import dotty.tools.dotc.core.Contexts._ -import dotty.tools.dotc.fromtasty.TASTYCompiler - -/** Compiler for TASTY files. - * Usage: - * - * scala dotty.tools.dotc.FromTasty (option | classname)* - * - * Options are as for dotc. - * Classnames are fully qualified names of top-level classes that need to have a TASTY attribute. - * Example: - * - * scala dotty.tools.dotc.FromTasty -Xprint:front extMethods.T - */ -object FromTasty extends Driver { - override def newCompiler(implicit ctx: Context): Compiler = new TASTYCompiler -} diff --git a/compiler/src/dotty/tools/dotc/Main.scala b/compiler/src/dotty/tools/dotc/Main.scala index 5ba3f35b0cc9..3288fded52a2 100644 --- a/compiler/src/dotty/tools/dotc/Main.scala +++ b/compiler/src/dotty/tools/dotc/Main.scala @@ -1,7 +1,5 @@ package dotty.tools package dotc -import core.Contexts.Context - /** Main class of the `dotc` batch compiler. */ object Main extends Driver diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index f921ce5041a9..776c9ee9d0d6 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -43,6 +43,7 @@ class ScalaSettings extends Settings.SettingGroup { val language = MultiStringSetting("-language", "feature", "Enable one or more language features.") val rewrite = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax") val silentWarnings = BooleanSetting("-nowarn", "Silence all warnings.") + val tasty = BooleanSetting("-tasty", "Compile classes from tasty in classpath. The arguments are used as class names.") /** -X "Advanced" settings */ diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index deb7cf182bd1..e383c1581927 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -395,7 +395,7 @@ trait ParallelTesting extends RunnerOrchestration { self => protected def compileFromTasty(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { val tastyOutput = new JFile(targetDir.getPath + "_from-tasty") tastyOutput.mkdir() - val flags = flags0 and ("-d", tastyOutput.getAbsolutePath) + val flags = flags0 and ("-d", tastyOutput.getAbsolutePath) and "-tasty" def hasTastyFileToClassName(f: JFile): String = targetDir.toPath.relativize(f.toPath).toString.dropRight(".hasTasty".length).replace('/', '.') @@ -405,9 +405,11 @@ trait ParallelTesting extends RunnerOrchestration { self => TestReporter.reporter(realStdout, logLevel = if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) + val driver = new Driver + // Compile with a try to catch any StackTrace generated by the compiler: try { - dotc.FromTasty.process(flags.all ++ classes, reporter = reporter) + driver.process(flags.all ++ classes, reporter = reporter) } catch { case NonFatal(ex) => reporter.logStackTrace(ex) diff --git a/dist/bin/dotc b/dist/bin/dotc index 8d70cce6b1b6..e51a95ef7f79 100755 --- a/dist/bin/dotc +++ b/dist/bin/dotc @@ -31,7 +31,6 @@ default_java_opts="-Xmx768m -Xms768m" bootcp=true CompilerMain=dotty.tools.dotc.Main -FromTasty=dotty.tools.dotc.FromTasty ReplMain=dotty.tools.repl.Main PROG_NAME=$CompilerMain @@ -82,7 +81,7 @@ case "$1" in # Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 -Oshort) addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" && shift ;; -repl) PROG_NAME="$ReplMain" && shift ;; - -tasty) addScala "-Yretain-trees" && PROG_NAME="$FromTasty" && shift ;; + -tasty) addScala "-Yretain-trees" && PROG_NAME="$CompilerMain" && shift ;; -compile) PROG_NAME="$CompilerMain" && shift ;; -run) PROG_NAME="$ReplMain" && shift ;; -bootcp) bootcp=true && shift ;; diff --git a/project/Build.scala b/project/Build.scala index 9f37bb9c8e4a..7658c875e9fa 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -523,8 +523,8 @@ object Build { } }, run := dotc.evaluated, - dotc := runCompilerMain(Nil).evaluated, - repl := runCompilerMain(List("-repl")).evaluated, + dotc := runCompilerMain(false).evaluated, + repl := runCompilerMain(true).evaluated, // enable verbose exception messages for JUnit testOptions in Test += Tests.Argument( @@ -618,17 +618,15 @@ object Build { } ) - def runCompilerMain(otherArgs: List[String]) = Def.inputTaskDyn { + def runCompilerMain(repl: Boolean) = Def.inputTaskDyn { val dottyLib = packageAll.value("dotty-library") - val args0: List[String] = spaceDelimited("").parsed.toList ++ otherArgs - val args = args0.filter(arg => arg != "-tasty" && arg != "-repl") + val args0: List[String] = spaceDelimited("").parsed.toList + val args = args0.filter(arg => arg != "-repl") - val repl = args0.contains("-repl") val tasty = args0.contains("-tasty") val main = if (repl) "dotty.tools.repl.Main" - else if (tasty) "dotty.tools.dotc.FromTasty" else "dotty.tools.dotc.Main" val extraArgs = From 6706b9e95d7305d379fb1ba453b423bfdb0d0ee8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 15 Nov 2017 11:53:15 +0100 Subject: [PATCH 13/14] Do not insert -Yretain-trees when compiling with -tasty --- .../dotty/tools/dotc/core/SymbolLoaders.scala | 5 ++- .../fromtasty/ReadTastyTreesFromClasses.scala | 1 - .../dotty/tools/vulpix/ParallelTesting.scala | 2 +- dist/bin/dotc | 1 - project/Build.scala | 8 +---- project/scripts/sbtBootstrappedTests | 31 +++++++++++++++++++ project/scripts/sbtTests | 4 +-- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 895147f6065e..abe7ff5a2ae7 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -326,7 +326,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { val (classRoot, moduleRoot) = rootDenots(root.asClass) val classfileParser = new ClassfileParser(classfile, classRoot, moduleRoot)(ctx) val result = classfileParser.run() - if (ctx.settings.YretainTrees.value || ctx.settings.XlinkOptimise.value) { + if (mayLoadTreesFromTasty) { result match { case Some(unpickler: tasty.DottyUnpickler) => classRoot.symbol.asClass.unpickler = unpickler @@ -335,6 +335,9 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { } } } + + private def mayLoadTreesFromTasty(implicit ctx: Context): Boolean = + ctx.settings.YretainTrees.value || ctx.settings.XlinkOptimise.value || ctx.settings.tasty.value } class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader { diff --git a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala index d212a9dd7d3f..9ba0a19ca311 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala @@ -20,7 +20,6 @@ class ReadTastyTreesFromClasses extends FrontEnd { def readTASTY(unit: CompilationUnit)(implicit ctx: Context): Option[CompilationUnit] = unit match { case unit: TASTYCompilationUnit => - assert(ctx.settings.YretainTrees.value) val className = unit.className.toTypeName def compilationUnit(className: TypeName): Option[CompilationUnit] = { tree(className).flatMap { diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index e383c1581927..ec9fd31ce5d8 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -1099,7 +1099,7 @@ trait ParallelTesting extends RunnerOrchestration { self => val target = JointCompilationSource( testGroup.name, Array(sourceFile), - flags.withClasspath(tastySource.getPath) and "-Yretain-trees", + flags.withClasspath(tastySource.getPath) and "-tasty", tastySource, fromTasty = true ) diff --git a/dist/bin/dotc b/dist/bin/dotc index e51a95ef7f79..15a34b8af32e 100755 --- a/dist/bin/dotc +++ b/dist/bin/dotc @@ -81,7 +81,6 @@ case "$1" in # Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 -Oshort) addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" && shift ;; -repl) PROG_NAME="$ReplMain" && shift ;; - -tasty) addScala "-Yretain-trees" && PROG_NAME="$CompilerMain" && shift ;; -compile) PROG_NAME="$CompilerMain" && shift ;; -run) PROG_NAME="$ReplMain" && shift ;; -bootcp) bootcp=true && shift ;; diff --git a/project/Build.scala b/project/Build.scala index 7658c875e9fa..56f49ae7dd31 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -623,17 +623,11 @@ object Build { val args0: List[String] = spaceDelimited("").parsed.toList val args = args0.filter(arg => arg != "-repl") - val tasty = args0.contains("-tasty") - val main = if (repl) "dotty.tools.repl.Main" else "dotty.tools.dotc.Main" - val extraArgs = - if (tasty && !args.contains("-Yretain-trees")) List("-Yretain-trees") - else Nil - - val fullArgs = main :: extraArgs ::: insertClasspathInArgs(args, dottyLib) + val fullArgs = main :: insertClasspathInArgs(args, dottyLib) (runMain in Compile).toTask(fullArgs.mkString(" ", " ", "")) } diff --git a/project/scripts/sbtBootstrappedTests b/project/scripts/sbtBootstrappedTests index a16a129c3e3b..9dcd382f7e4e 100755 --- a/project/scripts/sbtBootstrappedTests +++ b/project/scripts/sbtBootstrappedTests @@ -2,3 +2,34 @@ # check that benchmarks can run ./project/scripts/sbt "dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" + + +# setup for `dotc`/`dotr` script tests +./project/scripts/sbt dist-bootstrapped/pack + +# check that `dotc` compiles and `dotr` runs it +echo "testing sbt dotc and dotr" +mkdir out/scriptedtest0 +./dist-bootstrapped/target/pack/bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest0 +# FIXME #3477 +#./dist-bootstrapped/target/pack/bin/dotr -classpath out/scriptedtest0 dotrtest.Test" > sbtdotr1.out +#if grep -e "dotr test ok" sbtdotr1.out; then +# echo "output ok" +#else +# exit -1 +#fi + + +# check that `dotc` compiles and `dotr` runs it +echo "testing sbt dotc -tasty and dotr -classpath" +mkdir out/scriptedtest1 +mkdir out/scriptedtest2 +./dist-bootstrapped/target/pack/bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest1/ +./dist-bootstrapped/target/pack/bin/dotc -tasty -classpath out/scriptedtest1/ -d out/scriptedtest2/ dotrtest.Test +# FIXME #3477 +#./dist-bootstrapped/target/pack/bin/dotr -classpath out/scriptedtest2/ dotrtest.Test" > sbtdotr2.out +#if grep -e "dotr test ok" sbtdotr2.out; then +# echo "output ok" +#else +# exit -1 +#fi diff --git a/project/scripts/sbtTests b/project/scripts/sbtTests index d10f784428c9..f1bc42113281 100755 --- a/project/scripts/sbtTests +++ b/project/scripts/sbtTests @@ -3,7 +3,7 @@ # check that benchmarks can run ./project/scripts/sbt "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" -# check that `dotc` compiles and `dotr` runs it +# check that `sbt dotc` compiles and `sbt dotr` runs it echo "testing sbt dotc and dotr" mkdir out/scriptedtest0 ./project/scripts/sbt ";dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest0 ;dotr -classpath out/scriptedtest0 dotrtest.Test" > sbtdotr1.out @@ -13,7 +13,7 @@ else exit -1 fi -# check that `dotc` compiles and `dotr` runs it +# check that `sbt dotc` compiles and `sbt dotr` runs it echo "testing sbt dotc -tasty and dotr -classpath" mkdir out/scriptedtest1 mkdir out/scriptedtest2 From faedad728078207b908689dde0f0c85f0be3df71 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 15 Nov 2017 15:09:14 +0100 Subject: [PATCH 14/14] Change dist-bootstrapped/target/pack/bin to bin --- project/scripts/sbtBootstrappedTests | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/project/scripts/sbtBootstrappedTests b/project/scripts/sbtBootstrappedTests index 9dcd382f7e4e..587b43cd54c2 100755 --- a/project/scripts/sbtBootstrappedTests +++ b/project/scripts/sbtBootstrappedTests @@ -10,9 +10,9 @@ # check that `dotc` compiles and `dotr` runs it echo "testing sbt dotc and dotr" mkdir out/scriptedtest0 -./dist-bootstrapped/target/pack/bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest0 +./bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest0 # FIXME #3477 -#./dist-bootstrapped/target/pack/bin/dotr -classpath out/scriptedtest0 dotrtest.Test" > sbtdotr1.out +#./bin/dotr -classpath out/scriptedtest0 dotrtest.Test" > sbtdotr1.out #if grep -e "dotr test ok" sbtdotr1.out; then # echo "output ok" #else @@ -24,10 +24,10 @@ mkdir out/scriptedtest0 echo "testing sbt dotc -tasty and dotr -classpath" mkdir out/scriptedtest1 mkdir out/scriptedtest2 -./dist-bootstrapped/target/pack/bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest1/ -./dist-bootstrapped/target/pack/bin/dotc -tasty -classpath out/scriptedtest1/ -d out/scriptedtest2/ dotrtest.Test +./bin/dotc tests/pos/sbtDotrTest.scala -d out/scriptedtest1/ +./bin/dotc -tasty -classpath out/scriptedtest1/ -d out/scriptedtest2/ dotrtest.Test # FIXME #3477 -#./dist-bootstrapped/target/pack/bin/dotr -classpath out/scriptedtest2/ dotrtest.Test" > sbtdotr2.out +#./bin/dotr -classpath out/scriptedtest2/ dotrtest.Test" > sbtdotr2.out #if grep -e "dotr test ok" sbtdotr2.out; then # echo "output ok" #else