Skip to content

Commit c7d1826

Browse files
authored
Merge pull request #1314 from dotty-staging/topic/bridge-repl
Add console to bridge
2 parents 002ed8e + 42030aa commit c7d1826

File tree

9 files changed

+210
-14
lines changed

9 files changed

+210
-14
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* sbt -- Simple Build Tool
2+
* Copyright 2008, 2009 Mark Harrah
3+
*/
4+
package xsbt
5+
6+
import xsbti.Logger
7+
import scala.tools.nsc.{ GenericRunnerCommand, Interpreter, InterpreterLoop, ObjectRunner, Settings }
8+
import scala.tools.nsc.interpreter.InteractiveReader
9+
import scala.tools.nsc.reporters.Reporter
10+
import scala.tools.nsc.util.ClassPath
11+
12+
import dotty.tools.dotc.core.Contexts.Context
13+
import dotty.tools.dotc.repl.REPL
14+
import dotty.tools.dotc.repl.REPL.Config
15+
16+
class ConsoleInterface {
17+
def commandArguments(
18+
args: Array[String],
19+
bootClasspathString: String,
20+
classpathString: String,
21+
log: Logger
22+
): Array[String] = args
23+
24+
def run(args: Array[String],
25+
bootClasspathString: String,
26+
classpathString: String,
27+
initialCommands: String,
28+
cleanupCommands: String,
29+
loader: ClassLoader,
30+
bindNames: Array[String],
31+
bindValues: Array[Any],
32+
log: Logger
33+
): Unit = {
34+
val completeArgs =
35+
args :+
36+
"-bootclasspath" :+ bootClasspathString :+
37+
"-classpath" :+ classpathString
38+
39+
println("Starting dotty interpreter...")
40+
val repl = ConsoleInterface.customRepl(
41+
initialCommands :: Nil,
42+
cleanupCommands :: Nil,
43+
bindNames zip bindValues,
44+
loader
45+
)
46+
repl.process(completeArgs)
47+
}
48+
}
49+
50+
object ConsoleInterface {
51+
def customConfig(
52+
initCmds: List[String],
53+
cleanupCmds: List[String],
54+
boundVals: Array[(String, Any)],
55+
loader: ClassLoader
56+
) = new Config {
57+
override val initialCommands: List[String] = initCmds
58+
override val cleanupCommands: List[String] = cleanupCmds
59+
override val boundValues: Array[(String, Any)] = boundVals
60+
override val classLoader: Option[ClassLoader] = Option(loader)
61+
}
62+
63+
def customRepl(cfg: Config): REPL = new REPL {
64+
override lazy val config = cfg
65+
}
66+
67+
def customRepl(
68+
initCmds: List[String],
69+
cleanupCmds: List[String],
70+
boundVals: Array[(String, Any)],
71+
loader: ClassLoader
72+
): REPL = customRepl(customConfig(initCmds, cleanupCmds, boundVals, loader))
73+
}

project/Build.scala

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ object DottyBuild extends Build {
2525
override def settings: Seq[Setting[_]] = {
2626
super.settings ++ Seq(
2727
scalaVersion in Global := "2.11.5",
28-
version in Global := "0.1-SNAPSHOT",
28+
version in Global :=
29+
"0.1-" + VersionUtil.commitDate + "-" + VersionUtil.gitHash + "-SNAPSHOT",
2930
organization in Global := "ch.epfl.lamp",
3031
organizationName in Global := "LAMP/EPFL",
3132
organizationHomepage in Global := Some(url("http://lamp.epfl.ch")),
@@ -50,7 +51,8 @@ object DottyBuild extends Build {
5051
autoScalaLibrary := false,
5152
//Remove javac invalid options in Compile doc
5253
javacOptions in (Compile, doc) --= Seq("-Xlint:unchecked", "-Xlint:deprecation")
53-
)
54+
).
55+
settings(publishing)
5456

5557
lazy val dotty = project.in(file(".")).
5658
dependsOn(`dotty-interfaces`).
@@ -207,11 +209,15 @@ object DottyBuild extends Build {
207209
"org.scala-sbt" % "api" % sbtVersion.value % "test",
208210
"org.specs2" %% "specs2" % "2.3.11" % "test"
209211
),
210-
version := "0.1.1-SNAPSHOT",
211-
// The sources should be published with crossPaths := false, the binaries
212-
// are unused so it doesn't matter.
212+
version :=
213+
"0.1.1-" + VersionUtil.commitDate + "-" + VersionUtil.gitHash + "-SNAPSHOT",
214+
// The sources should be published with crossPaths := false since they
215+
// need to be compiled by the project using the bridge.
213216
crossPaths := false,
214217

218+
// Don't publish any binaries for the bridge because of the above
219+
publishArtifact in (Compile, packageBin) := false,
220+
215221
fork in Test := true,
216222
parallelExecution in Test := false
217223
).
@@ -244,7 +250,8 @@ object DottyInjectedPlugin extends AutoPlugin {
244250
""")
245251
}
246252
*/
247-
)
253+
).
254+
settings(publishing)
248255

249256

250257
/** A sandbox to play with the Scala.js back-end of dotty.
@@ -329,9 +336,9 @@ object DottyInjectedPlugin extends AutoPlugin {
329336
)
330337

331338
lazy val publishing = Seq(
332-
publishMavenStyle := true,
333339
publishMavenStyle := true,
334340
publishArtifact := true,
341+
isSnapshot := version.value.contains("SNAPSHOT"),
335342
publishTo := {
336343
val nexus = "https://oss.sonatype.org/"
337344
if (isSnapshot.value)
@@ -341,11 +348,47 @@ object DottyInjectedPlugin extends AutoPlugin {
341348
},
342349
publishArtifact in Test := false,
343350
homepage := Some(url("https://github.com/lampepfl/dotty")),
351+
licenses += ("BSD New",
352+
url("https://github.com/lampepfl/dotty/blob/master/LICENSE.md")),
344353
scmInfo := Some(
345354
ScmInfo(
346355
url("https://github.com/lampepfl/dotty"),
347356
"scm:git:[email protected]:lampepfl/dotty.git"
348357
)
358+
),
359+
pomExtra := (
360+
<developers>
361+
<developer>
362+
<id>odersky</id>
363+
<name>Martin Odersky</name>
364+
<email>martin.odersky@epfl.ch</email>
365+
<url>https://github.com/odersky</url>
366+
</developer>
367+
<developer>
368+
<id>DarkDimius</id>
369+
<name>Dmitry Petrashko</name>
370+
<email>me@d-d.me</email>
371+
<url>https://d-d.me</url>
372+
</developer>
373+
<developer>
374+
<id>smarter</id>
375+
<name>Guillaume Martres</name>
376+
<email>smarter@ubuntu.com</email>
377+
<url>http://guillaume.martres.me</url>
378+
</developer>
379+
<developer>
380+
<id>felixmulder</id>
381+
<name>Felix Mulder</name>
382+
<email>felix.mulder@gmail.com</email>
383+
<url>http://felixmulder.com</url>
384+
</developer>
385+
<developer>
386+
<id>liufengyun</id>
387+
<name>Liu Fengyun</name>
388+
<email>liufengyun@chaos-lab.com</email>
389+
<url>http://chaos-lab.com</url>
390+
</developer>
391+
</developers>
349392
)
350393
)
351394

project/VersionUtil.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import scala.sys.process.Process
2+
3+
object VersionUtil {
4+
def executeScript(scriptName: String) = {
5+
val cmd =
6+
if (System.getProperty("os.name").toLowerCase.contains("windows"))
7+
s"cmd.exe /c scripts\\build\\$scriptName.bat -p"
8+
else s"scripts/build/$scriptName"
9+
Process(cmd).lines.head.trim
10+
}
11+
12+
/** Seven letters of the SHA hash is considered enough to uniquely identify a
13+
* commit, albeit extremely large projects - such as the Linux kernel - need
14+
* more letters to stay unique
15+
*/
16+
def gitHash = executeScript("get-scala-commit-sha").substring(0, 7)
17+
def commitDate = executeScript("get-scala-commit-date")
18+
}

scripts/build/get-scala-commit-date

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Usage: get-scala-commit-date [dir]
4+
# Figures out current commit date of a git clone.
5+
# If no dir is given, current working dir is used.
6+
#
7+
# Example build version string:
8+
# 20120312
9+
#
10+
11+
[[ $# -eq 0 ]] || cd "$1"
12+
13+
lastcommitdate=$(git log --format="%ci" HEAD | head -n 1 | cut -d ' ' -f 1)
14+
15+
# 20120324
16+
echo "${lastcommitdate//-/}"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@echo off
2+
for %%X in (bash.exe) do (set FOUND=%%~$PATH:X)
3+
if defined FOUND (
4+
bash "%~dp0\get-scala-commit-date" 2>NUL
5+
) else (
6+
rem echo this script does not work with cmd.exe. please, install bash
7+
echo unknown
8+
exit 1
9+
)

scripts/build/get-scala-commit-sha

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Usage: get-scala-commit-sha [dir]
4+
# Figures out current commit sha of a git clone.
5+
# If no dir is given, current working dir is used.
6+
#
7+
# Example build version string:
8+
# 6f1c486d0ba
9+
#
10+
11+
[[ $# -eq 0 ]] || cd "$1"
12+
13+
# printf %016s is not portable for 0-padding, has to be a digit.
14+
# so we're stuck disassembling it.
15+
hash=$(git log -1 --format="%H" HEAD)
16+
hash=${hash#g}
17+
hash=${hash:0:10}
18+
echo "$hash"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@echo off
2+
for %%X in (bash.exe) do (set FOUND=%%~$PATH:X)
3+
if defined FOUND (
4+
bash "%~dp0\get-scala-commit-sha" 2>NUL
5+
) else (
6+
rem echo this script does not work with cmd.exe. please, install bash
7+
echo unknown
8+
exit 1
9+
)

src/dotty/tools/dotc/repl/CompilingInterpreter.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ import printing.SyntaxHighlighting
6060
* @param ictx The context to use for initialization of the interpreter,
6161
* needed to access the current classpath.
6262
*/
63-
class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler with Interpreter {
63+
class CompilingInterpreter(
64+
out: PrintWriter,
65+
ictx: Context,
66+
parentClassLoader: Option[ClassLoader]
67+
) extends Compiler with Interpreter {
6468
import ast.untpd._
6569
import CompilingInterpreter._
6670

@@ -136,8 +140,6 @@ class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler wit
136140
/** the compiler's classpath, as URL's */
137141
val compilerClasspath: List[URL] = ictx.platform.classPath(ictx).asURLs
138142

139-
protected def parentClassLoader: ClassLoader = classOf[Interpreter].getClassLoader
140-
141143
/* A single class loader is used for all commands interpreted by this Interpreter.
142144
It would also be possible to create a new class loader for each command
143145
to interpret. The advantages of the current approach are:
@@ -153,8 +155,10 @@ class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler wit
153155
*/
154156
/** class loader used to load compiled code */
155157
val classLoader: ClassLoader = {
156-
val parent = new URLClassLoader(compilerClasspath.toArray, parentClassLoader)
157-
new AbstractFileClassLoader(virtualDirectory, parent)
158+
lazy val parent = new URLClassLoader(compilerClasspath.toArray,
159+
classOf[Interpreter].getClassLoader)
160+
161+
new AbstractFileClassLoader(virtualDirectory, parentClassLoader.getOrElse(parent))
158162
}
159163

160164
// Set the current Java "context" class loader to this interpreter's class loader

src/dotty/tools/dotc/repl/REPL.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ package repl
44

55
import core.Contexts.Context
66
import reporting.Reporter
7-
import java.io.{BufferedReader, File, FileReader, PrintWriter}
7+
import io.{AbstractFile, PlainFile, VirtualDirectory}
8+
import scala.reflect.io.{PlainDirectory, Directory}
9+
import java.io.{BufferedReader, File => JFile, FileReader, PrintWriter}
10+
import java.net.{URL, URLClassLoader}
811

912
/** A compiler which stays resident between runs.
1013
* Usage:
@@ -31,7 +34,7 @@ class REPL extends Driver {
3134
}
3235

3336
override def newCompiler(implicit ctx: Context): Compiler =
34-
new repl.CompilingInterpreter(config.output, ctx)
37+
new repl.CompilingInterpreter(config.output, ctx, config.classLoader)
3538

3639
override def sourcesRequired = false
3740

@@ -80,6 +83,9 @@ object REPL {
8083
*/
8184
val boundValues: Array[(String, Any)] = Array.empty[(String, Any)]
8285

86+
/** To pass a custom ClassLoader to the Dotty REPL, overwride this value */
87+
val classLoader: Option[ClassLoader] = None
88+
8389
/** The default input reader */
8490
def input(in: Interpreter)(implicit ctx: Context): InteractiveReader = {
8591
val emacsShell = System.getProperty("env.emacs", "") != ""

0 commit comments

Comments
 (0)