diff --git a/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala b/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala index 67ac11104..d7bbba055 100644 --- a/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala +++ b/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala @@ -138,11 +138,12 @@ object ClipboardImpl extends Clipboard { } trait FrontEndAPIImpl extends FrontEndAPI { + protected def parser: ammonite.compiler.iface.Parser def apply(name: String): FrontEnd = name.toLowerCase(Locale.ROOT) match { - case "ammonite" => AmmoniteFrontEnd(ammonite.compiler.Parsers) - case "windows" => new FrontEnds.JLineWindows(ammonite.compiler.Parsers) - case "unix" => new FrontEnds.JLineUnix(ammonite.compiler.Parsers) + case "ammonite" => AmmoniteFrontEnd(parser) + case "windows" => new FrontEnds.JLineWindows(parser) + case "unix" => new FrontEnds.JLineUnix(parser) case _ => throw new NoSuchElementException(s"Front-end $name") } } diff --git a/amm/repl/src/main/scala/ammonite/repl/Repl.scala b/amm/repl/src/main/scala/ammonite/repl/Repl.scala index 7d5ad4fc6..e8d6826df 100644 --- a/amm/repl/src/main/scala/ammonite/repl/Repl.scala +++ b/amm/repl/src/main/scala/ammonite/repl/Repl.scala @@ -7,8 +7,7 @@ import ammonite.runtime._ import ammonite.terminal.Filter import ammonite.util.Util.{newLine, normalizeNewlines} import ammonite.util._ -import ammonite.compiler.Parsers -import ammonite.compiler.iface.CodeWrapper +import ammonite.compiler.iface.{CodeWrapper, CompilerBuilder, Parser} import ammonite.interp.Interpreter import coursierapi.Dependency @@ -29,6 +28,8 @@ class Repl(input: InputStream, scriptCodeWrapper: CodeWrapper, alreadyLoadedDependencies: Seq[Dependency], importHooks: Map[Seq[String], ImportHook], + compilerBuilder: CompilerBuilder, + parser: Parser, initialClassLoader: ClassLoader = classOf[ammonite.repl.api.ReplAPI].getClassLoader, classPathWhitelist: Set[Seq[String]]) { repl => @@ -37,9 +38,9 @@ class Repl(input: InputStream, val frontEnd = Ref[FrontEnd]( if (scala.util.Properties.isWin) - new ammonite.repl.FrontEnds.JLineWindows(ammonite.compiler.Parsers) + new ammonite.repl.FrontEnds.JLineWindows(parser) else - AmmoniteFrontEnd(ammonite.compiler.Parsers, Filter.empty) + AmmoniteFrontEnd(parser, Filter.empty) ) var lastException: Throwable = null @@ -73,8 +74,8 @@ class Repl(input: InputStream, def usedEarlierDefinitions = frames().head.usedEarlierDefinitions val interp = new Interpreter( - ammonite.compiler.CompilerBuilder, - ammonite.compiler.Parsers, + compilerBuilder, + parser, printer, storage, wd, @@ -134,7 +135,9 @@ class Repl(input: InputStream, ( "ammonite.repl.api.FrontEndBridge", "frontEnd", - new FrontEndAPIImpl {} + new FrontEndAPIImpl { + def parser = repl.parser + } ) ) @@ -153,7 +156,7 @@ class Repl(input: InputStream, // running the user code directly. Could be made longer to better warm more // code paths, but then the fixed overhead gets larger so not really worth it val code = s"""val array = Seq.tabulate(10)(_*2).toArray.max""" - val stmts = Parsers.split(code).get.toOption.get + val stmts = parser.split(code).get.toOption.get interp.processLine(code, stmts, 9999999, silent = true, () => () /*donothing*/) } diff --git a/amm/repl/src/test/scala/ammonite/TestRepl.scala b/amm/repl/src/test/scala/ammonite/TestRepl.scala index 1498a9867..718fc0ed9 100644 --- a/amm/repl/src/test/scala/ammonite/TestRepl.scala +++ b/amm/repl/src/test/scala/ammonite/TestRepl.scala @@ -22,7 +22,7 @@ import ammonite.runtime.ImportHook * A test REPL which does not read from stdin or stdout files, but instead lets * you feed in lines or sessions programmatically and have it execute them. */ -class TestRepl { +class TestRepl { self => var allOutput = "" def predef: (String, Option[os.Path]) = ("", None) def codeWrapper: CodeWrapper = DefaultCodeWrapper @@ -63,11 +63,13 @@ class TestRepl { ) val customPredefs = Seq() + val parser = ammonite.compiler.Parsers + var currentLine = 0 val interp = try { new Interpreter( ammonite.compiler.CompilerBuilder, - ammonite.compiler.Parsers, + parser, printer0, storage = storage, wd = os.pwd, @@ -162,7 +164,9 @@ class TestRepl { ( "ammonite.repl.api.FrontEndBridge", "frontEnd", - new FrontEndAPIImpl {} + new FrontEndAPIImpl { + def parser = self.parser + } ) ) diff --git a/amm/src/main/scala/ammonite/Main.scala b/amm/src/main/scala/ammonite/Main.scala index 713925fed..a9867b030 100644 --- a/amm/src/main/scala/ammonite/Main.scala +++ b/amm/src/main/scala/ammonite/Main.scala @@ -5,7 +5,7 @@ import java.net.URLClassLoader import java.nio.file.NoSuchFileException import ammonite.compiler.{CodeClassWrapper, DefaultCodeWrapper} -import ammonite.compiler.iface.CodeWrapper +import ammonite.compiler.iface.{CodeWrapper, CompilerBuilder, Parser} import ammonite.interp.{Watchable, Interpreter, PredefInitialization} import ammonite.interp.script.AmmoniteBuildServer import ammonite.runtime.{Frame, Storage} @@ -76,6 +76,9 @@ case class Main(predefCode: String = "", alreadyLoadedDependencies: Seq[Dependency] = Defaults.alreadyLoadedDependencies(), importHooks: Map[Seq[String], ImportHook] = ImportHook.defaults, + compilerBuilder: CompilerBuilder = ammonite.compiler.CompilerBuilder, + // by-name, so that fastparse isn't loaded when we don't need it + parser: () => Parser = () => ammonite.compiler.Parsers, classPathWhitelist: Set[Seq[String]] = Set.empty){ def loadedPredefFile = predefFile match{ @@ -137,6 +140,8 @@ case class Main(predefCode: String = "", scriptCodeWrapper = scriptCodeWrapper, alreadyLoadedDependencies = alreadyLoadedDependencies, importHooks = importHooks, + compilerBuilder = compilerBuilder, + parser = parser(), initialClassLoader = initialClassLoader, classPathWhitelist = classPathWhitelist ) @@ -161,9 +166,10 @@ case class Main(predefCode: String = "", val customPredefs = predefFileInfoOpt.toSeq ++ Seq( PredefInfo(Name("CodePredef"), predefCode, false, None) ) + lazy val parser0 = parser() val interp = new Interpreter( ammonite.compiler.CompilerBuilder, - ammonite.compiler.Parsers, + parser0, printer, storageBackend, wd, @@ -182,7 +188,9 @@ case class Main(predefCode: String = "", ( "ammonite.repl.api.FrontEndBridge", "frontEnd", - new FrontEndAPIImpl {} + new FrontEndAPIImpl { + def parser = parser0 + } ) ) interp.initializePredef(Seq(), customPredefs, bridges, augmentedImports) match{ @@ -454,6 +462,7 @@ class MainRunner(cliConfig: Config, new Storage.Folder(cliConfig.core.home, isRepl) } + lazy val parser = ammonite.compiler.Parsers val codeWrapper = if (cliConfig.repl.classBased.value) CodeClassWrapper else DefaultCodeWrapper @@ -473,6 +482,7 @@ class MainRunner(cliConfig: Config, colors = colors, replCodeWrapper = codeWrapper, scriptCodeWrapper = codeWrapper, + parser = () => parser, alreadyLoadedDependencies = Defaults.alreadyLoadedDependencies(), classPathWhitelist = ammonite.repl.Repl.getClassPathWhitelist(cliConfig.core.thin.value) diff --git a/build.sc b/build.sc index 1c3a50924..70809c978 100644 --- a/build.sc +++ b/build.sc @@ -283,7 +283,7 @@ object amm extends Cross[MainModule](fullCrossScalaVersions:_*){ ops(), amm.util(), amm.runtime(), amm.interp(), terminal(), - amm.compiler() + amm.compiler.interface() ) def ivyDeps = Agg( ivy"org.jline:jline-terminal:3.14.1", @@ -296,6 +296,7 @@ object amm extends Cross[MainModule](fullCrossScalaVersions:_*){ def crossScalaVersion = ReplModule.this.crossScalaVersion def scalaVersion = ReplModule.this.crossScalaVersion def dependencyResourceFileName = "amm-test-dependencies.txt" + def moduleDeps = super.moduleDeps ++ Seq(amm.compiler()) def thinWhitelist = T{ generateApiWhitelist( @@ -316,7 +317,7 @@ object amm extends Cross[MainModule](fullCrossScalaVersions:_*){ ReplModule.this.externalSources() ++ resolveDeps(ivyDeps, sources = true)()).distinct } - def ivyDeps = super.ivyDeps() ++ Agg( + def ivyDeps = super.ivyDeps() ++ amm.compiler().ivyDeps() ++ Agg( ivy"org.scalaz::scalaz-core:7.2.27" ) } @@ -337,7 +338,8 @@ class MainModule(val crossScalaVersion: String) amm.util(), amm.runtime(), amm.interp.api(), amm.repl.api(), - amm.interp(), amm.repl() + amm.interp(), amm.repl(), + amm.compiler() ) def runClasspath =