summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala20
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala41
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplDir.scala48
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/library/scala/collection/immutable/Stream.scala45
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala4
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala5
-rw-r--r--test/files/run/repl-out-dir.check53
-rw-r--r--test/files/run/repl-out-dir.scala13
-rw-r--r--test/files/run/streams.check1
-rw-r--r--test/files/run/streams.scala5
-rw-r--r--test/files/run/t6223.check2
-rw-r--r--test/files/run/t6223.scala2
-rw-r--r--test/files/run/t6584.check8
-rw-r--r--test/files/run/t6584.scala16
15 files changed, 214 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index f4921e79e5..18222794a8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -46,6 +46,16 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
getFile(outputDirectory(sym), clsName, suffix)
+ /** From the reference documentation of the Android SDK:
+ * The `Parcelable` interface identifies classes whose instances can be written to and restored from a `Parcel`.
+ * Classes implementing the `Parcelable` interface must also have a static field called `CREATOR`,
+ * which is an object implementing the `Parcelable.Creator` interface.
+ */
+ private val androidFieldName = newTermName("CREATOR")
+
+ private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable")
+ private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator")
+
/** JVM code generation phase
*/
class AsmPhase(prev: Phase) extends ICodePhase(prev) {
@@ -1202,16 +1212,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
trait JAndroidBuilder {
self: JPlainBuilder =>
- /** From the reference documentation of the Android SDK:
- * The `Parcelable` interface identifies classes whose instances can be written to and restored from a `Parcel`.
- * Classes implementing the `Parcelable` interface must also have a static field called `CREATOR`,
- * which is an object implementing the `Parcelable.Creator` interface.
- */
- private val androidFieldName = newTermName("CREATOR")
-
- private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable")
- private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator")
-
def isAndroidParcelableClass(sym: Symbol) =
(AndroidParcelableInterface != NoSymbol) &&
(sym.parentSymbols contains AndroidParcelableInterface)
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 92c2fc9768..4e702a09e6 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -30,18 +30,6 @@ import scala.reflect.runtime.{ universe => ru }
import scala.reflect.{ ClassTag, classTag }
import scala.tools.reflect.StdRuntimeTags._
-/** directory to save .class files to */
-private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) {
- private def pp(root: AbstractFile, indentLevel: Int) {
- val spaces = " " * indentLevel
- out.println(spaces + root.name)
- if (root.isDirectory)
- root.toList sortBy (_.name) foreach (x => pp(x, indentLevel + 1))
- }
- // print the contents hierarchically
- def show() = pp(this, 0)
-}
-
/** An interpreter for Scala code.
*
* The main public entry points are compile(), interpret(), and bind().
@@ -77,16 +65,19 @@ private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("
class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports {
imain =>
- /** Leading with the eagerly evaluated.
- */
- val virtualDirectory: VirtualDirectory = new ReplVirtualDirectory(out) // "directory" for classfiles
- private var currentSettings: Settings = initialSettings
- private[nsc] var printResults = true // whether to print result lines
- private[nsc] var totalSilence = false // whether to print anything
- private var _initializeComplete = false // compiler is initialized
- private var _isInitialized: Future[Boolean] = null // set up initialization future
- private var bindExceptions = true // whether to bind the lastException variable
- private var _executionWrapper = "" // code to be wrapped around all lines
+ object replOutput extends ReplOutput(settings.Yreploutdir) { }
+
+ @deprecated("Use replOutput.dir instead", "2.11.0")
+ def virtualDirectory = replOutput.dir
+ def showDirectory = replOutput.show(out)
+
+ private var currentSettings: Settings = initialSettings
+ private[nsc] var printResults = true // whether to print result lines
+ private[nsc] var totalSilence = false // whether to print anything
+ private var _initializeComplete = false // compiler is initialized
+ private var _isInitialized: Future[Boolean] = null // set up initialization future
+ private var bindExceptions = true // whether to bind the lastException variable
+ private var _executionWrapper = "" // code to be wrapped around all lines
/** We're going to go to some trouble to initialize the compiler asynchronously.
* It's critical that nothing call into it until it's been initialized or we will
@@ -258,7 +249,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** Instantiate a compiler. Overridable. */
protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = {
- settings.outputDirs setSingleOutput virtualDirectory
+ settings.outputDirs setSingleOutput replOutput.dir
settings.exposeEmptyPackage.value = true
if (settings.Yrangepos.value)
new Global(settings, reporter) with ReplGlobal with interactive.RangePositions
@@ -296,7 +287,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
ensureClassLoader()
_classLoader
}
- private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(virtualDirectory, parent) {
+ private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(replOutput.dir, parent) {
/** Overridden here to try translating a simple name to the generated
* class name if the original attempt fails. This method is used by
* getResourceAsStream as well as findClass.
@@ -670,7 +661,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
prevRequests.clear()
referencedNameMap.clear()
definedNameMap.clear()
- virtualDirectory.clear()
+ replOutput.dir.clear()
}
/** This instance is no longer needed, so release any resources
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala b/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala
new file mode 100644
index 0000000000..9fbf64acb5
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala
@@ -0,0 +1,48 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2012 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package interpreter
+
+import io.VirtualDirectory
+import settings.MutableSettings
+import scala.reflect.io.{ AbstractFile, PlainDirectory, Directory }
+import scala.collection.generic.Clearable
+
+/** Directory to save .class files to. */
+trait ReplDir extends AbstractFile with Clearable { }
+
+private class ReplVirtualDir() extends VirtualDirectory("(memory)", None) with ReplDir { }
+private class ReplRealDir(dir: Directory) extends PlainDirectory(dir) with ReplDir {
+ def clear() = {
+ dir.deleteRecursively()
+ dir.createDirectory()
+ }
+}
+
+class ReplOutput(val dirSetting: MutableSettings#StringSetting) {
+ // outdir for generated classfiles - may be in-memory (the default),
+ // a generated temporary directory, or a specified outdir.
+ val dir: ReplDir = (
+ if (dirSetting.isDefault)
+ new ReplVirtualDir()
+ else if (dirSetting.value == "")
+ new ReplRealDir(Directory.makeTemp("repl"))
+ else
+ new ReplRealDir(Directory(dirSetting.value))
+ )
+
+ // print the contents hierarchically
+ def show(out: JPrintWriter) = {
+ def pp(root: AbstractFile, indentLevel: Int) {
+ val label = root.name
+ val spaces = " " * indentLevel
+ out.println(spaces + label)
+ if (root.isDirectory)
+ root.toList sortBy (_.name) foreach (x => pp(x, indentLevel + 1))
+ }
+ pp(dir, 0)
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 404f5e6b6e..80336d9fa3 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -170,6 +170,7 @@ trait ScalaSettings extends AbsScalaSettings
val Ybuilderdebug = ChoiceSetting ("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
+ val Yreploutdir = StringSetting ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "")
val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.")
val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.")
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 461a375317..5566806c55 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -181,6 +181,7 @@ import scala.language.implicitConversions
* @define coll stream
* @define orderDependent
* @define orderDependentFold
+ * @define willTerminateInf Note: lazily evaluated; will terminate for infinite-sized collections.
*/
abstract class Stream[+A] extends AbstractSeq[A]
with LinearSeq[A]
@@ -286,9 +287,8 @@ self =>
len
}
- /** It's an imperfect world, but at least we can bottle up the
- * imperfection in a capsule.
- */
+ // It's an imperfect world, but at least we can bottle up the
+ // imperfection in a capsule.
@inline private def asThat[That](x: AnyRef): That = x.asInstanceOf[That]
@inline private def asStream[B](x: AnyRef): Stream[B] = x.asInstanceOf[Stream[B]]
@inline private def isStreamBuilder[B, That](bf: CanBuildFrom[Stream[A], B, That]) =
@@ -725,10 +725,15 @@ self =>
* // produces: "5, 6, 7, 8, 9"
* }}}
*/
- override def take(n: Int): Stream[A] =
+ override def take(n: Int): Stream[A] = (
+ // Note that the n == 1 condition appears redundant but is not.
+ // It prevents "tail" from being referenced (and its head being evaluated)
+ // when obtaining the last element of the result. Such are the challenges
+ // of working with a lazy-but-not-really sequence.
if (n <= 0 || isEmpty) Stream.empty
else if (n == 1) cons(head, Stream.empty)
else cons(head, tail take n-1)
+ )
@tailrec final override def drop(n: Int): Stream[A] =
if (n <= 0 || isEmpty) this
@@ -784,8 +789,23 @@ self =>
these
}
- // there's nothing we can do about dropRight, so we just keep the definition
- // in LinearSeq
+ /**
+ * @inheritdoc
+ * $willTerminateInf
+ */
+ override def dropRight(n: Int): Stream[A] = {
+ // We make dropRight work for possibly infinite streams by carrying
+ // a buffer of the dropped size. As long as the buffer is full and the
+ // rest is non-empty, we can feed elements off the buffer head. When
+ // the rest becomes empty, the full buffer is the dropped elements.
+ def advance(stub0: List[A], stub1: List[A], rest: Stream[A]): Stream[A] = {
+ if (rest.isEmpty) Stream.empty
+ else if (stub0.isEmpty) advance(stub1.reverse, Nil, rest)
+ else cons(stub0.head, advance(stub0.tail, rest.head :: stub1, rest.tail))
+ }
+ if (n <= 0) this
+ else advance((this take n).toList, Nil, this drop n)
+ }
/** Returns the longest prefix of this `Stream` whose elements satisfy the
* predicate `p`.
@@ -841,9 +861,16 @@ self =>
* // produces: "1, 2, 3, 4, 5, 6"
* }}}
*/
- override def distinct: Stream[A] =
- if (isEmpty) this
- else cons(head, tail.filter(head != _).distinct)
+ override def distinct: Stream[A] = {
+ // This should use max memory proportional to N, whereas
+ // recursively calling distinct on the tail is N^2.
+ def loop(seen: Set[A], rest: Stream[A]): Stream[A] = {
+ if (rest.isEmpty) rest
+ else if (seen(rest.head)) loop(seen, rest.tail)
+ else cons(rest.head, loop(seen + rest.head, rest.tail))
+ }
+ loop(Set(), this)
+ }
/** Returns a new sequence of given length containing the elements of this
* sequence followed by zero or more occurrences of given elements.
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index d16374476a..ff58a31d20 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -79,7 +79,9 @@ trait Mirrors extends api.Mirrors {
protected def universeMissingHook(owner: Symbol, name: Name): Symbol = thisUniverse.missingHook(owner, name)
- private[scala] def missingHook(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse universeMissingHook(owner, name)
+ private[scala] def missingHook(owner: Symbol, name: Name): Symbol = logResult(s"missingHook($owner, $name)")(
+ mirrorMissingHook(owner, name) orElse universeMissingHook(owner, name)
+ )
// todo: get rid of most the methods here and keep just staticClass/Module/Package
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index e18435d5b0..0f70a676fa 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -13,11 +13,12 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S
def picklerPhase = SomePhase
- lazy val settings = new Settings
def forInteractive = false
def forScaladoc = false
+ lazy val settings = new Settings
+ private val isLogging = sys.props contains "scala.debug.reflect"
- def log(msg: => AnyRef): Unit = println(" [] "+msg)
+ def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg)
type TreeCopier = InternalTreeCopierOps
def newStrictTreeCopier: TreeCopier = new StrictTreeCopier
diff --git a/test/files/run/repl-out-dir.check b/test/files/run/repl-out-dir.check
new file mode 100644
index 0000000000..a96f9ba9d9
--- /dev/null
+++ b/test/files/run/repl-out-dir.check
@@ -0,0 +1,53 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> case class Bippy(x: Int)
+defined class Bippy
+
+scala> val x = Bippy(1)
+x: Bippy = Bippy(1)
+
+scala> $intp.showDirectory
+repl-out-dir-run.obj
+ $line1
+ $eval$.class
+ $eval.class
+ $line2
+ $eval$.class
+ $eval.class
+ $read$$iw$$iw$.class
+ $read$$iw$.class
+ $read$.class
+ $read.class
+ $line3
+ $eval$.class
+ $eval.class
+ $read$$iw$$iw$.class
+ $read$$iw$$iw$Bippy$.class
+ $read$$iw$$iw$Bippy.class
+ $read$$iw$.class
+ $read$.class
+ $read.class
+ $line4
+ $eval$.class
+ $eval.class
+ $read$$iw$$iw$.class
+ $read$$iw$.class
+ $read$.class
+ $read.class
+ $line5
+ $eval$.class
+ $eval.class
+ $read$$iw$$iw$.class
+ $read$$iw$.class
+ $read$.class
+ $read.class
+ $repl_$init.class
+ Test$.class
+ Test.class
+
+scala>
+
+scala>
diff --git a/test/files/run/repl-out-dir.scala b/test/files/run/repl-out-dir.scala
new file mode 100644
index 0000000000..33c823aa2d
--- /dev/null
+++ b/test/files/run/repl-out-dir.scala
@@ -0,0 +1,13 @@
+import scala.tools.partest.ReplTest
+import scala.tools.nsc.Settings
+
+object Test extends ReplTest {
+ override def extraSettings = s"-Yrepl-outdir ${testOutput.path}"
+
+ def code = s"""
+case class Bippy(x: Int)
+val x = Bippy(1)
+$$intp.showDirectory
+ """
+
+}
diff --git a/test/files/run/streams.check b/test/files/run/streams.check
index 7f894052d9..032057d4a1 100644
--- a/test/files/run/streams.check
+++ b/test/files/run/streams.check
@@ -23,3 +23,4 @@ Stream(100001, ?)
true
true
705082704
+6
diff --git a/test/files/run/streams.scala b/test/files/run/streams.scala
index 51b4e5d76c..dc5d0204ac 100644
--- a/test/files/run/streams.scala
+++ b/test/files/run/streams.scala
@@ -29,7 +29,7 @@ object Test extends App {
def powers(x: Int) = if ((x&(x-1)) == 0) Some(x) else None
println(s3.flatMap(powers).reverse.head)
- // large enough to generate StackOverflows (on most systems)
+ // large enough to generate StackOverflows (on most systems)
// unless the following methods are tail call optimized.
val size = 100000
@@ -43,4 +43,7 @@ object Test extends App {
println(Stream.from(1).take(size).foldLeft(0)(_ + _))
val arr = new Array[Int](size)
Stream.from(1).take(size).copyToArray(arr, 0)
+
+ // dropRight terminates
+ println(Stream from 1 dropRight 1000 take 3 sum)
}
diff --git a/test/files/run/t6223.check b/test/files/run/t6223.check
index 90ec019407..4a09d1930f 100644
--- a/test/files/run/t6223.check
+++ b/test/files/run/t6223.check
@@ -1,4 +1,4 @@
bar
-bar$mcI$sp
bar$mIc$sp
bar$mIcI$sp
+bar$mcI$sp
diff --git a/test/files/run/t6223.scala b/test/files/run/t6223.scala
index 4ab7c832e6..fb176e32e6 100644
--- a/test/files/run/t6223.scala
+++ b/test/files/run/t6223.scala
@@ -5,7 +5,7 @@ class Foo[@specialized(Int) A](a:A) {
object Test {
def main(args:Array[String]) {
val f = new Foo(333)
- val ms = f.getClass().getDeclaredMethods()
+ val ms = f.getClass().getDeclaredMethods().sortBy(_.getName)
ms.foreach(m => println(m.getName))
}
}
diff --git a/test/files/run/t6584.check b/test/files/run/t6584.check
new file mode 100644
index 0000000000..35c8688751
--- /dev/null
+++ b/test/files/run/t6584.check
@@ -0,0 +1,8 @@
+Array: 102400
+Vector: 102400
+List: 102400
+Stream: 102400
+Array: 102400
+Vector: 102400
+List: 102400
+Stream: 102400
diff --git a/test/files/run/t6584.scala b/test/files/run/t6584.scala
new file mode 100644
index 0000000000..24c236ef35
--- /dev/null
+++ b/test/files/run/t6584.scala
@@ -0,0 +1,16 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ val size = 100 * 1024
+ val doubled = (1 to size) ++ (1 to size)
+
+ println("Array: " + Array.tabulate(size)(x => x).distinct.size)
+ println("Vector: " + Vector.tabulate(size)(x => x).distinct.size)
+ println("List: " + List.tabulate(size)(x => x).distinct.size)
+ println("Stream: " + Stream.tabulate(size)(x => x).distinct.size)
+
+ println("Array: " + doubled.toArray.distinct.size)
+ println("Vector: " + doubled.toVector.distinct.size)
+ println("List: " + doubled.toList.distinct.size)
+ println("Stream: " + doubled.toStream.distinct.size)
+ }
+}