summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SIP/compiler-phase-init/sip-00002-1.diabin0 -> 1608 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-1.pngbin0 -> 17837 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-10.scala521
-rw-r--r--SIP/compiler-phase-init/sip-00002-11.pngbin0 -> 74812 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-12.pngbin0 -> 70866 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-13.pngbin0 -> 70866 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-14.pngbin0 -> 66249 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-15.diabin0 -> 1266 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-15.pngbin0 -> 4547 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-16.diabin0 -> 1184 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-16.pngbin0 -> 3525 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-17.diabin0 -> 1550 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-17.pngbin0 -> 14670 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-18.diabin0 -> 1984 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-18.pngbin0 -> 24092 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-19.diabin0 -> 2267 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-19.pngbin0 -> 27719 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-2.diabin0 -> 1872 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-2.pngbin0 -> 28963 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-20.diabin0 -> 1709 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-20.pngbin0 -> 19697 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-21.diabin0 -> 2226 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-21.pngbin0 -> 28240 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-22.diabin0 -> 1572 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-22.pngbin0 -> 21025 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-23.diabin0 -> 2036 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-23.pngbin0 -> 33568 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-24.diabin0 -> 2335 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-24.pngbin0 -> 69413 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-3.diabin0 -> 2108 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-3.pngbin0 -> 33475 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-4.diabin0 -> 2458 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-4.pngbin0 -> 43127 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-5.diabin0 -> 3092 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-5.pngbin0 -> 52198 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-6.diabin0 -> 2535 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-6.pngbin0 -> 75908 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-7.diabin0 -> 1849 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-7.pngbin0 -> 25512 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-8.diabin0 -> 2301 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-8.pngbin0 -> 40297 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-9.diabin0 -> 2924 bytes
-rw-r--r--SIP/compiler-phase-init/sip-00002-9.pngbin0 -> 20512 bytes
-rw-r--r--SIP/compiler-phase-init/sip.xhtml1546
-rw-r--r--SIP/presip-classic.xhtml29
-rw-r--r--SIP/presip-constraints.xhtml29
-rw-r--r--SIP/presip-depmethods.xhtml29
-rw-r--r--SIP/sip.css5
-rw-r--r--SIP/virtual-traits/sip-0000X-1.xhtml100
-rw-r--r--SIP/virtual-traits/sip-0000X.xhtml341
-rw-r--r--build.number6
-rw-r--r--lib/scala-compiler.jar.desired.sha12
-rw-r--r--lib/scala-library-src.jar.desired.sha12
-rw-r--r--lib/scala-library.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala48
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala149
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/util/ShowPickled.scala8
-rwxr-xr-xsrc/library/scala/annotation/unchecked/uncheckedStable.scala13
-rw-r--r--src/library/scala/annotation/unchecked/uncheckedVariance.scala2
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala2
-rw-r--r--src/library/scala/collection/mutable/ResizableArray.scala4
-rwxr-xr-xsrc/library/scalax/Fractional.scala5
-rwxr-xr-xsrc/library/scalax/Integral.scala6
-rwxr-xr-xsrc/library/scalax/Numeric.scala79
-rwxr-xr-xsrc/library/scalax/collection/BufferedIterator.scala27
-rwxr-xr-xsrc/library/scalax/collection/Builder.scala21
-rwxr-xr-xsrc/library/scalax/collection/Iterable.scala143
-rwxr-xr-xsrc/library/scalax/collection/Iterator.scala970
-rwxr-xr-xsrc/library/scalax/collection/OrderedIterable.scala41
-rwxr-xr-xsrc/library/scalax/collection/Sequence.scala45
-rw-r--r--src/library/scalax/collection/SizedIterable.scala38
-rwxr-xr-xsrc/library/scalax/collection/Vector.scala21
-rwxr-xr-xsrc/library/scalax/collection/generic/IterableFactory.scala108
-rw-r--r--src/library/scalax/collection/generic/IterableForwarder.scala61
-rwxr-xr-xsrc/library/scalax/collection/generic/IterableTemplate.scala816
-rwxr-xr-xsrc/library/scalax/collection/generic/IterableView.scala121
-rwxr-xr-xsrc/library/scalax/collection/generic/OrderedIterableTemplate.scala23
-rwxr-xr-xsrc/library/scalax/collection/generic/SequenceFactory.scala11
-rw-r--r--src/library/scalax/collection/generic/SequenceForwarder.scala50
-rwxr-xr-xsrc/library/scalax/collection/generic/SequenceTemplate.scala382
-rwxr-xr-xsrc/library/scalax/collection/generic/SequenceView.scala129
-rw-r--r--src/library/scalax/collection/generic/VectorTemplate.scala264
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/IterableFactory.scala14
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/IterableTemplate.scala29
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/IterableView.scala21
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/OrderedIterableTemplate.scala17
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/SequenceFactory.scala3
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/SequenceTemplate.scala17
-rwxr-xr-xsrc/library/scalax/collection/generic/covariant/SequenceView.scala22
-rw-r--r--src/library/scalax/collection/generic/covariant/VectorTemplate.scala17
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/IterableFactory.scala108
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/IterableTemplate.scala816
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/IterableView.scala121
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala17
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/SequenceFactory.scala11
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/SequenceTemplate.scala382
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/SequenceView.scala129
-rw-r--r--src/library/scalax/collection/generic/covartest/VectorTemplate.scala264
-rw-r--r--src/library/scalax/collection/generic/mutable/VectorTemplate.scala55
-rw-r--r--src/library/scalax/collection/generic/mutable/VectorView.scala95
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/IterableFactory.scala3
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/IterableTemplate.scala24
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/IterableView.scala19
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/OrderedIterableTemplate.scala15
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/SequenceFactory.scala3
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/SequenceTemplate.scala15
-rwxr-xr-xsrc/library/scalax/collection/generic/nonvariant/SequenceView.scala21
-rw-r--r--src/library/scalax/collection/generic/nonvariant/VectorTemplate.scala15
-rw-r--r--src/library/scalax/collection/immutable/List.scala1222
-rw-r--r--src/library/scalax/collection/mutable/Appendable.scala94
-rw-r--r--src/library/scalax/collection/mutable/ArrayBuffer.scala118
-rw-r--r--src/library/scalax/collection/mutable/Buffer.scala264
-rw-r--r--src/library/scalax/collection/mutable/CloneableCollection.scala19
-rw-r--r--src/library/scalax/collection/mutable/ListBuffer.scala288
-rw-r--r--src/library/scalax/collection/mutable/ResizableArray.scala103
-rw-r--r--src/library/scalax/collection/mutable/Vector.scala20
-rwxr-xr-xsrc/library/scalax/util/control/Break.scala15
-rw-r--r--test/files/neg/accesses.check8
-rw-r--r--test/files/neg/bug521.check4
-rw-r--r--test/files/neg/bug630.check4
-rw-r--r--test/files/neg/bug708.check4
-rw-r--r--test/files/neg/lazy-override.check4
-rw-r--r--test/files/neg/t1163.check4
-rw-r--r--test/files/neg/tcpoly_variance.check4
-rw-r--r--test/files/run/t1524.check1
-rw-r--r--test/files/run/t1524.scala7
134 files changed, 10593 insertions, 90 deletions
diff --git a/SIP/compiler-phase-init/sip-00002-1.dia b/SIP/compiler-phase-init/sip-00002-1.dia
new file mode 100644
index 0000000000..94e4ffa3b3
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-1.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-1.png b/SIP/compiler-phase-init/sip-00002-1.png
new file mode 100644
index 0000000000..f4bbf67e79
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-1.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-10.scala b/SIP/compiler-phase-init/sip-00002-10.scala
new file mode 100644
index 0000000000..2065a7035d
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-10.scala
@@ -0,0 +1,521 @@
+/* Package information */
+package depgraph
+
+
+/* Simple import of data structures and IO */
+import scala.collection.mutable.{HashSet,HashMap}
+import java.io.{BufferedWriter,FileWriter}
+
+
+
+/* Class made to model the internal compiler phases
+ *
+ * All internal phases inherits from SubComponent
+ */
+abstract class SubComponent {
+ val phaseName: String
+ val runsAfter: List[String]
+ val runsRightAfter: Option[String]
+ val internal: Boolean = true
+}
+
+/*
+ *
+ */
+class Global extends Plugins with PhaseAssembly {
+
+ /* Simple option value to hold the compiler phase chain */
+ private var phasesCache : Option[List[SubComponent]] = None
+
+ /* The set of phase objects that is the basis for the compiler phase chain */
+ protected val phasesSet : HashSet[SubComponent] = new HashSet[SubComponent]
+
+ /* All the internal phase objects
+ *
+ */
+ object parser extends {
+ val phaseName = "nsc::parser"
+ val runsAfter = List[String]()
+ val runsRightAfter = None
+ } with SubComponent
+
+ object typer extends {
+ val phaseName = "nsc::typer"
+ val runsAfter = List[String]("nsc::parser")
+ val runsRightAfter = None
+ } with SubComponent
+
+ object pickler extends {
+ val phaseName = "nsc::pickler"
+ val runsAfter = List[String]("nsc::typer")
+ val runsRightAfter = None
+ } with SubComponent
+
+ object liftcode extends {
+ val phaseName = "nsc::liftcode"
+ val runsAfter = List[String]("nsc::pickler")
+ val runsRightAfter = None
+ } with SubComponent
+
+ object tailcalls extends {
+ val phaseName = "nsc::tailcalls"
+ val runsAfter = List[String]("nsc::pickler","nsc::liftcode")
+ val runsRightAfter = None
+ } with SubComponent
+
+ object erasure extends {
+ val phaseName = "nsc::erasure"
+ val runsAfter = List[String]()
+ val runsRightAfter = Some("nsc::tailcalls")
+ } with SubComponent
+
+ object cleanup extends {
+ val phaseName = "nsc::cleanup"
+ val runsAfter = List[String]("nsc::erasure")
+ val runsRightAfter = None
+ } with SubComponent
+
+ object jvm extends {
+ val phaseName = "nsc::jvm"
+ val runsAfter = List[String]("nsc::cleanup")
+ val runsRightAfter = None
+ } with SubComponent
+
+ object terminal extends {
+ val phaseName = "nsc::terminal"
+ val runsAfter = List[String]("nsc::jvm","nsc::msil")
+ val runsRightAfter = None
+ } with SubComponent
+
+ /* Helper method
+ */
+ private def computePhaseDescriptors: List[SubComponent] = {
+ computeInternalPhases() // Global.scala
+ computePluginPhases() // plugins/Plugins.scala
+ buildCompilerFromPhasesSet() // PhaseAssembly.scala
+ }
+
+ /* Will add the internal compiler phases to the phases set
+ */
+ protected def computeInternalPhases() {
+ phasesSet += parser
+ phasesSet += typer
+ phasesSet += pickler
+ phasesSet += liftcode
+ phasesSet += tailcalls
+ phasesSet += erasure
+ phasesSet += cleanup
+ phasesSet += jvm
+ phasesSet += terminal
+ }
+
+ /* Getter method for the compiler phases chain
+ */
+ def phaseDescriptors : List[SubComponent] = {
+ if (phasesCache.isEmpty) {
+ phasesCache = Some(computePhaseDescriptors)
+ }
+ phasesCache.get
+ }
+
+}
+
+
+/* Class make to model the Plug-in supplied phases
+ *
+ * All external phases inherits from PluginComponent
+ */
+abstract class PluginComponent extends SubComponent {
+ override val internal = false
+ val runsRightAfter: Option[String] = None
+}
+
+/* Trait made to model the behavior of the plugins
+ *
+ */
+trait Plugins { self: Global =>
+
+ /* Example plugin phases
+ *
+ */
+ object plugin1 extends {
+ val phaseName = "plug1::optimization1"
+ val runsAfter = List[String]("nsc::typer")
+ } with PluginComponent
+
+ object plugin2 extends {
+ val phaseName = "plug2::optimization1"
+ val runsAfter = List[String]("nsc::liftcode")
+ } with PluginComponent
+
+ object plugin3 extends {
+ val phaseName = "plug2::optimization2"
+ val runsAfter = List[String]("plug2::optimization1","nsc::cleanup")
+ } with PluginComponent
+
+ /* Add plug-in supplied phase objects to the phases set
+ */
+ def computePluginPhases() {
+ phasesSet += plugin1
+ phasesSet += plugin2
+ phasesSet += plugin3
+ }
+
+}
+
+
+/* Trait made to seperate the constraint solving from the rest of the compiler
+ *
+ */
+trait PhaseAssembly { self: Global =>
+
+ /* Aux datastructure for solving the constraint system
+ * Simple edge with to and from refs
+ */
+ class Edge(f: Node, t: Node, h: Boolean) {
+ var frm = f
+ var to = t
+ var hard = h
+ }
+
+ /* Aux datastructure for solving the constraint system
+ * Simple node with name and object ref for the phase object,
+ * also sets of in and out going dependencies
+ */
+ class Node(phs:SubComponent, name:String) {
+ var phasename: String = name
+ var phaseobj: SubComponent = phs
+ var after: HashSet[Edge] = new HashSet[Edge]()
+ var deps: HashSet[Edge] = new HashSet[Edge]()
+ }
+
+ /* Aux datastructure for solving the constraint system
+ * The depency graph container with helper methods for node and edge creation
+ */
+ class DependencyGraph {
+
+ val nodes = new HashMap[String,Node]()
+ val edges = new HashSet[Edge]()
+
+ /* Given a phase object, get the node for this phase object. If the
+ * node object does not exist, then create it.
+ */
+ def getNodeByPhase(phs : SubComponent) : Node = {
+ var node : Node = getNodeByPhase(phs.phaseName)
+ if (node.phaseobj == null) {
+ node.phaseobj = phs
+ }
+ node
+ }
+
+ /* Given the name of a phase object, get the node for that name. If the
+ * node object does not exits, then create it.
+ */
+ def getNodeByPhase(name : String) : Node = {
+ var node : Node = null
+ this.nodes.get(name) match {
+ case None =>
+ node = new Node(null,name)
+ nodes += (name->node)
+ case Some(n) =>
+ node = n
+ }
+ node
+ }
+
+ /* Connect the frm and to nodes with an edge and make it soft.
+ * Also add the edge object to the set of edges, and to the dependency
+ * list of the nodes
+ */
+ def softConnectNodes(frm: Node, to: Node) {
+ var e = new Edge(frm, to, false)
+ this.edges += e
+
+ frm.after += e
+ to.deps += e
+ }
+
+ /* Connect the frm and to nodes with an edge and make it hard.
+ * Also add the edge object to the set of edges, and to the dependency
+ * list of the nodes
+ */
+ def hardConnectNodes(frm: Node, to: Node) {
+ var e = new Edge(frm, to, true)
+ this.edges += e
+
+ frm.after += e
+ to.deps += e
+ }
+ }
+
+ /* This method will simplify the graph, by removing unneeded edges and turning the graph into
+ * a tree.
+ */
+ private def simplifyGraphFromNode(node : Node, graph : DependencyGraph) : Unit = {
+ var removal : List[Edge] = Nil
+ for(edge <- node.deps) {
+ if (edge.frm.after.size > 1)
+ removal = edge :: removal
+ }
+ for(edge <- removal) {
+ println("[removing edge: " + edge.frm.phasename + " => " + edge.to.phasename + "]")
+ node.deps -= edge
+ edge.frm.after -= edge
+ graph.edges -= edge
+ }
+
+ var nodes = dependencyOrder(node.deps)
+ for(nd <- nodes) {
+ simplifyGraphFromNode(nd, graph)
+ }
+ }
+
+ /* This is a simple method that tests for cycles in the graph. If a cycle is found, a fatal error
+ * will be produced.
+ */
+ private def testForCycles(node : Node, names : HashSet[String]) : Unit = {
+
+ if (names.contains( node.phasename ) ) {
+ println("There is a cycle in this graph! The algorithm was able to reach the node " + node.phasename + " twice!")
+ System.exit(1)
+ }
+
+ names += node.phasename
+
+ var nodes = dependencyOrder(node.deps)
+ for(nd <- nodes) {
+ testForCycles(nd, names)
+ }
+
+ names -= node.phasename
+ }
+
+ /* Given the dependency list of a node, return a list so that first come the reversed
+ * external phases sorted alphabetically, followed by the internal phase
+ */
+ private def dependencyOrder(deps : HashSet[Edge]) : List[Node] = {
+ var external = deps.filter(e => (! e.frm.phaseobj.internal))
+ var internal = deps.filter(e => e.frm.phaseobj.internal)
+
+ var extnodes = (Nil ++ external.map(e => e.frm)).sort((n1,n2) => (n1.phasename compareTo n2.phasename) < 0)
+ extnodes = extnodes.reverse
+
+ var nodes = Nil ++ internal.map(e => e.frm) ++ extnodes
+ nodes = nodes.reverse
+ return nodes
+ }
+
+ /* Find all edges in the given graph that are hard links. For each hard link we
+ * need to check that its the only dependency. If not, then we will promote the
+ * other dependencies down
+ */
+ private def enforceHardlinks(graph : DependencyGraph) : Unit = {
+ var rerun = true
+ while(rerun) {
+ rerun = false
+ var hardlinks = graph.edges.filter(e => e.hard)
+ for(hl <- hardlinks) {
+ var sanity = Nil ++ hl.to.deps.filter(e => e.hard)
+ if (sanity.length == 0) {
+
+ println("This is not supposed to happen!")
+ System.exit(1)
+ // throw new FataError()
+ } else if (sanity.length > 1) {
+
+ println("Multiple phases want to run right after the same phase")
+ println("Phases:")
+ for (edge <- sanity) {
+ println(" - " + edge.frm.phasename)
+ }
+ System.exit(1)
+
+ } else {
+
+ var promote = hl.to.deps.filter(e => (!e.hard))
+ hl.to.deps.clear
+ sanity foreach (edge => hl.to.deps += edge)
+ for (edge <- promote) {
+ rerun = true
+ println("[promote the dependency of " + edge.frm.phasename + ": " + edge.to.phasename + " => " + hl.frm.phasename + "]")
+ edge.to = hl.frm
+ hl.frm.deps += edge
+ }
+ }
+ }
+ }
+ }
+
+ /* Remove all nodes in the given graph, that have no phase object
+ * Make sure to clean up all edges when removing the node object
+ */
+ private def removeDanglingNodes(graph : DependencyGraph) : Unit = {
+ var dnodes = graph.nodes.values.filter(n => (n.phaseobj == null))
+ for(node <- dnodes) {
+ println("[dropping depend on node with no phase: " + node.phasename + "]")
+ graph.nodes -= node.phasename
+ for(edge <- node.deps) {
+ graph.edges -= edge
+ edge.frm.after -= edge
+ }
+ }
+ }
+
+ /* This is a helper method, that given a dependency graph will generate a graphviz dot
+ * file showing its structure.
+ * Plug-in supplied phases are marked as green nodes and hard links are marked as blue edges.
+ */
+ private def graphToDotFile(graph : DependencyGraph, filename : String) : Unit = {
+ var sbuf = new StringBuffer()
+ var extnodes = new HashSet[Node]()
+ sbuf.append("digraph G {\n")
+ for(edge <- graph.edges) {
+ sbuf.append("\"" + edge.frm.phasename + "\"->\"" + edge.to.phasename + "\"")
+ if (! edge.frm.phaseobj.internal) {
+ extnodes += edge.frm
+ }
+ if (edge.hard) {
+ sbuf.append(" [color=\"#0000ff\"]\n")
+ } else {
+ sbuf.append(" [color=\"#000000\"]\n")
+ }
+ }
+ for(node <- extnodes) {
+ sbuf.append("\"" + node.phasename + "\" [color=\"#00ff00\"]\n")
+ }
+ sbuf.append("}\n")
+ var out = new BufferedWriter(new FileWriter(filename))
+ out.write(sbuf.toString)
+ out.flush()
+ out.close()
+ }
+
+
+ /* Given the phases set, will build a dependency graph from the phases set
+ * Using the aux. method of the DependencyGraph to create nodes and egdes
+ */
+ private def phasesSetToDepGraph(phsSet : HashSet[SubComponent]) : DependencyGraph = {
+ val graph = new DependencyGraph()
+
+ for(phs <- phsSet) {
+
+ var fromnode = graph.getNodeByPhase(phs)
+
+ phs.runsRightAfter match {
+ case None =>
+ for(phsname <- phs.runsAfter) {
+ if (! (phsname equals "terminal")) {
+ var tonode = graph.getNodeByPhase(phsname)
+ graph.softConnectNodes(fromnode, tonode)
+ } else {
+ println("[depends on terminal not allowed, dropping depend: " + fromnode.phasename + " => "+ phsname +"]")
+ }
+ }
+ case Some(phsname) =>
+ if (! (phsname equals "terminal")) {
+ var tonode = graph.getNodeByPhase(phsname)
+ graph.hardConnectNodes(fromnode, tonode)
+ } else {
+ println("[depends on terminal not allowed, dropping depend: " + fromnode.phasename + " => "+ phsname +"]")
+ }
+ }
+
+ }
+
+ return graph
+ }
+
+
+ /* Simple transformation function, that given a dependency graph transforms it into a dependency tree
+ * Will return the root of the tree
+ */
+ private def depGraphToDepTree(graph : DependencyGraph) : Node = {
+
+ graphToDotFile(graph, "depgraph1.dot")
+
+ // Remove nodes without phaseobj
+ removeDanglingNodes(graph)
+
+ graphToDotFile(graph, "depgraph2.dot")
+
+ // Enforce hardlinks / runsRightAfter and promote nodes down the tree
+ enforceHardlinks(graph)
+
+ graphToDotFile(graph, "depgraph3.dot")
+
+ var root = graph.getNodeByPhase("nsc::parser")
+
+ // Test for cycles in graph, if found will generate fatal error
+ testForCycles(root, new HashSet[String]())
+
+ // Simplify graph by removing edges starting from the root
+ simplifyGraphFromNode(root, graph)
+
+ graphToDotFile(graph, "depgraph4.dot")
+
+ root
+ }
+
+
+ /* Given a node and a list of phases, it will traverse the dependencies of the node object and
+ * call itself recursively
+ *
+ */
+ private def depTree2CompilerPhaseList(node : Node, pchain : List[SubComponent]) : List[SubComponent] = {
+ var chain : List[SubComponent] = pchain
+ chain = chain ::: List(node.phaseobj)
+ if (node.deps.size == 0)
+ return chain
+
+ else if (node.deps.size == 1) {
+ for(edge <- node.deps)
+ chain = depTree2CompilerPhaseList(edge.frm, chain)
+ return chain
+
+ } else {
+
+ var nodes = dependencyOrder(node.deps)
+ for(nd <- nodes) {
+ chain = depTree2CompilerPhaseList(nd, chain)
+ }
+ return chain
+ }
+ }
+
+
+ /* Method called from computePhaseDescriptors in class Global
+ * This method will call three aux. methods to convert the phases set into a dependency graph
+ * Convert the dependency graph into a dependency tree and return the root of the tree
+ * Assemble the compiler phase chain from the root of the dependency tree
+ */
+ def buildCompilerFromPhasesSet() : List[SubComponent] = {
+
+ // Add all phases in the set to the graph
+ val graph = phasesSetToDepGraph(phasesSet)
+
+ val root = depGraphToDepTree(graph)
+
+ return depTree2CompilerPhaseList(root, Nil)
+ }
+
+}
+
+
+/**
+ * Test object that will create a new object from the Global class
+ * and call the method phaseDescriptors to get the list of phase objects
+ * and print the phase names to stdout
+ *
+ */
+object DepGraphTest extends Application {
+
+ val global = new Global()
+
+ var compilerchain = global.phaseDescriptors
+
+ for(phase <- compilerchain) {
+ println(" - " + phase.phaseName)
+ }
+
+}
+
diff --git a/SIP/compiler-phase-init/sip-00002-11.png b/SIP/compiler-phase-init/sip-00002-11.png
new file mode 100644
index 0000000000..c26f056d86
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-11.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-12.png b/SIP/compiler-phase-init/sip-00002-12.png
new file mode 100644
index 0000000000..b4e59a08f7
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-12.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-13.png b/SIP/compiler-phase-init/sip-00002-13.png
new file mode 100644
index 0000000000..9cfc543190
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-13.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-14.png b/SIP/compiler-phase-init/sip-00002-14.png
new file mode 100644
index 0000000000..d81df6dae3
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-14.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-15.dia b/SIP/compiler-phase-init/sip-00002-15.dia
new file mode 100644
index 0000000000..2b08cafc33
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-15.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-15.png b/SIP/compiler-phase-init/sip-00002-15.png
new file mode 100644
index 0000000000..a9b0ce4db2
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-15.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-16.dia b/SIP/compiler-phase-init/sip-00002-16.dia
new file mode 100644
index 0000000000..e05924ac67
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-16.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-16.png b/SIP/compiler-phase-init/sip-00002-16.png
new file mode 100644
index 0000000000..7351e6e7c9
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-16.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-17.dia b/SIP/compiler-phase-init/sip-00002-17.dia
new file mode 100644
index 0000000000..2e4068f82a
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-17.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-17.png b/SIP/compiler-phase-init/sip-00002-17.png
new file mode 100644
index 0000000000..e2026e51b4
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-17.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-18.dia b/SIP/compiler-phase-init/sip-00002-18.dia
new file mode 100644
index 0000000000..b1eb5003b4
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-18.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-18.png b/SIP/compiler-phase-init/sip-00002-18.png
new file mode 100644
index 0000000000..1f743e549b
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-18.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-19.dia b/SIP/compiler-phase-init/sip-00002-19.dia
new file mode 100644
index 0000000000..fc05ac6a2a
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-19.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-19.png b/SIP/compiler-phase-init/sip-00002-19.png
new file mode 100644
index 0000000000..ffd8930b59
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-19.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-2.dia b/SIP/compiler-phase-init/sip-00002-2.dia
new file mode 100644
index 0000000000..d08ee35f46
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-2.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-2.png b/SIP/compiler-phase-init/sip-00002-2.png
new file mode 100644
index 0000000000..66a0eb695b
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-2.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-20.dia b/SIP/compiler-phase-init/sip-00002-20.dia
new file mode 100644
index 0000000000..fb16133aa9
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-20.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-20.png b/SIP/compiler-phase-init/sip-00002-20.png
new file mode 100644
index 0000000000..5290bb1d83
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-20.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-21.dia b/SIP/compiler-phase-init/sip-00002-21.dia
new file mode 100644
index 0000000000..65b16a99a0
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-21.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-21.png b/SIP/compiler-phase-init/sip-00002-21.png
new file mode 100644
index 0000000000..152f0d7c0c
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-21.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-22.dia b/SIP/compiler-phase-init/sip-00002-22.dia
new file mode 100644
index 0000000000..7ce832d3fa
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-22.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-22.png b/SIP/compiler-phase-init/sip-00002-22.png
new file mode 100644
index 0000000000..42cf265fcf
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-22.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-23.dia b/SIP/compiler-phase-init/sip-00002-23.dia
new file mode 100644
index 0000000000..ae89016ca2
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-23.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-23.png b/SIP/compiler-phase-init/sip-00002-23.png
new file mode 100644
index 0000000000..1b0ea408dc
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-23.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-24.dia b/SIP/compiler-phase-init/sip-00002-24.dia
new file mode 100644
index 0000000000..d96f9cd319
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-24.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-24.png b/SIP/compiler-phase-init/sip-00002-24.png
new file mode 100644
index 0000000000..cdb4c91223
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-24.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-3.dia b/SIP/compiler-phase-init/sip-00002-3.dia
new file mode 100644
index 0000000000..e8c883917e
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-3.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-3.png b/SIP/compiler-phase-init/sip-00002-3.png
new file mode 100644
index 0000000000..b464735965
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-3.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-4.dia b/SIP/compiler-phase-init/sip-00002-4.dia
new file mode 100644
index 0000000000..9927a1291b
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-4.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-4.png b/SIP/compiler-phase-init/sip-00002-4.png
new file mode 100644
index 0000000000..043520450b
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-4.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-5.dia b/SIP/compiler-phase-init/sip-00002-5.dia
new file mode 100644
index 0000000000..b5bac4613f
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-5.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-5.png b/SIP/compiler-phase-init/sip-00002-5.png
new file mode 100644
index 0000000000..18a4b73dac
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-5.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-6.dia b/SIP/compiler-phase-init/sip-00002-6.dia
new file mode 100644
index 0000000000..9e8f0a56bf
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-6.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-6.png b/SIP/compiler-phase-init/sip-00002-6.png
new file mode 100644
index 0000000000..8da5b03efe
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-6.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-7.dia b/SIP/compiler-phase-init/sip-00002-7.dia
new file mode 100644
index 0000000000..9a35df0ee1
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-7.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-7.png b/SIP/compiler-phase-init/sip-00002-7.png
new file mode 100644
index 0000000000..382a505c79
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-7.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-8.dia b/SIP/compiler-phase-init/sip-00002-8.dia
new file mode 100644
index 0000000000..6ccfa0f2d8
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-8.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-8.png b/SIP/compiler-phase-init/sip-00002-8.png
new file mode 100644
index 0000000000..97a4c20fcb
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-8.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-9.dia b/SIP/compiler-phase-init/sip-00002-9.dia
new file mode 100644
index 0000000000..da22427789
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-9.dia
Binary files differ
diff --git a/SIP/compiler-phase-init/sip-00002-9.png b/SIP/compiler-phase-init/sip-00002-9.png
new file mode 100644
index 0000000000..17109c13b6
--- /dev/null
+++ b/SIP/compiler-phase-init/sip-00002-9.png
Binary files differ
diff --git a/SIP/compiler-phase-init/sip.xhtml b/SIP/compiler-phase-init/sip.xhtml
new file mode 100644
index 0000000000..10cb4c3189
--- /dev/null
+++ b/SIP/compiler-phase-init/sip.xhtml
@@ -0,0 +1,1546 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Scala Compiler Phase and Plug-In Initialization</title>
+ <meta name="sip" content="00002"/>
+ <meta name="author" content="Anders Bach Nielsen"/>
+ <meta name="version" content="0"/>
+ <meta name="type" content="standards"/>
+ <meta name="status" content="submission"/>
+ <meta name="created" content="2008-08-25"/>
+ <meta name="updated" content="2008-10-09"/>
+ <meta name="scala-version" content="2.8.0.final-"/>
+ <meta name="owner-contact" content="mailto:andersbach.nielsen@epfl.ch"/>
+ <meta name="discussion" content="http://www.nabble.com/SIP-00002%3A-Compiler-Phase-Initialization-and-Plugins-td19677473.html"/>
+ <!-- <link rel="auxiliary" href="[URI]" type="[mime type]"/> -->
+ <!-- <link rel="replaces" href="[URI]" type="application/xhtml+xml"/> -->
+ <!-- <link rel="depends-on" href="[URI]" type="application/xhtml+xml"/> -->
+ <!-- Stylesheet -->
+ <link rel="stylesheet" href="http://lampsvn.epfl.ch/svn-repos/scala/sip/trunk/sip.css" type="text/css"/>
+</head>
+<body>
+ <a name="top"></a>
+ <h1>Scala Compiler Phase and Plug-In Initialization</h1>
+
+ <h2>Abstract</h2>
+
+ <p>This document describes the design and implementation of a more
+ uniform way of handling internal compiler phases and external user
+ supplied phases via plug-ins in the Scala compiler.</p>
+
+ <h2>Contents</h2>
+
+ <ul>
+ <li><a href="#motivation">Motivation</a>
+ <ul>
+ <li><a href="#goalsandreq">Goals</a></li>
+ <li><a href="#usecases">Use Cases</a></li>
+ <li><a href="#detailedusecases">Detailed Use Cases</a>
+ <ul>
+ <li><a href="#usecase1">Assembling compiler internal phases for the JVM target ...</a></li>
+ <li><a href="#usecase2">Assembling compiler internal phases for the MSIL target ...</a></li>
+ <li><a href="#usecase3">Adding one plug-in supplied phase to the JVM target ...</a></li>
+ <li><a href="#usecase4">Adding two plug-in supplied phase to the JVM target ...</a></li>
+ <li><a href="#usecase5">Adding two plug-in supplied phases, where one has a ...</a></li>
+ <li><a href="#usecase6">Adding plug-in supplied phases with dependencies to ...</a></li>
+ <li><a href="#usecase7">Two separate phases that should be handled as a single ...</a></li>
+ <li><a href="#usecase8">A cyclic dependency among phases is a fatal error.</a></li>
+ <li><a href="#usecase9">Special handling of the <code>parser</code> and <code>terminal</code> phases.</a></li>
+ <li><a href="#usecase10">Larger compiler example with three plug-in supplied phases.</a></li>
+ </ul>
+ </li>
+ <li><a href="#futuregoals">Future Goals That Extend Beyond This Proposal</a></li>
+ </ul>
+ </li>
+ <li><a href="#description">Description</a>
+ <ul>
+ <li><a href="#presentdesign">The Present Design</a></li>
+ <li><a href="#proposeddesign">The Proposed Design</a>
+ <ul>
+ <li><a href="#propdesign1">Internal Phases</a></li>
+ <li><a href="#propdesign2">External Phases</a></li>
+ <li><a href="#propdesign3">Phases Set</a></li>
+ <li><a href="#propdesign4">Phase Assembly</a></li>
+ <li><a href="#propdesign5">Constraint System</a></li>
+ <li><a href="#constsolver">Constraint Solving Algorithm</a></li>
+ </ul>
+ </li>
+ <li><a href="#namingscheme">Naming Scheme for Internal and External Phases</a></li>
+ <li><a href="#implications">Implications of This Proposal</a></li>
+ </ul>
+ </li>
+ <li><a href="#implementation">Implementation</a></li>
+ </ul>
+
+
+ <a name="motivation"></a>
+ <h2>Motivation</h2>
+
+ <p>This section will cover the motivating goals of creating this
+ proposal and some use cases emphasizing these goals. There will also
+ be a section on goals that extend beyond this proposal and will
+ therefore not be covered by this proposal.</p>
+
+ <a name="goalsandreq"></a>
+ <h3>Goals</h3>
+
+ <ul>
+ <li>Handle inclusion and constraints for internal compiler phases
+ and external user supplied phases via plug-ins in a uniform
+ way.</li>
+
+ <li>Phase ordering is based on a simple, but sufficient powerful
+ and solvable constraint system.</li>
+
+ <li>Phase ordering of internal compiler phases and external user
+ supplied phases should retain as much compatibility with the
+ current scheme as possible.</li>
+
+ <li>Phase ordering is fully determined by the set of input phases.
+ It does not matter, for example, what order the compiler processes
+ the individual plug-ins that supply the external phases.</li>
+
+ <li>Ordering of the internal compiler phases should always succeed
+ in a valid compiler phase chain. Adding two plug-ins, which by
+ themselves give a valid compiler phase chain, should also give a
+ valid compiler phase chain.</li>
+
+ </ul>
+
+ <a name="usecases"></a> <h3>Use Cases</h3>
+
+ <ol>
+ <li><a href="#usecase1">Assembling compiler internal phases for
+ the JVM target and no plug-ins are loaded.</a></li>
+
+ <li><a href="#usecase2">Assembling compiler internal phases for
+ the MSIL target and no plug-ins are loaded.</a></li>
+
+ <li><a href="#usecase3">Adding one plug-in supplied phase to the
+ JVM target compiler after type checking.</a></li>
+
+ <li><a href="#usecase4">Adding two plug-in supplied phase to the
+ JVM target compiler after type checking.</a></li>
+
+ <li><a href="#usecase5">Adding two plug-in supplied phases, where
+ one has a dependency on the other, to the JVM target
+ compiler.</a></li>
+
+ <li><a href="#usecase6">Adding plug-in supplied phases with
+ dependencies to both plug-in supplied and internal phases to the
+ JVM target compiler.</a></li>
+
+ <li><a href="#usecase7">Two separate phases that should be handled
+ as a single phase.</a></li>
+
+ <li><a href="#usecase8">A cyclic dependency among phases is a
+ fatal error.</a></li>
+
+ <li><a href="#usecase9">Special handling of the
+ <code>parser</code> and <code>terminal</code> phases.</a></li>
+
+ <li><a href="#usecase10">Larger compiler example with three
+ plug-in supplied phases.</a></li>
+
+
+ </ol>
+
+ <a name="detailedusecases"></a>
+ <h3>Detailed Use Cases</h3>
+
+ <a name="usecase1"></a>
+ <h4>[1] Assembling compiler internal phases for the JVM target and
+ no plug-ins are loaded.</h4>
+
+ <p>All phases have to declare a <code>runsAfter</code> list of phase
+ names that should be run before the phase itself in the final
+ compiler phase chain. In this use case there are no plug-in supplied
+ phases, that have to be included. Depending on the command line
+ options and the JVM target the for this target default phases are
+ added to the phases set. This is a set, because a phase may only
+ occur once in the compiler phase chain.</p>
+
+ <p>Following these basic <code>runsAfter</code> constraints the
+ compiler phase chain is build from the phases set. In the example
+ below a simple set of phase constraints can be converted into a
+ graph, that in turn can be converted into a list of phases.
+ </p>
+ <div style="text-align: center;">
+ <img src="sip-00002-1.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <p>Using the <code>runsAfter</code> list as the basic ordering
+ constraints there are some more properties that have to be
+ full filled.
+ </p>
+ <ul>
+ <li>The phases <code>liftcode</code> and <code>flatten</code> are
+ only included for the JVM target. They have <code>runsAfter</code>
+ dependencies on the <code>refchecks</code> phase and the
+ <code>constructors</code> phase, respectively. Because they are
+ only included in the JVM target the <code>uncurry</code> phase and
+ the <code>mixin</code> phase, respectively, need to have multiple
+ dependencies as seen in the example below.
+
+ <p>This example shows the desired transformation steps of a small
+ dependency graph taken from the actual compiler phase graph. When
+ processing <code>refchecks</code> we notice that it has two
+ dependencies to it. One dependency comes from
+ <code>liftcode</code> and the other from <code>uncurry</code>. We
+ now look if any of these phases have more then one outgoing
+ dependency. The <code>liftcode</code> phase has one outgoing
+ dependency, but the <code>uncurry</code> phase has two, so one of
+ the outgoing dependencies of <code>uncurry</code> has to go to
+ <code>refchecks</code> and the other dependency has to go to some
+ place we have not visited yet. So by this reasoning, we can safely
+ remove the dependency from <code>uncurry</code> to
+ <code>refchecks</code> (marked red).</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-21.png" alt="" border="0" width="85%" height="" />
+ </div>
+ <p></p>
+ </li>
+
+ <li>Some internal phase pairs have very strong dependencies, like
+ the phases <code>explicitouter</code> and <code>erasure</code> and
+ also the <code>namer</code> and <code>typer</code> phases. See <a
+ href="#usecase7">use case 7</a> for more information on this
+ problem.</li>
+ </ul>
+
+
+ <a name="usecase2"></a>
+ <h4>[2] Assembling compiler internal phases for the MSIL target and
+ no plug-ins are loaded.</h4>
+
+ <p>Like in <a href="usecase1">use case 1</a> depending on command
+ line options and that the target being MSIL, the proper phases are
+ added to the phases set. Again there are no plug-in supplied phases
+ to be included. There are however some differences to use case 1.
+ </p>
+ <ul>
+ <li>The phases <code>liftcode</code> and <code>flatten</code> are
+ not included for the MSIL target. This makes the
+ <code>runsAfter</code> list of the phases <code>uncurry</code> and
+ <code>mixer</code> special by containing dependencies to phases
+ that are found in the phases set.
+
+ <p>For instance the <code>uncurry</code> phase has to specify that
+ it wants to run after both <code>refchecks</code> and
+ <code>liftcode</code>. <i>(For the JVM target this will force the
+ <code>liftcode</code> phase before <code>uncurry</code>.)</i> For
+ the MSIL target the phase <code>liftcode</code> is not present as
+ shown in the example diagram below. One solution that will work is
+ to silently drop all dependencies to phases, where there was no
+ phase object in the phases set.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-22.png" alt="" border="0" width="55%" height="" />
+ </div>
+ </li>
+ </ul>
+
+
+
+ <a name="usecase3"></a>
+ <h4>[3] Adding one plug-in supplied phase to the JVM target
+ compiler after type checking.</h4>
+
+ <p>Like in <a href="#usecase1">use case 1</a> the internal phases
+ are added to the phases set. In this use case a plug-in is loaded
+ that will supply one phase to the phases set with a constraint that
+ it wants to run after the <code>refchecks</code> phase. The original
+ plug-in handling code will still handle loading plug-ins, disabling
+ plug-ins, but will no longer have the responsibility of assembling
+ the compiler chain. The plug-in is loaded and the phase is added
+ to the phases set together with the internal phases.</p>
+ <p>When assembling the compiler phase chain in this use case, there
+ will be two phases directly after the <code>refchecks</code> phase
+ and the dependencies can not be removed as described in <a
+ href="#usecasee1">use case 1</a>. This situation is shown in the
+ example below.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-2.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <p>One of the goals of this proposal is to be as compatible with the
+ current behavior of the compiler as possible. So if the situation is
+ as shown above that after including A, we can either take B or R, we
+ need a deterministic scheme for always constructing the same phase
+ chain. This is done by taking the plug-in supplied phases first and
+ then the internal phase after wards.
+ </p>
+
+
+
+ <a name="usecase4"></a>
+ <h4>[4] Adding two plug-in supplied phase to the JVM target
+ compiler after type checking.</h4>
+
+ <p>This use case is very similar to <a href="#usecase3">use case
+ 3</a>, however instead of having one internal and one external phase
+ after the <code>refchecks</code> phase, we have one internal and two
+ external phases after the <code>refchecks</code> phase. This
+ situation is shown in the example below.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-23.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <p>To be able to deterministically create the compiler phase chain
+ we need a rule to handle multiple external phases at the same
+ level. The simplest rule it to include the external phases
+ alphabetically order, as shown in the example above.</p>
+
+
+ <a name="usecase5"></a>
+ <h4>[5] Adding two plug-in supplied phases, where one has a
+ dependency on the other, to the JVM target compiler.</h4>
+
+ <p>This use case is very similar to <a href="#usecase4">use case
+ 4</a>, however instead of the two plug-in supplied phases having a
+ dependency on the same internal, one of the plug-in supplied phases
+ has a dependency on the other and the other has a dependency on an
+ internal phase. This is the example shown in the diagram below.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-3.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <p>As described in <a href="#usecase3">use case 3</a>, after
+ inclusion of phase A the next phase to include is phase T. In the
+ example above phase R is dependent on phase T, so the next to
+ include is phase R. This means that including phase T, means to
+ include T and the ordered sub tree, under phase T.</p>
+
+ <p>The example shown below, can be solved applying the same logic as
+ described above.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-4.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+
+ <a name="usecase6"></a>
+ <h4>[6] Adding plug-in supplied phases with dependencies to both
+ plug-in supplied and internal phases to the JVM target
+ compiler.</h4>
+
+ <p>This use case builds upon <a href="#usecase1">use case 1</a>, <a
+ href="#usecase3">use case 3</a>, <a href="#usecase4">use case 4</a>
+ and <a href="#usecase5">use case 5</a> and shows how to handle
+ plug-in supplied phases with dependencies on other plug-in supplied
+ and internal phases.</p>
+
+ <p>In the example shown below the plug-in supplied phase T has
+ dependencies on the plug-in supplied phase P and the internal phase
+ B. The transformation shown below is made by applying the logic from
+ <a href="#usecase1">use case 1</a> to this example and using the
+ assumption that the dependencies of the internal phases will not
+ contain cycles and internal phases are visited last on each
+ level.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-5.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <a name="usecase7"></a>
+ <h4>[7] Two separate phases that should be handled as a single
+ phase.</h4>
+
+ <p>In <a href="#usecase1">use case 1</a> we specified the assembly
+ of the compiler phase chain based on runs after
+ constraints. However, the compiler contains some phase pairs that
+ have very strong dependencies on each other or it simply does not
+ make sense to put a phase in between. In this use case we will focus
+ on the situation that we have two individual phase objects, but one
+ needs to run right after the other and thereby act as one large
+ phase.</p>
+
+ <p>The solution to this is to introduce a new runs right after
+ constraint to all phases. To keep the compatibility with current
+ plug-ins as high as possible, this runs right after constraint is
+ only mandatory for internal phases. In the example below the
+ <code>runsRightAfter</code> constraint is marked as a blue arrow and
+ behaves as a normal runs after constraint.
+ </p>
+ <div style="text-align: center;">
+ <img src="sip-00002-7.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <p>In the example shown below, we can see the first four phases of
+ the Scala compiler. There is a <code>runsRightAfter</code>
+ constraint between <code>typer</code> and <code>namer</code>. There
+ is in this example a plug-in supplied phase (plugin1) that want to
+ run after the <code>namer</code> phase. The semantics of the run
+ after constraint is that is should run somewhere after a specified
+ phase, but as soon as possible. With this in mind it is perfectly
+ valid to change the dependency of <code>plugin1</code> from
+ <code>namer</code> to <code>typer</code>. </p>
+ <div style="text-align: center;">
+ <img src="sip-00002-8.png" alt="" border="0" width="100%" height="" />
+ </div>
+
+ <p>If the phase <code>plugin1</code> had declared to
+ <code>runRightAfter</code> the <code>namer</code> phase, this would
+ result in a unsolvable graph and would therefore generate an error,
+ because only one phase can come right after another phase.
+ </p>
+
+ <a name="usecase8"></a>
+ <h4>[8] A cyclic dependency among phases is a fatal error.</h4>
+
+ <p>Running the compiler without loading plug-ins, it is guaranteed
+ that there are do cyclic dependencies among the internal phases, so
+ the only way to introduce cycles in the phase graph is by loading
+ one or more plug-ins. If a cycle is detected in the phase graph the
+ compiler should refuse to start and give a proper error message.</p>
+
+ <p>In the example shown below a cycle is detected and marked in
+ pink. A cycle like this would generate a cyclic dependency error and
+ outputting the names of the involved phases.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-20.png" alt="" border="0" width="35%" />
+ </div>
+
+ <a name="usecase9"></a>
+ <h4>[9] Special handling of the <code>parser</code> and
+ <code>terminal</code> phases.</h4>
+
+ <p>There are two very special phase objects in the phase graph. The
+ first phase is the <code>parser</code> phase. This phase will be the
+ head of the compiler phase chain, there are however no other
+ restrictions on this phase.</p>
+
+ <p>The other special phase is the <code>terminal</code> phase, which
+ has to be the last phase in the compiler phase chain. For this
+ reason it is not allowed to run after or run right after the
+ <code>terminal</code> phase. Any phase that specifies a runs after
+ or runs right after dependency on the <code>terminal</code> phase
+ will have that dependency dropped silently.</p>
+
+
+ <a name="usecase10"></a>
+ <h4>[10] Larger compiler example with three plug-in supplied phases.</h4>
+
+ <p>This example is implemented in the <a
+ href="#implementation">reference implementation</a> of the algorithm
+ below. In this example the compiler consists of nine internal phases
+ and two plug-ins are loaded adding a total of three phases to the
+ compiler.
+ </p>
+
+ <table width="100%" border="1">
+ <tr>
+ <td><strong>Phase name</strong></td>
+ <td><strong>Runs after</strong></td>
+ <td><strong>Runs right after</strong></td>
+ </tr>
+ <tr>
+ <td colspan="3" align="center"><strong><i>Internal phases</i></strong></td>
+ </tr>
+ <tr>
+ <td>nsc::parser</td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::typer</td>
+ <td>nsc::parser</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::pickler</td>
+ <td>nsc::typer</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::liftcode</td>
+ <td>nsc::pickler</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::tailcalls</td>
+ <td>nsc::pickler<br />nsc::liftcode</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::erasure</td>
+ <td></td>
+ <td>nsc::tailcalls</td>
+ </tr>
+ <tr>
+ <td>nsc::cleanup</td>
+ <td>nsc::erasure</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::jvm</td>
+ <td>nsc::cleanup</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>nsc::terminal</td>
+ <td>nsc::jvm<br />nsc::msil</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td colspan="3" align="center"><strong><i>Plug-in supplied phases</i></strong></td>
+ </tr>
+ <tr>
+ <td>plug1::optimization1</td>
+ <td>nsc::typer</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>plug2::optimization1</td>
+ <td>nsc::liftcode</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>plug2::optimization2</td>
+ <td>plug2::optimization1<br />nsc::cleanup</td>
+ <td></td>
+ </tr>
+ </table>
+
+ <p>Using the phases in the table above as the basis for the
+ dependency graph, the following graph will be constructed. This
+ graph contains all the information that is also present in the
+ phases set. As seen in the diagram below there are nodes without
+ phase objects (marked with dotted lines) and nodes with multiple
+ dependencies. There could also be cycles at this stage, but there
+ are non in this example.
+ </p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-6.png" alt="" border="0" width="60%" height="" />
+ </div>
+
+ <p>The transformation of the dependency graph into a dependency tree
+ is the basis of this proposal. The resulting dependency tree is
+ shown below. This tree is then the basis for generating the compiler
+ phase list.
+ </p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-24.png" alt="" border="0" width="60%" height="" />
+ </div>
+
+ <p>The resulting compiler phase list of traversing the tree above is
+ shown below. It is ensured that the <code>parser</code> phase is the
+ first and that the <code>terminal</code> phase is the last in this list.</p>
+
+ <ul>
+ <li>nsc::parser</li>
+ <li>nsc::typer</li>
+ <li>plug1::optimization1</li>
+ <li>nsc::pickler</li>
+ <li>nsc::liftcode</li>
+ <li>plug2::optimization1</li>
+ <li>nsc::tailcalls</li>
+ <li>nsc::erasure</li>
+ <li>nsc::cleanup</li>
+ <li>plug2::optimization2</li>
+ <li>nsc::jvm</li>
+ <li>nsc::terminal</li>
+ </ul>
+
+ <a name="futuregoals"></a>
+ <h3>Future Goals That Extend Beyond This Proposal</h3>
+
+ <ul>
+ <li>Create and add new backends to the compiler that will replace
+ the JVM or MSIL specific phases using plug-ins.</li>
+ <li>Creating internal tools by subclassing the class
+ <code>Global</code>.</li>
+ <li>The constraint system should not contain support for the
+ following constraints.
+ <ul>
+ <li>A phase should be able to declare that it will replace a
+ given phase and thereby ignoring other constraints declared by
+ this phase and taking over the constraints from the replaced
+ phase.</li>
+ <li>A phase should be able to declare that if included it will
+ remove a given number of phases and removing constraints to
+ these phases.</li>
+ <li>A phase should be able to declare that it only wants to be
+ included if a given phase is also present or else it will be
+ silently dropped.</li>
+ </ul>
+ </li>
+ </ul>
+
+ <a href="#top">To the top</a>
+
+ <a name="description"></a>
+ <h2>Description</h2>
+
+ <p>This section will cover a short description of the present design
+ and the full description of the proposed design changes, including
+ the constraint system and algorithm for solving the constraint
+ system.
+ </p>
+
+ <a name="presentdesign"></a>
+ <h3>The Present Design</h3>
+
+ <p>Currently phases in the compiler are ordered statically by a hard
+ coded list structure in <code>class Global</code> (found in
+ Global.scala), where the method <code>builtInPhaseDescriptors</code>
+ returns the list of phase objects. The resulting list from invoking
+ this method is then extended with the phases from the plug-in
+ supplied by the user. This is done in the
+ <code>computePhaseDescriptors</code> method in <code>class
+ Plugins</code> (found in plugins/Plugins.scala). This method is
+ then again called from the method <code>phaseDescriptors</code> in
+ <code>class Global</code>. So all together the process of
+ calculating the phases of the compiler is spread over several files
+ and quite complicated.</p>
+
+ <p>A plug-in can supply a number of phases to the compiler and the
+ architecture of the plug-in subsystem already supply some of the
+ functionality that will be added to all internal phases. All phases
+ are a subclass of <code>class SubComponent</code> and all phases
+ supplied by plug-ins are subclasses of <code>class
+ PluginComponent</code> (which is a subclass of <code>class
+ SubComponent</code>).</p>
+
+ <a name="proposeddesign"></a>
+ <h3>The Proposed Design</h3>
+
+ <p>This section will cover the design of the proposed system for
+ handling inclusion of internal and external phases uniformly. It
+ will also cover a description of the constraint system and a
+ algorithm for solving these constraint for generating the compiler
+ phase chain. This design will focus on satisfying the use cases <a
+ href="#usecases">described earlier</a>.
+ </p>
+
+ <p>From the use cases above it is possible to identify two kinds of
+ constraints. The first constraint is the <i>runs after</i>
+ dependency and the second constraint is the <i>runs right after</i>
+ dependency. It is necessary to declare that a given phase has to
+ <i>runs after</i> a list of phase names, however the <i>runs right
+ after</i> constraint only needs to declare the name one phase.
+ </p>
+ <ul>
+ <li>Lets define the <i>runs after</i> constraint using the
+ <code>runsAfter</code> variable with the Scala type
+ <code>List[String]</code>. Using this constraint, phase B would
+ declare <code>runsAfter=List(A)</code>, meaning that phase B would
+ like to run somewhere after phase A, but as early as possible.</li>
+
+ <li>Lets define the <i>runs right after</i> constraint using the
+ <code>runsRightAfter</code> variable with the Scala type
+ <code>Option[String]</code>. Using this constraint, phase B would
+ declare <code>runsRightAfter=Some(A)</code>, meaning that phase B
+ wants to run right after phase A and no other phases are allowed to
+ come between phase A and B. From a larger perspective meaning that
+ phase A and B can be regarded as on large phase with one input and
+ one output.</li>
+ </ul>
+
+ <p>A goal of this work is to handle the inclusion and constraint
+ resolution of internal and plug-in supplied phases in a uniform way,
+ this also means that the responsibility of phase assembly should not
+ be handled by the plug-in subsystem any more, but by a separate
+ instance. For this separate instance we create a new
+ <code>PhaseAssembly</code> trait that is mixed into the
+ <code>Global</code> class in the same way as <code>Plug-Ins</code>
+ is mixed in.
+ </p>
+
+ <p>In the diagram below a schematic overview of the proposed system
+ is shown. A description of the individual components and the
+ modification needed are given below.
+ </p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-9.png" alt="" border="0" width="55%" />
+ </div>
+
+ <a name="propdesign1"></a>
+ <h4>1. Internal Phases</h4>
+
+ <p>All internal phase objects are declared in class
+ <code>Global</code> and will be extended to include the
+ <code>runsAfter</code> and the <code>runsRightAfter</code> variables
+ with the types described above. This will ensure that the internal
+ phases will always succeed in creating a compiler phase chain
+ depending on the compiler target.
+ </p>
+ <p>The phase objects that are needed for a given target will be
+ added to the phases set. See <a href="#propdesign3">3. Phases
+ Set</a> for more information.
+ </p>
+
+
+ <a name="propdesign2"></a>
+ <h4>2. External Phases</h4>
+
+ <p>All external phases are supplied through plug-ins. All these
+ phases inherit from class <code>PluginComponent</code>. Defining the
+ <code>runsRightAfter=None</code> in class
+ <code>PluginComponent</code> will make the changes to the existing
+ plug-ins minimal, but makes it possible for external phases to use
+ the feature by simple overriding the variable if needed.
+ </p>
+ <p>It is still the responsibility of the plug-in subsystem to load
+ the actual plug-ins from the jar files and also the processing of
+ all the <code>-Xplugin*</code> compiler options available at the
+ command line. The phase assembly code currently present in the
+ plug-in subsystem will be replaced by code that adds all plug-in
+ supplied phases to the phases set. See <a
+ href="#propdesign3">3. Phases Set</a> for more information.
+ </p>
+
+ <a name="propdesign3"></a>
+ <h4>3. Phases Set</h4>
+
+ <p>The phases set contains all the phase objects that should be
+ taken into consideration when performing compiler phase chain
+ assembly. This phases set would located in the class
+ <code>Global</code>. A proper Scala declaration of such a phases set
+ is shown below.
+ </p>
+ <pre>protected val phasesSet : HashSet[SubComponent] = new HashSet[SubComponent]()</pre>
+
+ <p>Ensuring that all phase objects are unique with respect to the
+ phase names, the <code>hashCode</code> method in class
+ <code>SubComponent</code> will be overridden to return the hash code
+ of the phase name and not the object itself.
+ </p>
+
+ <a name="propdesign4"></a>
+ <h4>4. Phase Assembly</h4>
+
+ <p>From a compiler design perspective this component will include
+ the data structures and implementation of the constraint solving
+ algorithm that are needed to implement this proposal. It would be
+ integrated as a <code>trait PhaseAssembly</code> that is mixed into
+ <code>class Global</code> with this self type <code>self: Global
+ =&gt;</code>.
+ </p>
+
+ <p>A very high level description of the actions performed by this
+ component can be split into three distinct parts. A detailed
+ algorithm that implements this high level description can be found
+ below in the <a href="#constsolver">section on the constraint
+ solving algorithm</a>.
+ </p>
+
+ <ol>
+ <li><strong>Phases Set to Dependency Graph</strong><br />
+ <p>From the phase objects in the phases set a dependency graph is
+ created, where the edges in this graph are constructed from the
+ <code>runsAfter</code> and <code>runsRightAfter</code>
+ constraints. Each node in the dependency graph has both a phase
+ name and a phase object, because all constraints in the phase
+ objects are only given by name.
+ </p>
+ </li>
+ <li><strong>Dependency Graph to Dependency Tree</strong><br />
+ <p>To be able to create the compiler phase chain the dependency
+ graph has to be converted into a dependency tree. The dependency
+ graph contains nodes that have a phase name, but no phase
+ object. These nodes have to be removed. Also all edges in the
+ graph that are generated from <code>runsRightAfter</code>
+ constraints have to be handled special to enforce this constraint
+ and the graph is checked for cycles. If a cycle is found, the
+ algorithm will terminal with a fatal error, preventing the
+ compiler from starting. If no cycles are found in the dependency
+ graph is simplified with respect to what will become the root in
+ the dependency tree, by removing unneeded dependency edges. This
+ will transform the dependency graph into a dependency tree.
+ </p>
+ </li>
+ <li><strong>Dependency Tree to Compiler Phase List</strong><br />
+ <p>The compiler phase list is constructed by traversing the
+ dependency tree from the root. The traversal algorithm will be
+ described below.
+ </p>
+ </li>
+ </ol>
+
+
+ <a name="propdesign5"></a>
+ <h4>5. Constraint System</h4>
+
+ <p>The constraint system is implemented as a graph structure where
+ phases are modeled as nodes and the constraints are modeled as
+ directed edges. This section will describe the basic entities of the
+ constraint system and how they are modeled in the dependency graph.</p>
+ <table>
+ <tr>
+ <td colspan="2">
+ <p>Each node in the dependency graph contains several items of
+ information about the phase object and the dependencies to and
+ from it.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <ul>
+ <li><strong>phaseobj:</strong> <i>(type:
+ SubComponent)</i><br /> A reference to the actual phase
+ object, if there is any. If there is a phase object then
+ there is also a phase name, but the constraints are only
+ given by name, so some nodes may have a phase name and no
+ phase object.
+ </li>
+ <li><strong>phasename:</strong> <i>(type: String)</i><br />
+ The name of the phase object. This is always set.
+ </li>
+ <li><strong>after:</strong> <i>(type: HashSet[Edge]())</i>
+ <br />
+ This is the set of <code>Edge</code> object that point to
+ <code>Node</code> objects that have to come before this
+ <code>Node</code>. So all <code>runsAfter</code> and
+ <code>runsRightAfter</code> constraints given by a phase
+ object are present in this <code>after</code> list.
+ </li>
+ <li><strong>deps:</strong> <i>(type: HashSet[Edge]())</i>
+ <br />
+ This is the set of <code>Edge</code> object that points to
+ this <code>Node</code> object. So its the opposite of the
+ <code>after</code> list.
+ </li>
+ </ul>
+ </td>
+ <td>
+ <div style="text-align: center;">
+ <img src="sip-00002-15.png" alt="" border="0" width="235" height="186" />
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <p>Each edge in the dependency graph is directed, so it has
+ references to its to and from <code>Node</code> objects and
+ knows if it is created from a <code>runsAfter</code>
+ constraint (soft) or created from a
+ <code>runsRightAfter</code> constraint (hard). </p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <ul>
+ <li><strong>to:</strong> <i>(type: Node)</i>
+ <br />
+ This is a reference to the <code>Node</code> object this
+ <code>Edge</code> object is pointing to. This means that the
+ <code>frm</code> node has a dependency on the
+ <code>to</code> node.
+ </li>
+ <li><strong>frm:</strong> <i>(type: Node)</i>
+ <br />
+ This is a reference to the <code>Node</code> object this
+ <code>Edge</code> object is pointing from.
+ </li>
+ <li><strong>hard:</strong> <i>(type: Boolean)</i>
+ <br />
+ In the dependency graph we have soft and hard
+ dependencies. The soft dependencies are created from the
+ <code>runsAfter</code> list of constraints. The hard
+ dependencies are created from the
+ <code>runsRightAfter</code> constraint, if any.
+ </li>
+ </ul>
+ </td>
+ <td>
+ <div style="text-align: center;">
+ <img src="sip-00002-16.png" alt="" border="0" width="152" height="186" />
+ </div>
+ </td>
+ </tr>
+ </table>
+
+ <p>Below is the interface implementation of the dependency graph in
+ Scala. There are classes implementing the edges and nodes and the
+ container for storing the edges and nodes and aux. method for easy
+ access to the stored information.
+ </p>
+ <pre>
+class Edge(f: Node, t: Node, h: Boolean) {
+ var frm = f
+ var to = t
+ var hard = h
+}
+
+class Node(phs:SubComponent, name:String) {
+ var phasename: String = name
+ var phaseobj: SubComponent = phs
+ var after: HashSet[Edge] = new HashSet[Edge]()
+ var deps: HashSet[Edge] = new HashSet[Edge]()
+}
+
+class DependencyGraph {
+
+ val nodes = new HashMap[String,Node]()
+ val edges = new HashSet[Edge]()
+
+ def getNodeByPhase(name : String) : Node
+ def getNodeByPhase(phs : SubComponent) : Node
+ def softConnectNodes(frm: Node, to: Node) : Unit
+ def hardConnectNodes(frm: Node, to: Node) : Unit
+}
+ </pre>
+
+
+ <a name="constsolver"></a>
+ <h4>Constraint Solving Algorithm</h4>
+
+ <p>This algorithm will build a list of phase objects from a set of
+ phase objects with constraints. The position of each phase object in
+ the final list will ensure that all its constraints are
+ satisfied. The algorithm does this by constructing a dependency
+ graph from the set of phase objects. This dependency graph is then
+ over a series of steps converted into a dependency tree with a root
+ node. To construct the final compiler phase list the dependency tree
+ is traversed from the root building the list of phase objects.</p>
+
+ <p>The function below is the top most function of this algorithm
+ that transforms the set of phase objects into a ordered list of
+ phase objects so all constraints are satisfied. This function
+ follows the description given about the <a href="#propdesign4">phase
+ assembly component</a>. All the auxiliary functions will be covered
+ below.</p>
+
+<pre> <b>function</b> phasesSetToPhasesList(phasesSet)
+
+ <i>// call function to generate dependency graph from phases set</i>
+ graph &lt;- phasesSetToDepGraph( phaseSet )
+
+ <i>// call function to transform the dependency graph to a dependency tree.</i>
+ <i>// if the dependency graph contains a cycle a fatal error will be generated.</i>
+ rootnode &lt;- depGraphToDepTree( graph )
+
+ <i>// call function to recursively build phase list from the root of </i>
+ <i>// the dependency tree</i>
+ phaselist &lt;- depTreeToPhaseList( rootnode, <b>new</b> List() )
+
+ <b>return</b> phaselist
+</pre>
+
+ <p> List of functions called:</p>
+ <ul>
+ <li><a href="#func1">The <code>phasesSetToDepGraph</code> function</a></li>
+ <li><a href="#func2">The <code>depGraphToDepTree</code> function</a></li>
+ <li><a href="#func3">The <code>depTreeToPhaseList</code> function</a></li>
+ </ul>
+
+ <a name="func1"></a>
+ <h5>The <code>phasesSetToDepGraph</code> function</h5>
+
+ <p>The dependency graph, with the elements described in the <a
+ href="#propdesign5">section about the constraint system</a>, is
+ build from the phase objects in the phases set.<br />
+ It works as follows:
+ </p>
+ <ul>
+ <li>create a new dependency graph</li>
+ <li>foreach phase in the phasesSet
+ <ul>
+ <li>create a new graph node <i>fromnode</i> from the phase object and add the
+ ndoe to the graph</li>
+ <li>if the phase object has a runs right after constraint, then
+ create a node <i>tonode</i> from the phase name of the constraint and create a
+ hard edge between <i>fromnode</i> and <i>tonode</i>. Eventual
+ runs after constraints are ignored.</li>
+ <li>if the phase object has no runs right after constraints a
+ node <i>tonode</i> is created from each runs after constraint
+ and connected with a soft edge to the <i>fromnode</i>.</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>A pseudo code version of this algorithm is shown below.</p>
+
+<pre> <b>function</b> phasesSetToDepGraph( phaseSet )
+ <i>// create new graph structure to hold data</i>
+ graph &lt;- <b>new</b> DependencyGraph
+ <i>// iterate over all phase objects in the phasesSet</i>
+ <b>for</b> phs <b>in</b> phasesSet
+ <i>// create a node from the phase object</i>
+ fromnode &lt;- graph.getNodeByName(phs)
+ <i>// test if the phase object has a runs right after constraint</i>
+ <b>if</b> phs.runRightAfter <b>not eq</b> ""
+ <i>// create a node from the phase constraint name and connect with hard edge</i>
+ tonode &lt;- graph.getNodeByName( phs.runRightAfter )
+ graph.hardConnectNodes( fromnode, tonode )
+ <b>else</b>
+ <i>// the phase object did not have a runs right after constraint</i>
+ <i>// iterate over all phase constraints in the runs after constraint list</i>
+ <b>for</b> phsname <b>in</b> phs.runsAfter
+ <i>// create a node from the phase constraint name and connect with soft edge</i>
+ tonode &lt;- graph.getNodeByName( phsname )
+ graph.softConnectNodes( fromnode, tonode )
+
+ <b>return</b> graph
+</pre>
+
+
+
+ <a name="func2"></a>
+ <h5>The <code>depGraphToDepTree</code> function</h5>
+
+ <p>The process of converting the dependency graph into a dependency
+ tree is complex, so to simplify the algorithm the individual steps
+ are split into functions.<br />
+ It works as follows:
+ </p>
+
+ <ul>
+ <li>call method that will remove all nodes from the graph that
+ have no phase object attached</li>
+ <li>call method that will find all edges in the graph that are
+ marked as hard and enforce that the <code>deps</code> list of the
+ edges <code>to</code> node reference only contains this
+ edge. Other edges are moved down to the edges <code>frm</code>
+ node reference</li>
+ <li>What is to become the root of the dependency tree and also the
+ first element in the phase list is extracted from the graph.</li>
+ <li>call method to check if there are cycles in the graph starting
+ from the root node, if there are cycles a fatal error is generated</li>
+ <li>call method to simplify graph into a tree by removing edges
+ that will not break the constraints given</li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> depGraphToDepTree( graph )
+
+ <i>// Remove all nodes where phaseobj == null</i>
+ removeDanglingNodes( graph )
+
+ <i>// Enforce hardlinks / runsRightAfter and promote nodes down the tree</i>
+ enforceHardlinks( graph )
+
+ <i>// Extract the root node from the graph</i>
+ root &lt;- graph.getNodeByPhase( ROOTNAME )
+
+ <i>// Test for cycles in the graph, if found generate fatal error</i>
+ testForCycles( root, <b>new</b> Set() )
+
+ <i>// Simplify graph by removing edges, starting from the given root node</i>
+ simplifyGraphFromNode( root, graph )
+
+ <b>return</b> root
+ </pre>
+
+ <p> List of functions called:</p>
+ <ul>
+ <li><a href="#func4">Helper function <code>removeDanglingNodes</code></a></li>
+ <li><a href="#func5">Helper function <code>enforceHardlinks</code></a></li>
+ <li><a href="#func6">Helper function <code>testForCycles</code></a></li>
+ <li><a href="#func7">Helper function <code>simplifyGraphFromNode</code></a></li>
+ </ul>
+
+ <a name="func3"></a>
+ <h5>The <code>depTreeToPhaseList</code> function</h5>
+
+ <p>The graph has been transformed into a tree and a reference to the
+ root node is identified. The tree is now traversed from the root
+ node, by calling itself recursively on each node object. The empty
+ list is given to the function together with the root node and the
+ phase objects are added to the list as the function traverses the
+ tree.<br />
+ It works as follows:</p>
+
+ <ul>
+ <li>the function is called with a node object and a list</li>
+ <li>the phase object of the node object, the function was call
+ with, is added to the list</li>
+ <li>if this node has no nodes that depend on it, the list of phase
+ objects is returned</li>
+ <li>if this node has only one node that depends on it, we call
+ recursively with that node and the list as arguments, the result
+ of this is returned</li>
+ <li>if this node has more then one node that depends upon it,
+ these dependent nodes are ordered. We now iterate over this
+ ordered list of nodes and call recursively the function.</li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> depTreeToPhaseList( node, chain )
+ <i>// add the phase object of the node to the chain list</i>
+ chain &lt;- chain.append( node.phaseobj )
+ <i>// no more depends, return the chain</i>
+ <b>if</b> node.deps.length == 0
+ <b>return</b> chain
+ <i>// only one depend, so no need to order one element, just call recursively </i>
+ <b>else if</b> node.deps.length == 1
+ <b>return</b> depTreeToPhaseList( node.deps.getFirst().frm, chain )
+ <i>// more then one depend</i>
+ <b>else</b>
+ <i>// the depends are ordered and saved as a list</i>
+ order &lt;- dependencyOrder( node.deps )
+ <i>// iterate over the list of ordered depend nodes and call recursively </i>
+ <b>for</b> nd <b>in</b> order
+ chain &lt;- depTreeToPhaseList( nd, chain )
+ <i>// return the complete chain</i>
+ return chain
+ </pre>
+
+ <p> List of functions called:</p>
+ <ul>
+ <li><a href="#func8">Helper function <code>dependencyOrder</code></a></li>
+ </ul>
+
+ <a name="func4"></a>
+ <h5>Helper function <code>removeDanglingNodes</code></h5>
+
+ <p>This helper function will given a dependency graph find all nodes
+ that have no reference to a phase object and remove these nodes from
+ the graph. (See <a href="#usecase2">use caes 2</a>) These nodes that
+ have no phase object are generated from runs after or runs right
+ after constraints to phases that are not loaded.<br /> It is done as
+ follows:</p>
+
+ <ul>
+ <li>create a list L of all nodes in the given graph that have no
+ phase object</li>
+ <li>foreach node in L
+ <ul>
+ <li>remove the node from the graph</li>
+ <li>foreach edge in the nodes deps list, remove this edge from
+ the graph</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> removeDanglingNodes( graph )
+ <i>// find all nodes with no phase object</i>
+ dnodes &lt;- filter( lambda node: node.phaseobj == null, graph.nodes )
+ <i>// iterate over these nodes and remove them one by one</i>
+ <b>for</b> node <b>in</b> dnodes
+ graph.nodes.remove( node )
+ <i>// also remove all edge objects related to this node object</i>
+ <b>for</b> edge <b>in</b> node.deps
+ graph.edges.remove( edge )
+ edge.frm.after.remove( edge )
+ </pre>
+
+
+ <a name="func5"></a>
+ <h5>Helper function <code>enforceHardlinks</code></h5>
+
+ <p>This helper function will given a dependency graph find all edges
+ in the graph that are marked as hard. It will then ensure that the
+ <code>to</code> node the edge is pointing to only has this edge in
+ its deps list. (See <a href="#usecase7">use case 7</a>).<br />
+ It works as follows:
+ </p>
+
+ <ul>
+ <li>loop until no edges are moved
+ <ul>
+ <li>create list L of all edges in the given graph that are marked
+ as hard</li>
+ <li>foreach edge in L
+ <ul>
+ <li>create list HE of edges marked as hard in the deps list of
+ the node object this edge is pointing to</li>
+ <li>if there is more then one element in HE it will not be possible
+ to generate a compiler phase list and a fatal error is
+ generated</li>
+ <li>if there is only one element in HE, create a list E of all
+ the edges not marked as hard in the deps list of
+ the node object this edge is pointing to</li>
+ <li>override the deps list of the node object this edge is
+ pointing to with the HE list</li>
+ <li>foreach pedge in E
+ <ul>
+ <li>attach the pedge to the deps list of the node object this
+ edge is pointing from</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> enforceHardlinks( graph )
+ <b>do</b>
+ <i>// lets assume that no edges are moved until proven otherwise</i>
+ rerun &lt;- <b>false</b>
+ <i>// find all edges in the graph that are marked as hard</i>
+ hardlinks &lt;- <b>filter</b>( <b>lambda</b> e: e.hard, graph.edges )
+ <i>// iterate over all hard edges found</i>
+ <b>for</b> edge <b>in</b> hardlinks
+ <i>// find all hard edges in the deps list of the node this edge points to</i>
+ sanity &lt;- <b>filter</b>( <b>lambda</b> e: e.hard, edge.to.deps )
+ <b>if</b> sanity.length > 1
+ <i>// generate fatal error, there is more then one runs right
+ // after constraint on the same node</i>
+ <b>else</b>
+ <i>// find all non hard edges in the deps list of the node this edge points to</i>
+ promote &lt;- <b>filter</b>( <b>lambda</b> e: not e.hard, edge.to.deps )
+ <i>// assign the list of hard edges to the deps list of the node this
+ // edge points to</i>
+ edge.to.deps &lt;- sanity
+ <i>// iterate over all non hard edges and attach them to the deps list of the
+ // node this edge points from</i>
+ <b>for</b> pedge <b>in</b> promote
+ <i>// we have moved an edge - we need to rerun this to check</i>
+ rerun &lt;- true
+ <i>// move the edge object down along the hard edge</i>
+ pedge.to &lt;- edge.frm
+ edge.frm.deps.attach(pedge)
+ <i>// if edges where moved, then rerun to make sure the structure is valid</i>
+ <b>while</b> rerun
+ </pre>
+
+ <p>To better understand this little function, lets look at some
+ diagrams and how this function works on these examples. The first
+ example is shown below. Here phase B wants to run right after phase
+ A and phase C just wants to run somewhere after phase A, so there is
+ no problem in pushing phase C down to run after phase B. The
+ function does this be first finding all the hard edges (the blue
+ edges). It then inspects the edges one by one and in this example we
+ have only one hard edge. The edge goes from phase B to phase A,
+ meaning that phase B want to run right after phase A. The algorithm
+ now looks at the <code>deps</code> list of phase A and finds that
+ there is only one hard edges (this is very good). The algorithm now
+ filters out the non-hard edges and finds the edge to phase C. This
+ edge is now detached from phase A and attached to phase B.
+ </p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-17.png" alt="" border="0" width="40%" />
+ </div>
+
+ <p>With the same arguments can we also handle the situation shown
+ below.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-18.png" alt="" border="0" width="45%" />
+ </div>
+
+
+ <a name="func6"></a>
+ <h5>Helper function <code>testForCycles</code></h5>
+
+ <p>This helper function will, given a node in the graph and a set
+ containing node names, determine of there are any cycles in the
+ graph. This will ensure that <a href="#usecase8">use case 8</a> is
+ addressed. Please note that this function will call itself
+ recursively and is called the first time with the root node and an
+ empty set of node names.
+ <br />
+ It is done as follows:
+ </p>
+
+ <ul>
+ <li>test if the name of the node is already contained in the set,
+ if it is a cycle is found and a fatal error is generated.</li>
+ <li>if the name is not in the set, the name of the node is added
+ to the set</li>
+ <li>the deps list of the node is ordered and stored in nodes</li>
+ <li>foreach nd in nodes
+ <ul>
+ <li>call the function recursively with the node nd and the set
+ of node names</li>
+ </ul>
+ </li>
+ <li>remove the name of the node from the set</li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> testForCycles( node, names )
+ <i>// test if the name of the node is already in the set</i>
+ <b>if</b> names.contains( node.phasename )
+ <i>// names are unique, so this is a fatal error, there is a cycle
+ // the same name has been visited twice</i>
+
+ <i>// add the name of the node to the set</i>
+ names.add( node.phasename )
+ <i>// use the dependencyOrder function to sort the deps of the node</i>
+ nodes &lt;- dependencyOrder( node.deps )
+ <i>// iterate over all deps nodes and call recursively</i>
+ <b>for</b> nd <b>in</b> nodes
+ testForCycles(nd, names)
+
+ <i>// remove the name of the node from the set</i>
+ names.remove( node.phasename )
+ </pre>
+
+ <p> List of functions called:</p>
+ <ul>
+ <li><a href="#func8">Helper function <code>dependencyOrder</code></a></li>
+ </ul>
+
+ <p>There are other ways of detecting cycles in graphs, that are
+ faster and more efficient, please <a
+ href="http://www.cs.umu.se/kurser/TDBA77/VT06/algorithms/BOOK/BOOK2/NODE68.HTM">read
+ here</a> for more information.</p>
+
+ <a name="func7"></a>
+ <h5>Helper function <code>simplifyGraphFromNode</code></h5>
+
+ <p>This helper function will, given a node in the graph and a
+ reference to the graph structure, remove unneeded edges and
+ transforming the graph into a tree. Please note that this
+ function will call itself recursively and is called the first time
+ with the root node and the full graph.
+ <br />
+ It is done as follows:
+ </p>
+
+ <ul>
+ <li>create an empty list RM</li>
+ <li>foreach edge in the deps list of the node, if the node this
+ edge is pointing from has mode then one dependencies then add this
+ edge to RM</li>
+ <li>foreach edge in RM, remove this edge from the graph</li>
+ <li>the deps list of the node is ordered and stored in nodes</li>
+ <li>foreach nd in nodes
+ <ul>
+ <li>call the function recursively with the node nd and the
+ updated graph</li>
+ </ul>
+ </li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> simplifyGraphFromNode( node, graph )
+ removal &lt;- <b>new</b> List()
+ <b>for</b> edge <b>in</b> node.deps
+ <b>if</b> edge.frm.after.length > 1
+ removal.append( edge )
+
+ <b>for</b> edge <b>in</b> removal
+ node.deps.remove( edge )
+ edge.frm.after.remove( edge )
+ graph.edges.remove( edge )
+
+ nodes &lt;- dependencyOrder( node.deps )
+ <b>for</b> nd <b>in</b> nodes
+ simplifyGraphFromNode( nd, graph )
+ </pre>
+
+ <p> List of functions called:</p>
+ <ul>
+ <li><a href="#func8">Helper function <code>dependencyOrder</code></a></li>
+ </ul>
+
+
+ <p>In the example shown below we simplify this graph into a tree
+ from the node A. This means that we start the traversal from node A
+ and uses the <code>A.deps</code> list to continue the traversal. If
+ <code>A.deps</code> contains more then one element, the list is
+ sorted so we first visit all plug-in supplied phases in alphabetical
+ order and then the internal phase. In this example this gives the
+ order <code>[P,R,B]</code>. Before the algorithm traverses to a new
+ node it checks that node for its number of <code>after</code>
+ links. If it has more then one after link, it simply deletes the
+ link to it so it can carry on. In the example below this is the case
+ of node P and T. When the algorithm visits node P and wants to
+ traverse on to node T, it checks the number of <code>after</code>
+ constraints in node T. Node T has two after constraints so it can
+ safely delete the edge between node P and T, because there must be
+ another node that we have not included yet, that will include this
+ node T.</p>
+
+ <div style="text-align: center;">
+ <img src="sip-00002-19.png" alt="" border="0" width="70%" />
+ </div>
+
+
+ <a name="func8"></a>
+ <h5>Helper function <code>dependencyOrder</code></h5>
+
+ <p>This helper function will given a list of edges sort them
+ according to a specific scheme are return them as a list. The
+ sorting scheme is as follows. The returned list is the reverse of
+ first having the plug-in supplied phases in alphabetical order
+ followed by the internal phases. <br />
+ This is done as follows:
+ </p>
+ <ul>
+ <li>nodes for internal and external phases are filtered from the
+ deps list</li>
+ <li>the external nodes are ordered by the phase name and
+ reversed</li>
+ <li>the external nodes are appended to the internal nodes list and
+ the resulting list is reversed</li>
+ </ul>
+
+ <p>Below is shown a pseudo code version of the function.</p>
+
+ <pre> <b>function</b> dependencyOrder( deps )
+ external &lt;- <b>filter</b>(<b>lambda</b> e: (! e.frm.phaseobj.internal), deps)
+ internal &lt;- <b>filter</b>(<b>lambda</b> e: e.frm.phaseobj.internal, deps)
+
+ extnodes &lt;- <b>map</b>(<b>lambda</b> e: e.frm, external)
+ extnodes &lt;- extnodes.sort(<b>lambda</b> (n1,n2): (n1.phasename compareTo n2.phasename) &lt; 0)
+ extnodes &lt;- extnodes.reverse
+
+ nodes &lt;- (<b>map</b>(<b>lambda</b> e: e.frm, internal)).<b>extend</b>( extnodes )
+ nodes &lt;- nodes.reverse
+ <b>return</b> nodes
+ </pre>
+
+
+
+ <a name="namingscheme"></a>
+ <h3>Naming Scheme for Internal and External Phases</h3>
+
+ <p>Having the ability to load a large number of plug-ins, where each
+ plug-in can supply several named phases, gives a high possibility of
+ name clashes. There is no way to enforce unique names in plug-in
+ supplied phases because they can have inter dependencies. The best
+ solution is to suggest a naming scheme for phase names.</p>
+
+ <p>This naming scheme composes all names from the package/plug-in
+ name, then a double colon <code>::</code> and then the actual phase
+ name. So for the internal compiler phase names this would be:</p>
+
+ <pre> val phaseName = "nsc::tailcalls"</pre>
+
+ <p>For a plug-in with name <code>unit</code> that supplies a phase
+ with name <code>convert</code> the full phase name would be:</p>
+
+ <pre> val phaseName = "unit::convert"</pre>
+
+ <p>By using this naming scheme for all phases there is a namespace
+ for phase names within each plug-in and external phases will never
+ clash with internal phase names.</p>
+
+ <a name="implications"></a>
+ <h3>Implications of This Proposal</h3>
+
+ <p>All plug-ins need to be updated to the design in this
+ proposal. This means that all current plug-ins will not be able to
+ load. However the modifications to the existing plug-ins are
+ minor. Current variables and types:
+ </p>
+ <pre> val runsAfter: String</pre>
+ <p>The proposed changes are:</p>
+ <pre> val runsAfter: List[String]</pre>
+
+ <p>All internal phases in the compiler need to declare there
+ ordering. This means that instead of having the ordering very
+ explicit in the list structure, the ordering is encoded into each
+ phase object. The following signatures will be added to the
+ <code>SubComponent</code> class.</p>
+
+ <pre> val runsAfter: List[String]
+ val runsRightAfter: Option[String]</pre>
+
+ <p>The following items must be added to each phase
+ object to implement the signatures (however they must be adapted to
+ the individual phase object).</p>
+
+ <pre> val runsAfter = List[String]("phasename")
+ val runsRightAfter = None</pre>
+
+ <p>There is no reason to change the names of the phases as suggested in
+ the section above, but it will minimize the chance of name clashes
+ and will also minimize the chance of accidental dependencies.</p>
+
+ <a href="#top">To the top</a>
+
+ <a name="implementation"></a>
+ <h2>Implementation</h2>
+
+ <p>An example implementation has been created that follows the
+ algorithm sketched in this proposal and models the compilers
+ internal structure. This implementation can be found in the file <a
+ href="sip-00002-10.scala">sip-00002-10.scala</a>. The example
+ implementation uses the phases from <a href="#usecase10">use case
+ 10</a> as its data.
+ </p>
+
+ <p>Running the example code</p>
+
+ <ul>
+ <li>Compile the code using <code>scalac
+ sip-00002-10.scala</code></li>
+ <li>Run the example using <code>scala
+ depgraph.DepGraphTest</code></li>
+ <li>This will generate the console output as seen below and <a
+ href="http://www.graphviz.org/">Graphviz</a> dot files that can be
+ compiled into png images. These png images are also shown
+ below.</li>
+ </ul>
+
+ <a name="consoleexample"></a>
+ <p>Console output</p>
+
+ <pre>$ scalac sip-00002-10.scala
+$ scala depgraph.DepGraphTest
+[dropping depend on node with no phase: nsc::msil]
+[removing edge: nsc::tailcalls =&gt; nsc::pickler]
+[removing edge: plug2::optimization2 =&gt; plug2::optimization1]
+ - nsc::parser
+ - nsc::typer
+ - plug1::optimization1
+ - nsc::pickler
+ - nsc::liftcode
+ - plug2::optimization1
+ - nsc::tailcalls
+ - nsc::erasure
+ - nsc::cleanup
+ - plug2::optimization2
+ - nsc::jvm
+ - nsc::terminal
+$ </pre>
+
+ <p>PNG images of the generated dot files showing the graph
+ structure. Internal phases are marked as black circles and plug-in
+ phases are marked as green circles. The hard links (runsRightAfter
+ constraints) are marked as blue arrows. Click on the pictures to
+ enlarge.</p>
+ <a name="examples"></a>
+ <table>
+ <tr>
+ <td valign="top"><strong>1. </strong><br />
+ <div style="text-align: center;">
+ <a href="sip-00002-11.png">
+ <img src="sip-00002-11.png" alt="" border="0" width="100%"/>
+ </a>
+ </div>
+ </td>
+
+ <td valign="top"><strong>2. </strong><br />
+ <div style="text-align: center;">
+ <a href="sip-00002-12.png">
+ <img src="sip-00002-12.png" alt="" border="0" width="100%" />
+ </a>
+ </div>
+ </td>
+ <td valign="top"><strong>3. </strong><br />
+ <div style="text-align: center;">
+ <a href="sip-00002-13.png">
+ <img src="sip-00002-13.png" alt="" border="0" width="100%" />
+ </a>
+ </div>
+ </td>
+ <td valign="top"><strong>4. </strong><br />
+ <div style="text-align: center;">
+ <a href="sip-00002-14.png">
+ <img src="sip-00002-14.png" alt="" border="0" width="100%" />
+ </a>
+ </div>
+ </td>
+ </tr>
+ </table>
+
+ <a href="#top">To the top</a>
+
+</body>
+</html>
diff --git a/SIP/presip-classic.xhtml b/SIP/presip-classic.xhtml
new file mode 100644
index 0000000000..3dac7c6e1d
--- /dev/null
+++ b/SIP/presip-classic.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>The Scala Classic Calculus</title>
+ <meta name="sip" content="XXXXX"/>
+ <meta name="author" content="Geoffrey Washburn"/>
+ <meta name="version" content="0"/>
+ <meta name="type" content="informational"/>
+ <meta name="status" content="submission"/>
+ <meta name="created" content="2008-08-21"/>
+ <meta name="updated" content="2008-08-21"/>
+ <!-- Stylesheet -->
+ <link rel="stylesheet" href="http://lampsvn.epfl.ch/svn-repos/scala/sip/trunk/sip.css" type="text/css"/>
+</head>
+<body>
+ <h1>The Scala Classic Calculus</h1>
+
+ <p>Copyright &copy; 2008, Geoffrey Washburn</p>
+
+ <h2>Abstract</h2>
+
+ This document describes the Scala Classic calculus that provides a
+ verified formal modal for a subset of the Scala language. This
+ calculus can be useful in understanding the Scala language
+ independently of the Scala Language Specification.
+
+</body>
+</html>
diff --git a/SIP/presip-constraints.xhtml b/SIP/presip-constraints.xhtml
new file mode 100644
index 0000000000..a53d32e97a
--- /dev/null
+++ b/SIP/presip-constraints.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Generalized type constraints</title>
+ <meta name="sip" content="XXXXX"/>
+ <meta name="author" content="Geoffrey Washburn"/>
+ <meta name="version" content="0"/>
+ <meta name="type" content="standards"/>
+ <meta name="status" content="submission"/>
+ <meta name="created" content="2008-08-21"/>
+ <meta name="updated" content="2008-08-21"/>
+ <meta name="scala-version" content="2.8.0"/>
+ <!-- <meta name="owner-contact" content="[URI]"/> -->
+ <!-- <meta name="discussion" content="[URI]"/> -->
+ <!-- <link rel="auxiliary" href="[URI]" type="[mime type]"/> -->
+ <!-- <link rel="replaces" href="[URI]" type="application/xhtml+xml"/> -->
+ <!-- <link rel="depends-on" href="[URI]" type="application/xhtml+xml"/> -->
+ <!-- Stylesheet -->
+ <link rel="stylesheet" href="http://lampsvn.epfl.ch/svn-repos/scala/sip/trunk/sip.css" type="text/css"/>
+</head>
+<body>
+ <h1>Generalized type constraints</h1>
+ <p>Copyright &copy; 2008, Geoffrey Washburn</p>
+
+ <h2>Abstract</h2>
+
+</body>
+</html>
diff --git a/SIP/presip-depmethods.xhtml b/SIP/presip-depmethods.xhtml
new file mode 100644
index 0000000000..170a018423
--- /dev/null
+++ b/SIP/presip-depmethods.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Dependent method types</title>
+ <meta name="sip" content="XXXXX"/>
+ <meta name="author" content="Geoffrey Washburn"/>
+ <meta name="version" content="0"/>
+ <meta name="type" content="standards"/>
+ <meta name="status" content="submission"/>
+ <meta name="created" content="2008-08-21"/>
+ <meta name="updated" content="2008-08-21"/>
+ <meta name="scala-version" content="2.8.0"/>
+ <!-- <meta name="owner-contact" content="[URI]"/> -->
+ <!-- <meta name="discussion" content="[URI]"/> -->
+ <!-- <link rel="auxiliary" href="[URI]" type="[mime type]"/> -->
+ <!-- <link rel="replaces" href="[URI]" type="application/xhtml+xml"/> -->
+ <!-- <link rel="depends-on" href="[URI]" type="application/xhtml+xml"/> -->
+ <!-- Stylesheet -->
+ <link rel="stylesheet" href="http://lampsvn.epfl.ch/svn-repos/scala/sip/trunk/sip.css" type="text/css"/>
+</head>
+<body>
+ <h1>Dependent method types</h1>
+ <p>Copyright &copy; 2008, Geoffrey Washburn</p>
+
+ <h2>Abstract</h2>
+
+</body>
+</html>
diff --git a/SIP/sip.css b/SIP/sip.css
new file mode 100644
index 0000000000..6c1a877fc9
--- /dev/null
+++ b/SIP/sip.css
@@ -0,0 +1,5 @@
+/* Default stylesheet for SIPs */
+
+body {
+ width: 40em;
+} \ No newline at end of file
diff --git a/SIP/virtual-traits/sip-0000X-1.xhtml b/SIP/virtual-traits/sip-0000X-1.xhtml
new file mode 100644
index 0000000000..e9cda55ae6
--- /dev/null
+++ b/SIP/virtual-traits/sip-0000X-1.xhtml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Virtual Traits for Scala : Bibtex</title>
+ <link rel="stylesheet" href="http://lampsvn.epfl.ch/svn-repos/scala/sip/trunk/sip.css" type="text/css"/>
+ </head>
+<body>
+
+<a name="madsen93:_objec_orien_progr_beta_progr_languag"></a><pre>
+@book{<a href="used.html#madsen93:_objec_orien_progr_beta_progr_languag">madsen93:_objec_orien_progr_beta_progr_languag</a>,
+ author = {Madsen, Ole Lehrmann and Nygaard, Kristen and M\o{}ller-Pedersen, Birger},
+ title = {Object-Oriented Programming in The Beta Programming Language},
+ publisher = {Addison-Wesley},
+ year = 1993
+}
+</pre>
+
+<a name="Mads89a"></a><pre>
+@inproceedings{<a href="used.html#Mads89a">Mads89a</a>,
+ author = {Ole Lehrmann Madsen and Birger M{\o}ller-Pedersen},
+ title = {Virtual Classes: {A} Powerful Mechanism
+ in Object-Oriented Programming},
+ booktitle = {Proceedings {OOPSLA}'89, {ACM SIGPLAN Notices}},
+ pages = {397--406},
+ volume = {24, 10},
+ month = oct,
+ year = {1989}
+}
+</pre>
+
+<a name="ernst99b"></a><pre>
+@phdthesis{<a href="used.html#ernst99b">ernst99b</a>,
+ author = {Erik Ernst},
+ title = {gbeta -- a Language with Virtual Attributes, Block Structure, and Propagating, Dynamic Inheritance},
+ school = {Department of Computer Science, University of Aarhus, \AA{}rhus, Denmark},
+ year = {1999}
+}
+</pre>
+
+<a name="1111062"></a><pre>
+@inproceedings{<a href="used.html#1111062">1111062</a>,
+ author = {Erik Ernst and Klaus Ostermann and William R. Cook},
+ title = {A virtual class calculus},
+ booktitle = {POPL '06: Conference record of the 33rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages},
+ year = 2006,
+ isbn = {1-59593-027-2},
+ pages = {270--282},
+ location = {Charleston, South Carolina, USA},
+ doi = {<a href="http://doi.acm.org/10.1145/1111037.1111062">http://doi.acm.org/10.1145/1111037.1111062</a>},
+ publisher = {ACM Press},
+ address = {New York, NY, USA}
+}
+</pre>
+
+<a name="Erns01a"></a><pre>
+@inproceedings{<a href="used.html#Erns01a">Erns01a</a>,
+ author = {Erik Ernst},
+ booktitle = {ECOOP 2001},
+ editor = {J. L. Knudsen},
+ number = {2072},
+ pages = {303--326},
+ publisher = {Springer Verlag},
+ series = {LNCS},
+ title = {Family Polymorphism},
+ year = {2001}
+}
+</pre>
+
+<a name="EE99"></a><pre>
+@inproceedings{<a href="used.html#EE99">EE99</a>,
+ author = {Erik Ernst},
+ title = {Propagating Class and Method Combination},
+ pages = {67--91},
+ editor = {Rachid Guerraoui},
+ booktitle = {Proceedings {ECOOP}'99},
+ address = {Lisboa, Portugal},
+ month = jun,
+ year = 1999,
+ series = {LNCS 1628},
+ publisher = {Springer-Verlag},
+ isbn = {ISBN 3-540-66156-5}
+}
+</pre>
+
+<a name="aracic06:_overv_of_caesarj"></a><pre>
+@inproceedings{<a href="used.html#aracic06:_overv_of_caesarj">aracic06:_overv_of_caesarj</a>,
+ author = {Ivica Aracic and Vaidas Gasiunas and Mira Mezini and Klaus Ostermann},
+ title = { An Overview of CaesarJ},
+ booktitle = {Transactions on Aspect-Oriented Software Development I},
+ pages = {135-173},
+ year = 2006,
+ volume = {3880/2006},
+ series = {Lecture Notes in Computer Science},
+ publisher = {Springer Berlin / Heidelberg}
+}
+</pre>
+
+</body>
+</html>
diff --git a/SIP/virtual-traits/sip-0000X.xhtml b/SIP/virtual-traits/sip-0000X.xhtml
new file mode 100644
index 0000000000..170a1ec436
--- /dev/null
+++ b/SIP/virtual-traits/sip-0000X.xhtml
@@ -0,0 +1,341 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Virtual Traits for Scala</title>
+ <meta name="sip" content="0000X"/>
+ <meta name="author" content="Anders Bach Nielsen"/>
+ <meta name="version" content="0"/>
+ <meta name="type" content="standards"/>
+ <meta name="status" content="submission"/>
+ <meta name="created" content="2008-08-21"/>
+ <meta name="updated" content="2008-11-24"/>
+ <meta name="scala-version" content="2.8.0.final-"/>
+ <meta name="owner-contact" content="mailto:andersbach.nielsen@epfl.ch"/>
+ <!-- <meta name="discussion" content="[URI]"/> -->
+ <!-- <link rel="auxiliary" href="[URI]" type="[mime type]"/> -->
+ <!-- <link rel="replaces" href="[URI]" type="application/xhtml+xml"/> -->
+ <link rel="depends-on" href="PATH-TO-TRAIT-PARAMETERS-SIP" type="application/xhtml+xml"/>
+ <!-- Stylesheet -->
+ <link rel="stylesheet" href="http://lampsvn.epfl.ch/svn-repos/scala/sip/trunk/sip.css" type="text/css"/>
+</head>
+<body>
+ <a name="top"></a>
+ <h1>Virtual Traits for Scala</h1>
+
+ <h2>Abstract</h2>
+
+ <p>This document describes the design, integration and implementation
+ of Virtual Traits (VT) into the Scala language. Virtual traits in
+ Scala are modeled after the BETA [<a
+ href="#madsen93:_objec_orien_progr_beta_progr_languag">1</a>] and
+ gbeta [<a href="#ernst99b">3</a>] notion of virtual classes [<a
+ href="#Mads89a">2</a>, <a href="#1111062">4</a>]. </p>
+
+ <h2>Contents</h2>
+
+ <ul>
+ <li><a href="#motivation">Motivation</a>
+ <ul>
+ <li><a href="#goals">Goals</a></li>
+ <li><a href="#usecases">Use cases</a></li>
+ <li><a href="#usecasedetail">Use cases in detail</a></li>
+ <li><a href="#futuregoals">Future goals that extend beyond this proposal</a></li>
+ </ul>
+ </li>
+ <li><a href="#languagespec">Language specification changes</a></li>
+ <li><a href="#implementation">Implementation</a></li>
+ <li><a href="#references">References</a></li>
+ </ul>
+
+
+ <a name="motivation"></a>
+ <h2>Motivation</h2>
+
+ <p>The Scala language already has abstract type members that behave
+ like the types of virtual classes, however this is only for
+ types. Scala supports both classes and traits, where traits act as
+ mixins that can be composed together to create classes. The reason
+ why there are both classes and traits, is to support the
+ interoperability with Java which has only classes and for this
+ reason classes are treated specially in the compiler.</p>
+
+ <p>Using abstract type members and a complicated rewriting scheme it
+ is possible to create virtual classes manually, but there are
+ several typing issues which will be covered later. We will in this
+ proposal show the extensions to the Scala language specification to
+ include virtual traits, the rewriting scheme for translating virtual
+ trait programs into regular Scala programs and discuss the
+ implementation of this in the Scala compiler.</p>
+
+ <p>This proposal builds upon the parametrized traits.</p>
+
+ <a name="goals"></a>
+ <h3>Goals</h3>
+
+ <ul>
+ <li>Present the additions and changes to the Scala Language
+ Specification to cover Virtual Traits.</li>
+ <li>Show in detail the rewriting scheme used in the translation of
+ Scala programs with virtual traits to programs in Scala
+ proper.</li>
+ <li>Present a sample implementation in the Scala compiler.</li>
+ </ul>
+
+
+ <a name="usecases"></a>
+ <h3>Use cases</h3>
+
+ <ol>
+ <li><a href="#usecase1">Initial binding of virtual trait</a></li>
+ <li><a href="#usecase2">Further binding of a virtual trait</a></li>
+ <li><a href="#usecase3">Final binding of a virtual trait</a></li>
+ <li><a href="#usecase4">Diamond inheritance involving virtual traits</a></li>
+ <li><a href="#usecase5">Virtual traits with nested virtual traits</a></li>
+ </ol>
+
+ <a name="usecasedetail"></a>
+ <h3>Use cases in detail</h3>
+
+ <a name="usecase1"></a>
+ <h4>(1) Initial binding of virtual trait</h4>
+
+ <p></p>
+
+ <pre>
+ <b>trait</b> A &lt;: { ... }
+ <b>trait</b> B &lt;: A { ... }
+ <b>trait</b> C &lt;: Foo <b>with</b> B { ... }
+ </pre>
+
+ <a name="usecase2"></a>
+ <h4>(2) Further binding of a virtual trait</h4>
+
+ <p></p>
+
+ <pre>
+ <b>override trait</b> A &lt;: { ... }
+ <b>override trait</b> B &lt;: { ... }
+ <b>override trait</b> C &lt;: Bar { ... }
+ </pre>
+
+ <a name="usecase3"></a>
+ <h4>(3) Final binding of a virtual trait</h4>
+
+ <p></p>
+
+ <pre>
+ <b>override trait</b> A
+ <b>override trait</b> B { ... }
+ <b>override trait</b> C <b>extends</b> Baz { ... }
+ </pre>
+
+ <a name="usecase4"></a>
+ <h4>(4) Diamond inheritance involving virtual traits</h4>
+
+ <p></p>
+
+ <pre>
+ <b>trait</b> A {
+ <b>trait</b> V &lt;: { ... }
+ }
+ <b>trait</b> B <b>extends</b> A {
+ <b>override trait</b> V &lt;: { ... }
+ }
+ <b>trait</b> C <b>extends</b> A {
+ <b>override trait</b> V &lt;: { ... }
+ }
+ <b>trait</b> D <b>extends</b> B <b>with</b> C {
+ <b>override trait</b> V &lt;: { ... }
+ }
+ </pre>
+
+ <a name="usecase5"></a>
+ <h4>(5) Virtual traits with nested virtual traits</h4>
+
+ <p></p>
+
+ <pre>
+ <b>trait</b> A {
+ <b>trait</b> V &lt;: {
+ <b>trait</b> W &lt;: { ... }
+ }
+ }
+ <b>trait</b> B <b>extends</b> A {
+ <b>override trait</b> V &lt;: {
+ <b>override trait</b> W &lt;: { ... }
+ }
+ }
+ </pre>
+
+ <a name="futuregoals"></a>
+ <h3>Future goals that extend beyond this proposal</h3>
+
+ <ul>
+ <li>Having virtual classes, these would have to be converted from
+ classes to traits and so</li>
+ </ul>
+
+ <a name="languagespec"></a>
+ <h2>Language specification changes</h2>
+
+ This section will cover the changes to the Scala language, both the
+ syntactic and sematic changes that are nessesary to make virtual
+ traits work under Scala.
+
+ <p>
+ Normal declaration of a trait in Scala.
+ </p>
+ <pre>
+ trait Foo { ... }
+ </pre>
+
+ <pre>
+ TmplDef ::= ['case'] 'class' ClassDef
+ | ['case'] 'object' ObjectDef
+ | ['override'] 'trait' TraitDef
+
+TraitDef ::= id [TypeParamClause] TraitTemplateOpt
+
+TraitTemplateOpt ::= TraitExtends TraitTemplate
+ | [['extends'] TemplateBody ]
+ | '&lt;:' TemplateBody
+
+TraitExtends ::= 'extends' | '&lt;:'
+
+
+---------- FLAGS -------------
+
+TRAIT + DEFERED + ! OVERRIDE =&gt; Initial binding
+TRAIT + DEFERED + OVERRIDE =&gt; Further binding
+TRAIT + ! DEFERED + OVERRIDE =&gt; Final binding
+
+classes that extend virtuals are marked with a VIRTUALSUBCLASS
+
+ </pre>
+
+ <h3>Syntactic</h3>
+
+ From the virtual class litterateur there is a distinction between
+ the initial binding and the further binding of a virtual class. To
+ have the same expressiveness in Scala this is the way to declare a
+ initial binding of a virtual trait.
+ <pre>
+ trait Bar &lt;: { ... }
+ </pre>
+ To be able to tell the difference between a initial and a further
+ binding of a trait on the syntactical level, further bindings are
+ written as.
+ <pre>
+ override trait Bar &lt;: { ... }
+ </pre>
+
+ <h3>Semantic</h3>
+
+
+ <a name="implementation"></a>
+ <h2>Implementation</h2>
+
+
+
+ <a name="references"></a>
+ <h2>References</h2>
+
+ <table>
+ <tr valign="top">
+ <td align="right">
+ [<a name="madsen93:_objec_orien_progr_beta_progr_languag">1</a>]
+ </td>
+ <td>
+ Ole&nbsp;Lehrmann Madsen, Kristen Nygaard, and Birger M&oslash;ller-Pedersen.
+ <em>Object-Oriented Programming in The Beta Programming Language</em>.
+ Addison-Wesley, 1993.
+ [&nbsp;<a href="sip-0000X-1.xhtml#madsen93:_objec_orien_progr_beta_progr_languag">bib</a>&nbsp;]
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td align="right">
+ [<a name="Mads89a">2</a>]
+ </td>
+ <td>
+ Ole&nbsp;Lehrmann Madsen and Birger M&oslash;ller-Pedersen.
+ Virtual classes: A powerful mechanism in object-oriented
+ programming.
+ In <em>Proceedings OOPSLA'89, ACM SIGPLAN Notices</em>, volume 24,
+ 10, pages 397-406, October 1989.
+ [&nbsp;<a href="sip-0000X-1.xhtml#Mads89a">bib</a>&nbsp;]
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td align="right">
+ [<a name="ernst99b">3</a>]
+ </td>
+ <td>
+ Erik Ernst.
+ <em>gbeta - a Language with Virtual Attributes, Block Structure,
+ and Propagating, Dynamic Inheritance</em>.
+ PhD thesis, Department of Computer Science, University of Aarhus,
+ &Aring;rhus, Denmark, 1999.
+ [&nbsp;<a href="sip-0000X-1.xhtml#ernst99b">bib</a>&nbsp;]
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td align="right">
+ [<a name="1111062">4</a>]
+ </td>
+ <td>
+ Erik Ernst, Klaus Ostermann, and William&nbsp;R. Cook.
+ A virtual class calculus.
+ In <em>POPL '06: Conference record of the 33rd ACM SIGPLAN-SIGACT
+ symposium on Principles of programming languages</em>, pages 270-282, New York,
+ NY, USA, 2006. ACM Press.
+ [&nbsp;<a href="sip-0000X-1.xhtml#1111062">bib</a>&nbsp;]
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td align="right">
+ [<a name="Erns01a">5</a>]
+ </td>
+ <td>
+ Erik Ernst.
+ Family polymorphism.
+ In J.&nbsp;L. Knudsen, editor, <em>ECOOP 2001</em>, number 2072 in LNCS,
+ pages 303-326. Springer Verlag, 2001.
+ [&nbsp;<a href="sip-0000X-1.xhtml#Erns01a">bib</a>&nbsp;]
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td align="right">
+ [<a name="EE99">6</a>]
+ </td>
+ <td>
+ Erik Ernst.
+ Propagating class and method combination.
+ In Rachid Guerraoui, editor, <em>Proceedings ECOOP'99</em>, LNCS 1628,
+ pages 67-91, Lisboa, Portugal, June 1999. Springer-Verlag.
+ [&nbsp;<a href="sip-0000X-1.xhtml#EE99">bib</a>&nbsp;]
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td align="right">
+ [<a name="aracic06:_overv_of_caesarj">7</a>]
+ </td>
+ <td>
+ Ivica Aracic, Vaidas Gasiunas, Mira Mezini, and Klaus Ostermann.
+ An overview of caesarj.
+ In <em>Transactions on Aspect-Oriented Software Development I</em>,
+ volume 3880/2006 of <em>Lecture Notes in Computer Science</em>, pages 135-173.
+ Springer Berlin / Heidelberg, 2006.
+ [&nbsp;<a href="sip-0000X-1.xhtml#aracic06:_overv_of_caesarj">bib</a>&nbsp;]
+ </td>
+ </tr>
+ </table>
+
+</body>
+</html>
diff --git a/build.number b/build.number
index b96c8a8f69..88a6ad113e 100644
--- a/build.number
+++ b/build.number
@@ -1,5 +1,5 @@
#Tue Sep 11 19:21:09 CEST 2007
-version.minor=7
-version.patch=2
-version.suffix=RC4
+version.minor=8
+version.patch=0
+version.suffix=alpha
version.major=2
diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1
index a2f0fac1e6..b3a59785b2 100644
--- a/lib/scala-compiler.jar.desired.sha1
+++ b/lib/scala-compiler.jar.desired.sha1
@@ -1 +1 @@
-467e21e8f22b32953dbe41a9a091f9524816b61b ?scala-compiler.jar
+7cd5469aa4e85530aa99234d983952589a030e8e ?scala-compiler.jar
diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1
index b2103d3ed8..53f7fee70a 100644
--- a/lib/scala-library-src.jar.desired.sha1
+++ b/lib/scala-library-src.jar.desired.sha1
@@ -1 +1 @@
-feb5f36c8fc1eefd7c01a17cf7c1d7497e4adc4e ?scala-library-src.jar
+6f717f2a07d59605f1937cae43bfb0c4e7376937 ?scala-library-src.jar
diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1
index 83fb1fd94d..7adc0e712b 100644
--- a/lib/scala-library.jar.desired.sha1
+++ b/lib/scala-library.jar.desired.sha1
@@ -1 +1 @@
-79ec54337732231ba14fb716ee3feea79ec34a8e ?scala-library.jar
+4ad240bdf0649fb2b07b3d18a555134651329910 ?scala-library.jar
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index add169ad53..7a6452709e 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -155,6 +155,7 @@ class Settings(error: String => Unit) {
val XnoVarargsConversion = BooleanSetting("-Xno-varargs-conversion", "disable varags conversion")
val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations")
+ val suppressVTWarn = BooleanSetting ("-Ysuppress-vt-typer-warnings", "Suppress warnings from the typer when testing the virtual class encoding, NOT FOR FINAL!")
/** A list of all settings */
def allSettings: List[Setting] = allsettings.reverse
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 94f6039737..b0b55c5528 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2007 LAMP/EPFL
+ * Copyright 2005-2008 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -150,7 +150,7 @@ trait Parsers extends NewScanners with MarkupParsers {
t
}
-/////////// PLACEHOLDERS ///////////////////////////////////////////////////////
+/* -------- PLACEHOLDERS ------------------------------------------- */
/** The implicit parameters introduced by `_' in the current expression.
* Parameters appear in reverse order
@@ -200,7 +200,7 @@ trait Parsers extends NewScanners with MarkupParsers {
t
}
-/////// ERROR HANDLING //////////////////////////////////////////////////////
+/* -------- ERROR HANDLING ------------------------------------------- */
protected def skip() {
var nparens = 0
@@ -326,7 +326,7 @@ trait Parsers extends NewScanners with MarkupParsers {
def errorTermTree = Literal(Constant(null)).setPos((inCurrentPos))
def errorPatternTree = Ident(nme.WILDCARD).setPos((inCurrentPos))
-/////// TOKEN CLASSES //////////////////////////////////////////////////////
+/* -------- TOKEN CLASSES ------------------------------------------- */
def isModifier: Boolean = inToken match {
case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE | IMPLICIT | LAZY => true
@@ -374,7 +374,7 @@ trait Parsers extends NewScanners with MarkupParsers {
def isStatSep: Boolean = isStatSep(inToken)
-/////// COMMENT AND ATTRIBUTE COLLECTION //////////////////////////////////////
+/* -------- COMMENT AND ATTRIBUTE COLLECTION ------------------------------------------- */
/** Join the comment associated with a definition
*/
@@ -384,7 +384,7 @@ trait Parsers extends NewScanners with MarkupParsers {
else trees
}
-/////// TREE CONSTRUCTION ////////////////////////////////////////////////////
+/* -------- TREE CONSTRUCTION ------------------------------------------- */
/** Convert tree to formal parameter list
*/
@@ -448,7 +448,7 @@ trait Parsers extends NewScanners with MarkupParsers {
Function(List(makeSyntheticParam(pname)), insertParam(tree))
}
-/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////
+/* -------- OPERAND/OPERATOR STACK ------------------------------------------- */
var opstack: List[OpInfo] = Nil
@@ -499,7 +499,7 @@ trait Parsers extends NewScanners with MarkupParsers {
top
}
-/////// IDENTIFIERS AND LITERALS ////////////////////////////////////////////////////////////
+/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */
def ident(): Name =
@@ -659,7 +659,7 @@ trait Parsers extends NewScanners with MarkupParsers {
if (inToken == NEWLINE && p(inNextTokenCode)) newLineOpt()
}
-//////// TYPES ///////////////////////////////////////////////////////////////
+/* -------- TYPES ------------------------------------------- */
/** TypedOpt ::= [`:' Type]
*/
@@ -900,7 +900,7 @@ trait Parsers extends NewScanners with MarkupParsers {
typ()
}
-//////// EXPRESSIONS ////////////////////////////////////////////////////////
+/* -------- EXPRESSIONS ------------------------------------------- */
/** EqualsExpr ::= `=' Expr
*/
@@ -1317,7 +1317,7 @@ trait Parsers extends NewScanners with MarkupParsers {
}
//def p2i(pos : ScanPosition) : Int;
-//////// PATTERNS ////////////////////////////////////////////////////////////
+/* -------- PATTERNS ------------------------------------------- */
/** Patterns ::= Pattern { `,' Pattern }
* SeqPatterns ::= SeqPattern { `,' SeqPattern }
@@ -1493,7 +1493,7 @@ trait Parsers extends NewScanners with MarkupParsers {
ps
}
-////////// MODIFIERS and ANNOTATIONS /////////////////////////////////////////////////
+/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */
private def normalize(mods: Modifiers): Modifiers =
if ((mods hasFlag Flags.PRIVATE) && mods.privateWithin != nme.EMPTY.toTypeName)
@@ -1629,7 +1629,7 @@ trait Parsers extends NewScanners with MarkupParsers {
Annotation(constr, nameValuePairs) setPos pos
}
-//////// PARAMETERS //////////////////////////////////////////////////////////
+/* -------- PARAMETERS ------------------------------------------- */
/** ParamClauses ::= {ParamClause} [[nl] `(' implicit Params `)']
* ParamClause ::= [nl] `(' [Params] ')'
@@ -1807,7 +1807,7 @@ trait Parsers extends NewScanners with MarkupParsers {
if (inToken == tok) { inNextToken; typ() }
else scalaDot(default.toTypeName)
-//////// DEFS ////////////////////////////////////////////////////////////////
+/* -------- DEFS ------------------------------------------- */
/** Import ::= import ImportExpr {`,' ImportExpr}
@@ -2141,7 +2141,7 @@ trait Parsers extends NewScanners with MarkupParsers {
/** TmplDef ::= [case] class ClassDef
* | [case] object ObjectDef
- * | trait TraitDef
+ * | [override] trait TraitDef
*/
def tmplDef(mods: Modifiers): Tree = {
if (mods.hasFlag(Flags.LAZY)) syntaxError("classes cannot be lazy", false)
@@ -2185,7 +2185,8 @@ trait Parsers extends NewScanners with MarkupParsers {
if (mods.hasFlag(Flags.TRAIT)) (Modifiers(Flags.TRAIT), List())
else (accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE)))
val thistpe = requiresTypeOpt()
- var mods1 = if (inToken == SUBTYPE) mods | Flags.DEFERRED else mods
+ var mods1 = if (mods.hasFlag( Flags.TRAIT )) if (inToken == SUBTYPE) mods | Flags.DEFERRED else mods
+ else if (inToken == SUBTYPE) { syntaxError("classes are not allowed to be virtual", false); mods } else mods
var template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss)
if (!thistpe.isEmpty) {
if (template.self.isEmpty) {
@@ -2267,9 +2268,9 @@ trait Parsers extends NewScanners with MarkupParsers {
def isInterface(mods: Modifiers, body: List[Tree]) =
(mods.hasFlag(Flags.TRAIT) && (body forall treeInfo.isInterfaceMember))
- /** ClassTemplateOpt ::= Extends ClassTemplate | [[Extends] TemplateBody]
- * TraitTemplateOpt ::= Extends TraitTemplate | [[Extends] TemplateBody]
- * Extends ::= extends | `<:'
+ /** ClassTemplateOpt ::= 'extends' ClassTemplate | [['extends'] TemplateBody]
+ * TraitTemplateOpt ::= TraitExtends TraitTemplate | [['extends'] TemplateBody] | '<:' TemplateBody
+ * TraitExtends ::= 'extends' | `<:'
*/
def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): Template = {
val pos = inCurrentPos;
@@ -2277,7 +2278,10 @@ trait Parsers extends NewScanners with MarkupParsers {
if (inToken == EXTENDS || settings.Xexperimental.value && (mods hasFlag Flags.TRAIT) && inToken == SUBTYPE) {
inNextToken
template(mods hasFlag Flags.TRAIT)
- } else {
+ } else if ((inToken == SUBTYPE) && (mods hasFlag Flags.TRAIT)) {
+ inNextToken
+ template(true)
+ } else {
newLineOptWhenFollowedBy(LBRACE)
val (self, body) = templateBodyOpt(false)
(List(), List(List()), self, body)
@@ -2296,7 +2300,7 @@ trait Parsers extends NewScanners with MarkupParsers {
// if (pos == inCurrentPos || inIDE) tree else atPos(pos) {tree}
}
-////////// TEMPLATES ////////////////////////////////////////////////////////////
+/* -------- TEMPLATES ------------------------------------------- */
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
* @param isPre specifies whether in early initializer (true) or not (false)
@@ -2328,7 +2332,7 @@ trait Parsers extends NewScanners with MarkupParsers {
body
}
-/////// STATSEQS //////////////////////////////////////////////////////////////
+/* -------- STATSEQS ------------------------------------------- */
/** Packaging ::= package QualId [nl] `{' TopStatSeq `}'
*/
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 3da23547af..9e2edfab64 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -44,7 +44,7 @@ trait Definitions {
var NullClass: Symbol = _
var NothingClass: Symbol = _
var SingletonClass: Symbol = _
- lazy val uncheckedStableClass = getClass("scala.uncheckedStable") // todo: move to annotation.unchecked
+ lazy val uncheckedStableClass = getClass("scala.annotation.unchecked.uncheckedStable")
lazy val uncheckedVarianceClass = getClass("scala.annotation.unchecked.uncheckedVariance")
lazy val ClassClass: Symbol = getClass(sn.Class)
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 4d4bb4c70f..c387feefea 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2007 LAMP/EPFL
+ * Copyright 2005-2008 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -9,22 +9,23 @@ package scala.tools.nsc.symtab
object Flags extends Enumeration {
// modifiers
- final val IMPLICIT = 0x00000001
- final val FINAL = 0x00000002
+ final val IMPLICIT = 0x00000200
+ final val FINAL = 0x00000020
final val PRIVATE = 0x00000004
- final val PROTECTED = 0x00000008
+ final val PROTECTED = 0x00000001
- final val SEALED = 0x00000010
- final val OVERRIDE = 0x00000020
- final val CASE = 0x00000040
- final val ABSTRACT = 0x00000080 // abstract class, or used in conjunction
+ final val SEALED = 0x00000400
+ final val OVERRIDE = 0x00000002
+ final val CASE = 0x00000800
+ final val ABSTRACT = 0x00000008 // abstract class, or used in conjunction
// with abstract override.
// Note difference to DEFERRED!
- final val DEFERRED = 0x00000100 // was `abstract' for members
- final val METHOD = 0x00000200 // a method
- final val MODULE = 0x00000400 // symbol is module or class implementing a module
- final val INTERFACE = 0x00000800 // symbol is an interface (i.e. a trait which defines only abstract methods)
+ final val DEFERRED = 0x00000010 // was `abstract' for members | trait is virtual
+ final val METHOD = 0x00000040 // a method
+ final val MODULE = 0x00000100 // symbol is module or class implementing a module
+ final val INTERFACE = 0x00000080 // symbol is an interface (i.e. a trait which defines only abstract methods)
+
final val MUTABLE = 0x00001000 // symbol is a mutable variable.
final val PARAM = 0x00002000 // symbol is a (value or type) parameter to a method
@@ -80,11 +81,11 @@ object Flags extends Enumeration {
final val LOCKED = 0x8000000000L // temporary flag to catch cyclic dependencies
- final val InitialFlags = 0x000000FFFFFFFFFFL // flags that are enabled from phase 1.
- final val LateFlags = 0x000FFF0000000000L // flags that override flags in 0xFFF.
- final val AntiFlags = 0x7FF0000000000000L // flags that cancel flags in 0x7FF
- final val LateShift = 40L
- final val AntiShift = 52L
+ final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1.
+ final val LateFlags = 0x00FE000000000000L // flags that override flags in 0x1FC.
+ final val AntiFlags = 0x7F00000000000000L // flags that cancel flags in 0x07F
+ final val LateShift = 47L
+ final val AntiShift = 56L
// late flags (set by a transformer phase)
final val latePRIVATE = (PRIVATE: Long) << LateShift
@@ -104,6 +105,118 @@ object Flags extends Enumeration {
final val notMETHOD = (METHOD: Long) << AntiShift
+ // The flags from 0x001 to 0x800 are different in the raw flags
+ // and in the pickled format.
+
+ private final val IMPLICIT_PKL = 0x00000001
+ private final val FINAL_PKL = 0x00000002
+ private final val PRIVATE_PKL = 0x00000004
+ private final val PROTECTED_PKL = 0x00000008
+
+ private final val SEALED_PKL = 0x00000010
+ private final val OVERRIDE_PKL = 0x00000020
+ private final val CASE_PKL = 0x00000040
+ private final val ABSTRACT_PKL = 0x00000080
+
+ private final val DEFERRED_PKL = 0x00000100
+ private final val METHOD_PKL = 0x00000200
+ private final val MODULE_PKL = 0x00000400
+ private final val INTERFACE_PKL = 0x00000800
+
+ private final val PKL_MASK = 0x00000FFF
+
+
+ private val r2p = {
+ def rawFlagsToPickledAux(flags:Int) = {
+ var pflags=0
+ if ((flags & IMPLICIT )!=0) pflags|=IMPLICIT_PKL
+ if ((flags & FINAL )!=0) pflags|=FINAL_PKL
+ if ((flags & PRIVATE )!=0) pflags|=PRIVATE_PKL
+ if ((flags & PROTECTED)!=0) pflags|=PROTECTED_PKL
+ if ((flags & SEALED )!=0) pflags|=SEALED_PKL
+ if ((flags & OVERRIDE )!=0) pflags|=OVERRIDE_PKL
+ if ((flags & CASE )!=0) pflags|=CASE_PKL
+ if ((flags & ABSTRACT )!=0) pflags|=ABSTRACT_PKL
+ if ((flags & DEFERRED )!=0) pflags|=DEFERRED_PKL
+ if ((flags & METHOD )!=0) pflags|=METHOD_PKL
+ if ((flags & MODULE )!=0) pflags|=MODULE_PKL
+ if ((flags & INTERFACE)!=0) pflags|=INTERFACE_PKL
+ pflags
+ }
+ val v=new Array[Int](PKL_MASK+1)
+ var i=0
+ while (i<=PKL_MASK) {
+ v(i)=rawFlagsToPickledAux(i)
+ i+=1
+ }
+ v
+ }
+
+ private val p2r = {
+ def pickledToRawFlagsAux(pflags:Int) = {
+ var flags=0
+ if ((pflags & IMPLICIT_PKL )!=0) flags|=IMPLICIT
+ if ((pflags & FINAL_PKL )!=0) flags|=FINAL
+ if ((pflags & PRIVATE_PKL )!=0) flags|=PRIVATE
+ if ((pflags & PROTECTED_PKL)!=0) flags|=PROTECTED
+ if ((pflags & SEALED_PKL )!=0) flags|=SEALED
+ if ((pflags & OVERRIDE_PKL )!=0) flags|=OVERRIDE
+ if ((pflags & CASE_PKL )!=0) flags|=CASE
+ if ((pflags & ABSTRACT_PKL )!=0) flags|=ABSTRACT
+ if ((pflags & DEFERRED_PKL )!=0) flags|=DEFERRED
+ if ((pflags & METHOD_PKL )!=0) flags|=METHOD
+ if ((pflags & MODULE_PKL )!=0) flags|=MODULE
+ if ((pflags & INTERFACE_PKL)!=0) flags|=INTERFACE
+ flags
+ }
+ val v=new Array[Int](PKL_MASK+1)
+ var i=0
+ while (i<=PKL_MASK) {
+ v(i)=pickledToRawFlagsAux(i)
+ i+=1
+ }
+ v
+ }
+
+ def rawFlagsToPickled(flags:Long):Long =
+ (flags & ~PKL_MASK) | r2p(flags.toInt & PKL_MASK)
+
+ def pickledToRawFlags(pflags:Long):Long =
+ (pflags & ~PKL_MASK) | p2r(pflags.toInt & PKL_MASK)
+
+ // List of the raw flags, in pickled order
+ private val pickledListOrder = {
+ def findBit(m:Long):Int = {
+ var mask=m
+ var i=0
+ while (i <= 62) {
+ if ((mask&1) == 1) return i
+ mask >>= 1
+ i += 1
+ }
+ throw new FatalError("Internal error: mask is zero")
+ }
+ val v=new Array[Long](63)
+ v(findBit(IMPLICIT_PKL ))=IMPLICIT
+ v(findBit(FINAL_PKL ))=FINAL
+ v(findBit(PRIVATE_PKL ))=PRIVATE
+ v(findBit(PROTECTED_PKL))=PROTECTED
+ v(findBit(SEALED_PKL ))=SEALED
+ v(findBit(OVERRIDE_PKL ))=OVERRIDE
+ v(findBit(CASE_PKL ))=CASE
+ v(findBit(ABSTRACT_PKL ))=ABSTRACT
+ v(findBit(DEFERRED_PKL ))=DEFERRED
+ v(findBit(METHOD_PKL ))=METHOD
+ v(findBit(MODULE_PKL ))=MODULE
+ v(findBit(INTERFACE_PKL))=INTERFACE
+ var i=findBit(PKL_MASK+1)
+ while (i <= 62) {
+ v(i)=1L << i
+ i += 1
+ }
+ v.toList
+ }
+
// masks
/** This flags can be set when class or module symbol is first created. */
final val TopLevelCreationFlags: Long =
@@ -134,7 +247,7 @@ object Flags extends Enumeration {
ss.filter("" !=).mkString("", " ", "")
def flagsToString(flags: Long): String =
- listToString(for (i <- List.range(0, 63)) yield flagToString(flags & (1L << i)))
+ listToString(for (mask <- pickledListOrder) yield flagToString(flags & mask))
def flagsToString(flags: Long, privateWithin: String): String = {
var f = flags
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 81a4258b06..85e19a2b6b 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -976,6 +976,7 @@ trait Types {
underlyingCache
}
+ override def isVolatile : Boolean = underlying.isVolatile && (!sym.isStable)
/*
override def narrow: Type = {
if (phase.erasedTypes) this
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index c318c08ffb..1d1dc2e857 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2007 LAMP/EPFL
+ * Copyright 2005-2008 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -470,7 +470,7 @@ abstract class Pickler extends SubComponent {
var posOffset = 0
writeRef(sym.name)
writeRef(normalizedOwner(sym))
- writeNat((sym.flags & PickledFlags).asInstanceOf[Int])
+ writeNat((rawFlagsToPickled(sym.flags & PickledFlags)).asInstanceOf[Int])
if (sym.privateWithin != NoSymbol) writeRef(sym.privateWithin)
writeRef(sym.info)
posOffset
@@ -917,8 +917,9 @@ abstract class Pickler extends SubComponent {
case Modifiers(flags, privateWithin, annotations) =>
- writeNat((flags >> 32).toInt)
- writeNat((flags & 0xFFFFFFFF).toInt)
+ val pflags = rawFlagsToPickled(flags)
+ writeNat((pflags >> 32).toInt)
+ writeNat((pflags & 0xFFFFFFFF).toInt)
writeRef(privateWithin)
writeRefs(annotations)
MODIFIERS
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 625dd820ed..76aa52b306 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -182,7 +182,7 @@ abstract class UnPickler {
}
val name = readNameRef()
val owner = readSymbolRef()
- val flags = readNat()
+ val flags = pickledToRawFlags(readNat())
var privateWithin: Symbol = NoSymbol
var inforef = readNat()
if (isSymbolRef(inforef)) {
@@ -701,9 +701,10 @@ abstract class UnPickler {
if (tag != MODIFIERS)
errorBadSignature("expected a modifiers tag (" + tag + ")")
val end = readNat() + readIndex
- val flagsHi = readNat()
- val flagsLo = readNat()
- val flags = (flagsHi.toLong << 32) + flagsLo
+ val pflagsHi = readNat()
+ val pflagsLo = readNat()
+ val pflags = (pflagsHi.toLong << 32) + pflagsLo
+ val flags = pickledToRawFlags(pflags)
val privateWithin = readNameRef()
val annotations = until(end, readAnnotationTreeRef)
Modifiers(flags, privateWithin, annotations)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 54ddcdb25d..d3f6689b6e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2007 LAMP/EPFL
+ * Copyright 2005-2008 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -935,6 +935,7 @@ trait Namers { self: Analyzer =>
Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2) +
" for: " + sym + Flags.flagsToString(sym.rawflags));
}
+
if (sym.hasFlag(IMPLICIT) && !sym.isTerm)
context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods")
if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass && !inIDE)
@@ -942,7 +943,7 @@ trait Namers { self: Analyzer =>
if (sym.hasFlag(ABSTRACT) && !sym.isClass)
context.error(sym.pos, "`abstract' modifier can be used only for classes; " +
"\nit should be omitted for abstract members")
- if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isClass)
+ if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && !sym.hasFlag(TRAIT) && sym.isClass)
context.error(sym.pos, "`override' modifier not allowed for classes")
if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isConstructor)
context.error(sym.pos, "`override' modifier not allowed for constructors")
@@ -964,11 +965,12 @@ trait Namers { self: Analyzer =>
sym.resetFlag(DEFERRED)
}
}
+
checkNoConflict(DEFERRED, PRIVATE)
checkNoConflict(FINAL, SEALED)
checkNoConflict(PRIVATE, PROTECTED)
checkNoConflict(PRIVATE, OVERRIDE)
- //checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant
+ /* checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant */
checkNoConflict(DEFERRED, FINAL)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index e18b3f6130..d1f0edc7c1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -134,7 +134,7 @@ abstract class RefChecks extends InfoTransform {
def overrideError(msg: String) {
if (other.tpe != ErrorType && member.tpe != ErrorType)
- unit.error(pos, "error overriding " + infoStringWithLocation(other) +
+ unit.error(pos, "overriding " + infoStringWithLocation(other) +
";\n " + infoString(member) + " " + msg +
(if ((other.owner isSubClass member.owner) &&
other.isDeferred && !member.isDeferred)
@@ -146,7 +146,7 @@ abstract class RefChecks extends InfoTransform {
def overrideTypeError() {
if (other.tpe != ErrorType && member.tpe != ErrorType) {
- overrideError("has incompatible type "+analyzer.underlying(member).tpe.normalize)
+ overrideError("has incompatible type")
}
}
@@ -455,8 +455,9 @@ abstract class RefChecks extends InfoTransform {
case ExistentialType(tparams, result) =>
validateVariances(tparams map (_.info), variance)
validateVariance(result, variance)
- case AnnotatedType(attribs, tp, selfsym) =>
- validateVariance(tp, variance)
+ case AnnotatedType(annots, tp, selfsym) =>
+ if (!(annots exists (_.atp.typeSymbol.isNonBottomSubClass(uncheckedVarianceClass))))
+ validateVariance(tp, variance)
}
def validateVariances(tps: List[Type], variance: Int) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3ca63f55d9..209760a66e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1033,7 +1033,8 @@ trait Typers { self: Analyzer =>
}
if (!(selfType <:< parent.tpe.typeOfThis) &&
!phase.erasedTypes &&
- !(context.owner hasFlag SYNTHETIC)) // don't do this check for synthetic concrete classes for virtuals (part of DEVIRTUALIZE)
+ !(context.owner hasFlag SYNTHETIC) && // don't do this check for synthetic concrete classes for virtuals (part of DEVIRTUALIZE)
+ !(settings.suppressVTWarn.value))
{
//Console.println(context.owner);//DEBUG
//Console.println(context.owner.unsafeTypeParams);//DEBUG
@@ -3344,7 +3345,7 @@ trait Typers { self: Analyzer =>
tree.tpe = null
if (tree.hasSymbol) tree.symbol = NoSymbol
}
- if (printTypings) println("typing "+tree+", "+context.undetparams+(mode & TYPEPATmode));//DEBUG
+ if (printTypings) println("typing "+tree+", "+context.undetparams+(mode & TYPEPATmode)); //DEBUG
def dropExistential(tp: Type): Type = tp match {
case ExistentialType(tparams, tpe) =>
if (settings.debug.value) println("drop ex "+tree+" "+tp)
@@ -3356,12 +3357,12 @@ trait Typers { self: Analyzer =>
case _ => tp
}
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
- if (printTypings) println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt);//DEBUG
+ if (printTypings) println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt); //DEBUG
tree1.tpe = addAnnotations(tree1, tree1.tpe)
val result = if (tree1.isEmpty || (inIDE && tree1.tpe == null)) tree1 else adapt(tree1, mode, pt)
- if (printTypings) println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
+ if (printTypings) println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams); //DEBUG
// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
result
} catch {
diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
index 3000e6d61a..7cbc21b814 100644
--- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala
+++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2007 LAMP/EPFL
+ * Copyright 2005-2008 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -84,9 +84,9 @@ object ShowPickled extends Names {
def printSymInfo() {
printNameRef()
printSymbolRef()
- val flags = buf.readNat()
- out.print(" " + toHexString(flags) +
- "[" + Flags.flagsToString(flags) + "] ")
+ val pflags = buf.readNat()
+ out.print(" " + toHexString(pflags) +
+ "[" + Flags.flagsToString(Flags.pickledToRawFlags(pflags)) + "] ")
printTypeRef()
}
diff --git a/src/library/scala/annotation/unchecked/uncheckedStable.scala b/src/library/scala/annotation/unchecked/uncheckedStable.scala
new file mode 100755
index 0000000000..d6fcdf2127
--- /dev/null
+++ b/src/library/scala/annotation/unchecked/uncheckedStable.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.unchecked
+
+/** An annotation for values that are assumed to be stable even though their
+ * types are volatile.
+ */
+final class uncheckedStable extends StaticAnnotation {}
diff --git a/src/library/scala/annotation/unchecked/uncheckedVariance.scala b/src/library/scala/annotation/unchecked/uncheckedVariance.scala
index 862db90809..1cb9a82d6b 100644
--- a/src/library/scala/annotation/unchecked/uncheckedVariance.scala
+++ b/src/library/scala/annotation/unchecked/uncheckedVariance.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index eb3f8a07ce..74bef697bc 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala
index 2e2e51ecb9..211d785a61 100644
--- a/src/library/scala/collection/mutable/ResizableArray.scala
+++ b/src/library/scala/collection/mutable/ResizableArray.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -74,7 +74,7 @@ trait ResizableArray[A] extends RandomAccessSeq[A] {
/** ensure that the internal array has at n cells */
protected def ensureSize(n: Int) {
if (n > array.length) {
- var newsize = array.length * 2
+ var newsize = if (array.length == 0) 2 else array.length * 2
while (n > newsize)
newsize = newsize * 2
val newar: Array[AnyRef] = new Array(newsize)
diff --git a/src/library/scalax/Fractional.scala b/src/library/scalax/Fractional.scala
new file mode 100755
index 0000000000..b29a903519
--- /dev/null
+++ b/src/library/scalax/Fractional.scala
@@ -0,0 +1,5 @@
+package scalax
+
+trait Fractional[T] extends Numeric[T] {
+ def div(x: T, y: T): T
+}
diff --git a/src/library/scalax/Integral.scala b/src/library/scalax/Integral.scala
new file mode 100755
index 0000000000..2e80b1bb7b
--- /dev/null
+++ b/src/library/scalax/Integral.scala
@@ -0,0 +1,6 @@
+package scalax
+
+trait Integral[T] extends Numeric[T] {
+ def quot(x: T, y: T): T
+ def rem(x: T, y: T): T
+}
diff --git a/src/library/scalax/Numeric.scala b/src/library/scalax/Numeric.scala
new file mode 100755
index 0000000000..6e61851dc5
--- /dev/null
+++ b/src/library/scalax/Numeric.scala
@@ -0,0 +1,79 @@
+package scalax
+
+object Numeric {
+ implicit object IntIsIntegral extends Integral[Int] {
+ def plus(x: Int, y: Int): Int = x + y
+ def minus(x: Int, y: Int): Int = x - y
+ def times(x: Int, y: Int): Int = x * y
+ def quot(x: Int, y: Int): Int = x / y
+ def rem(x: Int, y: Int): Int = x % y
+ def negate(x: Int): Int = -x
+ def abs(x: Int): Int = if (x < 0) -x else x
+ def signum(x: Int): Int = if (x < 0) -1 else if (x > 0) 1 else 0
+ def fromInt(x: Int): Int = x
+ def toInt(x: Int): Int = x
+ def toLong(x: Int): Long = x
+ def toFloat(x: Int): Float = x
+ def toDouble(x: Int): Double = x
+ }
+ implicit object LongIsIntegral extends Integral[Long] {
+ def plus(x: Long, y: Long): Long = x + y
+ def minus(x: Long, y: Long): Long = x - y
+ def times(x: Long, y: Long): Long = x * y
+ def quot(x: Long, y: Long): Long = x / y
+ def rem(x: Long, y: Long): Long = x % y
+ def negate(x: Long): Long = -x
+ def abs(x: Long): Long = if (x < 0) -x else x
+ def signum(x: Long): Long = if (x < 0) -1 else if (x > 0) 1 else 0
+ def fromInt(x: Int): Long = x
+ def toInt(x: Long): Int = x.toInt
+ def toLong(x: Long): Long = x
+ def toFloat(x: Long): Float = x
+ def toDouble(x: Long): Double = x
+ }
+ implicit object FloatIsFractional extends Fractional[Float] {
+ def plus(x: Float, y: Float): Float = x + y
+ def minus(x: Float, y: Float): Float = x - y
+ def times(x: Float, y: Float): Float = x * y
+ def div(x: Float, y: Float): Float = x / y
+ def negate(x: Float): Float = -x
+ def abs(x: Float): Float = if (x < 0) -x else x
+ def signum(x: Float): Float = if (x < 0) -1 else if (x > 0) 1 else 0
+ def fromInt(x: Int): Float = x
+ def toInt(x: Float): Int = x.toInt
+ def toLong(x: Float): Long = x.toLong
+ def toFloat(x: Float): Float = x
+ def toDouble(x: Float): Double = x
+ }
+ implicit object DoubleIsFractional extends Fractional[Double] {
+ def plus(x: Double, y: Double): Double = x + y
+ def minus(x: Double, y: Double): Double = x - y
+ def times(x: Double, y: Double): Double = x * y
+ def div(x: Double, y: Double): Double = x / y
+ def negate(x: Double): Double = -x
+ def abs(x: Double): Double = if (x < 0) -x else x
+ def signum(x: Double): Double = if (x < 0) -1 else if (x > 0) 1 else 0
+ def fromInt(x: Int): Double = x
+ def toInt(x: Double): Int = x.toInt
+ def toLong(x: Double): Long = x.toLong
+ def toFloat(x: Double): Float = x.toFloat
+ def toDouble(x: Double): Double = x
+ }
+}
+
+
+trait Numeric[T] {
+ def plus(x: T, y: T): T
+ def minus(x: T, y: T): T
+ def times(x: T, y: T): T
+ def negate(x: T): T
+ def abs(x: T): T
+ def signum(x: T): T
+ def fromInt(x: Int): T
+ def toInt(x: T): Int
+ def toLong(x: T): Long
+ def toFloat(x: T): Float
+ def toDouble(x: T): Double
+ def zero = fromInt(0)
+ def one = fromInt(1)
+}
diff --git a/src/library/scalax/collection/BufferedIterator.scala b/src/library/scalax/collection/BufferedIterator.scala
new file mode 100755
index 0000000000..07509c2758
--- /dev/null
+++ b/src/library/scalax/collection/BufferedIterator.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: BufferedIterator.scala 12641 2007-08-22 16:01:57Z mcdirmid $
+
+
+package scalax.collection
+
+/** Buffered iterators are iterators which allow to inspect the next
+ * element without discarding it.
+ *
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait BufferedIterator[+A] extends Iterator[A] {
+
+ /** Returns current element of iterator without advancing beyond it.
+ */
+ def head: A
+
+ override def buffered: this.type = this
+}
diff --git a/src/library/scalax/collection/Builder.scala b/src/library/scalax/collection/Builder.scala
new file mode 100755
index 0000000000..eedd89537a
--- /dev/null
+++ b/src/library/scalax/collection/Builder.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $
+
+package scalax.collection
+
+
+trait Builder[+CC[B], A] extends mutable.Appendable[A] {
+ def +=(x: A)
+ def elements: Iterator[A]
+ def result: CC[A]
+ override def ++=(xs: Iterator[A]) { for (x <- xs) this += x }
+ override def ++=(xs: Iterable[A]) { for (x <- xs) this += x }
+}
+
diff --git a/src/library/scalax/collection/Iterable.scala b/src/library/scalax/collection/Iterable.scala
new file mode 100755
index 0000000000..b6abd8d559
--- /dev/null
+++ b/src/library/scalax/collection/Iterable.scala
@@ -0,0 +1,143 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection
+
+import generic._
+
+/** Collection classes mixing in this class provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>.
+ *
+ * @author Matthias Zenger
+ * @autor Martin Odersky
+ * @owner Martin Odersky
+ * @version 2.8
+ */
+trait Iterable[+A] extends covariant.IterableTemplate[Iterable, A] { self =>
+
+ /** Creates a view of this iterable @see Iterable.View
+ def view: View[Iterable, A] = new View[Iterable, A] { // !!! Martin: We should maybe infer the type parameters here?
+ val origin: self.type = self
+ val elements: Iterator[A] = self.elements
+ }
+ */
+}
+
+/** Various utilities for instances of <a href="Iterable.html">Iterable</a>.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+object Iterable extends covariant.IterableFactory[Iterable] {
+
+ /** The empty iterable */
+ val empty: Iterable[Nothing] = null // !!!
+
+ class OrderedIterableOps[A](seq: Iterable[A], cmp: Ordering[A]) {
+ def min: A = {
+ require(!seq.isEmpty, "min(<empty>)")
+ var acc = seq.elements.next
+ for (x <- seq)
+ if (cmp.lt(x, acc)) acc = x
+ acc
+ }
+ def max: A = {
+ require(!seq.isEmpty, "max(<empty>)")
+ var acc = seq.elements.next
+ for (x <- seq)
+ if (cmp.gt(x, acc)) acc = x
+ acc
+ }
+ }
+
+ class NumericIterableOps[A](seq: Iterable[A], num: Numeric[A]) {
+ def sum: A = {
+ var acc = num.zero
+ for (x <- seq) acc = num.plus(acc, x)
+ acc
+ }
+ def product: A = {
+ var acc = num.one
+ for (x <- seq) acc = num.times(acc, x)
+ acc
+ }
+ }
+
+ class IterableIterableOps[C[+B] <: Iterable[B], A](self: C[Iterable[A]]) {
+ def flatten: C[A] = {
+ val b = self.newBuilder[A].asInstanceOf[Builder[C, A]]
+ for (xs <- self)
+ b ++= xs
+ b.result
+ }
+ }
+
+ class PairCollectionOps[C[+B] <: Iterable[B], A1, A2](self: C[(A1, A2)]) {
+ def unzip: (C[A1], C[A2]) = {
+ val as = self.newBuilder[A1].asInstanceOf[Builder[C, A1]]
+ val bs = self.newBuilder[A2].asInstanceOf[Builder[C, A2]]
+ for ((a, b) <- self) {
+ as += a
+ bs += b
+ }
+ (as.result, bs.result)
+ }
+ }
+
+ implicit def orderedIterableWrapper[A](seq: Iterable[A])(implicit cmp: Ordering[A]) =
+ new OrderedIterableOps(seq, cmp)
+ implicit def numericIterableWrapper[A](seq: Iterable[A])(implicit num: Numeric[A]) =
+ new NumericIterableOps(seq, num)
+ implicit def iterableIterableWrapper[C[+B] <: Iterable[B], A](seq: C[Iterable[A]]) =
+ new IterableIterableOps[C, A](seq)
+ implicit def pairCollectionWrapper[C[+B] <: Iterable[B], A1, A2](seq: C[(A1, A2)]) =
+ new PairCollectionOps[C, A1, A2](seq)
+
+ type View[+UC[+B] <: Sequence[B], +A] = covariant.IterableView[UC, A]
+
+ /** @deprecated use View instead
+ */
+ @deprecated type Projection[+A] = View[C, A] forSome { type C[B] <: Iterable[B] }
+
+ /** The minimum element of a non-empty sequence of ordered elements
+ * @deprecated use seq.min instead
+ */
+ @deprecated def min[A <% Ordered[A]](seq: Iterable[A]): A = {
+ val xs = seq.elements
+ if (!xs.hasNext) throw new IllegalArgumentException("min(<empty>)")
+ var min = xs.next
+ while (xs.hasNext) {
+ val x = xs.next
+ if (x < min) min = x
+ }
+ min
+ }
+
+ /** The maximum element of a non-empty sequence of ordered elements
+ * @deprecated use seq.max iConstead
+ */
+ @deprecated def max[A <% Ordered[A]](seq: Iterable[A]): A = {
+ val xs = seq.elements
+ if (!xs.hasNext) throw new IllegalArgumentException("max(<empty>)")
+ var max = xs.next
+ while (xs.hasNext) {
+ val x = xs.next
+ if (max < x) max = x
+ }
+ max
+ }
+
+}
+
diff --git a/src/library/scalax/collection/Iterator.scala b/src/library/scalax/collection/Iterator.scala
new file mode 100755
index 0000000000..2758faf854
--- /dev/null
+++ b/src/library/scalax/collection/Iterator.scala
@@ -0,0 +1,970 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterator.scala 15939 2008-08-26 14:33:17Z stepancheg $
+
+
+package scalax.collection
+
+import mutable.{Buffer, ArrayBuffer, ListBuffer}
+import immutable.{List, Nil, ::}
+
+/** The <code>Iterator</code> object provides various functions for
+ * creating specialized iterators.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 2.8
+ */
+object Iterator {
+
+ val empty = new Iterator[Nothing] {
+ def hasNext: Boolean = false
+ def next(): Nothing = throw new NoSuchElementException("next on empty iterator")
+ }
+
+ def apply[A](args: A*): Iterator[A] = args.asInstanceOf[Iterable[A]].elements // !!!
+
+ /** Concatenate all the argument iterators into a single iterator.
+ *
+ * @param xss the lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def concat[A](xss: Iterator[A]*): Iterator[A] =
+ xss.asInstanceOf[Iterable[Iterator[A]]].elements.flatten // !!!
+
+ /** An iterator that returns the same element a number of times
+ * @param len The number of elements returned
+ * @param elem The element returned each time
+ */
+ def fill[A](len: Int, elem: => A) = new Iterator[A] {
+ private var i = 0
+ def hasNext: Boolean = i < len
+ def next(): A =
+ if (hasNext) { i += 1; elem }
+ else empty.next()
+ }
+
+ /** An iterator that returns values of a function <code>f(0), ..., f(n-1)</code>,
+ * for given `f` and `n`.
+ */
+ def tabulate[A](n: Int)(f: Int => A) = new Iterator[A] {
+ private var i = 0
+ def hasNext: Boolean = i < n
+ def next(): A =
+ if (hasNext) { val result = f(i); i += 1; result }
+ else empty.next()
+ }
+
+ /** Nn iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code>
+ * where <code>e<sub>0</sub> = start</code>
+ * and <code>e<sub>i</sub> &lt; end</code>. However,
+ * if <code>start &ge; end</code>, then it will return an empty range.
+ *
+ * @param start the start value of the iterator
+ * @param end the end value of the iterator
+ * @return the iterator with values in range <code>[start;end)</code>.
+ */
+ def range(start: Int, end: Int): Iterator[Int] = range(start, end, 1)
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code>
+ * where <code>e<sub>0</sub> = start</code>
+ * and elements are in the range between <code>start</code> (inclusive)
+ * and <code>end</code> (exclusive)
+ *
+ * @param start the start value of the iterator
+ * @param end the end value of the iterator
+ * @param step the increment value of the iterator (must be positive or negative)
+ * @return the iterator with values in range <code>[start;end)</code>.
+ */
+ def range(start: Int, end: Int, step: Int) = new Iterator[Int] {
+ private var i = start
+ def hasNext: Boolean = (step <= 0 || i < end) && (step >= 0 || i > end)
+ def next(): Int =
+ if (hasNext) { val result = i; i += step; result }
+ else empty.next()
+ }
+
+ /** An iterator that repeatedly applies a given function to a start value.
+ *
+ * @param start the start value of the iteratpr
+ * @param len the number of elements returned by the iterator
+ * @param f the function that's repeatedly applied
+ * @return the iterator returning values <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code>
+ */
+ def iterate(start: Int, len: Int)(f: Int => Int) = new Iterator[Int] {
+ private var acc = start
+ private var i = 0
+ def hasNext: Boolean = i < len
+ def next(): Int =
+ if (hasNext) { val result = f(acc); i += 1; result }
+ else empty.next()
+ }
+
+ /** An infinite iterator that repeatedly applies a given function to a start value.
+ *
+ * @param start the start value of the iteratpr
+ * @param f the function that's repeatedly applied
+ * @return the iterator returning values <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code>
+ */
+ def iterate(start: Int)(f: Int => Int) = new Iterator[Int] {
+ private var acc = start
+ private var i = 0
+ def hasNext: Boolean = true
+ def next(): Int = { val result = f(acc); i += 1; result }
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code>
+ * where <code>e<sub>0</sub> = start</code>.
+ *
+ * @param start the start value of the iterator
+ * @return the iterator starting at value <code>start</code>.
+ */
+ def from(start: Int): Iterator[Int] = from(start, 1)
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code>
+ * where <code>e<sub>0</sub> = start</code>.
+ *
+ * @param start the start value of the iterator
+ * @param step the increment value of the iterator
+ * @return the iterator starting at value <code>start</code>.
+ */
+ def from(start: Int, step: Int): Iterator[Int] = new Iterator[Int] {
+ private var i = 0
+ def hasNext: Boolean = true
+ def next(): Int = { val result = i; i += 1; result }
+ }
+
+ class IteratorIteratorOps[A](its: Iterator[Iterator[A]]) {
+ /** Create an iterator that is the concantenation of all iterators
+ * returned by a given iterator of iterators.
+ * @param its The iterator which returns on each call to next
+ * a new iterator whose elements are to be concatenated to the result.
+ */
+ def flatten: Iterator[A] = new Iterator[A] {
+ private var it = its.next
+ def hasNext: Boolean = {
+ while (!it.hasNext && its.hasNext) it = its.next
+ it.hasNext
+ }
+ def next(): A =
+ if (hasNext) it.next
+ else empty.next()
+ }
+ }
+
+ implicit def iteratorIteratorWrapper[A](its: Iterator[Iterator[A]]): IteratorIteratorOps[A] =
+ new IteratorIteratorOps[A](its)
+
+ /**
+ * @param x the element
+ * @return the iterator with one single element
+ * @deprecated use Iterator(x) instead
+ */
+ @deprecated def single[a](x: a) = new Iterator[a] {
+ private var hasnext = true
+ def hasNext: Boolean = hasnext
+ def next(): a =
+ if (hasnext) { hasnext = false; x }
+ else empty.next()
+ }
+
+ /** @deprecated use `xs.elements` instead
+ */
+ @deprecated def fromValues[a](xs: a*) = xs.elements
+
+ /**
+ * @param xs the array of elements
+ * @see also: Vector.elements and slice
+ * @deprecated use `xs.elements` instead
+ */
+ @deprecated def fromArray[a](xs: Array[a]): Iterator[a] =
+ fromArray(xs, 0, xs.length)
+
+ /**
+ * @param xs the array of elements
+ * @param start the start index
+ * @param length the length
+ * @see also: Vector.elements and slice
+ * @deprecated use `xs.slice(start, start + length).elements` instead
+ */
+ @deprecated def fromArray[a](xs: Array[a], start: Int, length: Int): Iterator[a] =
+ xs.slice(start, start + length).elements.asInstanceOf[Iterator[a]] // !!!
+
+ /**
+ * @param str the given string
+ * @return the iterator on <code>str</code>
+ * @deprecated replaced by <code>str.elements</code>
+ */
+ @deprecated def fromString(str: String): Iterator[Char] =
+ str.elements.asInstanceOf[Iterator[Char]] // !!!
+
+ /**
+ * @param n the product arity
+ * @return the iterator on <code>Product&lt;n&gt;</code>.
+ * @deprecated use product.productElements instead
+ */
+ @deprecated def fromProduct(n: Product): Iterator[Any] = new Iterator[Any] {
+ private var c: Int = 0
+ private val cmax = n.productArity
+ def hasNext = c < cmax
+ def next() = { val a = n productElement c; c += 1; a }
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code>
+ * where <code>e<sub>0</sub> = start</code>
+ * and elements are in the range between <code>start</code> (inclusive)
+ * and <code>end</code> (exclusive)
+ *
+ * @param start the start value of the iterator
+ * @param end the end value of the iterator
+ * @param step the increment function of the iterator, must be monotonically increasing or decreasing
+ * @return the iterator with values in range <code>[start;end)</code>.
+ * @deprecated use Iterator.iterate(start, end - start)(step) instead
+ */
+ @deprecated def range(start: Int, end: Int, step: Int => Int) = new Iterator[Int] {
+ private val up = step(start) > start
+ private val down = step(start) < start
+ private var i = start
+ def hasNext: Boolean = (!up || i < end) && (!down || i > end)
+ def next(): Int =
+ if (hasNext) { val j = i; i = step(i); j }
+ else empty.next()
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code>
+ * where <code>e<sub>0</sub> = start</code>.
+ *
+ * @param start the start value of the iterator
+ * @param step the increment function of the iterator
+ * @return the iterator starting at value <code>start</code>.
+ * @deprecated use iterate(start)(step) instead
+ */
+ @deprecated def from(start: Int, step: Int => Int): Iterator[Int] = new Iterator[Int] {
+ private var i = start
+ override def hasNext: Boolean = true
+ def next(): Int = { val j = i; i = step(i); j }
+ }
+
+ /** Create an iterator that is the concantenation of all iterators
+ * returned by a given iterator of iterators.
+ * @param its The iterator which returns on each call to next
+ * a new iterator whose elements are to be concatenated to the result.
+ * @deprecated use its.flatten instead
+ */
+ @deprecated def flatten[T](its: Iterator[Iterator[T]]): Iterator[T] = new Iterator[T] {
+ private var it = its.next
+ def hasNext: Boolean = {
+ while (!it.hasNext && its.hasNext) it = its.next
+ it.hasNext
+ }
+ def next(): T =
+ if (hasNext) it.next
+ else empty.next()
+ }
+}
+
+import Iterator.empty
+
+/** Iterators are data structures that allow to iterate over a sequence
+ * of elements. They have a <code>hasNext</code> method for checking
+ * if there is a next element available, and a <code>next</code> method
+ * which returns the next element and discards it from the iterator.
+ *
+ * @author Martin Odersky, Matthias Zenger
+ * @version 2.8
+ */
+trait Iterator[+A] {
+self =>
+
+ /** Does this iterator provide another element?
+ */
+ def hasNext: Boolean
+
+ /** Returns the next element.
+ */
+ def next(): A
+
+ /** Returns a new iterator that iterates only over the first <code>n</code>
+ * elements.
+ *
+ * @param n the number of elements to take
+ * @return the new iterator
+ */
+ def take(n: Int): Iterator[A] = new Iterator[A] {
+ private var remaining = n
+ def hasNext = remaining > 0 && self.hasNext
+ def next(): A =
+ if (hasNext) { remaining -= 1; self.next }
+ else throw new NoSuchElementException("next on empty iterator")
+ }
+
+ /** Removes the first <code>n</code> elements from this iterator.
+ *
+ * @param n the number of elements to drop
+ * @return the new iterator
+ */
+ def drop(n: Int): Iterator[A] =
+ if (n > 0 && hasNext) { next(); drop(n - 1) } else this
+
+ /** A sub-iterator of <code>until - from elements
+ * starting at index <code>from</code>
+ *
+ * @param from The index of the first element of the slice
+ * @param until The index of the element following the slice
+ */
+ def slice(from: Int, until: Int): Iterator[A] = drop(from).take(until - from)
+
+ /** Returns a new iterator that maps all elements of this iterator
+ * to new elements using function <code>f</code>.
+ */
+ def map[B](f: A => B): Iterator[B] = new Iterator[B] {
+ def hasNext = self.hasNext
+ def next() = f(self.next())
+ }
+
+ /** Returns a new iterator that first yields the elements of this
+ * iterator followed by the elements provided by iterator <code>that</code>.
+ * @deprecated use <code>++</code>
+ */
+ def append[B >: A](that: Iterator[B]) = new Iterator[B] {
+ def hasNext = self.hasNext || that.hasNext
+ def next() = (if (self.hasNext) self else that).next()
+ }
+
+ /** Returns a new iterator that first yields the elements of this
+ * iterator followed by the elements provided by iterator <code>that</code>.
+ */
+ def ++[B >: A](that: => Iterator[B]) = new Iterator[B] {
+ // optimize a little bit to prevent n log n behavior.
+ var cur : Iterator[B] = self
+ def hasNext = cur.hasNext || (cur eq self) && { cur = that; hasNext }
+ def next() = { hasNext; cur.next }
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this iterator, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return an iterator over <code>f(a<sub>0</sub>), ... ,
+ * f(a<sub>n</sub>)</code> if this iterator yields the
+ * elements <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def flatMap[B](f: A => Iterator[B]): Iterator[B] = new Iterator[B] {
+ private var cur: Iterator[B] = empty
+ def hasNext: Boolean =
+ cur.hasNext || self.hasNext && { cur = f(self.next); hasNext }
+ def next(): B = (if (hasNext) cur else empty).next()
+ }
+
+ /** Returns an iterator over all the elements of this iterator that
+ * satisfy the predicate <code>p</code>. The order of the elements
+ * is preserved.
+ *
+ * @param p the predicate used to filter the iterator.
+ * @return the elements of this iterator satisfying <code>p</code>.
+ */
+ def filter(p: A => Boolean): Iterator[A] = {
+ val self = buffered
+ new Iterator[A] {
+ private def skip() = while (self.hasNext && !p(self.head)) self.next()
+ def hasNext = { skip(); self.hasNext }
+ def next() = { skip(); self.next() }
+ }
+ }
+
+ /** Returns an iterator over the longest prefix of this iterator such that
+ * all elements of the result satisfy the predicate <code>p</code>.
+ * The order of the elements is preserved.
+ *
+ * The behavior of <code>this</code> iterator is undefined after this method invocation.
+ *
+ * @param p the predicate used to filter the iterator.
+ * @return the longest prefix of this iterator satisfying <code>p</code>.
+ */
+ def takeWhile(p: A => Boolean): Iterator[A] = {
+ val self = buffered
+ new Iterator[A] {
+ def hasNext = { self.hasNext && p(self.head) }
+ def next() = (if (hasNext) self else empty).next()
+ }
+ }
+
+ /** Partitions this iterator in two iterators according to a predicate.
+ *
+ * @param p the predicate on which to partition
+ * @return a pair of iterators: the iterator that satisfies the predicate
+ * <code>p</code> and the iterator that does not.
+ * The relative order of the elements in the resulting iterators
+ * is the same as in the original iterator.
+ */
+ def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
+ val self = buffered
+ class PartitionIterator(p: A => Boolean) extends Iterator[A] {
+ var other: PartitionIterator = _
+ val lookahead = new scala.collection.mutable.Queue[A]
+ def skip() =
+ while (self.hasNext && !p(self.head)) {
+ other.lookahead += self.next
+ }
+ def hasNext = !lookahead.isEmpty || self.hasNext
+ def next() = if (lookahead.isEmpty) self.next() else lookahead.dequeue()
+ }
+ val l = new PartitionIterator(p)
+ val r = new PartitionIterator(!p(_))
+ l.other = r
+ r.other = l
+ (l, r)
+ }
+
+ /** Skips longest sequence of elements of this iterator which satisfy given
+ * predicate <code>p</code>, and returns an iterator of the remaining elements.
+ *
+ * The behavior of <code>this</code> iterator is undefined after this method invocation.
+ *
+ * @param p the predicate used to skip elements.
+ * @return an iterator consisting of the remaining elements
+ */
+ def dropWhile(p: A => Boolean): Iterator[A] = {
+ val self = buffered
+ new Iterator[A] {
+ var dropped = false
+ private def skip() =
+ if (!dropped) {
+ while (self.hasNext && p(self.head)) self.next()
+ dropped = true
+ }
+ def hasNext = { skip(); self.hasNext }
+ def next() = { skip(); self.next() }
+ }
+ }
+
+ /** Return an iterator formed from this iterator and the specified iterator
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two iterators is longer than the other, its remaining elements are ignored.
+ *
+ * @return an iterator yielding <code>{a<sub>0</sub>,b<sub>0</sub>},
+ * {a<sub>1</sub>,b<sub>1</sub>}, ...</code> where
+ * <code>a<sub>i</sub></code> are the elements from this iterator
+ * and <code>b<sub>i</sub></code> are the elements from iterator
+ * <code>that</code>.
+ */
+ def zip[B](that: Iterator[B]) = new Iterator[(A, B)] {
+ def hasNext = self.hasNext && that.hasNext
+ def next = (self.next, that.next)
+ }
+
+ /** Return an iterator that pairs each element of this iterator
+ * with its index, counting from 0.
+ *
+ * @return an iterator yielding <code>{a<sub>0</sub>,0},
+ * {a<sub>1</sub>,1}...</code> where <code>a<sub>i</sub></code>
+ * are the elements from this iterator.
+ */
+ def zipWithIndex = new Iterator[(A, Int)] {
+ var idx = 0
+ def hasNext = self.hasNext
+ def next = {
+ val ret = (self.next, idx)
+ idx += 1
+ ret
+ }
+ }
+
+ /** Returns an iterator formed from this iterator and the specified iterator
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param that iterator <code>that</code> may have a different length
+ * as the self iterator.
+ * @param thisElem element <code>thisElem</code> is used to fill up the
+ * resulting iterator if the self iterator is shorter than
+ * <code>that</code>
+ * @param thatElem element <code>thatElem</code> is used to fill up the
+ * resulting iterator if <code>that</code> is shorter than
+ * the self iterator
+ * @return <code>Iterator((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>),
+ * ..., {elem,b<sub>m</sub>})</code>
+ * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
+ * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
+ * invoked where <code>m &gt; n</code>.
+ */
+ def zipAll[B, A1 >: A, B1 >: B](that: Iterator[B], thisElem: A1, thatElem: B1) = new Iterator[(A1, B1)] {
+ def hasNext = self.hasNext || that.hasNext
+ def next(): (A1, B1) =
+ if (self.hasNext) {
+ if (that.hasNext) (self.next(), that.next())
+ else (self.next(), thatElem)
+ } else {
+ if (that.hasNext) (thisElem, that.next())
+ else empty.next()
+ }
+ }
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @param f a function that is applied to every element.
+ */
+ def foreach(f: A => Unit) { while (hasNext) f(next()) }
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return <code>true</code> iff the predicate yields
+ * <code>true</code> for all elements.
+ *
+ * @param p the predicate
+ * @return <code>true</code> iff the predicate yields <code>true</code>
+ * for all elements.
+ */
+ def forall(p: A => Boolean): Boolean = {
+ var res = true
+ while (res && hasNext) res = p(next())
+ res
+ }
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff there is at least one
+ * element for which <code>p</code> yields <code>true</code>.
+ *
+ * @param p the predicate
+ * @return <code>true</code> iff the predicate yields <code>true</code>
+ * for at least one element.
+ */
+ def exists(p: A => Boolean): Boolean = {
+ var res = false
+ while (!res && hasNext) res = p(next())
+ res
+ }
+
+ /** Tests if the given value <code>elem</code> is a member of this iterator.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return <code>true</code> iff there is an element of this iterator which
+ * is equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): Boolean = exists { _ == elem }
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the iterable object satisfying
+ * <code>p</code>, or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = {
+ var res: Option[A] = None
+ while (res.isEmpty && hasNext) {
+ val e = next()
+ if (p(e)) res = Some(e)
+ }
+ res
+ }
+
+ /** Returns index of the first element satisying a predicate, or -1.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @return the index of the first element satisfying <code>p</code>,
+ * or -1 if such an element does not exist
+ */
+ def indexWhere(p: A => Boolean): Int = {
+ var i = 0
+ var found = false
+ while (!found && hasNext) {
+ if (p(next())) {
+ found = true
+ } else {
+ i += 1
+ }
+ }
+ if (found) i else -1
+ }
+
+ /** Returns index of the first element satisying a predicate, or -1.
+ *
+ * @deprecated use `indexWhere` instead
+ */
+ @deprecated def findIndexOf(p: A => Boolean): Int = indexWhere(p)
+
+ /** Returns the index of the first occurence of the specified
+ * object in this iterable object.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param elem element to search for.
+ * @return the index in this sequence of the first occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def indexOf[B >: A](elem: B): Int = {
+ var i = 0
+ var found = false
+ while (!found && hasNext) {
+ if (next() == elem) {
+ found = true
+ } else {
+ i += 1
+ }
+ }
+ if (found) i else -1
+ }
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>op(... (op(op(z,a<sub>0</sub>),a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the iterator yields elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = {
+ var acc = z
+ while (hasNext) acc = op(acc, next())
+ acc
+ }
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n</sub> op z)...)</code>
+ * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = {
+ def fold(z: B): B = if (hasNext) op(next(), fold(z)) else z
+ fold(z)
+ }
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of iterator and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>.
+ *
+ * @param z the left argument of the first application of <code>op</code>
+ * (evaluation occurs from left to right).
+ * @param op the applied operator.
+ * @return the result value
+ * @see <code><a href="#foldLeft">foldLeft</a></code>.
+ */
+ def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>.
+ *
+ * @param z the right argument of the first application of <code>op</code>
+ * (evaluation occurs from right to left).
+ * @param op the applied operator.
+ * @return the result value.
+ * @see <code><a href="#foldRight">foldRight</a></code>.
+ */
+ def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from left to right
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the iterator yields elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceLeft[B >: A](op: (B, A) => B): B = {
+ if (hasNext) foldLeft[B](next())(op)
+ else throw new UnsupportedOperationException("empty.reduceLeft")
+ }
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from right to left
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceRight[B >: A](op: (A, B) => B): B = {
+ if (!hasNext) throw new UnsupportedOperationException("empty.reduceRight")
+ foldRight[B](next())(op)
+ }
+
+ /** Returns a buffered iterator from this iterator.
+ */
+ def buffered = new BufferedIterator[A] {
+ private var hd: A = _
+ private var hdDefined: Boolean = false
+
+ def head: A = {
+ if (!hdDefined) {
+ hd = next()
+ hdDefined = true
+ }
+ hd
+ }
+
+ def hasNext =
+ hdDefined || self.hasNext
+
+ def next =
+ if (hdDefined) {
+ hdDefined = false
+ hd
+ } else self.next
+ }
+
+ def length: Int = {
+ var i = 0
+ while (hasNext) {
+ next(); i += 1
+ }
+ i
+ }
+
+ /** Returns a counted iterator from this iterator.
+ * @deprecated use @see zipWithIndex in Iterator
+ */
+ def counted = new CountedIterator[A] {
+ private var cnt = -1
+ def count = cnt
+ def hasNext: Boolean = self.hasNext
+ def next(): A = { cnt += 1; self.next }
+ }
+
+ /** Creates two new iterators that both iterate over the same elements
+ * than this iterator (in the same order).
+ *
+ * @return a pair of iterators
+ */
+ def duplicate: (Iterator[A], Iterator[A]) = {
+ var xs: List[A] = Nil
+ var ahead: Iterator[A] = null
+ class Partner extends Iterator[A] {
+ var ys: List[A] = Nil
+ def hasNext: Boolean = self.synchronized (
+ ((this == ahead) && self.hasNext) ||
+ ((this != ahead) && (!xs.isEmpty || !ys.isEmpty || self.hasNext))
+ )
+ def next(): A = self.synchronized {
+ if (this == ahead) {
+ val e = self.next()
+ xs = e :: xs; e
+ } else {
+ if (ys.isEmpty) {
+ ys = xs.reverse
+ xs = Nil
+ }
+ ys match {
+ case Nil =>
+ val e = self.next()
+ ahead = this
+ xs = e :: xs; e
+ case z :: zs =>
+ ys = zs; z
+ }
+ }
+ }
+ }
+ ahead = new Partner
+ (ahead, new Partner)
+ }
+
+ def patch[B >: A](from: Int, ps: Sequence[B], replaced: Int) = new Iterator[B] {
+ private val plen = ps.length
+ private var origElems = self
+ private val patchElems = ps.elements
+ private var i = 0
+ def hasNext: Boolean =
+ if (i < from) origElems.hasNext
+ else patchElems.hasNext || origElems.hasNext
+ def next(): B = {
+ val result: B =
+ if (i < from || i >= from + plen) origElems.next()
+ else patchElems.next()
+ i += 1
+ if (i == from) origElems = origElems drop replaced
+ result
+ }
+ }
+
+ /** Fills the given array <code>xs</code> with at most `len` elements of
+ * this iterator starting at position `start`.
+ * Copying will stop once either the end of the current iterable is reached or
+ * `len` elements have been copied.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @param len number of elements to copy
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = {
+ var i = start
+ val end = start + len
+ while (hasNext && i < end) {
+ xs(i) = next()
+ i += 1
+ }
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this iterator starting at position <code>start</code>
+ * until either the end of the current iterator or the end of array `xs` is reached.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int): Unit =
+ copyToArray(xs, start, xs.length - start)
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this iterator starting at position <code>0</code>
+ * until either the end of the current iterator or the end of array `xs` is reached.
+ *
+ * @param xs the array to fill.
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B]): Unit = copyToArray(xs, 0, xs.length)
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>. Like <code>copyToArray</code>,
+ * but designed to accomodate IO stream operations.
+ *
+ * @param xs the array to fill.
+ * @param start the starting index.
+ * @param sz the maximum number of elements to be read.
+ * @pre the array must be large enough to hold <code>sz</code> elements.
+ * @deprecated use copyToArray instead
+ */
+ @deprecated def readInto[B >: A](xs: Array[B], start: Int, sz: Int) {
+ var i = start
+ while (hasNext && i - start < sz) {
+ xs(i) = next
+ i += 1
+ }
+ }
+ @deprecated def readInto[B >: A](xs: Array[B], start: Int) {
+ readInto(xs, start, xs.length - start)
+ }
+ @deprecated def readInto[B >: A](xs: Array[B]) {
+ readInto(xs, 0, xs.length)
+ }
+
+ /** Copy all elements to a buffer
+ * @param The buffer to which elements are copied
+ */
+ def copyToBuffer[B >: A](dest: Buffer[B]) {
+ while (hasNext) dest += next
+ }
+
+ /** Transform this iterator into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this iterator.
+ */
+ def toList: List[A] = {
+ val res = new ListBuffer[A]
+ while (hasNext) res += next
+ res.toList
+ }
+
+ /**
+ * Create a stream which contains all the elements of this iterator.
+ */
+ def toStream: Stream[A] =
+ if (hasNext) Stream.cons(next, toStream) else Stream.empty
+
+ /**
+ * Create a sequence which contains all the elements of this iterator.
+ */
+ def toSequence: Sequence[A] = {
+ val buffer = new ArrayBuffer[A]
+ this copyToBuffer buffer
+ null // !!! should be: buffer.readOnly
+ }
+
+ /** Collect elements into a seq.
+ *
+ * @return a sequence which enumerates all elements of this iterator.
+ * @deprecated use toSequence instead
+ */
+ @deprecated def collect: Sequence[A] = toSequence
+
+ /** Returns a string representation of the elements in this iterator. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * <p/>
+ * Ex: <br/>
+ * <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ *
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(start: String, sep: String, end: String): String = {
+ val buf = new StringBuilder
+ addString(buf, start, sep, end).toString
+ }
+
+ /** Returns a string representation of this iterable object. The string
+ * representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ *
+ * @param sep separator string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(sep: String): String = this.mkString("", sep, "")
+
+ /** Returns a string representation of this iterable object. The string
+ * representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by a comma.
+ *
+ * @return a string representation of this iterable object.
+ */
+ def mkString: String =
+ mkString("")
+
+ /** Write all elements of this iterator into given string builder.
+ * The written text begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ */
+ def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ buf.append(start)
+ val elems = this
+ if (elems.hasNext) buf.append(elems.next)
+ while (elems.hasNext) {
+ buf.append(sep); buf.append(elems.next)
+ }
+ buf.append(end)
+ }
+
+ /** Write all elements of this iterator into given string builder.
+ * The string representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ */
+ def addString(buf: StringBuilder, sep: String): StringBuilder =
+ addString(buf, "", sep, "")
+
+ /** Write all elements of this string into given string builder without using
+ * any separator between consecutive elements.
+ */
+ def addString(buf: StringBuilder): StringBuilder =
+ addString(buf, "", "", "")
+
+ override def toString = (if (hasNext) "non-empty" else "empty")+" iterator"
+
+}
diff --git a/src/library/scalax/collection/OrderedIterable.scala b/src/library/scalax/collection/OrderedIterable.scala
new file mode 100755
index 0000000000..97bd96e667
--- /dev/null
+++ b/src/library/scalax/collection/OrderedIterable.scala
@@ -0,0 +1,41 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection
+
+import generic._
+
+/** An ordered collection is a collection with a fixed sequence of elements
+ * which corresponds to append order. In particular, it holds that
+ *
+ * (c1 ++ c2).elements = c1.elements ++ c2.elements
+ *
+ * for any two ordered collections c1 and c2.
+ * Ordered collections support
+ * - operations that form subsequences: take, takeWhile, drop, dropWhile,
+ * - zip, unzip
+ *
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait OrderedIterable[+A] extends Iterable[A] with covariant.OrderedIterableTemplate[OrderedIterable, A]
+
+/** Various utilities for instances of <a href="Iterable.html">Iterable</a>.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+object OrderedIterable extends covariant.IterableFactory[OrderedIterable] {
+
+ val empty: OrderedIterable[Nothing] = null // !!!
+
+}
diff --git a/src/library/scalax/collection/Sequence.scala b/src/library/scalax/collection/Sequence.scala
new file mode 100755
index 0000000000..0ee88e3575
--- /dev/null
+++ b/src/library/scalax/collection/Sequence.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection
+
+import generic._
+
+/** Class <code>Sequence[A]</code> represents finite sequences of elements
+ * of type <code>A</code>.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.0, 16/07/2003
+ */
+trait Sequence[+A] extends OrderedIterable[A] with SizedIterable[A] with covariant.SequenceTemplate[Sequence, A]
+
+object Sequence extends covariant.SequenceFactory[Sequence] {
+
+ /** The empty sequence */
+ val empty : Sequence[Nothing] = null // !!!
+
+ type View[+UC[+B] <: Sequence[B], +A] = covariant.SequenceView[UC, A]
+
+ /** @deprecated use View instead
+ */
+ @deprecated type Projection[A] = View[C, A] forSome { type C[+B] <: Sequence[B] }
+
+ /** @deprecated use Sequence(value) instead */
+ @deprecated def singleton[A](value: A) = Sequence(value)
+
+ /** Builds a singleton sequence.
+ *
+ * @deprecated use <code>Sequence(x)</code> instead.
+ */
+ @deprecated def single[A](x: A) = singleton(x)
+}
+
diff --git a/src/library/scalax/collection/SizedIterable.scala b/src/library/scalax/collection/SizedIterable.scala
new file mode 100644
index 0000000000..f4e13f3521
--- /dev/null
+++ b/src/library/scalax/collection/SizedIterable.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Collection.scala 12340 2007-07-17 15:29:47Z mcdirmid $
+
+
+package scalax.collection
+
+/** Variant of <code>Iterable</code> which also demands
+ * implementation of a `size` method.
+ * Basically, this trait just adds size to Iterable,
+ * and provides an optimized implementation of toArray based on it.
+ *
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait SizedIterable[+A] extends Iterable[A] {
+
+ /** Returns the number of elements in this collection.
+ *
+ * @return number of collection elements.
+ */
+ def size : Int
+
+ /** Converts this iterable to a fresh Array with <code>size</code> elements.
+ */
+ override def toArray[B >: A]: Array[B] = {
+ val result = new Array[B](size)
+ copyToArray(result, 0)
+ result
+ }
+}
+
diff --git a/src/library/scalax/collection/Vector.scala b/src/library/scalax/collection/Vector.scala
new file mode 100755
index 0000000000..8787d7fd42
--- /dev/null
+++ b/src/library/scalax/collection/Vector.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $
+
+package scalax.collection
+
+import generic._
+
+trait Vector[+A] extends Sequence[A] with covariant.VectorTemplate[Vector, A]
+
+object Vector extends covariant.SequenceFactory[Vector] {
+
+ /** The empty sequence */
+ val empty : Vector[Nothing] = null // !!!
+}
diff --git a/src/library/scalax/collection/generic/IterableFactory.scala b/src/library/scalax/collection/generic/IterableFactory.scala
new file mode 100755
index 0000000000..264e333ac5
--- /dev/null
+++ b/src/library/scalax/collection/generic/IterableFactory.scala
@@ -0,0 +1,108 @@
+package scalax.collection.generic
+
+trait IterableFactory[CC[A] <: Iterable[A]] {
+
+ /** Create CC collection of specified elements */
+ def apply[A](args: A*): CC[A]
+
+ protected def newBuilder[A]: Builder[CC, A] =
+ apply().newBuilder[A].asInstanceOf[Builder[CC, A]]
+
+ /** Concatenate all the argument lists into a single list.
+ *
+ * @param xss the lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def concat[A](xss: CC[A]*): CC[A] = {
+ val b = newBuilder[A]
+ for (xs <- xss) b ++= xs
+ b.result
+ }
+
+ /** An iterable that contains the same element a number of times
+ * @param n The number of elements returned
+ * @param elem The element returned each time
+ */
+ def fill[A](n: Int, elem: => A): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ while (i < n) {
+ b += elem
+ i += 1
+ }
+ b.result
+ }
+
+ def fill[A](n1: Int, n2: Int, elem: => A): CC[CC[A]] =
+ tabulate(n1)(_ => fill(n2, elem))
+
+ def fill[A](n1: Int, n2: Int, n3: Int, elem: => A): CC[CC[CC[A]]] =
+ tabulate(n1)(_ => fill(n2, n3, elem))
+
+ def tabulate[A](n: Int)(f: Int => A): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ while (i < n) {
+ b += f(i)
+ i += 1
+ }
+ b.result
+ }
+
+ def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] =
+ tabulate(n1)(i1 => tabulate(n2)(i2 => f(i1, i2)))
+
+ def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] =
+ tabulate(n1)(i1 => tabulate(n2)(i2 => tabulate(n3)(i3 => f(i1, i2, i3))))
+// todo: go up to 5(?)
+
+ /** Create a sequence of increasing integers in a range.
+ *
+ * @param from the start value of the sequence
+ * @param end the end value of the sequence
+ * @return the sorted list of all from `from` (inclusive)
+ * up to, but exclusding, `end`.
+ */
+ def range[A](start: Int, end: Int): CC[Int] = range(start, end, 1)
+
+ /** Create a sequence of increasing integers in a range.
+ *
+ * @param from the start value of the sequence
+ * @param end the end value of the sequence
+ * @param step the increment value of successive elements
+ * @return a list of values <code>from + n * step</code> for
+ * increasing n. If `step > 0` the sequence terminates
+ * with the largest value less than `end`. If `step < 0`
+ * the sequence terminates with the smallest value greater than `end`.
+ * If `step == 0`, the sequence gors on infinitely (in that
+ * case the `range` operation might not terminate.
+ */
+ def range(start: Int, end: Int, step: Int): CC[Int] = {
+ val b = newBuilder[Int]
+ var i = start
+ while ((step <= 0 || i < end) && (step >= 0 || i > end)) {
+ b += i
+ i += step
+ }
+ b.result
+ }
+
+ /** Create a sequence by repeatedly applying a given function to a start value.
+ *
+ * @param start the start value of the sequence
+ * @param len the length of the sequence
+ * @param f the function that's repeatedly applied
+ * @return the sequence with elements <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code>
+ */
+ def iterate(start: Int, len: Int)(f: Int => Int): CC[Int] = {
+ val b = newBuilder[Int]
+ var acc = start
+ var i = 0
+ while (i < len) {
+ b += acc
+ acc = f(acc)
+ i += 1
+ }
+ b.result
+ }
+}
diff --git a/src/library/scalax/collection/generic/IterableForwarder.scala b/src/library/scalax/collection/generic/IterableForwarder.scala
new file mode 100644
index 0000000000..fba1e6d0e9
--- /dev/null
+++ b/src/library/scalax/collection/generic/IterableForwarder.scala
@@ -0,0 +1,61 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: IterableProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $
+
+
+package scalax.collection.generic
+
+import collection.mutable.Buffer
+import collection.immutable.List
+
+/** This trait implements a forwarder for iterable objects. It forwards
+ * all calls to a different iterable object, except for
+ *
+ * - toString, hashCode, equals, stringPrefix
+ * - newBuilder, view
+ * - all calls creating a new iterable objetc of the same kind
+ *
+ * The above methods are forwarded by subclass IterableProxy
+ *
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait IterableForwarder[+A] extends Iterable[A] {
+
+ /** The iterable object to which calls are forwarded */
+ protected def underlying: Iterable[A]
+
+ // Iterable delegates
+ // Iterable methods could be printed by cat IterableTemplate.scala | sed -n '/trait Iterable/,$ p' | egrep '^ (override )?def'
+
+ override def elements = underlying.elements
+ override def isEmpty = underlying.isEmpty
+ override def hasDefiniteSize = underlying.hasDefiniteSize
+ override def foreach(f: A => Unit) = underlying.foreach(f)
+ override def forall(p: A => Boolean): Boolean = underlying.forall(p)
+ override def exists(p: A => Boolean): Boolean = underlying.exists(p)
+ override def count(p: A => Boolean): Int = underlying.count(p)
+ override def find(p: A => Boolean): Option[A] = underlying.find(p)
+ override def foldLeft[B](z: B)(op: (B, A) => B): B = underlying.foldLeft(z)(op)
+ override def foldRight[B](z: B)(op: (A, B) => B): B = underlying.foldRight(z)(op)
+ override def reduceLeft[B >: A](op: (B, A) => B): B = underlying.reduceLeft(op)
+ override def reduceRight[B >: A](op: (A, B) => B): B = underlying.reduceRight(op)
+ override def copyToBuffer[B >: A](dest: Buffer[B]) = underlying.copyToBuffer(dest)
+ override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = underlying.copyToArray(xs, start, len)
+ override def toArray[B >: A]: Array[B] = underlying.toArray
+ override def toList: List[A] = underlying.toList
+ override def toSequence: Sequence[A] = underlying.toSequence
+ override def toStream: Stream[A] = underlying.toStream
+ override def mkString(start: String, sep: String, end: String): String = underlying.mkString(start, sep, end)
+ override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = underlying.addString(b, start, sep, end)
+
+ override def head: A = underlying.head
+ override def last: A = underlying.last
+ override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = underlying.sameElements(that)
+}
diff --git a/src/library/scalax/collection/generic/IterableTemplate.scala b/src/library/scalax/collection/generic/IterableTemplate.scala
new file mode 100755
index 0000000000..01a23f5ecf
--- /dev/null
+++ b/src/library/scalax/collection/generic/IterableTemplate.scala
@@ -0,0 +1,816 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic
+
+import scalax.collection.mutable.{Buffer, ArrayBuffer, ListBuffer}
+import scalax.collection.immutable.{List, Nil, ::}
+import util.control.Break._
+import Iterable._
+
+/** Collection classes mixing in this class provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>.
+ * Only potentially unbounded collections should directly sub-class <code>Iterable</code>.
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait IterableTemplate[+CC[/*+*/B] <: IterableTemplate[CC, B] with Iterable[B], /*+*/A] { self/*: CC[A]*/ =>
+
+ /** The template itself seen as an instance of `CC[A]`.
+ * @note: It would be logical to have a self type `CC[A]` instead, then we would not need
+ * this method. Unfortunately, tyis runs afoul some pecularities in Scala's member resolution
+ * algorithm: If the self type is a CC, then Iterable is one of its supertypes. Iterable
+ * defines a number of concrete methods such as newBuilder which are abstract here.
+ * The newBuilder method in Iterable[A] has type Builder[Iterable, A]. Because Scala
+ * prefers concrete over abstract members, it is this newBuilder which is chosen, instead of
+ * the abstract newBuilder in class IterableTemplate of type Builder[CC, A].
+ * Even for concrete methods we have a problem because the last mixin in the parents of CC is
+ * Iterable, not IterableTemplate. So resolution picks the version in Iterable, which returns
+ * again an Iterable, not a CC, as would be required.
+ * These problems would be avoided if Scala computed the type of a member as the glb of the types
+ * all members in the class and its superclasses types.
+ * I think overall this would be a better design.
+ */
+ protected[this] def thisCC: CC[A] = this.asInstanceOf[CC[A]]
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A]
+
+ /** Create a new builder for this IterableType
+ */
+ def newBuilder[B]: Builder[CC, B]
+
+ /** Is this collection empty? */
+ def isEmpty: Boolean = !elements.hasNext
+
+ /** returns true iff this collection has a bound size.
+ * Many APIs in this trait will not work on collections of
+ * unbound sizes.
+ */
+ def hasDefiniteSize = true
+
+ /** Create a new sequence of type CC which contains all elements of this sequence
+ * followed by all elements of Iterable `that'
+ */
+ def ++[B >: A](that: Iterable[B]): CC[B] = {
+ val b: Builder[CC, B] = (this: IterableTemplate[CC, A]).newBuilder[B]
+ b ++= thisCC
+ b ++= that
+ b.result
+ }
+
+ /** Create a new sequence of type IterableType which contains all elements of this sequence
+ * followed by all elements of Iterator `that'
+ */
+ def ++[B >: A](that: Iterator[B]): CC[B] = {
+ val b = newBuilder[B]
+ b ++= thisCC
+ b ++= that
+ b.result
+ }
+
+ /** Returns the sequence resulting from applying the given function
+ * <code>f</code> to each element of this sequence.
+ *
+ * @param f function to apply to each element.
+ * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this
+ * sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def map[B](f: A => B): CC[B] = {
+ val b = newBuilder[B]
+ for (x <- this) b += f(x)
+ b.result
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this sequence, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def flatMap[B](f: A => Iterable[B]): CC[B] = {
+ val b = newBuilder[B]
+ for (x <- this) b ++= f(x)
+ b.result
+ }
+
+ /** Returns all the elements of this sequence that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ def filter(p: A => Boolean): CC[A] = {
+ val b = newBuilder[A]
+ for (x <- this)
+ if (p(x)) b += x
+ b.result
+ }
+
+ /** Removes all elements of the iterable which satisfy the predicate
+ * <code>p</code>. This is like <code>filter</code> with the
+ * predicate inversed.
+ *
+ * @param p the predicate to use to test elements
+ * @return the list without all elements which satisfy <code>p</code>
+ */
+ def remove(p: A => Boolean): CC[A] = filter(!p(_))
+
+ /** Partitions this iterable in two iterables according to a predicate.
+ *
+ * @param p the predicate on which to partition
+ * @return a pair of iterables: the iterable that satisfies the predicate
+ * <code>p</code> and the iterable that does not.
+ * The relative order of the elements in the resulting iterables
+ * is the same as in the original iterable.
+ */
+ def partition(p: A => Boolean): (CC[A], CC[A]) = {
+ val l, r = newBuilder[A]
+ for (x <- this) (if (p(x)) l else r) += x
+ (l.result, r.result)
+ }
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param f a function that is applied to every element.
+ * Note this function underlies the implementation of most other bulk operations.
+ * It should be overridden in concrete collectionc classes with efficient implementations.
+ */
+ def foreach(f: A => Unit): Unit = elements.foreach(f)
+
+ /** Return true iff the given predicate `p` yields true for all elements
+ * of this iterable.
+ *
+ * @note May not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def forall(p: A => Boolean): Boolean = {
+ var result = true
+ breakable {
+ for (x <- this)
+ if (!p(x)) { result = false; break }
+ }
+ result
+ }
+
+ /** Return true iff there is an element in this iterable for which the
+ * given predicate `p` yields true.
+ *
+ * @note May not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def exists(p: A => Boolean): Boolean = {
+ var result = false
+ breakable {
+ for (x <- this)
+ if (p(x)) { result = true; break }
+ }
+ result
+ }
+
+ /** Count the number of elements in the iterable which satisfy a predicate.
+ *
+ * @param p the predicate for which to count
+ * @return the number of elements satisfying the predicate <code>p</code>.
+ */
+ def count(p: A => Boolean): Int = {
+ var cnt = 0
+ for (x <- this) {
+ if (p(x)) cnt += 1
+ }
+ cnt
+ }
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @return an option containing the first element in the iterable object
+ * satisfying <code>p</code>, or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = {
+ var result: Option[A] = None
+ breakable {
+ for (x <- this)
+ if (p(x)) { result = Some(x); break }
+ }
+ result
+ }
+
+ /** Combines the elements of this iterable object together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the list is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = {
+ var result = z
+ for (x <- this)
+ result = op(result, x)
+ result
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op)
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of list and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
+
+ /** Combines the elements of this iterable object together using the binary
+ * operator <code>op</code>, from left to right
+ * @note Will not terminate for infinite-sized collections.
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the iterable object has elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the iterable object is empty.
+ */
+ def reduceLeft[B >: A](op: (B, A) => B): B = {
+ if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft")
+ var result: B = elements.next
+ var first = true
+ for (x <- this)
+ if (first) first = false
+ else result = op(result, x)
+ result
+ }
+
+ /** Combines the elements of this iterable object together using the binary
+ * operator <code>op</code>, from right to left
+ * @note Will not terminate for infinite-sized collections.
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ *
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceRight[B >: A](op: (A, B) => B): B =
+ elements.reduceRight(op)
+
+ /** Returns an iterable formed from this iterable and the specified list
+ * `other` by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two iterables is longer than the other, its remaining elements are ignored.
+ */
+ def zip[B](that: Iterable[B]): CC[(A, B)] = {
+ val these = this.elements
+ val those = that.elements
+ val b = this.newBuilder[(A, B)]
+ while (these.hasNext && those.hasNext)
+ b += ((these.next, those.next))
+ b.result
+ }
+
+ /** Returns a iterable formed from this iterable and the specified iterable
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param that iterable <code>that</code> may have a different length
+ * as the self iterable.
+ * @param thisElem element <code>thisElem</code> is used to fill up the
+ * resulting iterable if the self iterable is shorter than
+ * <code>that</code>
+b * @param thatElem element <code>thatElem</code> is used to fill up the
+ * resulting iterable if <code>that</code> is shorter than
+ * the self iterable
+ * @return <code>Iterable((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>),
+ * ..., {elem,b<sub>m</sub>})</code>
+ * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
+ * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
+ * invoked where <code>m &gt; n</code>.
+ */
+ def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = {
+ val these = this.elements
+ val those = that.elements
+ val b = newBuilder[(A1, B1)]
+ while (these.hasNext && those.hasNext)
+ b += ((these.next, those.next))
+ while (these.hasNext)
+ b += ((these.next, thatElem))
+ while (those.hasNext)
+ b += ((thisElem, those.next))
+ b.result
+ }
+
+ /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to
+ * `s zip s.indices`, but is usually more efficient.
+ */
+ def zipWithIndex: CC[(A, Int)] = {
+ val b = newBuilder[(A, Int)]
+ var i = 0
+ for (x <- this) {
+ b += ((x, i))
+ i +=1
+ }
+ b.result
+ }
+
+ /** Copy all elements to a given buffer
+ * @note Will not terminate for infinite-sized collections.
+ * @param dest The buffer to which elements are copied
+ */
+ def copyToBuffer[B >: A](dest: Buffer[B]) {
+ for (x <- this) dest += x
+ }
+
+ /** Fills the given array <code>xs</code> with at most `len` elements of
+ * this sequence starting at position `start`.
+ * Copying will stop oce either the end of the current iterable is reached or
+ * `len` elements have been copied.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @param len number of elements to copy
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
+ var i = start
+ val end = (start + len) min xs.length
+ for (x <- this) {
+ if (i < end) {
+ xs(i) = x
+ i += 1
+ }
+ }
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>
+ * until either the end of the current iterable or the end of array `xs` is reached.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int) {
+ copyToArray(xs, start, xs.length - start)
+ }
+
+ /** Converts this collection to a fresh Array elements.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def toArray[B >: A]: Array[B] = {
+ var size = 0
+ for (x <- this) size += 1
+ val result = new Array[B](size)
+ copyToArray(result, 0)
+ result
+ }
+
+ /**
+ * Create a fresh list with all the elements of this iterable object.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def toList: List[A] = (new ListBuffer[A] ++ thisCC).toList
+
+ /**
+ * Returns a sequence containing all of the elements in this iterable object.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def toSequence: Sequence[A] = toList.asInstanceOf[Sequence[A]] // !!!
+
+ /** @deprecated use toSequence instead
+ */
+ @deprecated def toSeq: Sequence[A] = toSequence
+
+ /**
+ * Create a stream which contains all the elements of this iterable object.
+ * @note consider using <code>projection</code> for lazy behavior.
+ */
+ def toStream: Stream[A] = elements.toStream
+
+ /** Sort the iterable according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>,
+ * which should be true iff <code>e1</code> is smaller than
+ * <code>e2</code>.
+ * The sort is stable. That is elements that are equal wrt `lt` appear in the
+ * same order in the sorted iterable as in the original.
+ *
+ * @param lt the comparison function
+ * @return a list sorted according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>.
+ * @ex <pre>
+ * List("Steve", "Tom", "John", "Bob")
+ * .sort((e1, e2) => (e1 compareTo e2) &lt; 0) =
+ * List("Bob", "John", "Steve", "Tom")</pre>
+ * !!!
+ def sortWith(lt : (A,A) => Boolean): CC[A] = {
+ val arr = toArray
+ Array.sortWith(arr, lt)
+ val b = newBuilder[A]
+ for (x <- arr) b += x
+ b.result
+ }
+ */
+
+ /** Returns a string representation of this iterable object. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ *
+ * @ex <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ * @note Will not terminate for infinite-sized collections.
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(start: String, sep: String, end: String): String =
+ addString(new StringBuilder(), start, sep, end).toString
+
+ /** Returns a string representation of this iterable object. The string
+ * representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param sep separator string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(sep: String): String =
+ addString(new StringBuilder(), sep).toString
+
+ /** Converts a collection into a flat <code>String</code> by each element's toString method.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def mkString =
+ addString(new StringBuilder()).toString
+
+ /** Write all elements of this iterable into given string builder.
+ * The written text begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ b append start
+ var first = true
+ for (x <- this) {
+ if (first) first = false
+ else b append sep
+ b append x
+ }
+ b append end
+ }
+
+ /** Write all elements of this string into given string builder.
+ * The string representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def addString(b: StringBuilder, sep: String): StringBuilder = {
+ var first = true
+ for (x <- this) {
+ if (first) first = false
+ else b append sep
+ b append x
+ }
+ b
+ }
+
+ /** Write all elements of this string into given string builder without using
+ * any separator between consecutive elements.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def addString(b: StringBuilder): StringBuilder = {
+ for (x <- this) {
+ b append x
+ }
+ b
+ }
+
+ /**
+ * returns a projection that can be used to call non-strict <code>filter</code>,
+ * <code>map</code>, and <code>flatMap</code> methods that build projections
+ * of the collection.
+ def projection : Iterable.Projection[A] = new Iterable.Projection[A] {
+ def elements = Iterable.this.elements
+ override def force = Iterable.this
+ }
+ */
+
+ override def toString = mkString(stringPrefix + "(", ", ", ")")
+
+ /** Defines the prefix of this object's <code>toString</code> representation.
+ */
+ def stringPrefix : String = {
+ var string = this.getClass.getName
+ val idx1 = string.lastIndexOf('.' : Int)
+ if (idx1 != -1) string = string.substring(idx1 + 1)
+ val idx2 = string.indexOf('$')
+ if (idx2 != -1) string = string.substring(0, idx2)
+ string
+ }
+
+
+ /** Creates a view of this iterable @see IterableView
+ */
+ def view: IterableView[CC, A] = new IterableView[CC, A] { // !!! Martin: We should maybe infer the type parameters here?
+ val origin = thisCC
+ val elements: Iterator[A] = self.elements
+ }
+
+// The following methods return non-deterministic results, unless this iterable is an OrderedIterable
+
+ /** The first element of this sequence.
+ *
+ * @note Might return different results for different runs, unless this iterable is ordered
+ * @throws Predef.NoSuchAentException if the sequence is empty.
+ */
+ def head: A = if (isEmpty) throw new NoSuchElementException else elements.next
+
+ /** @deprecated use head instead */
+ @deprecated def first: A = head
+
+ /** Returns as an option the first element of this iterable
+ * or <code>None</code> if iterable is empty.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def headOption: Option[A] = if (isEmpty) None else Some(head)
+
+ /** @deprecated use headOption instead
+ * <code>None</code> if list is empty.
+ */
+ @deprecated def firstOption: Option[A] = headOption
+
+ /** An iterable consisting of all elements of this iterable
+ * except the first one.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def tail: CC[A] = drop(1)
+
+ /** Return an iterable consisting only of the first <code>n</code>
+ * elements of this iterable, or else the whole iterable, if it has less
+ * than <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return a possibly projected sequence
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def take(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ breakable {
+ for (x <- this) {
+ b += x
+ i += 1
+ if (i == n) break
+ }
+ }
+ b.result
+ }
+
+ /** Returns this iterable without its <code>n</code> first elements
+ * If this iterable has less than <code>n</code> elements, the empty
+ * iterable is returned.
+ *
+ * @param n the number of elements to drop
+ * @return the new iterable
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def drop(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ for (x <- this) {
+ if (i >= n) b += x
+ i += 1
+ }
+ b.result
+ }
+
+ /** A sub-iterable starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @note c.slice(from, to) is equivalent to (but possibly more efficient than)
+ * c.drop(from).take(to - from)
+ *
+ * @param from The index of the first element of the returned subsequence
+ * @param until The index of the element following the returned subsequence
+ * @throws IndexOutOfBoundsException if <code>from &lt; 0</code>
+ * or <code>length &lt; from + len<code>
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def slice(from: Int, until: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ breakable {
+ for (x <- this) {
+ if (i >= from) b += x
+ i += 1
+ if (i == until) break
+ }
+ }
+ b.result
+ }
+
+ /** The last element of this iterable.
+ *
+ * @throws Predef.NoSuchElementException if the sequence is empty.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def last: A = {
+ var lst = head
+ for (x <- this)
+ lst = x
+ lst
+ }
+
+ /** Returns as an option the last element of this iterable or
+ * <code>None</code> if iterable is empty.
+ *
+ * @return the last element as an option.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def lastOption: Option[A] = if (isEmpty) None else Some(last)
+
+ /** An iterable consisting of all elements of this iterable except the last one.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def init: CC[A] = {
+ var lst = head
+ val b = newBuilder[A]
+ for (x <- this) {
+ b += lst
+ lst = x
+ }
+ b.result
+ }
+
+ /** Returns the rightmost <code>n</code> elements from this iterable.
+ *
+ * @param n the number of elements to take
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def takeRight(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ val lead = elements drop n
+ var go = false
+ for (x <- this) {
+ if (go) b += x
+ else if (lead.hasNext) lead.next
+ else go = true
+ }
+ b.result
+ }
+
+ /** Returns the iterable wihtout its rightmost <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def dropRight(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ val lead = elements drop n
+ breakable {
+ for (x <- this) {
+ if (!lead.hasNext) break
+ lead.next
+ b += x
+ }
+ }
+ b.result
+ }
+
+ /** Split the iterable at a given point and return the two parts thus
+ * created.
+ *
+ * @param n the position at which to split
+ * @return a pair of iterables composed of the first <code>n</code>
+ * elements, and the other elements.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def splitAt(n: Int): (CC[A], CC[A]) = {
+ val l, r = newBuilder[A]
+ var i = 0
+ for (x <- this)
+ (if (i < n) l else r) += x
+ (l.result, r.result)
+ }
+
+ /** Returns the longest prefix of this sequence whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this sequence whose elements satisfy
+ * the predicate <code>p</code>.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def takeWhile(p: A => Boolean): CC[A] = {
+ val b = newBuilder[A]
+ breakable {
+ for (x <- this) {
+ if (!p(x)) break
+ b += x
+ }
+ }
+ b.result
+ }
+
+ /** Returns the longest suffix of this sequence whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the sequence whose first element
+ * does not satisfy the predicate <code>p</code>.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def dropWhile(p: A => Boolean): CC[A] = {
+ val b = newBuilder[A]
+ var go = false
+ for (x <- this) {
+ if (go) b += x
+ else if (!p(x)) { go = true; b += x }
+ }
+ b.result
+ }
+
+ /** Returns a pair consisting of the longest prefix of the list whose
+ * elements all satisfy the given predicate, and the rest of the list.
+ *
+ * @param p the test predicate
+ * @return a pair consisting of the longest prefix of the list whose
+ * elements all satisfy <code>p</code>, and the rest of the list.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def span(p: A => Boolean): (CC[A], CC[A]) = {
+ val l, r = newBuilder[A]
+ var toLeft = true
+ for (x <- this) {
+ toLeft = toLeft && p(x)
+ (if (toLeft) l else r) += x
+ }
+ (l.result, r.result)
+ }
+
+ /** Checks if the other iterable object contains the same elements as this one.
+ *
+ * @note will not terminate for infinite-sized iterables.
+ * @param that the other iterable
+ * @return true, iff both iterables contain the same elements.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def sameElements[B >: A](that: OrderedIterable[B]): Boolean = {
+ val these = this.elements
+ val those = that.elements
+ while (these.hasNext && those.hasNext && these.next() == those.next()) {}
+ !these.hasNext && !those.hasNext
+ }
+
+ /** A sub-sequence view starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @param from The index of the first element of the slice
+ * @param until The index of the element following the slice
+ * @note The difference between `view` and `slice` is that `view` produces
+ * a view of the current sequence, whereas `slice` produces a new sequence.
+ *
+ * @note Might return different results for different runs, unless this iterable is ordered
+ * @note view(from, to) is equivalent to view.slice(from, to)
+ */
+ def view(from: Int, until: Int): IterableView[CC, A] = view.slice(from, until)
+}
diff --git a/src/library/scalax/collection/generic/IterableView.scala b/src/library/scalax/collection/generic/IterableView.scala
new file mode 100755
index 0000000000..b9b826b0a4
--- /dev/null
+++ b/src/library/scalax/collection/generic/IterableView.scala
@@ -0,0 +1,121 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+package scalax.collection.generic
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait IterableView[+UC[/*+*/B] <: Iterable[B], /*+*/A] extends Iterable[A] { self =>
+
+ val origin: Iterable[_]
+ def elements: Iterator[A]
+
+ val underlying: Iterable[_] = origin match {
+ case v: IterableView[t, _] => v.underlying
+ case _ => origin
+ }
+
+ private def isDelay = elements eq underlying.elements
+
+ private[this] var forced: UC[A] = _
+ private[this] var wasForced = false
+
+ def force: UC[A] = {
+ if (!wasForced) {
+ forced = {
+ val b = underlying.newBuilder[A]
+ for (x <- elements)
+ b += x
+ b.result
+ }.asInstanceOf[UC[A]]
+ wasForced = true
+ }
+ forced
+ }
+
+ def newBuilder[A] = underlying.newBuilder[A]
+
+ /** Builds a new view object. This method needs to be overridden in subclasses
+ * which refine in IterableView type
+ */
+ protected def newView[B](elems: Iterator[B]) = new IterableView[UC, B] {
+ val origin = if (self.isDelay) self.origin else self
+ val elements = elems
+ }
+
+ /** Non-strict variant of @see IterableLike.++ */
+ override def ++[B >: A](that: Iterator[B]): IterableView[UC, B] = newView(elements ++ that)
+
+ /** Non-strict variant of @see IterableLike.++ */
+ override def ++[B >: A](that: Iterable[B]): IterableView[UC, B] = newView(elements ++ that.elements)
+
+ /** Non-strict variant of @see IterableLike.map */
+ override def map[B](f: A => B): IterableView[UC, B] = newView(elements map f)
+
+ /** Non-strict variant of @see IterableLike.flatMap */
+ override def flatMap[B](f: A => Iterable[B]): IterableView[UC, B] = newView(elements flatMap (f(_).elements))
+
+ /** Non-strict variant of @see IterableLike.filter */
+ override def filter(p: A => Boolean): IterableView[UC, A] = newView(elements filter p)
+
+ /** Non-strict variant of @see IterableLike.partition */
+ override def partition(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = {
+ val (li, ri) = elements partition p
+ (newView(li), newView(ri))
+ }
+
+ /** Non-strict variant of @see IterableLike.zip */
+ override def zip[B](other: Iterable[B]): IterableView[UC, (A, B)] = newView(elements zip other.elements)
+
+ /** Non-strict variant of @see IterableLike.zipWithIndex */
+ override def zipWithIndex: IterableView[UC, (A, Int)] = newView(elements.zipWithIndex)
+
+ /* Non-strict variant of @see IterableLike.zipAll
+ * This is not enabled because it can't be specialized in VectorView:
+ * VectorView is not covariant, yet must maintain updatability. Impossible to do this
+ * with this type signature.
+ override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): IterableView[UC, (A1, B1)] =
+ newView(elements zipAll (that.elements, thisElem, thatElem))
+ */
+
+ /** Non-strict variant of @see Iterable.take */
+ override def take(n: Int): IterableView[UC, A] = newView(elements take n)
+
+ /** Non-strict variant of @see Iterable.drop */
+ override def drop(n: Int): IterableView[UC, A] = newView(elements drop n)
+
+ /** Non-strict variant of @see Iterable.splitAt */
+ override def splitAt(n: Int): (IterableView[UC, A], IterableView[UC, A]) = (take(n), drop(n))
+
+ /** Non-strict variant of @see Iterable.slice */
+ override def slice(from: Int, until: Int): IterableView[UC, A] = newView(elements slice (from, until))
+
+ /** Non-strict variant of @see Iterable.takeWhile */
+ override def takeWhile(p: A => Boolean): IterableView[UC, A] = newView(elements takeWhile p)
+
+ /** Non-strict variant of @see Iterable.dropWhile */
+ override def dropWhile(p: A => Boolean): IterableView[UC, A] = newView(elements dropWhile p)
+
+ /** Non-strict variant of @see Iterable.span */
+ override def span(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = (takeWhile(p), dropWhile(p))
+
+ /** The projection resulting from the concatenation of this projection with the <code>rest</code> projection.
+ * @param rest The projection that gets appended to this projection
+ * @deprecated Use ++ instead
+ */
+ @deprecated def append[B >: A](rest : => Iterable[B]): IterableView[UC, B] = this ++ rest.elements
+
+ override def stringPrefix = origin.stringPrefix+"V"
+
+
+}
diff --git a/src/library/scalax/collection/generic/OrderedIterableTemplate.scala b/src/library/scalax/collection/generic/OrderedIterableTemplate.scala
new file mode 100755
index 0000000000..fd2dbac8e4
--- /dev/null
+++ b/src/library/scalax/collection/generic/OrderedIterableTemplate.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic
+
+import OrderedIterable._
+
+/** Ordered iterables are iterables where the `elements` method always returns elements in the same
+ * order (namely the order in which elements were appended to the iterable). In particular, one has
+ * for every two ordered iterables `xs` and `ys`:
+ *
+ * `(xs ++ ys).elements = xs.elements ++ ys.elements
+ */
+trait OrderedIterableTemplate[+CC[/*+*/B] <: OrderedIterableTemplate[CC, B] with OrderedIterable[B], /*+*/A]
+ extends IterableTemplate[CC, A]
diff --git a/src/library/scalax/collection/generic/SequenceFactory.scala b/src/library/scalax/collection/generic/SequenceFactory.scala
new file mode 100755
index 0000000000..ee97c80c75
--- /dev/null
+++ b/src/library/scalax/collection/generic/SequenceFactory.scala
@@ -0,0 +1,11 @@
+package scalax.collection.generic
+
+trait SequenceFactory[CC[A] <: Sequence[A]] extends IterableFactory[CC] {
+
+ /** This method is called in a pattern match { case Sequence(...) => }.
+ *
+ * @param x the selector value
+ * @return sequence wrapped in an option, if this is a Sequence, otherwise none
+ */
+ def unapplySequence[A](x: CC[A]): Some[CC[A]] = Some(x)
+}
diff --git a/src/library/scalax/collection/generic/SequenceForwarder.scala b/src/library/scalax/collection/generic/SequenceForwarder.scala
new file mode 100644
index 0000000000..208d0079f1
--- /dev/null
+++ b/src/library/scalax/collection/generic/SequenceForwarder.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: SeqProxy.scala 15458 2008-06-28 20:23:22Z stepancheg $
+
+
+package scalax.collection.generic
+
+/** This class implements a forwarder for sequences. It forwards
+ * all calls to a different sequence object except for
+ *
+ * - toString, hashCode, equals, stringPrefix
+ * - newBuilder, view, toSequence
+ * - all calls creating a new iterable objetc of the same kind
+ *
+ * The above methods are forwarded by subclass SequenceProxy
+ *
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait SequenceForwarder[+A] extends Sequence[A] with IterableForwarder[A] {
+
+ protected override def underlying: Sequence[A]
+
+ // PartialFunction delegates
+
+ override def apply(i: Int): A = underlying.apply(i)
+ override def isDefinedAt(x: Int): Boolean = underlying.isDefinedAt(x)
+
+ // Sequence delegates
+ // Sequence methods could be printed by cat SequenceTemplate.scala | sed -n '/trait Seq/,$ p' | egrep '^ (override )?def'
+
+ override def length: Int = underlying.length
+ override def lengthCompare(l: Int) = underlying lengthCompare l
+ override def segmentLength(p: A => Boolean, from: Int): Int = underlying.segmentLength(p, from)
+ override def prefixLength(p: A => Boolean) = underlying.prefixLength(p)
+ override def indexWhere(p: A => Boolean, from: Int): Int = underlying.indexWhere(p, from)
+ override def indexOf[B >: A](elem: B, from: Int): Int = underlying.indexOf(elem, from)
+ override def reversedElements: Iterator[A] = underlying.reversedElements
+ override def startsWith[B](that: Sequence[B], offset: Int): Boolean = underlying.startsWith(that, offset)
+ override def endsWith[B](that: Sequence[B]): Boolean = underlying.endsWith(that)
+ override def indexOf[B >: A](that: Sequence[B]): Int = underlying.indexOf(that)
+ override def contains(elem: Any): Boolean = underlying.contains(elem)
+ override def indices: Range = underlying.indices
+}
diff --git a/src/library/scalax/collection/generic/SequenceTemplate.scala b/src/library/scalax/collection/generic/SequenceTemplate.scala
new file mode 100755
index 0000000000..eba0e4bf98
--- /dev/null
+++ b/src/library/scalax/collection/generic/SequenceTemplate.scala
@@ -0,0 +1,382 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic
+
+import util.control.Break._
+import scalax.collection.immutable.{List, Nil, ::}
+
+import Sequence._
+
+trait SequenceTemplate[+CC[/*+*/B] <: SequenceTemplate[CC, B] with Sequence[B], /*+*/A] extends PartialFunction[Int, A] with OrderedIterableTemplate[CC, A] {
+self /*: CC[A]*/ =>
+
+ /** Returns the length of the sequence.
+ *
+ * @return the sequence length.
+ */
+ def length: Int
+
+ /** Result of comparing <code>length</code> with operand <code>len</code>.
+ * returns <code>x</code> where
+ * <code>x &lt; 0</code> iff <code>this.length &lt; len</code>
+ * <code>x == 0</code> iff <code>this.length == len</code>
+ * <code>x &gt; 0</code> iff <code>this.length &gt; len</code>.
+ *
+ * The method as implemented here does not call length directly; its running time
+ * is O(length min len) instead of O(length). The method should be overwritten
+ * if computing length is cheap.
+ */
+ def lengthCompare(len: Int): Int = {
+ var i = 0
+ breakable {
+ for (_ <- this) {
+ i += 1
+ if (i > len) break
+ }
+ }
+ i - len
+ }
+
+ /** Should always be <code>length</code> */
+ def size = length
+
+ /** Is this partial function defined for the index <code>x</code>?
+ */
+ def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length)
+
+ /** Returns index of the first element satisying a predicate, or -1, if none exists.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def indexWhere(p: A => Boolean): Int = indexWhere(p, 0)
+
+ /** Returns length of longest segment starting from a start index `from`
+ * such that every element of the segment satisfies predicate `p`.
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @param from the start index
+ */
+ def segmentLength(p: A => Boolean, from: Int): Int = {
+ var result = 0
+ var i = from
+ breakable {
+ for (x <- this) {
+ if (i >= from && !p(x)) { result = i - from; break }
+ else i += 1
+ }
+ }
+ result
+ }
+
+ /** Returns length of longest prefix of this seqence
+ * such that every element of the prefix satisfies predicate `p`.
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def prefixLength(p: A => Boolean) = segmentLength(p, 0)
+
+ /** Returns index of the first element starting from a start index
+ * satisying a predicate, or -1, if none exists.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @param from the start index
+ */
+ def indexWhere(p: A => Boolean, from: Int): Int = {
+ var result = -1
+ var i = from
+ breakable {
+ for (x <- this) {
+ if (i >= from && p(x)) { result = i; break }
+ else i += 1
+ }
+ }
+ result
+ }
+
+ /** Returns index of the first element satisying a predicate, or -1.
+ *
+ * @deprecated Use `indexWhere` instead
+ */
+ @deprecated def findIndexOf(p: A => Boolean): Int = indexWhere(p)
+
+ /** Returns the index of the first occurence of the specified
+ * object in this iterable object.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param elem element to search for.
+ * @return the index in this sequence of the first occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def indexOf[B >: A](elem: B): Int = indexOf(elem, 0)
+
+ /** Returns the index of the first occurence of the specified
+ * object in this iterable object, starting from a start index, or
+ * -1, if none exists.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param elem element to search for.
+ */
+ def indexOf[B >: A](elem: B, from: Int): Int = indexWhere(elem ==, from)
+
+ /** Returns the index of the last occurence of the specified element
+ * in this sequence, or -1 if the sequence does not contain this element.
+ *
+ * @param elem element to search for.
+ * @return the index in this sequence of the last occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def lastIndexOf[B >: A](elem: B): Int = lastIndexOf(elem, length - 1)
+
+ /** Returns the index of the last
+ * occurence of the specified element in this sequence
+ * before or at a given end index,
+ * or -1 if the sequence does not contain this element.
+ *
+ * @param elem element to search for.
+ * @param end the end index
+ */
+ def lastIndexOf[B >: A](elem: B, end: Int): Int = {
+ var i = end
+ val it = reversedElements
+ while (it.hasNext && it.next != elem) i -= 1
+ i
+ }
+
+ /** Returns index of the last element satisying a predicate, or -1, if none exists.
+ *
+ * @param p the predicate
+ * @return the index of the last element satisfying <code>p</code>,
+ * or -1 if such an element does not exist
+ */
+ def lastIndexWhere(p: A => Boolean): Int = lastIndexWhere(p, length - 1)
+
+ /** Returns index of the last element not exceeding a given end index
+ * and satisying a predicate, or -1 if none exists.
+ *
+ * @param end the end index
+ * @param p the predicate
+ */
+ def lastIndexWhere(p: A => Boolean, end: Int): Int = {
+ var i = end
+ val it = reversedElements
+ while (it.hasNext && (i > end || !p(it.next))) i -= 1
+ i
+ }
+
+ /** A sequence of type <code>C</code> consisting of all elements of
+ * this sequence in reverse order.
+ * @note the operation is implemented by building a new sequence
+ * from <code>this(length - 1), ..., this(0)</code>
+ * If random access is inefficient for the given sequence implementation,
+ * this operation should be overridden.
+ */
+ def reverse: CC[A] = {
+ var xs: List[A] = List()
+ for (x <- this)
+ xs = x :: xs
+ val b = newBuilder[A]
+ for (x <- xs)
+ b += x
+ b.result
+ }
+
+ /** The elements of this sequence in reversed order
+ */
+ def reversedElements: Iterator[A] = reverse.elements
+
+ /**
+ * Checks whether the argument sequence is contained at the
+ * specified index within the receiver object.
+ *
+ * If the both the receiver object, <code>this</code> and
+ * the argument, <code>that</code> are infinite sequences
+ * this method may not terminate.
+ *
+ * @return true if <code>that</code> is contained in
+ * <code>this</code>, at the specified index, otherwise false
+ *
+ * @see String.startsWith
+ */
+ def startsWith[B](that: Sequence[B], offset: Int): Boolean = {
+ val i = elements.drop(offset)
+ val j = that.elements
+ while (j.hasNext && i.hasNext && i.next == j.next) {}
+ !j.hasNext
+ }
+
+ /**
+ * Check whether the receiver object starts with the argument sequence.
+ *
+ * @return true if <code>that</code> is a prefix of <code>this</code>,
+ * otherwise false
+ *
+ * @see Sequence.startsWith
+ */
+ def startsWith[B](that: Sequence[B]): Boolean = startsWith(that, 0)
+
+ /** @return true if this sequence end with that sequence
+ * @see String.endsWith
+ */
+ def endsWith[B](that: Sequence[B]): Boolean = {
+ val i = this.elements.drop(length - that.length)
+ val j = that.elements
+ while (i.hasNext && j.hasNext && i.next == j.next) ()
+ !j.hasNext
+ }
+
+ /** @return -1 if <code>that</code> not contained in this, otherwise the
+ * index where <code>that</code> is contained
+ * @see String.indexOf
+ */
+ def indexOf[B >: A](that: Sequence[B]): Int = {
+ var i = 0
+ var s: Sequence[A] = thisCC
+ while (!s.isEmpty && !(s startsWith that)) {
+ i += 1
+ s = s drop 1
+ }
+ if (!s.isEmpty || that.isEmpty) i else -1
+ }
+
+ /** Tests if the given value <code>elem</code> is a member of this
+ * sequence.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return <code>true</code> iff there is an element of this sequence
+ * which is equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): Boolean = exists (_ == elem)
+
+ /** Computes the union of this sequence and the given sequence
+ * <code>that</code>.
+ *
+ * @param that the sequence of elements to add to the sequence.
+ * @return an sequence containing the elements of this
+ * sequence and those of the given sequence <code>that</code>
+ * which are not contained in this sequence.
+ */
+ def union[B >: A](that: Sequence[B]): CC[B] = this ++ (that diff thisCC)
+
+ /** Computes the difference between this sequence and the given sequence
+ * <code>that</code>.
+ *
+ * @param that the sequence of elements to remove from this sequence.
+ * @return this sequence without the elements of the given sequence
+ * <code>that</code>.
+ */
+ def diff[B >: A](that: Sequence[B]): CC[A] = this remove (that contains _)
+
+ /** Computes the intersection between this sequence and the given sequence
+ * <code>that</code>.
+ *
+ * @param that the sequence to intersect.
+ * @return the sequence of elements contained both in this sequence and
+ * in the given sequence <code>that</code>.
+ */
+ def intersect[B >: A](that: Sequence[B]): CC[A] = this filter(that contains _)
+
+ /** Builds a new sequence from this sequence in which any duplicates (wrt to ==) removed.
+ * Among duplicate elements, only the first one is retained in the result sequence
+ */
+ def removeDuplicates: CC[A] = {
+ val b = newBuilder[A]
+ var seen = Set[A]()
+ for (x <- this) {
+ if (!(seen contains x)) {
+ b += x
+ seen += x
+ }
+ }
+ b.result
+ }
+
+ /** Returns a sequence of given length containing the elements of this sequence followed by zero
+ * or more occurrences of given elements. If this sequence is already at least as long as given
+ * length, it is returned directly. Otherwise, a new sequence is created consisting of the elements
+ * of this sequence followed by enough occurrences of the given elements to reach the given length.
+ */
+ def padTo[B >: A](len: Int, elem: B): CC[B] = {
+ var diff = len - length
+ val b = newBuilder[B] //!!! drop [B] and get surprising results!
+ b ++= thisCC
+ while (diff > 0) {
+ b += elem
+ diff -=1
+ }
+ b.result
+ }
+
+ /**
+ * Overridden for efficiency.
+ *
+ * @return the sequence itself
+ */
+ override def toSequence: Sequence[A] = this.asInstanceOf[Null] // !!!
+
+ def indices: Range = 0 until length
+
+ /** Creates a view of this iterable @see OrderedIterable.View
+ */
+ override def view: SequenceView[CC, A] = new SequenceView[CC, A] { // !!! Martin: We should maybe infer the type parameters here?
+ val origin: Sequence[_] = thisCC
+ val elements: Iterator[A] = self.elements
+ val length: Int = self.length
+ def apply(idx: Int): A = self.apply(idx)
+ }
+
+ /** A sub-sequence view starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @param from The index of the first element of the slice
+ * @param until The index of the element following the slice
+ * @note The difference between `view` and `slice` is that `view` produces
+ * a view of the current sequence, whereas `slice` produces a new sequence.
+ *
+ * @note view(from, to) is equivalent to view.slice(from, to)
+ */
+ override def view(from: Int, until: Int): SequenceView[CC, A] = view.slice(from, until)
+
+ /** Returns index of the last element satisying a predicate, or -1.
+ * @deprecated use `lastIndexWhere` instead
+ */
+ @deprecated def findLastIndexOf(p: A => Boolean): Int = lastIndexWhere(p)
+
+ /** A sub-sequence starting at index <code>from</code>
+ * and extending up to the length of the current sequence
+ *
+ * @param from The index of the first element of the slice
+ * @throws IndexOutOfBoundsException if <code>from &lt; 0</code>
+ * @deprecated use <code>drop</code> instead
+ */
+ @deprecated def slice(from: Int): Sequence[A] = slice(from, length)
+
+ /** @deprecated Should be replaced by
+ *
+ * <code>(s1, s2) forall { case (x, y) => f(x, y) }</code>
+ */
+ @deprecated def equalsWith[B](that: Sequence[B])(f: (A,B) => Boolean): Boolean = {
+ val i = this.elements
+ val j = that.elements
+ while (i.hasNext && j.hasNext && f(i.next, j.next)) ()
+ !i.hasNext && !j.hasNext
+ }
+
+ /** Is <code>that</code> a slice in this?
+ * @deprecated Should be repaced by <code>indexOf(that) != -1</code>
+ */
+ @deprecated def containsSlice[B](that: Sequence[B]): Boolean = indexOf(that) != -1
+
+}
diff --git a/src/library/scalax/collection/generic/SequenceView.scala b/src/library/scalax/collection/generic/SequenceView.scala
new file mode 100755
index 0000000000..6178542241
--- /dev/null
+++ b/src/library/scalax/collection/generic/SequenceView.scala
@@ -0,0 +1,129 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic
+
+import util.control.Break._
+import annotation.unchecked.uncheckedVariance
+
+import Sequence._
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait SequenceView[+UC[/*+*/B] <: Sequence[B], /*+*/A] extends IterableView[UC, A] with Sequence[A] {
+self =>
+
+ /** refined from Iterable.View */
+ val origin: Sequence[_]
+
+ trait Transformed[/*+*/B] extends SequenceView[UC, B] {
+ val origin = self
+ protected def asCC = asInstanceOf[SequenceView[UC, B]]
+ }
+
+ class Appended[/*+*/B >: A](that: Sequence[B]) extends Transformed[B] {
+ override def elements: Iterator[B] = self.elements ++ that.elements
+ override def length: Int = self.length + that.length
+ override def apply(idx: Int): B = {
+ val ll = self.length
+ if (idx < ll) self.apply(idx) else that.apply(idx - ll)
+ }
+ override def stringPrefix = self.stringPrefix + "A"
+ }
+
+ class Sliced(from: Int, to: Int) extends Transformed[A] {
+ override def elements: Iterator[A] = self.elements slice (from, to)
+ override lazy val length: Int = ((to min self.length) - (from max 0) min 0)
+ override def apply(idx: Int): A =
+ if (idx >= 0 && idx < length) self.apply(idx + from)
+ else throw new IndexOutOfBoundsException(idx.toString)
+ override def stringPrefix = self.stringPrefix + "S"
+ override def slice(from1: Int, to1: Int) =
+ new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0)).asInstanceOf[SequenceView[UC, A]]
+ }
+
+ class Mapped[/*+*/B](f: A => B) extends Transformed[B] {
+ override def elements: Iterator[B] = self.elements map f
+ override def length: Int = self.length
+ override def apply(idx: Int): B = f(self.apply(idx))
+ override def stringPrefix = self.stringPrefix + "M"
+ }
+
+ class Reversed extends Transformed[A] {
+ override def elements: Iterator[A] = self.reversedElements
+ override def length: Int = self.length
+ override def apply(idx: Int): A = self.apply(length - 1 - idx)
+ override def stringPrefix = super.stringPrefix+"R"
+ }
+
+ class Patched[/*+*/B >: A](from: Int, patch: Sequence[B], replaced: Int) extends Transformed[B] {
+ val plen = patch.length
+ override def elements: Iterator[B] = self.elements patch (from, patch.asInstanceOf[Null], replaced) // !!!
+ override def length: Int = self.length + plen - replaced
+ override def apply(idx: Int): B =
+ if (idx < from) self.apply(idx)
+ else if (idx < from + plen) patch.apply(idx - from)
+ else self.apply(idx - plen + replaced)
+ override def stringPrefix = super.stringPrefix+"P"
+ }
+
+ class Zipped[/*+*/B](that: Sequence[B]) extends Transformed[(A, B)] {
+ override def elements: Iterator[(A, B)] = self.elements zip that.elements
+ override def length = self.length min that.length
+ override def apply(idx: Int): (A, B) = (self.apply(idx), that.apply(idx))
+ override def stringPrefix = super.stringPrefix+"Z"
+ }
+
+ override def ++[B >: A](that: Iterable[B]): SequenceView[UC, B] =
+ new Appended[B](that.toSequence).asCC
+ override def ++[B >: A](that: Iterator[B]): SequenceView[UC, B] =
+ new Appended[B](that.toSequence).asCC
+ override def map[B](f: A => B): SequenceView[UC, B] =
+ new Mapped(f).asCC
+ override def reverse: SequenceView[UC, A] =
+ (new Reversed).asCC
+ def patch[B >: A](from: Int, patch: Sequence[B], replaced: Int): SequenceView[UC, B] =
+ if (0 <= from && from < length) new Patched(from, patch, replaced).asCC
+ else throw new IndexOutOfBoundsException(from.toString)
+ override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] =
+ patch(length, fill((len - length) max 0, elem), 0)
+ override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] =
+ new Zipped(that.toSequence).asCC
+ override def zipWithIndex: SequenceView[UC, (A, Int)] =
+ zip((0 until length).asInstanceOf[Null]) // !!!
+ /*
+ override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): SequenceView[UC, (A1, B1)] = {
+ val that1 = that.toSequence
+ self.padTo(that1.length, thisElem) zip that1.padTo(this.length, thatElem)//.asInstanceOf[SequenceView[UC, (A1, B1)]]
+ }*/
+ override def take(n: Int): SequenceView[UC, A] =
+ slice(0, n)
+ override def drop(n: Int): SequenceView[UC, A] =
+ slice(n, Math.MAX_INT)
+ override def splitAt(n: Int): (SequenceView[UC, A], SequenceView[UC, A]) = (take(n), drop(n))
+ override def slice(from: Int, until: Int): SequenceView[UC, A] =
+ new Sliced(from, until).asCC
+ override def takeWhile(p: A => Boolean): SequenceView[UC, A] =
+ take(prefixLength(p))
+ override def dropWhile(p: A => Boolean): SequenceView[UC, A] =
+ drop(prefixLength(p))
+ override def span(p: A => Boolean): (SequenceView[UC, A], SequenceView[UC, A]) = {
+ val n = prefixLength(p)
+ (take(n), drop(n))
+ }
+
+ // missing here because we can't do anything about them, so we fall back to default construction
+ // if an IterableView via newView: flatMap, filter, partition
+}
+
diff --git a/src/library/scalax/collection/generic/VectorTemplate.scala b/src/library/scalax/collection/generic/VectorTemplate.scala
new file mode 100644
index 0000000000..bc18ac45c2
--- /dev/null
+++ b/src/library/scalax/collection/generic/VectorTemplate.scala
@@ -0,0 +1,264 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $
+
+package scalax.collection.generic
+
+import Vector._
+
+/** Sequences that support O(1) element access and O(1) length computation.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait VectorTemplate[+CC[/*+*/B] <: VectorTemplate[CC, B] with Vector[B], /*+*/A] extends SequenceTemplate[CC, A] {
+self =>
+
+ // Overridden methods from IterableTemplate
+
+ /** The iterator returned by the elements method
+ */
+ protected class Elements(start: Int, end: Int) extends scalax.collection.BufferedIterator[A] {
+ var i = start
+ def hasNext: Boolean = i < end
+ def next: A =
+ if (i < end) {
+ val x = self(i)
+ i += 1
+ x
+ } else Iterator.empty.next
+ def head =
+ self(i)
+ /** drop is overridden to enable fast searching in the middle of random access sequences */
+ override def drop(n: Int): Iterator[A] =
+ if (n > 0) new Elements(start + n, end) else this
+ /** is overridden to be symmetric to drop */
+ override def take(n: Int): Iterator[A] =
+ if (n < 0) Iterator.empty.buffered
+ else if (start + n < end) new Elements(start, start + n)
+ else this
+ }
+
+ override def elements: Iterator[A] = new Elements(0, length)
+
+ override def isEmpty: Boolean = { length == 0 }
+
+ override def foreach(f: A => Unit): Unit = {
+ var i = 0
+ val len = length
+ while (i < len) { f(this(i)); i += 1 }
+ }
+
+ override def forall(p: A => Boolean): Boolean = prefixLength(p(_)) == length
+ override def exists(p: A => Boolean): Boolean = prefixLength(!p(_)) != length
+
+ override def find(p: A => Boolean): Option[A] = {
+ val i = prefixLength(!p(_))
+ if (i < length) Some(this(i)) else None
+ }
+
+ private def foldl[B](start: Int, z: B, op: (B, A) => B): B = {
+ var i = start
+ val len = length
+ var result = z
+ while (i < len) {
+ result = op(result, this(i))
+ i += 1
+ }
+ result
+ }
+
+ private def foldr[B](start: Int, len: Int, z: B, op: (A, B) => B): B =
+ if (start == len) z
+ else op(this(start), foldr(start + 1, len, z, op))
+
+ override def foldLeft[B](z: B)(op: (B, A) => B): B = foldl(0, z, op)
+ override def foldRight[B](z: B)(op: (A, B) => B): B = foldr(0, length, z, op)
+ override def reduceLeft[B >: A](op: (B, A) => B): B =
+ if (length > 0) foldl(0, this(0), op) else super.reduceLeft(op)
+ override def reduceRight[B >: A](op: (A, B) => B): B =
+ if (length > 0) foldr(0, length - 1, this(length - 1), op) else super.reduceRight(op)
+
+ override def zip[B](that: Iterable[B]): CC[(A, B)] = that match {
+ case that: Vector[_] =>
+ var i = 0
+ val len = this.length min that.length
+ val b = this.newBuilder[(A, B)]
+ while (i < len) {
+ b += ((this(i), that(i).asInstanceOf[B]))
+ i += 1
+ }
+ b.result
+ case _ =>
+ super.zip(that)
+ }
+
+ override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = that match {
+ case that: Vector[_] =>
+ var i = 0
+ val len = this.length min that.length
+ val b = this.newBuilder[(A1, B1)]
+ while (i < len) {
+ b += ((this(i), that(i).asInstanceOf[B]))
+ i += 1
+ }
+ while (i < this.length) {
+ b += ((this(i), thatElem))
+ i += 1
+ }
+ while (i < that.length) {
+ b += ((this(i), thatElem.asInstanceOf[B]))
+ i += 1
+ }
+ b.result
+ case _ =>
+ super.zipAll(that, thisElem, thatElem)
+ }
+
+ override def zipWithIndex: CC[(A, Int)] = {
+ val b = newBuilder[(A, Int)]
+ var i = 0
+ val len = length
+ while (i < len) {
+ b += ((this(i), i))
+ i += 1
+ }
+ b.result
+ }
+
+ override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
+ var i = 0
+ var j = start
+ val end = length min len min (xs.length - start)
+ while (i < end) {
+ xs(j) = this(i)
+ i += 1
+ j += 1
+ }
+ }
+
+ // Overridden methods from OrderedIterableTemplate
+
+ override def head: A = if (isEmpty) throw new NoSuchElementException else this(0)
+
+ override def slice(from: Int, until: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = from max 0
+ val end = until min length
+ while (i < end) {
+ b += this(i)
+ i += 1
+ }
+ b.result
+ }
+
+ override def take(n: Int): CC[A] = slice(0, n)
+ override def drop(n: Int): CC[A] = slice(n, length)
+ override def takeRight(n: Int): CC[A] = slice(length - n, length)
+ override def dropRight(n: Int): CC[A] = slice(0, length - n)
+ override def splitAt(n: Int): (CC[A], CC[A]) = (take(n), drop(n))
+ override def takeWhile(p: A => Boolean): CC[A] = take(prefixLength(p))
+ override def dropWhile(p: A => Boolean): CC[A] = drop(prefixLength(p))
+ override def span(p: A => Boolean): (CC[A], CC[A]) = splitAt(prefixLength(p))
+ override def last: A = if (length > 0) this(length - 1) else super.last
+ override def init: CC[A] = if (length > 0) slice(0, length - 1) else super.init
+
+ override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = that match {
+ case that: Vector[_] =>
+ val len = length
+ len == that.length && {
+ var i = 0
+ while (i < len && this(i) == that(i)) i += 1
+ i == len
+ }
+ case _ =>
+ super.sameElements(that)
+ }
+
+ // Overridden methods from Sequence
+
+ override def lengthCompare(len: Int): Int = length - len
+
+ private def negLength(n: Int) = if (n == length) -1 else n
+
+ override def indexWhere(p: A => Boolean, from: Int): Int =
+ negLength(from + segmentLength(!p(_), from))
+
+ override def lastIndexWhere(p: A => Boolean, end: Int): Int = {
+ var i = end
+ while (i >= 0 && !p(this(i))) i -= 1
+ i
+ }
+
+ override def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end)
+
+ override def reverse: CC[A] = {
+ val b = newBuilder[A]
+ var i = length
+ while (0 < i) {
+ i -= 1
+ b += this(i)
+ }
+ b.result
+ }
+
+ override def reversedElements: Iterator[A] = new Iterator[A] {
+ var i = length
+ def hasNext: Boolean = 0 < i
+ def next: A =
+ if (0 < i) {
+ i -= 1
+ self(i)
+ } else Iterator.empty.next
+ }
+
+ override def startsWith[B](that: Sequence[B], offset: Int): Boolean = that match {
+ case that: Vector[_] =>
+ var i = offset
+ var j = 0
+ val thisLen = length
+ val thatLen = that.length
+ while (i < thisLen && j < thatLen && this(i) == that(j)) {
+ i += 1
+ j += 1
+ }
+ j == thatLen
+ case _ =>
+ var i = offset
+ val thisLen = length
+ val thatElems = that.elements
+ while (i < thisLen && thatElems.hasNext && this(i) == thatElems.next) {
+ i += 1
+ }
+ !thatElems.hasNext
+ }
+
+ override def endsWith[B](that: Sequence[B]): Boolean = that match {
+ case that: Vector[_] =>
+ val thisLen = length
+ val thatLen = that.length
+ var i = thisLen - 1
+ var j = thatLen - 1
+ while (i >= 0 && j >= 0 && this(i) == that(j)) {
+ i -= 1
+ j -= 1
+ }
+ j == 0
+ case _ =>
+ super.endsWith(that)
+ }
+
+ override def indexOf[B >: A](that: Sequence[B]): Int = {
+ var i = 0
+ val last = length - that.length
+ while (i <= last && !startsWith(that, i)) i += 1
+ negLength(i)
+ }
+}
+
diff --git a/src/library/scalax/collection/generic/covariant/IterableFactory.scala b/src/library/scalax/collection/generic/covariant/IterableFactory.scala
new file mode 100755
index 0000000000..67445f54d9
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/IterableFactory.scala
@@ -0,0 +1,14 @@
+package scalax.collection.generic.covariant
+
+trait IterableFactory[CC[+A] <: Iterable[A]] extends generic.IterableFactory[CC] {
+
+ /** The empty collection of type CC */
+ val empty: CC[Nothing]
+
+ override protected def newBuilder[A]: Builder[CC, A] =
+ empty.newBuilder[A].asInstanceOf[Builder[CC, A]]
+
+ /** Create CC collection of specified elements */
+ override def apply[A](args: A*): CC[A] =
+ (empty ++ args.asInstanceOf[Iterable[A]]).asInstanceOf[CC[A]] // !!!
+}
diff --git a/src/library/scalax/collection/generic/covariant/IterableTemplate.scala b/src/library/scalax/collection/generic/covariant/IterableTemplate.scala
new file mode 100755
index 0000000000..41155a5ad5
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/IterableTemplate.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic.covariant
+
+import annotation.unchecked.uncheckedVariance
+
+/** Collection classes mixing in this class provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>.
+ * Only potentially unbounded collections should directly sub-class <code>Iterable</code>.
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+trait IterableTemplate[+CC[+B] <: IterableTemplate[CC, B] with Iterable[B], +A]
+ extends generic.IterableTemplate[CC, A @uncheckedVariance] { self /*: CC[A]*/ => }
+
+// !!! todo: explain why @uncheckedVariance is justified here.
+
diff --git a/src/library/scalax/collection/generic/covariant/IterableView.scala b/src/library/scalax/collection/generic/covariant/IterableView.scala
new file mode 100755
index 0000000000..7ccad07405
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/IterableView.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+package scalax.collection.generic.covariant
+
+import annotation.unchecked.uncheckedVariance
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait IterableView[+UC[+B] <: Iterable[B], +A]
+ extends generic.IterableView[UC, A @uncheckedVariance]
diff --git a/src/library/scalax/collection/generic/covariant/OrderedIterableTemplate.scala b/src/library/scalax/collection/generic/covariant/OrderedIterableTemplate.scala
new file mode 100755
index 0000000000..449bac9cfc
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/OrderedIterableTemplate.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic.covariant
+
+import annotation.unchecked.uncheckedVariance
+
+trait OrderedIterableTemplate[+CC[+B] <: OrderedIterableTemplate[CC, B] with OrderedIterable[B], +A]
+ extends generic.OrderedIterableTemplate[CC, A @uncheckedVariance] {self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/generic/covariant/SequenceFactory.scala b/src/library/scalax/collection/generic/covariant/SequenceFactory.scala
new file mode 100755
index 0000000000..49a6e685fa
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/SequenceFactory.scala
@@ -0,0 +1,3 @@
+package scalax.collection.generic.covariant
+
+trait SequenceFactory[CC[+A] <: Sequence[A]] extends IterableFactory[CC] with generic.SequenceFactory[CC]
diff --git a/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala b/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala
new file mode 100755
index 0000000000..958e73cd47
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.covariant
+
+import annotation.unchecked.uncheckedVariance
+
+trait SequenceTemplate[+CC[+B] <: SequenceTemplate[CC, B] with Sequence[B], +A]
+ extends generic.SequenceTemplate[CC, A @uncheckedVariance] {self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/generic/covariant/SequenceView.scala b/src/library/scalax/collection/generic/covariant/SequenceView.scala
new file mode 100755
index 0000000000..cfcf9d4a25
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/SequenceView.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.covariant
+
+import annotation.unchecked.uncheckedVariance
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait SequenceView[+UC[+B] <: Sequence[B], +A]
+ extends IterableView[UC, A] with generic.SequenceView[UC, A @uncheckedVariance]
diff --git a/src/library/scalax/collection/generic/covariant/VectorTemplate.scala b/src/library/scalax/collection/generic/covariant/VectorTemplate.scala
new file mode 100644
index 0000000000..1f75c68e82
--- /dev/null
+++ b/src/library/scalax/collection/generic/covariant/VectorTemplate.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.covariant
+
+import annotation.unchecked.uncheckedVariance
+
+trait VectorTemplate[+CC[+B] <: VectorTemplate[CC, B] with Vector[B], +A]
+ extends generic.VectorTemplate[CC, A @uncheckedVariance] {self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/generic/covartest/IterableFactory.scala b/src/library/scalax/collection/generic/covartest/IterableFactory.scala
new file mode 100755
index 0000000000..d12da89987
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/IterableFactory.scala
@@ -0,0 +1,108 @@
+package scalax.collection.generic.covartest
+
+trait IterableFactory[CC[A] <: Iterable[A]] {
+
+ /** Create CC collection of specified elements */
+ def apply[A](args: A*): CC[A]
+
+ protected def newBuilder[A]: Builder[CC, A] =
+ apply().newBuilder[A].asInstanceOf[Builder[CC, A]]
+
+ /** Concatenate all the argument lists into a single list.
+ *
+ * @param xss the lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def concat[A](xss: CC[A]*): CC[A] = {
+ val b = newBuilder[A]
+ for (xs <- xss) b ++= xs
+ b.result
+ }
+
+ /** An iterable that contains the same element a number of times
+ * @param n The number of elements returned
+ * @param elem The element returned each time
+ */
+ def fill[A](n: Int, elem: => A): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ while (i < n) {
+ b += elem
+ i += 1
+ }
+ b.result
+ }
+
+ def fill[A](n1: Int, n2: Int, elem: => A): CC[CC[A]] =
+ tabulate(n1)(_ => fill(n2, elem))
+
+ def fill[A](n1: Int, n2: Int, n3: Int, elem: => A): CC[CC[CC[A]]] =
+ tabulate(n1)(_ => fill(n2, n3, elem))
+
+ def tabulate[A](n: Int)(f: Int => A): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ while (i < n) {
+ b += f(i)
+ i += 1
+ }
+ b.result
+ }
+
+ def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] =
+ tabulate(n1)(i1 => tabulate(n2)(i2 => f(i1, i2)))
+
+ def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] =
+ tabulate(n1)(i1 => tabulate(n2)(i2 => tabulate(n3)(i3 => f(i1, i2, i3))))
+// todo: go up to 5(?)
+
+ /** Create a sequence of increasing integers in a range.
+ *
+ * @param from the start value of the sequence
+ * @param end the end value of the sequence
+ * @return the sorted list of all from `from` (inclusive)
+ * up to, but exclusding, `end`.
+ */
+ def range[A](start: Int, end: Int): CC[Int] = range(start, end, 1)
+
+ /** Create a sequence of increasing integers in a range.
+ *
+ * @param from the start value of the sequence
+ * @param end the end value of the sequence
+ * @param step the increment value of successive elements
+ * @return a list of values <code>from + n * step</code> for
+ * increasing n. If `step > 0` the sequence terminates
+ * with the largest value less than `end`. If `step < 0`
+ * the sequence terminates with the smallest value greater than `end`.
+ * If `step == 0`, the sequence gors on infinitely (in that
+ * case the `range` operation might not terminate.
+ */
+ def range(start: Int, end: Int, step: Int): CC[Int] = {
+ val b = newBuilder[Int]
+ var i = start
+ while ((step <= 0 || i < end) && (step >= 0 || i > end)) {
+ b += i
+ i += step
+ }
+ b.result
+ }
+
+ /** Create a sequence by repeatedly applying a given function to a start value.
+ *
+ * @param start the start value of the sequence
+ * @param len the length of the sequence
+ * @param f the function that's repeatedly applied
+ * @return the sequence with elements <code>(start, f(start), f(f(start)), ..., f<sup>len-1</sup>(start))</code>
+ */
+ def iterate(start: Int, len: Int)(f: Int => Int): CC[Int] = {
+ val b = newBuilder[Int]
+ var acc = start
+ var i = 0
+ while (i < len) {
+ b += acc
+ acc = f(acc)
+ i += 1
+ }
+ b.result
+ }
+}
diff --git a/src/library/scalax/collection/generic/covartest/IterableTemplate.scala b/src/library/scalax/collection/generic/covartest/IterableTemplate.scala
new file mode 100755
index 0000000000..b83f3b9247
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/IterableTemplate.scala
@@ -0,0 +1,816 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic.covartest
+
+import scalax.collection.mutable.{Buffer, ArrayBuffer, ListBuffer}
+import scalax.collection.immutable.{List, Nil, ::}
+import util.control.Break._
+import Iterable._
+
+/** Collection classes mixing in this class provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>.
+ * Only potentially unbounded collections should directly sub-class <code>Iterable</code>.
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait IterableTemplate[+CC[+B] <: IterableTemplate[CC, B] with Iterable[B], +A] { self/*: CC[A]*/ =>
+
+ /** The template itself seen as an instance of `CC[A]`.
+ * @note: It would be logical to have a self type `CC[A]` instead, then we would not need
+ * this method. Unfortunately, tyis runs afoul some pecularities in Scala's member resolution
+ * algorithm: If the self type is a CC, then Iterable is one of its supertypes. Iterable
+ * defines a number of concrete methods such as newBuilder which are abstract here.
+ * The newBuilder method in Iterable[A] has type Builder[Iterable, A]. Because Scala
+ * prefers concrete over abstract members, it is this newBuilder which is chosen, instead of
+ * the abstract newBuilder in class IterableTemplate of type Builder[CC, A].
+ * Even for concrete methods we have a problem because the last mixin in the parents of CC is
+ * Iterable, not IterableTemplate. So resolution picks the version in Iterable, which returns
+ * again an Iterable, not a CC, as would be required.
+ * These problems would be avoided if Scala computed the type of a member as the glb of the types
+ * all members in the class and its superclasses types.
+ * I think overall this would be a better design.
+ */
+ protected[this] def thisCC: CC[A] = this.asInstanceOf[CC[A]]
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A]
+
+ /** Create a new builder for this IterableType
+ */
+ def newBuilder[B]: Builder[CC, B]
+
+ /** Is this collection empty? */
+ def isEmpty: Boolean = !elements.hasNext
+
+ /** returns true iff this collection has a bound size.
+ * Many APIs in this trait will not work on collections of
+ * unbound sizes.
+ */
+ def hasDefiniteSize = true
+
+ /** Create a new sequence of type CC which contains all elements of this sequence
+ * followed by all elements of Iterable `that'
+ */
+ def ++[B >: A](that: Iterable[B]): CC[B] = {
+ val b: Builder[CC, B] = (this: IterableTemplate[CC, A]).newBuilder[B]
+ b ++= thisCC
+ b ++= that
+ b.result
+ }
+
+ /** Create a new sequence of type IterableType which contains all elements of this sequence
+ * followed by all elements of Iterator `that'
+ */
+ def ++[B >: A](that: Iterator[B]): CC[B] = {
+ val b = newBuilder[B]
+ b ++= thisCC
+ b ++= that
+ b.result
+ }
+
+ /** Returns the sequence resulting from applying the given function
+ * <code>f</code> to each element of this sequence.
+ *
+ * @param f function to apply to each element.
+ * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this
+ * sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def map[B](f: A => B): CC[B] = {
+ val b = newBuilder[B]
+ for (x <- this) b += f(x)
+ b.result
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this sequence, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def flatMap[B](f: A => Iterable[B]): CC[B] = {
+ val b = newBuilder[B]
+ for (x <- this) b ++= f(x)
+ b.result
+ }
+
+ /** Returns all the elements of this sequence that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ def filter(p: A => Boolean): CC[A] = {
+ val b = newBuilder[A]
+ for (x <- this)
+ if (p(x)) b += x
+ b.result
+ }
+
+ /** Removes all elements of the iterable which satisfy the predicate
+ * <code>p</code>. This is like <code>filter</code> with the
+ * predicate inversed.
+ *
+ * @param p the predicate to use to test elements
+ * @return the list without all elements which satisfy <code>p</code>
+ */
+ def remove(p: A => Boolean): CC[A] = filter(!p(_))
+
+ /** Partitions this iterable in two iterables according to a predicate.
+ *
+ * @param p the predicate on which to partition
+ * @return a pair of iterables: the iterable that satisfies the predicate
+ * <code>p</code> and the iterable that does not.
+ * The relative order of the elements in the resulting iterables
+ * is the same as in the original iterable.
+ */
+ def partition(p: A => Boolean): (CC[A], CC[A]) = {
+ val l, r = newBuilder[A]
+ for (x <- this) (if (p(x)) l else r) += x
+ (l.result, r.result)
+ }
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param f a function that is applied to every element.
+ * Note this function underlies the implementation of most other bulk operations.
+ * It should be overridden in concrete collectionc classes with efficient implementations.
+ */
+ def foreach(f: A => Unit): Unit = elements.foreach(f)
+
+ /** Return true iff the given predicate `p` yields true for all elements
+ * of this iterable.
+ *
+ * @note May not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def forall(p: A => Boolean): Boolean = {
+ var result = true
+ breakable {
+ for (x <- this)
+ if (!p(x)) { result = false; break }
+ }
+ result
+ }
+
+ /** Return true iff there is an element in this iterable for which the
+ * given predicate `p` yields true.
+ *
+ * @note May not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def exists(p: A => Boolean): Boolean = {
+ var result = false
+ breakable {
+ for (x <- this)
+ if (p(x)) { result = true; break }
+ }
+ result
+ }
+
+ /** Count the number of elements in the iterable which satisfy a predicate.
+ *
+ * @param p the predicate for which to count
+ * @return the number of elements satisfying the predicate <code>p</code>.
+ */
+ def count(p: A => Boolean): Int = {
+ var cnt = 0
+ for (x <- this) {
+ if (p(x)) cnt += 1
+ }
+ cnt
+ }
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @return an option containing the first element in the iterable object
+ * satisfying <code>p</code>, or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = {
+ var result: Option[A] = None
+ breakable {
+ for (x <- this)
+ if (p(x)) { result = Some(x); break }
+ }
+ result
+ }
+
+ /** Combines the elements of this iterable object together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the list is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = {
+ var result = z
+ for (x <- this)
+ result = op(result, x)
+ result
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op)
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of list and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def /: [B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def :\ [B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
+
+ /** Combines the elements of this iterable object together using the binary
+ * operator <code>op</code>, from left to right
+ * @note Will not terminate for infinite-sized collections.
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the iterable object has elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the iterable object is empty.
+ */
+ def reduceLeft[B >: A](op: (B, A) => B): B = {
+ if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft")
+ var result: B = elements.next
+ var first = true
+ for (x <- this)
+ if (first) first = false
+ else result = op(result, x)
+ result
+ }
+
+ /** Combines the elements of this iterable object together using the binary
+ * operator <code>op</code>, from right to left
+ * @note Will not terminate for infinite-sized collections.
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ *
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceRight[B >: A](op: (A, B) => B): B =
+ elements.reduceRight(op)
+
+ /** Returns an iterable formed from this iterable and the specified list
+ * `other` by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two iterables is longer than the other, its remaining elements are ignored.
+ */
+ def zip[B](that: Iterable[B]): CC[(A, B)] = {
+ val these = this.elements
+ val those = that.elements
+ val b = this.newBuilder[(A, B)]
+ while (these.hasNext && those.hasNext)
+ b += ((these.next, those.next))
+ b.result
+ }
+
+ /** Returns a iterable formed from this iterable and the specified iterable
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param that iterable <code>that</code> may have a different length
+ * as the self iterable.
+ * @param thisElem element <code>thisElem</code> is used to fill up the
+ * resulting iterable if the self iterable is shorter than
+ * <code>that</code>
+b * @param thatElem element <code>thatElem</code> is used to fill up the
+ * resulting iterable if <code>that</code> is shorter than
+ * the self iterable
+ * @return <code>Iterable((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>),
+ * ..., {elem,b<sub>m</sub>})</code>
+ * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
+ * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
+ * invoked where <code>m &gt; n</code>.
+ */
+ def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = {
+ val these = this.elements
+ val those = that.elements
+ val b = newBuilder[(A1, B1)]
+ while (these.hasNext && those.hasNext)
+ b += ((these.next, those.next))
+ while (these.hasNext)
+ b += ((these.next, thatElem))
+ while (those.hasNext)
+ b += ((thisElem, those.next))
+ b.result
+ }
+
+ /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to
+ * `s zip s.indices`, but is usually more efficient.
+ */
+ def zipWithIndex: CC[(A, Int)] = {
+ val b = newBuilder[(A, Int)]
+ var i = 0
+ for (x <- this) {
+ b += ((x, i))
+ i +=1
+ }
+ b.result
+ }
+
+ /** Copy all elements to a given buffer
+ * @note Will not terminate for infinite-sized collections.
+ * @param dest The buffer to which elements are copied
+ */
+ def copyToBuffer[B >: A](dest: Buffer[B]) {
+ for (x <- this) dest += x
+ }
+
+ /** Fills the given array <code>xs</code> with at most `len` elements of
+ * this sequence starting at position `start`.
+ * Copying will stop oce either the end of the current iterable is reached or
+ * `len` elements have been copied.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @param len number of elements to copy
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
+ var i = start
+ val end = (start + len) min xs.length
+ for (x <- this) {
+ if (i < end) {
+ xs(i) = x
+ i += 1
+ }
+ }
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>
+ * until either the end of the current iterable or the end of array `xs` is reached.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int) {
+ copyToArray(xs, start, xs.length - start)
+ }
+
+ /** Converts this collection to a fresh Array elements.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def toArray[B >: A]: Array[B] = {
+ var size = 0
+ for (x <- this) size += 1
+ val result = new Array[B](size)
+ copyToArray(result, 0)
+ result
+ }
+
+ /**
+ * Create a fresh list with all the elements of this iterable object.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def toList: List[A] = (new ListBuffer[A] ++ thisCC).toList
+
+ /**
+ * Returns a sequence containing all of the elements in this iterable object.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def toSequence: Sequence[A] = toList.asInstanceOf[Sequence[A]] // !!!
+
+ /** @deprecated use toSequence instead
+ */
+ @deprecated def toSeq: Sequence[A] = toSequence
+
+ /**
+ * Create a stream which contains all the elements of this iterable object.
+ * @note consider using <code>projection</code> for lazy behavior.
+ */
+ def toStream: Stream[A] = elements.toStream
+
+ /** Sort the iterable according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>,
+ * which should be true iff <code>e1</code> is smaller than
+ * <code>e2</code>.
+ * The sort is stable. That is elements that are equal wrt `lt` appear in the
+ * same order in the sorted iterable as in the original.
+ *
+ * @param lt the comparison function
+ * @return a list sorted according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>.
+ * @ex <pre>
+ * List("Steve", "Tom", "John", "Bob")
+ * .sort((e1, e2) => (e1 compareTo e2) &lt; 0) =
+ * List("Bob", "John", "Steve", "Tom")</pre>
+ * !!!
+ def sortWith(lt : (A,A) => Boolean): CC[A] = {
+ val arr = toArray
+ Array.sortWith(arr, lt)
+ val b = newBuilder[A]
+ for (x <- arr) b += x
+ b.result
+ }
+ */
+
+ /** Returns a string representation of this iterable object. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ *
+ * @ex <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ * @note Will not terminate for infinite-sized collections.
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(start: String, sep: String, end: String): String =
+ addString(new StringBuilder(), start, sep, end).toString
+
+ /** Returns a string representation of this iterable object. The string
+ * representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ *
+ * @note Will not terminate for infinite-sized collections.
+ * @param sep separator string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(sep: String): String =
+ addString(new StringBuilder(), sep).toString
+
+ /** Converts a collection into a flat <code>String</code> by each element's toString method.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def mkString =
+ addString(new StringBuilder()).toString
+
+ /** Write all elements of this iterable into given string builder.
+ * The written text begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ b append start
+ var first = true
+ for (x <- this) {
+ if (first) first = false
+ else b append sep
+ b append x
+ }
+ b append end
+ }
+
+ /** Write all elements of this string into given string builder.
+ * The string representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def addString(b: StringBuilder, sep: String): StringBuilder = {
+ var first = true
+ for (x <- this) {
+ if (first) first = false
+ else b append sep
+ b append x
+ }
+ b
+ }
+
+ /** Write all elements of this string into given string builder without using
+ * any separator between consecutive elements.
+ * @note Will not terminate for infinite-sized collections.
+ */
+ def addString(b: StringBuilder): StringBuilder = {
+ for (x <- this) {
+ b append x
+ }
+ b
+ }
+
+ /**
+ * returns a projection that can be used to call non-strict <code>filter</code>,
+ * <code>map</code>, and <code>flatMap</code> methods that build projections
+ * of the collection.
+ def projection : Iterable.Projection[A] = new Iterable.Projection[A] {
+ def elements = Iterable.this.elements
+ override def force = Iterable.this
+ }
+ */
+
+ override def toString = mkString(stringPrefix + "(", ", ", ")")
+
+ /** Defines the prefix of this object's <code>toString</code> representation.
+ */
+ def stringPrefix : String = {
+ var string = this.getClass.getName
+ val idx1 = string.lastIndexOf('.' : Int)
+ if (idx1 != -1) string = string.substring(idx1 + 1)
+ val idx2 = string.indexOf('$')
+ if (idx2 != -1) string = string.substring(0, idx2)
+ string
+ }
+
+
+ /** Creates a view of this iterable @see IterableView
+ */
+ def view: IterableView[CC, A] = new IterableView[CC, A] { // !!! Martin: We should maybe infer the type parameters here?
+ val origin = thisCC
+ val elements: Iterator[A] = self.elements
+ }
+
+// The following methods return non-deterministic results, unless this iterable is an OrderedIterable
+
+ /** The first element of this sequence.
+ *
+ * @note Might return different results for different runs, unless this iterable is ordered
+ * @throws Predef.NoSuchAentException if the sequence is empty.
+ */
+ def head: A = if (isEmpty) throw new NoSuchElementException else elements.next
+
+ /** @deprecated use head instead */
+ @deprecated def first: A = head
+
+ /** Returns as an option the first element of this iterable
+ * or <code>None</code> if iterable is empty.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def headOption: Option[A] = if (isEmpty) None else Some(head)
+
+ /** @deprecated use headOption instead
+ * <code>None</code> if list is empty.
+ */
+ @deprecated def firstOption: Option[A] = headOption
+
+ /** An iterable consisting of all elements of this iterable
+ * except the first one.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def tail: CC[A] = drop(1)
+
+ /** Return an iterable consisting only of the first <code>n</code>
+ * elements of this iterable, or else the whole iterable, if it has less
+ * than <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return a possibly projected sequence
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def take(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ breakable {
+ for (x <- this) {
+ b += x
+ i += 1
+ if (i == n) break
+ }
+ }
+ b.result
+ }
+
+ /** Returns this iterable without its <code>n</code> first elements
+ * If this iterable has less than <code>n</code> elements, the empty
+ * iterable is returned.
+ *
+ * @param n the number of elements to drop
+ * @return the new iterable
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def drop(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ for (x <- this) {
+ if (i >= n) b += x
+ i += 1
+ }
+ b.result
+ }
+
+ /** A sub-iterable starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @note c.slice(from, to) is equivalent to (but possibly more efficient than)
+ * c.drop(from).take(to - from)
+ *
+ * @param from The index of the first element of the returned subsequence
+ * @param until The index of the element following the returned subsequence
+ * @throws IndexOutOfBoundsException if <code>from &lt; 0</code>
+ * or <code>length &lt; from + len<code>
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def slice(from: Int, until: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = 0
+ breakable {
+ for (x <- this) {
+ if (i >= from) b += x
+ i += 1
+ if (i == until) break
+ }
+ }
+ b.result
+ }
+
+ /** The last element of this iterable.
+ *
+ * @throws Predef.NoSuchElementException if the sequence is empty.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def last: A = {
+ var lst = head
+ for (x <- this)
+ lst = x
+ lst
+ }
+
+ /** Returns as an option the last element of this iterable or
+ * <code>None</code> if iterable is empty.
+ *
+ * @return the last element as an option.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def lastOption: Option[A] = if (isEmpty) None else Some(last)
+
+ /** An iterable consisting of all elements of this iterable except the last one.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def init: CC[A] = {
+ var lst = head
+ val b = newBuilder[A]
+ for (x <- this) {
+ b += lst
+ lst = x
+ }
+ b.result
+ }
+
+ /** Returns the rightmost <code>n</code> elements from this iterable.
+ *
+ * @param n the number of elements to take
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def takeRight(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ val lead = elements drop n
+ var go = false
+ for (x <- this) {
+ if (go) b += x
+ else if (lead.hasNext) lead.next
+ else go = true
+ }
+ b.result
+ }
+
+ /** Returns the iterable wihtout its rightmost <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def dropRight(n: Int): CC[A] = {
+ val b = newBuilder[A]
+ val lead = elements drop n
+ breakable {
+ for (x <- this) {
+ if (!lead.hasNext) break
+ lead.next
+ b += x
+ }
+ }
+ b.result
+ }
+
+ /** Split the iterable at a given point and return the two parts thus
+ * created.
+ *
+ * @param n the position at which to split
+ * @return a pair of iterables composed of the first <code>n</code>
+ * elements, and the other elements.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def splitAt(n: Int): (CC[A], CC[A]) = {
+ val l, r = newBuilder[A]
+ var i = 0
+ for (x <- this)
+ (if (i < n) l else r) += x
+ (l.result, r.result)
+ }
+
+ /** Returns the longest prefix of this sequence whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this sequence whose elements satisfy
+ * the predicate <code>p</code>.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def takeWhile(p: A => Boolean): CC[A] = {
+ val b = newBuilder[A]
+ breakable {
+ for (x <- this) {
+ if (!p(x)) break
+ b += x
+ }
+ }
+ b.result
+ }
+
+ /** Returns the longest suffix of this sequence whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the sequence whose first element
+ * does not satisfy the predicate <code>p</code>.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def dropWhile(p: A => Boolean): CC[A] = {
+ val b = newBuilder[A]
+ var go = false
+ for (x <- this) {
+ if (go) b += x
+ else if (!p(x)) { go = true; b += x }
+ }
+ b.result
+ }
+
+ /** Returns a pair consisting of the longest prefix of the list whose
+ * elements all satisfy the given predicate, and the rest of the list.
+ *
+ * @param p the test predicate
+ * @return a pair consisting of the longest prefix of the list whose
+ * elements all satisfy <code>p</code>, and the rest of the list.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def span(p: A => Boolean): (CC[A], CC[A]) = {
+ val l, r = newBuilder[A]
+ var toLeft = true
+ for (x <- this) {
+ toLeft = toLeft && p(x)
+ (if (toLeft) l else r) += x
+ }
+ (l.result, r.result)
+ }
+
+ /** Checks if the other iterable object contains the same elements as this one.
+ *
+ * @note will not terminate for infinite-sized iterables.
+ * @param that the other iterable
+ * @return true, iff both iterables contain the same elements.
+ * @note Might return different results for different runs, unless this iterable is ordered
+ */
+ def sameElements[B >: A](that: OrderedIterable[B]): Boolean = {
+ val these = this.elements
+ val those = that.elements
+ while (these.hasNext && those.hasNext && these.next() == those.next()) {}
+ !these.hasNext && !those.hasNext
+ }
+
+ /** A sub-sequence view starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @param from The index of the first element of the slice
+ * @param until The index of the element following the slice
+ * @note The difference between `view` and `slice` is that `view` produces
+ * a view of the current sequence, whereas `slice` produces a new sequence.
+ *
+ * @note Might return different results for different runs, unless this iterable is ordered
+ * @note view(from, to) is equivalent to view.slice(from, to)
+ */
+ def view(from: Int, until: Int): IterableView[CC, A] = view.slice(from, until)
+}
diff --git a/src/library/scalax/collection/generic/covartest/IterableView.scala b/src/library/scalax/collection/generic/covartest/IterableView.scala
new file mode 100755
index 0000000000..80a455f776
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/IterableView.scala
@@ -0,0 +1,121 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+package scalax.collection.generic.covartest
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait IterableView[+UC[+B] <: Iterable[B], +A] extends Iterable[A] { self =>
+
+ val origin: Iterable[_]
+ def elements: Iterator[A]
+
+ val underlying: Iterable[_] = origin match {
+ case v: IterableView[t, _] => v.underlying
+ case _ => origin
+ }
+
+ private def isDelay = elements eq underlying.elements
+
+ private[this] var forced: UC[A] = _
+ private[this] var wasForced = false
+
+ def force: UC[A] = {
+ if (!wasForced) {
+ forced = {
+ val b = underlying.newBuilder[A]
+ for (x <- elements)
+ b += x
+ b.result
+ }.asInstanceOf[UC[A]]
+ wasForced = true
+ }
+ forced
+ }
+
+ def newBuilder[A] = underlying.newBuilder[A]
+
+ /** Builds a new view object. This method needs to be overridden in subclasses
+ * which refine in IterableView type
+ */
+ protected def newView[B](elems: Iterator[B]) = new IterableView[UC, B] {
+ val origin = if (self.isDelay) self.origin else self
+ val elements = elems
+ }
+
+ /** Non-strict variant of @see IterableLike.++ */
+ override def ++[B >: A](that: Iterator[B]): IterableView[UC, B] = newView(elements ++ that)
+
+ /** Non-strict variant of @see IterableLike.++ */
+ override def ++[B >: A](that: Iterable[B]): IterableView[UC, B] = newView(elements ++ that.elements)
+
+ /** Non-strict variant of @see IterableLike.map */
+ override def map[B](f: A => B): IterableView[UC, B] = newView(elements map f)
+
+ /** Non-strict variant of @see IterableLike.flatMap */
+ override def flatMap[B](f: A => Iterable[B]): IterableView[UC, B] = newView(elements flatMap (f(_).elements))
+
+ /** Non-strict variant of @see IterableLike.filter */
+ override def filter(p: A => Boolean): IterableView[UC, A] = newView(elements filter p)
+
+ /** Non-strict variant of @see IterableLike.partition */
+ override def partition(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = {
+ val (li, ri) = elements partition p
+ (newView(li), newView(ri))
+ }
+
+ /** Non-strict variant of @see IterableLike.zip */
+ override def zip[B](other: Iterable[B]): IterableView[UC, (A, B)] = newView(elements zip other.elements)
+
+ /** Non-strict variant of @see IterableLike.zipWithIndex */
+ override def zipWithIndex: IterableView[UC, (A, Int)] = newView(elements.zipWithIndex)
+
+ /* Non-strict variant of @see IterableLike.zipAll
+ * This is not enabled because it can't be specialized in VectorView:
+ * VectorView is not covariant, yet must maintain updatability. Impossible to do this
+ * with this type signature.
+ override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): IterableView[UC, (A1, B1)] =
+ newView(elements zipAll (that.elements, thisElem, thatElem))
+ */
+
+ /** Non-strict variant of @see Iterable.take */
+ override def take(n: Int): IterableView[UC, A] = newView(elements take n)
+
+ /** Non-strict variant of @see Iterable.drop */
+ override def drop(n: Int): IterableView[UC, A] = newView(elements drop n)
+
+ /** Non-strict variant of @see Iterable.splitAt */
+ override def splitAt(n: Int): (IterableView[UC, A], IterableView[UC, A]) = (take(n), drop(n))
+
+ /** Non-strict variant of @see Iterable.slice */
+ override def slice(from: Int, until: Int): IterableView[UC, A] = newView(elements slice (from, until))
+
+ /** Non-strict variant of @see Iterable.takeWhile */
+ override def takeWhile(p: A => Boolean): IterableView[UC, A] = newView(elements takeWhile p)
+
+ /** Non-strict variant of @see Iterable.dropWhile */
+ override def dropWhile(p: A => Boolean): IterableView[UC, A] = newView(elements dropWhile p)
+
+ /** Non-strict variant of @see Iterable.span */
+ override def span(p: A => Boolean): (IterableView[UC, A], IterableView[UC, A]) = (takeWhile(p), dropWhile(p))
+
+ /** The projection resulting from the concatenation of this projection with the <code>rest</code> projection.
+ * @param rest The projection that gets appended to this projection
+ * @deprecated Use ++ instead
+ */
+ @deprecated def append[B >: A](rest : => Iterable[B]): IterableView[UC, B] = this ++ rest.elements
+
+ override def stringPrefix = origin.stringPrefix+"V"
+
+
+}
diff --git a/src/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala b/src/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala
new file mode 100755
index 0000000000..c6be1a5acd
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/OrderedIterableTemplate.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic.covartest
+
+import OrderedIterable._
+
+trait OrderedIterableTemplate[+CC[+B] <: OrderedIterableTemplate[CC, B] with OrderedIterable[B], +A]
+ extends IterableTemplate[CC, A]
diff --git a/src/library/scalax/collection/generic/covartest/SequenceFactory.scala b/src/library/scalax/collection/generic/covartest/SequenceFactory.scala
new file mode 100755
index 0000000000..1fb85d02db
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/SequenceFactory.scala
@@ -0,0 +1,11 @@
+package scalax.collection.generic.covartest
+
+trait SequenceFactory[CC[A] <: Sequence[A]] extends IterableFactory[CC] {
+
+ /** This method is called in a pattern match { case Sequence(...) => }.
+ *
+ * @param x the selector value
+ * @return sequence wrapped in an option, if this is a Sequence, otherwise none
+ */
+ def unapplySequence[A](x: CC[A]): Some[CC[A]] = Some(x)
+}
diff --git a/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala b/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala
new file mode 100755
index 0000000000..bf1915edf0
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala
@@ -0,0 +1,382 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.covartest
+
+import util.control.Break._
+import scalax.collection.immutable.{List, Nil, ::}
+
+import Sequence._
+
+trait SequenceTemplate[+CC[+B] <: SequenceTemplate[CC, B] with Sequence[B], +A] extends PartialFunction[Int, A] with OrderedIterableTemplate[CC, A] {
+self /*: CC[A]*/ =>
+
+ /** Returns the length of the sequence.
+ *
+ * @return the sequence length.
+ */
+ def length: Int
+
+ /** Result of comparing <code>length</code> with operand <code>len</code>.
+ * returns <code>x</code> where
+ * <code>x &lt; 0</code> iff <code>this.length &lt; len</code>
+ * <code>x == 0</code> iff <code>this.length == len</code>
+ * <code>x &gt; 0</code> iff <code>this.length &gt; len</code>.
+ *
+ * The method as implemented here does not call length directly; its running time
+ * is O(length min len) instead of O(length). The method should be overwritten
+ * if computing length is cheap.
+ */
+ def lengthCompare(len: Int): Int = {
+ var i = 0
+ breakable {
+ for (_ <- this) {
+ i += 1
+ if (i > len) break
+ }
+ }
+ i - len
+ }
+
+ /** Should always be <code>length</code> */
+ def size = length
+
+ /** Is this partial function defined for the index <code>x</code>?
+ */
+ def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length)
+
+ /** Returns index of the first element satisying a predicate, or -1, if none exists.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def indexWhere(p: A => Boolean): Int = indexWhere(p, 0)
+
+ /** Returns length of longest segment starting from a start index `from`
+ * such that every element of the segment satisfies predicate `p`.
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @param from the start index
+ */
+ def segmentLength(p: A => Boolean, from: Int): Int = {
+ var result = 0
+ var i = from
+ breakable {
+ for (x <- this) {
+ if (i >= from && !p(x)) { result = i - from; break }
+ else i += 1
+ }
+ }
+ result
+ }
+
+ /** Returns length of longest prefix of this seqence
+ * such that every element of the prefix satisfies predicate `p`.
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ */
+ def prefixLength(p: A => Boolean) = segmentLength(p, 0)
+
+ /** Returns index of the first element starting from a start index
+ * satisying a predicate, or -1, if none exists.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param p the predicate
+ * @param from the start index
+ */
+ def indexWhere(p: A => Boolean, from: Int): Int = {
+ var result = -1
+ var i = from
+ breakable {
+ for (x <- this) {
+ if (i >= from && p(x)) { result = i; break }
+ else i += 1
+ }
+ }
+ result
+ }
+
+ /** Returns index of the first element satisying a predicate, or -1.
+ *
+ * @deprecated Use `indexWhere` instead
+ */
+ @deprecated def findIndexOf(p: A => Boolean): Int = indexWhere(p)
+
+ /** Returns the index of the first occurence of the specified
+ * object in this iterable object.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param elem element to search for.
+ * @return the index in this sequence of the first occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def indexOf[B >: A](elem: B): Int = indexOf(elem, 0)
+
+ /** Returns the index of the first occurence of the specified
+ * object in this iterable object, starting from a start index, or
+ * -1, if none exists.
+ *
+ * @note may not terminate for infinite-sized collections.
+ * @param elem element to search for.
+ */
+ def indexOf[B >: A](elem: B, from: Int): Int = indexWhere(elem ==, from)
+
+ /** Returns the index of the last occurence of the specified element
+ * in this sequence, or -1 if the sequence does not contain this element.
+ *
+ * @param elem element to search for.
+ * @return the index in this sequence of the last occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def lastIndexOf[B >: A](elem: B): Int = lastIndexOf(elem, length - 1)
+
+ /** Returns the index of the last
+ * occurence of the specified element in this sequence
+ * before or at a given end index,
+ * or -1 if the sequence does not contain this element.
+ *
+ * @param elem element to search for.
+ * @param end the end index
+ */
+ def lastIndexOf[B >: A](elem: B, end: Int): Int = {
+ var i = end
+ val it = reversedElements
+ while (it.hasNext && it.next != elem) i -= 1
+ i
+ }
+
+ /** Returns index of the last element satisying a predicate, or -1, if none exists.
+ *
+ * @param p the predicate
+ * @return the index of the last element satisfying <code>p</code>,
+ * or -1 if such an element does not exist
+ */
+ def lastIndexWhere(p: A => Boolean): Int = lastIndexWhere(p, length - 1)
+
+ /** Returns index of the last element not exceeding a given end index
+ * and satisying a predicate, or -1 if none exists.
+ *
+ * @param end the end index
+ * @param p the predicate
+ */
+ def lastIndexWhere(p: A => Boolean, end: Int): Int = {
+ var i = end
+ val it = reversedElements
+ while (it.hasNext && (i > end || !p(it.next))) i -= 1
+ i
+ }
+
+ /** A sequence of type <code>C</code> consisting of all elements of
+ * this sequence in reverse order.
+ * @note the operation is implemented by building a new sequence
+ * from <code>this(length - 1), ..., this(0)</code>
+ * If random access is inefficient for the given sequence implementation,
+ * this operation should be overridden.
+ */
+ def reverse: CC[A] = {
+ var xs: List[A] = List()
+ for (x <- this)
+ xs = x :: xs
+ val b = newBuilder[A]
+ for (x <- xs)
+ b += x
+ b.result
+ }
+
+ /** The elements of this sequence in reversed order
+ */
+ def reversedElements: Iterator[A] = reverse.elements
+
+ /**
+ * Checks whether the argument sequence is contained at the
+ * specified index within the receiver object.
+ *
+ * If the both the receiver object, <code>this</code> and
+ * the argument, <code>that</code> are infinite sequences
+ * this method may not terminate.
+ *
+ * @return true if <code>that</code> is contained in
+ * <code>this</code>, at the specified index, otherwise false
+ *
+ * @see String.startsWith
+ */
+ def startsWith[B](that: Sequence[B], offset: Int): Boolean = {
+ val i = elements.drop(offset)
+ val j = that.elements
+ while (j.hasNext && i.hasNext && i.next == j.next) {}
+ !j.hasNext
+ }
+
+ /**
+ * Check whether the receiver object starts with the argument sequence.
+ *
+ * @return true if <code>that</code> is a prefix of <code>this</code>,
+ * otherwise false
+ *
+ * @see Sequence.startsWith
+ */
+ def startsWith[B](that: Sequence[B]): Boolean = startsWith(that, 0)
+
+ /** @return true if this sequence end with that sequence
+ * @see String.endsWith
+ */
+ def endsWith[B](that: Sequence[B]): Boolean = {
+ val i = this.elements.drop(length - that.length)
+ val j = that.elements
+ while (i.hasNext && j.hasNext && i.next == j.next) ()
+ !j.hasNext
+ }
+
+ /** @return -1 if <code>that</code> not contained in this, otherwise the
+ * index where <code>that</code> is contained
+ * @see String.indexOf
+ */
+ def indexOf[B >: A](that: Sequence[B]): Int = {
+ var i = 0
+ var s: Sequence[A] = thisCC
+ while (!s.isEmpty && !(s startsWith that)) {
+ i += 1
+ s = s drop 1
+ }
+ if (!s.isEmpty || that.isEmpty) i else -1
+ }
+
+ /** Tests if the given value <code>elem</code> is a member of this
+ * sequence.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return <code>true</code> iff there is an element of this sequence
+ * which is equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): Boolean = exists (_ == elem)
+
+ /** Computes the union of this sequence and the given sequence
+ * <code>that</code>.
+ *
+ * @param that the sequence of elements to add to the sequence.
+ * @return an sequence containing the elements of this
+ * sequence and those of the given sequence <code>that</code>
+ * which are not contained in this sequence.
+ */
+ def union[B >: A](that: Sequence[B]): CC[B] = this ++ (that diff thisCC)
+
+ /** Computes the difference between this sequence and the given sequence
+ * <code>that</code>.
+ *
+ * @param that the sequence of elements to remove from this sequence.
+ * @return this sequence without the elements of the given sequence
+ * <code>that</code>.
+ */
+ def diff[B >: A](that: Sequence[B]): CC[A] = this remove (that contains _)
+
+ /** Computes the intersection between this sequence and the given sequence
+ * <code>that</code>.
+ *
+ * @param that the sequence to intersect.
+ * @return the sequence of elements contained both in this sequence and
+ * in the given sequence <code>that</code>.
+ */
+ def intersect[B >: A](that: Sequence[B]): CC[A] = this filter(that contains _)
+
+ /** Builds a new sequence from this sequence in which any duplicates (wrt to ==) removed.
+ * Among duplicate elements, only the first one is retained in the result sequence
+ */
+ def removeDuplicates: CC[A] = {
+ val b = newBuilder[A]
+ var seen = Set[A]()
+ for (x <- this) {
+ if (!(seen contains x)) {
+ b += x
+ seen += x
+ }
+ }
+ b.result
+ }
+
+ /** Returns a sequence of given length containing the elements of this sequence followed by zero
+ * or more occurrences of given elements. If this sequence is already at least as long as given
+ * length, it is returned directly. Otherwise, a new sequence is created consisting of the elements
+ * of this sequence followed by enough occurrences of the given elements to reach the given length.
+ */
+ def padTo[B >: A](len: Int, elem: B): CC[B] = {
+ var diff = len - length
+ val b = newBuilder[B] //!!! drop [B] and get surprising results!
+ b ++= thisCC
+ while (diff > 0) {
+ b += elem
+ diff -=1
+ }
+ b.result
+ }
+
+ /**
+ * Overridden for efficiency.
+ *
+ * @return the sequence itself
+ */
+ override def toSequence: Sequence[A] = this.asInstanceOf[Null] // !!!
+
+ def indices: Range = 0 until length
+
+ /** Creates a view of this iterable @see OrderedIterable.View
+ */
+ override def view: SequenceView[CC, A] = new SequenceView[CC, A] { // !!! Martin: We should maybe infer the type parameters here?
+ val origin: Sequence[_] = thisCC
+ val elements: Iterator[A] = self.elements
+ val length: Int = self.length
+ def apply(idx: Int): A = self.apply(idx)
+ }
+
+ /** A sub-sequence view starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @param from The index of the first element of the slice
+ * @param until The index of the element following the slice
+ * @note The difference between `view` and `slice` is that `view` produces
+ * a view of the current sequence, whereas `slice` produces a new sequence.
+ *
+ * @note view(from, to) is equivalent to view.slice(from, to)
+ */
+ override def view(from: Int, until: Int): SequenceView[CC, A] = view.slice(from, until)
+
+ /** Returns index of the last element satisying a predicate, or -1.
+ * @deprecated use `lastIndexWhere` instead
+ */
+ @deprecated def findLastIndexOf(p: A => Boolean): Int = lastIndexWhere(p)
+
+ /** A sub-sequence starting at index <code>from</code>
+ * and extending up to the length of the current sequence
+ *
+ * @param from The index of the first element of the slice
+ * @throws IndexOutOfBoundsException if <code>from &lt; 0</code>
+ * @deprecated use <code>drop</code> instead
+ */
+ @deprecated def slice(from: Int): Sequence[A] = slice(from, length)
+
+ /** @deprecated Should be replaced by
+ *
+ * <code>(s1, s2) forall { case (x, y) => f(x, y) }</code>
+ */
+ @deprecated def equalsWith[B](that: Sequence[B])(f: (A,B) => Boolean): Boolean = {
+ val i = this.elements
+ val j = that.elements
+ while (i.hasNext && j.hasNext && f(i.next, j.next)) ()
+ !i.hasNext && !j.hasNext
+ }
+
+ /** Is <code>that</code> a slice in this?
+ * @deprecated Should be repaced by <code>indexOf(that) != -1</code>
+ */
+ @deprecated def containsSlice[B](that: Sequence[B]): Boolean = indexOf(that) != -1
+
+}
diff --git a/src/library/scalax/collection/generic/covartest/SequenceView.scala b/src/library/scalax/collection/generic/covartest/SequenceView.scala
new file mode 100755
index 0000000000..48477cf6e7
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/SequenceView.scala
@@ -0,0 +1,129 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.covartest
+
+import util.control.Break._
+import annotation.unchecked.uncheckedVariance
+
+import Sequence._
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait SequenceView[+UC[+B] <: Sequence[B], +A] extends IterableView[UC, A] with Sequence[A] {
+self =>
+
+ /** refined from Iterable.View */
+ val origin: Sequence[_]
+
+ trait Transformed[+B] extends SequenceView[UC, B] {
+ val origin = self
+ protected def asCC = asInstanceOf[SequenceView[UC, B]]
+ }
+
+ class Appended[+B >: A](that: Sequence[B]) extends Transformed[B] {
+ override def elements: Iterator[B] = self.elements ++ that.elements
+ override def length: Int = self.length + that.length
+ override def apply(idx: Int): B = {
+ val ll = self.length
+ if (idx < ll) self.apply(idx) else that.apply(idx - ll)
+ }
+ override def stringPrefix = self.stringPrefix + "A"
+ }
+
+ class Sliced(from: Int, to: Int) extends Transformed[A] {
+ override def elements: Iterator[A] = self.elements slice (from, to)
+ override lazy val length: Int = ((to min self.length) - (from max 0) min 0)
+ override def apply(idx: Int): A =
+ if (idx >= 0 && idx < length) self.apply(idx + from)
+ else throw new IndexOutOfBoundsException(idx.toString)
+ override def stringPrefix = self.stringPrefix + "S"
+ override def slice(from1: Int, to1: Int) =
+ new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0)).asInstanceOf[SequenceView[UC, A]]
+ }
+
+ class Mapped[+B](f: A => B) extends Transformed[B] {
+ override def elements: Iterator[B] = self.elements map f
+ override def length: Int = self.length
+ override def apply(idx: Int): B = f(self.apply(idx))
+ override def stringPrefix = self.stringPrefix + "M"
+ }
+
+ class Reversed extends Transformed[A] {
+ override def elements: Iterator[A] = self.reversedElements
+ override def length: Int = self.length
+ override def apply(idx: Int): A = self.apply(length - 1 - idx)
+ override def stringPrefix = super.stringPrefix+"R"
+ }
+
+ class Patched[+B >: A](from: Int, patch: Sequence[B], replaced: Int) extends Transformed[B] {
+ val plen = patch.length
+ override def elements: Iterator[B] = self.elements patch (from, patch.asInstanceOf[Null], replaced) // !!!
+ override def length: Int = self.length + plen - replaced
+ override def apply(idx: Int): B =
+ if (idx < from) self.apply(idx)
+ else if (idx < from + plen) patch.apply(idx - from)
+ else self.apply(idx - plen + replaced)
+ override def stringPrefix = super.stringPrefix+"P"
+ }
+
+ class Zipped[+B](that: Sequence[B]) extends Transformed[(A, B)] {
+ override def elements: Iterator[(A, B)] = self.elements zip that.elements
+ override def length = self.length min that.length
+ override def apply(idx: Int): (A, B) = (self.apply(idx), that.apply(idx))
+ override def stringPrefix = super.stringPrefix+"Z"
+ }
+
+ override def ++[B >: A](that: Iterable[B]): SequenceView[UC, B] =
+ new Appended[B](that.toSequence).asCC
+ override def ++[B >: A](that: Iterator[B]): SequenceView[UC, B] =
+ new Appended[B](that.toSequence).asCC
+ override def map[B](f: A => B): SequenceView[UC, B] =
+ new Mapped(f).asCC
+ override def reverse: SequenceView[UC, A] =
+ (new Reversed).asCC
+ def patch[B >: A](from: Int, patch: Sequence[B], replaced: Int): SequenceView[UC, B] =
+ if (0 <= from && from < length) new Patched(from, patch, replaced).asCC
+ else throw new IndexOutOfBoundsException(from.toString)
+ override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] =
+ patch(length, fill((len - length) max 0, elem), 0)
+ override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] =
+ new Zipped(that.toSequence).asCC
+ override def zipWithIndex: SequenceView[UC, (A, Int)] =
+ zip((0 until length).asInstanceOf[Null]) // !!!
+ /*
+ override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): SequenceView[UC, (A1, B1)] = {
+ val that1 = that.toSequence
+ self.padTo(that1.length, thisElem) zip that1.padTo(this.length, thatElem)//.asInstanceOf[SequenceView[UC, (A1, B1)]]
+ }*/
+ override def take(n: Int): SequenceView[UC, A] =
+ slice(0, n)
+ override def drop(n: Int): SequenceView[UC, A] =
+ slice(n, Math.MAX_INT)
+ override def splitAt(n: Int): (SequenceView[UC, A], SequenceView[UC, A]) = (take(n), drop(n))
+ override def slice(from: Int, until: Int): SequenceView[UC, A] =
+ new Sliced(from, until).asCC
+ override def takeWhile(p: A => Boolean): SequenceView[UC, A] =
+ take(prefixLength(p))
+ override def dropWhile(p: A => Boolean): SequenceView[UC, A] =
+ drop(prefixLength(p))
+ override def span(p: A => Boolean): (SequenceView[UC, A], SequenceView[UC, A]) = {
+ val n = prefixLength(p)
+ (take(n), drop(n))
+ }
+
+ // missing here because we can't do anything about them, so we fall back to default construction
+ // if an IterableView via newView: flatMap, filter, partition
+}
+
diff --git a/src/library/scalax/collection/generic/covartest/VectorTemplate.scala b/src/library/scalax/collection/generic/covartest/VectorTemplate.scala
new file mode 100644
index 0000000000..0771b078d9
--- /dev/null
+++ b/src/library/scalax/collection/generic/covartest/VectorTemplate.scala
@@ -0,0 +1,264 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $
+
+package scalax.collection.generic.covartest
+
+import Vector._
+
+/** Sequences that support O(1) element access and O(1) length computation.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait VectorTemplate[+CC[+B] <: VectorTemplate[CC, B] with Vector[B], +A] extends SequenceTemplate[CC, A] {
+self =>
+
+ // Overridden methods from IterableTemplate
+
+ /** The iterator returned by the elements method
+ */
+ protected class Elements(start: Int, end: Int) extends scalax.collection.BufferedIterator[A] {
+ var i = start
+ def hasNext: Boolean = i < end
+ def next: A =
+ if (i < end) {
+ val x = self(i)
+ i += 1
+ x
+ } else Iterator.empty.next
+ def head =
+ self(i)
+ /** drop is overridden to enable fast searching in the middle of random access sequences */
+ override def drop(n: Int): Iterator[A] =
+ if (n > 0) new Elements(start + n, end) else this
+ /** is overridden to be symmetric to drop */
+ override def take(n: Int): Iterator[A] =
+ if (n < 0) Iterator.empty.buffered
+ else if (start + n < end) new Elements(start, start + n)
+ else this
+ }
+
+ override def elements: Iterator[A] = new Elements(0, length)
+
+ override def isEmpty: Boolean = { length == 0 }
+
+ override def foreach(f: A => Unit): Unit = {
+ var i = 0
+ val len = length
+ while (i < len) { f(this(i)); i += 1 }
+ }
+
+ override def forall(p: A => Boolean): Boolean = prefixLength(p(_)) == length
+ override def exists(p: A => Boolean): Boolean = prefixLength(!p(_)) != length
+
+ override def find(p: A => Boolean): Option[A] = {
+ val i = prefixLength(!p(_))
+ if (i < length) Some(this(i)) else None
+ }
+
+ private def foldl[B](start: Int, z: B, op: (B, A) => B): B = {
+ var i = start
+ val len = length
+ var result = z
+ while (i < len) {
+ result = op(result, this(i))
+ i += 1
+ }
+ result
+ }
+
+ private def foldr[B](start: Int, len: Int, z: B, op: (A, B) => B): B =
+ if (start == len) z
+ else op(this(start), foldr(start + 1, len, z, op))
+
+ override def foldLeft[B](z: B)(op: (B, A) => B): B = foldl(0, z, op)
+ override def foldRight[B](z: B)(op: (A, B) => B): B = foldr(0, length, z, op)
+ override def reduceLeft[B >: A](op: (B, A) => B): B =
+ if (length > 0) foldl(0, this(0), op) else super.reduceLeft(op)
+ override def reduceRight[B >: A](op: (A, B) => B): B =
+ if (length > 0) foldr(0, length - 1, this(length - 1), op) else super.reduceRight(op)
+
+ override def zip[B](that: Iterable[B]): CC[(A, B)] = that match {
+ case that: Vector[_] =>
+ var i = 0
+ val len = this.length min that.length
+ val b = this.newBuilder[(A, B)]
+ while (i < len) {
+ b += ((this(i), that(i).asInstanceOf[B]))
+ i += 1
+ }
+ b.result
+ case _ =>
+ super.zip(that)
+ }
+
+ override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = that match {
+ case that: Vector[_] =>
+ var i = 0
+ val len = this.length min that.length
+ val b = this.newBuilder[(A1, B1)]
+ while (i < len) {
+ b += ((this(i), that(i).asInstanceOf[B]))
+ i += 1
+ }
+ while (i < this.length) {
+ b += ((this(i), thatElem))
+ i += 1
+ }
+ while (i < that.length) {
+ b += ((this(i), thatElem.asInstanceOf[B]))
+ i += 1
+ }
+ b.result
+ case _ =>
+ super.zipAll(that, thisElem, thatElem)
+ }
+
+ override def zipWithIndex: CC[(A, Int)] = {
+ val b = newBuilder[(A, Int)]
+ var i = 0
+ val len = length
+ while (i < len) {
+ b += ((this(i), i))
+ i += 1
+ }
+ b.result
+ }
+
+ override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
+ var i = 0
+ var j = start
+ val end = length min len min (xs.length - start)
+ while (i < end) {
+ xs(j) = this(i)
+ i += 1
+ j += 1
+ }
+ }
+
+ // Overridden methods from OrderedIterableTemplate
+
+ override def head: A = if (isEmpty) throw new NoSuchElementException else this(0)
+
+ override def slice(from: Int, until: Int): CC[A] = {
+ val b = newBuilder[A]
+ var i = from max 0
+ val end = until min length
+ while (i < end) {
+ b += this(i)
+ i += 1
+ }
+ b.result
+ }
+
+ override def take(n: Int): CC[A] = slice(0, n)
+ override def drop(n: Int): CC[A] = slice(n, length)
+ override def takeRight(n: Int): CC[A] = slice(length - n, length)
+ override def dropRight(n: Int): CC[A] = slice(0, length - n)
+ override def splitAt(n: Int): (CC[A], CC[A]) = (take(n), drop(n))
+ override def takeWhile(p: A => Boolean): CC[A] = take(prefixLength(p))
+ override def dropWhile(p: A => Boolean): CC[A] = drop(prefixLength(p))
+ override def span(p: A => Boolean): (CC[A], CC[A]) = splitAt(prefixLength(p))
+ override def last: A = if (length > 0) this(length - 1) else super.last
+ override def init: CC[A] = if (length > 0) slice(0, length - 1) else super.init
+
+ override def sameElements[B >: A](that: OrderedIterable[B]): Boolean = that match {
+ case that: Vector[_] =>
+ val len = length
+ len == that.length && {
+ var i = 0
+ while (i < len && this(i) == that(i)) i += 1
+ i == len
+ }
+ case _ =>
+ super.sameElements(that)
+ }
+
+ // Overridden methods from Sequence
+
+ override def lengthCompare(len: Int): Int = length - len
+
+ private def negLength(n: Int) = if (n == length) -1 else n
+
+ override def indexWhere(p: A => Boolean, from: Int): Int =
+ negLength(from + segmentLength(!p(_), from))
+
+ override def lastIndexWhere(p: A => Boolean, end: Int): Int = {
+ var i = end
+ while (i >= 0 && !p(this(i))) i -= 1
+ i
+ }
+
+ override def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end)
+
+ override def reverse: CC[A] = {
+ val b = newBuilder[A]
+ var i = length
+ while (0 < i) {
+ i -= 1
+ b += this(i)
+ }
+ b.result
+ }
+
+ override def reversedElements = new Iterator[A] {
+ var i = length
+ def hasNext: Boolean = 0 < i
+ def next: A =
+ if (0 < i) {
+ i -= 1
+ self(i)
+ } else Iterator.empty.next
+ }
+
+ override def startsWith[B](that: Sequence[B], offset: Int): Boolean = that match {
+ case that: Vector[_] =>
+ var i = offset
+ var j = 0
+ val thisLen = length
+ val thatLen = that.length
+ while (i < thisLen && j < thatLen && this(i) == that(j)) {
+ i += 1
+ j += 1
+ }
+ j == thatLen
+ case _ =>
+ var i = offset
+ val thisLen = length
+ val thatElems = that.elements
+ while (i < thisLen && thatElems.hasNext && this(i) == thatElems.next) {
+ i += 1
+ }
+ !thatElems.hasNext
+ }
+
+ override def endsWith[B](that: Sequence[B]): Boolean = that match {
+ case that: Vector[_] =>
+ val thisLen = length
+ val thatLen = that.length
+ var i = thisLen - 1
+ var j = thatLen - 1
+ while (i >= 0 && j >= 0 && this(i) == that(j)) {
+ i -= 1
+ j -= 1
+ }
+ j == 0
+ case _ =>
+ super.endsWith(that)
+ }
+
+ override def indexOf[B >: A](that: Sequence[B]): Int = {
+ var i = 0
+ val last = length - that.length
+ while (i <= last && !startsWith(that, i)) i += 1
+ negLength(i)
+ }
+}
+
diff --git a/src/library/scalax/collection/generic/mutable/VectorTemplate.scala b/src/library/scalax/collection/generic/mutable/VectorTemplate.scala
new file mode 100644
index 0000000000..aafee3ae3b
--- /dev/null
+++ b/src/library/scalax/collection/generic/mutable/VectorTemplate.scala
@@ -0,0 +1,55 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $
+
+package scalax.collection.generic.mutable
+
+import collection.mutable.Vector
+import collection.mutable.Vector._
+
+/** Sequences that support O(1) element access and O(1) length computation.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @version 2.8
+ */
+trait VectorTemplate[+CC[B] <: VectorTemplate[CC, B] with Vector[B], A] extends nonvariant.VectorTemplate[CC, A] {
+self =>
+
+ def update(idx: Int, elem: A)
+
+ /** Creates a view of this iterable @see OrderedIterable.View
+ */
+ override def view: VectorView[CC, A] = new VectorView[CC, A] { // !!! Martin: We should maybe infer the type parameters here?
+ val origin: Vector[_] = thisCC
+ val length: Int = self.length
+ def apply(idx: Int): A = self.apply(idx)
+ def update(idx: Int, elem: A) = self.update(idx, elem)
+ }
+
+ /** A sub-sequence view starting at index `from`
+ * and extending up to (but not including) index `until`.
+ *
+ * @param from The index of the first element of the slice
+ * @param until The index of the element following the slice
+ * @note The difference between `view` and `slice` is that `view` produces
+ * a view of the current sequence, whereas `slice` produces a new sequence.
+ *
+ * @note view(from, to) is equivalent to view.slice(from, to)
+ */
+ override def view(from: Int, until: Int): VectorView[CC, A] = view.slice(from, until)
+
+ def readOnly: Sequence[A] = new collection./*immutable.*/Vector[A] { //!!!
+ def length = self.length
+ def apply(idx : Int) = self.apply(idx)
+ def newBuilder[B]: Builder[CC, B] = self.newBuilder[B]
+ override def foreach(f: A => Unit) = self.foreach(f)
+ override def stringPrefix = self.stringPrefix+"RO"
+ }
+}
+
diff --git a/src/library/scalax/collection/generic/mutable/VectorView.scala b/src/library/scalax/collection/generic/mutable/VectorView.scala
new file mode 100644
index 0000000000..05a7bf6f5a
--- /dev/null
+++ b/src/library/scalax/collection/generic/mutable/VectorView.scala
@@ -0,0 +1,95 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.mutable
+
+import collection.mutable.Vector
+import collection.mutable.Vector._
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait VectorView[+UC[B] <: Vector[B], A] extends SequenceView[UC, A] with Vector[A] {
+self =>
+
+ /** refined from Iterable.View */
+ val origin: Vector[_]
+
+ trait Transformed[B] extends super.Transformed[B] with VectorView[UC, B] {
+ override val origin = self
+ override def elements: Iterator[B] = new Elements(0, length)
+ override protected def asCC = asInstanceOf[VectorView[UC, B]]
+ }
+
+ class Appended(that: Vector[A]) extends super.Appended[A](that) with Transformed[A] {
+ override def update(idx: Int, elem: A) {
+ val ll = self.length
+ if (idx < ll) self.update(idx, elem) else that.update(idx - ll, elem)
+ }
+ }
+
+ class Sliced(from: Int, to: Int) extends super.Sliced(from, to) with Transformed[A] {
+ override def update(idx: Int, elem: A) {
+ if (idx >= 0 && idx < length) self.update(idx + from, elem)
+ else throw new IndexOutOfBoundsException(idx.toString)
+ }
+ override def slice(from1: Int, to1: Int) =
+ new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0))
+ }
+
+ class Reversed extends super.Reversed with Transformed[A] {
+ override def update(idx: Int, elem: A) {
+ self.update(length - 1 - idx, elem)
+ }
+ }
+
+ class Zipped[B](that: Vector[B]) extends super.Zipped[B](that) with Transformed[(A, B)] {
+ override def update(idx: Int, elem: (A, B)) {
+ self.update(idx, elem._1)
+ that.update(idx, elem._2)
+ }
+ }
+
+ def ++(that: Vector[A]): VectorView[UC, A] =
+ new Appended(that).asCC
+
+ override def reverse: VectorView[UC, A] =
+ (new Reversed).asCC
+
+ private def toVector[B](xs: Iterable[B]): Vector[B] = xs match {
+ case ras: Vector[_] => ras.asInstanceOf[Vector[B]]
+ case _ => Vector() ++ xs
+ }
+
+ override def zip[B](that: Iterable[B]): VectorView[UC, (A, B)] =
+ new Zipped(toVector(that)).asCC
+
+ override def zipWithIndex: VectorView[UC, (A, Int)] =
+ zip((0 until length).asInstanceOf[Null]) // !!!
+ override def take(n: Int): VectorView[UC, A] =
+ slice(0, n)
+ override def drop(n: Int): VectorView[UC, A] =
+ slice(n, Math.MAX_INT)
+ override def splitAt(n: Int): (VectorView[UC, A], VectorView[UC, A]) = (take(n), drop(n))
+ override def slice(from: Int, until: Int): VectorView[UC, A] =
+ new Sliced(from, until).asCC
+ override def takeWhile(p: A => Boolean): VectorView[UC, A] =
+ take(prefixLength(p))
+ override def dropWhile(p: A => Boolean): VectorView[UC, A] =
+ drop(prefixLength(p))
+ override def span(p: A => Boolean): (VectorView[UC, A], VectorView[UC, A]) = {
+ val n = prefixLength(p)
+ (take(n), drop(n))
+ }
+}
+
diff --git a/src/library/scalax/collection/generic/nonvariant/IterableFactory.scala b/src/library/scalax/collection/generic/nonvariant/IterableFactory.scala
new file mode 100755
index 0000000000..a3786a246d
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/IterableFactory.scala
@@ -0,0 +1,3 @@
+package scalax.collection.generic.nonvariant
+
+trait IterableFactory[CC[A] <: Iterable[A]] extends generic.IterableFactory[CC]
diff --git a/src/library/scalax/collection/generic/nonvariant/IterableTemplate.scala b/src/library/scalax/collection/generic/nonvariant/IterableTemplate.scala
new file mode 100755
index 0000000000..cb4b5bdaac
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/IterableTemplate.scala
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic.nonvariant
+
+/** Collection classes mixing in this class provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @note If a collection has a known <code>size</code>, it should also sub-type <code>Collection</code>.
+ * Only potentially unbounded collections should directly sub-class <code>Iterable</code>.
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+trait IterableTemplate[+CC[B] <: IterableTemplate[CC, B] with Iterable[B] , A]
+ extends generic.IterableTemplate[CC, A] { self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/generic/nonvariant/IterableView.scala b/src/library/scalax/collection/generic/nonvariant/IterableView.scala
new file mode 100755
index 0000000000..66238b19ac
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/IterableView.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+package scalax.collection.generic.nonvariant
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait IterableView[+UC[B] <: Iterable[B], A]
+ extends generic.IterableView[UC, A]
diff --git a/src/library/scalax/collection/generic/nonvariant/OrderedIterableTemplate.scala b/src/library/scalax/collection/generic/nonvariant/OrderedIterableTemplate.scala
new file mode 100755
index 0000000000..59358875a0
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/OrderedIterableTemplate.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+
+package scalax.collection.generic.nonvariant
+
+trait OrderedIterableTemplate[+CC[B] <: OrderedIterableTemplate[CC, B] with OrderedIterable[B], A]
+ extends generic.OrderedIterableTemplate[CC, A] {self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/generic/nonvariant/SequenceFactory.scala b/src/library/scalax/collection/generic/nonvariant/SequenceFactory.scala
new file mode 100755
index 0000000000..5c658b0bfb
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/SequenceFactory.scala
@@ -0,0 +1,3 @@
+package scalax.collection.generic.nonvariant
+
+trait SequenceFactory[CC[A] <: Sequence[A]] extends IterableFactory[CC] with generic.SequenceFactory[CC]
diff --git a/src/library/scalax/collection/generic/nonvariant/SequenceTemplate.scala b/src/library/scalax/collection/generic/nonvariant/SequenceTemplate.scala
new file mode 100755
index 0000000000..7f9b2acd60
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/SequenceTemplate.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.nonvariant
+
+trait SequenceTemplate[+CC[B] <: SequenceTemplate[CC, B] with Sequence[B], A]
+ extends generic.SequenceTemplate[CC, A] {self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/generic/nonvariant/SequenceView.scala b/src/library/scalax/collection/generic/nonvariant/SequenceView.scala
new file mode 100755
index 0000000000..46f5716ad4
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/SequenceView.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.nonvariant
+
+
+/** A non-strict projection of an iterable.
+ * @author Sean McDirmid
+ * @author Martin Odersky
+ * @note this should really be a virtual class of SequenceFactory
+ */
+trait SequenceView[+UC[B] <: Sequence[B], A]
+ extends IterableView[UC, A] with generic.SequenceView[UC, A]
diff --git a/src/library/scalax/collection/generic/nonvariant/VectorTemplate.scala b/src/library/scalax/collection/generic/nonvariant/VectorTemplate.scala
new file mode 100644
index 0000000000..7dfc4db64d
--- /dev/null
+++ b/src/library/scalax/collection/generic/nonvariant/VectorTemplate.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $
+
+
+package scalax.collection.generic.nonvariant
+
+trait VectorTemplate[+CC[B] <: VectorTemplate[CC, B] with Vector[B], A]
+ extends generic.VectorTemplate[CC, A] {self /*: CC[A]*/ => }
diff --git a/src/library/scalax/collection/immutable/List.scala b/src/library/scalax/collection/immutable/List.scala
new file mode 100644
index 0000000000..366ae15d15
--- /dev/null
+++ b/src/library/scalax/collection/immutable/List.scala
@@ -0,0 +1,1222 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: List.scala 16287 2008-10-18 13:41:36Z nielsen $
+
+
+package scalax.collection.immutable
+
+import mutable.ListBuffer
+import generic.covariant.SequenceTemplate
+
+/** A class representing an ordered collection of elements of type
+ * <code>a</code>. This class comes with two implementing case
+ * classes <code>scala.Nil</code> and <code>scala.::</code> that
+ * implement the abstract members <code>isEmpty</code>,
+ * <code>head</code> and <code>tail</code>.
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 16/07/2003
+ */
+sealed abstract class List[+A] extends Sequence[A] with SequenceTemplate[List, A] with Product {
+
+ /** Returns true if the list does not contain any elements.
+ * @return <code>true</code>, iff the list is empty.
+ */
+ def isEmpty: Boolean
+
+ /** Returns this first element of the list.
+ *
+ * @return the first element of this list.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ def head: A
+
+ /** Returns this list without its first element.
+ *
+ * @return this list without its first element.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ def tail: List[A]
+
+ def newBuilder[B]: Builder[List, B] = new ListBuffer[B]
+
+ /** <p>
+ * Add an element <code>x</code> at the beginning of this list.
+ * </p>
+ *
+ * @param x the element to prepend.
+ * @return the list with <code>x</code> added at the beginning.
+ * @ex <code>1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)</code>
+ */
+ def ::[B >: A] (x: B): List[B] =
+ new scalax.collection.immutable.::(x, this)
+
+ /** <p>
+ * Returns a list resulting from the concatenation of the given
+ * list <code>prefix</code> and this list.
+ * </p>
+ *
+ * @param prefix the list to concatenate at the beginning of this list.
+ * @return the concatenation of the two lists.
+ * @ex <code>List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)</code>
+ */
+ def :::[B >: A](prefix: List[B]): List[B] =
+ if (isEmpty) prefix
+ else (new ListBuffer[B] ++ prefix).prependToList(this)
+
+ /** Appends two list objects.
+ */
+ override def ++[B >: A](that: Iterable[B]): List[B] =
+ this ::: that.toList
+
+ /** Reverse the given prefix and append the current list to that.
+ * This function is equivalent to an application of <code>reverse</code>
+ * on the prefix followed by a call to <code>:::</code>, but more
+ * efficient (and tail recursive).
+ *
+ * @param prefix the prefix to reverse and then prepend
+ * @return the concatenation of the reversed prefix and the current list.
+ */
+ def reverse_:::[B >: A](prefix: List[B]): List[B] = {
+ var these: List[B] = this
+ var pres = prefix
+ while (!pres.isEmpty) {
+ these = pres.head :: these
+ pres = pres.tail
+ }
+ these
+ }
+
+ /** Returns the number of elements in the list.
+ *
+ * @return the number of elements in the list.
+ */
+ def length: Int = {
+ var these = this
+ var len = 0
+ while (!these.isEmpty) {
+ len += 1
+ these = these.tail
+ }
+ len
+ }
+
+ /** Returns the elements in the list as an iterator
+ *
+ * @return an iterator on the list elements.
+ */
+ override def elements: Iterator[A] = new Iterator[A] {
+ var these = List.this
+ def hasNext: Boolean = !these.isEmpty
+ def next: A =
+ if (!hasNext)
+ throw new NoSuchElementException("next on empty Iterator")
+ else {
+ val result = these.head; these = these.tail; result
+ }
+ override def toList: List[A] = these
+ }
+
+ /** Overrides the method in Iterable for efficiency.
+ *
+ * @return the list itself
+ */
+ override def toList: List[A] = this
+
+ /** Returns the <code>n</code> first elements of this list, or else the whole
+ * list, if it has less than <code>n</code> elements.
+ *
+ * @param n the number of elements to take.
+ * @return the <code>n</code> first elements of this list.
+ */
+ override def take(n: Int): List[A] = {
+ val b = new ListBuffer[A]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i += 1
+ b += these.head
+ these = these.tail
+ }
+ if (these.isEmpty) this
+ else b.toList
+ }
+
+ /** Returns the list with elements belonging to the given index range.
+ *
+ * @param start the start position of the list slice.
+ * @param end the end position (exclusive) of the list slice.
+ * @return the list with elements belonging to the given index range.
+ */
+ override def slice(start: Int, end: Int): List[A] = {
+ val s = start max 0
+ val e = end min this.length
+ drop(s) take (e - s)
+ }
+
+ /** Returns the list without its <code>n</code> first elements.
+ * If this list has less than <code>n</code> elements, the empty list is returned.
+ *
+ * @param n the number of elements to drop.
+ * @return the list without its <code>n</code> first elements.
+ */
+ override def drop(n: Int): List[A] = {
+ var these = this
+ var count = n
+ while (!these.isEmpty && count > 0) {
+ these = these.tail
+ count -= 1
+ }
+ these
+ }
+
+ /** Returns the rightmost <code>n</code> elements from this list.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ */
+ override def takeRight(n: Int): List[A] = {
+ def loop(lead: List[A], lag: List[A]): List[A] = lead match {
+ case Nil => lag
+ case _ :: tail => loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Returns the list wihout its rightmost <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return the list without its rightmost <code>n</code> elements
+ */
+ override def dropRight(n: Int): List[A] = {
+ def loop(lead: List[A], lag: List[A]): List[A] = lead match {
+ case Nil => Nil
+ case _ :: tail => lag.head :: loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Split the list at a given point and return the two parts thus
+ * created.
+ *
+ * @param n the position at which to split
+ * @return a pair of lists composed of the first <code>n</code>
+ * elements, and the other elements.
+ */
+ override def splitAt(n: Int): (List[A], List[A]) = {
+ val b = new ListBuffer[A]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i += 1
+ b += these.head
+ these = these.tail
+ }
+ (b.toList, these)
+ }
+
+ /** Returns the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ override def takeWhile(p: A => Boolean): List[A] = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Returns the longest suffix of this list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ */
+ override def dropWhile(p: A => Boolean): List[A] =
+ if (isEmpty || !p(head)) this
+ else tail dropWhile p
+
+ /** Returns the longest prefix of the list whose elements all satisfy
+ * the given predicate, and the rest of the list.
+ *
+ * @param p the test predicate
+ * @return a pair consisting of the longest prefix of the list whose
+ * elements all satisfy <code>p</code>, and the rest of the list.
+ */
+ override def span(p: A => Boolean): (List[A], List[A]) = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ (b.toList, these)
+ }
+
+ /** Returns the <code>n</code>-th element of this list. The first element
+ * (head of the list) is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this list.
+ * @throws Predef.NoSuchElementException if the list is too short.
+ */
+ def apply(n: Int): A = drop(n).head
+
+ /** Returns the list resulting from applying the given function <code>f</code> to each
+ * element of this list.
+ *
+ * @param f function to apply to each element.
+ * @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>.
+ */
+ final override def map[B](f: A => B): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ b += f(these.head)
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Apply a function to all the elements of the list, and return the
+ * reversed list of results. This is equivalent to a call to <code>map</code>
+ * followed by a call to <code>reverse</code>, but more efficient.
+ *
+ * @param f the function to apply to each elements.
+ * @return the reversed list of results.
+ */
+ def reverseMap[B](f: A => B): List[B] = {
+ def loop(l: List[A], res: List[B]): List[B] = l match {
+ case Nil => res
+ case head :: tail => loop(tail, f(head) :: res)
+ }
+ loop(this, Nil)
+ }
+
+ /** Apply the given function <code>f</code> to each element of this list
+ * (while respecting the order of the elements).
+ *
+ * @param f the treatment to apply to each element.
+ */
+ final override def foreach(f: A => Unit) {
+ var these = this
+ while (!these.isEmpty) {
+ f(these.head)
+ these = these.tail
+ }
+ }
+
+ /** Returns all the elements of this list that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ * It is guarenteed that the receiver list itself is returned iff all its
+ * elements satisfy the predicate `p'. Hence the following equality is valid:
+ *
+ * (xs filter p) eq xs == xs forall p
+ *
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ final override def filter(p: A => Boolean): List[A] = {
+ // return same list if all elements satisfy p
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ these = these.tail
+ }
+ if (these.isEmpty) this
+ else {
+ val b = new ListBuffer[A]
+ var these1 = this
+ while (these1 ne these) {
+ b += these1.head
+ these1 = these1.tail
+ }
+
+ these = these.tail // prevent the second evaluation of the predicate
+ // on the element on which it first failed
+ while (!these.isEmpty) {
+ if (p(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+ }
+
+ /** <p>
+ * Sort the list according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>,
+ * which should be true iff <code>e1</code> is smaller than
+ * <code>e2</code>.
+ * </p>
+ *
+ * @param lt the comparison function
+ * @return a list sorted according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>.
+ * @ex <pre>
+ * List("Steve", "Tom", "John", "Bob")
+ * .sort((e1, e2) => (e1 compareTo e2) &lt; 0) =
+ * List("Bob", "John", "Steve", "Tom")</pre>
+ */
+ def sort(lt : (A,A) => Boolean): List[A] = {
+ /** Merge two already-sorted lists */
+ def merge(l1: List[A], l2: List[A]): List[A] = {
+ val res = new ListBuffer[A]
+ var left1 = l1
+ var left2 = l2
+
+ while (!left1.isEmpty && !left2.isEmpty) {
+ if(lt(left1.head, left2.head)) {
+ res += left1.head
+ left1 = left1.tail
+ } else {
+ res += left2.head
+ left2 = left2.tail
+ }
+ }
+
+ res ++= left1
+ res ++= left2
+
+ res.toList
+ }
+
+ /** Split a list into two lists of about the same size */
+ def split(lst: List[A]) = {
+ val res1 = new ListBuffer[A]
+ val res2 = new ListBuffer[A]
+ var left = lst
+
+ while (!left.isEmpty) {
+ res1 += left.head
+ left = left.tail
+ if (!left.isEmpty) {
+ res2 += left.head
+ left = left.tail
+ }
+ }
+
+ (res1.toList, res2.toList)
+ }
+
+
+ /** Merge-sort the specified list */
+ def ms(lst: List[A]): List[A] =
+ lst match {
+ case Nil => lst
+ case x :: Nil => lst
+ case x :: y :: Nil =>
+ if (lt(x,y))
+ lst
+ else
+ y :: x :: Nil
+
+ case lst =>
+ val (l1, l2) = split(lst)
+ val l1s = ms(l1)
+ val l2s = ms(l2)
+ merge(l1s, l2s)
+ }
+
+ ms(this)
+ }
+
+ /** Tests if the predicate <code>p</code> is satisfied by all elements
+ * in this list.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff all elements of this list satisfy the
+ * predicate <code>p</code>.
+ */
+ override def forall(p: A => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (!p(these.head)) return false
+ these = these.tail
+ }
+ true
+ }
+
+ /** Tests the existence in this list of an element that satisfies the
+ * predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff there exists an element in this list that
+ * satisfies the predicate <code>p</code>.
+ */
+ override def exists(p: A => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return true
+ these = these.tail
+ }
+ false
+ }
+
+ /** Find and return the first element of the list satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the list satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ override def find(p: A => Boolean): Option[A] = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return Some(these.head)
+ these = these.tail
+ }
+ None
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the list is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldLeft[B](z: B)(f: (B, A) => B): B = {
+ var acc = z
+ var these = this
+ while (!these.isEmpty) {
+ acc = f(acc, these.head)
+ these = these.tail
+ }
+ acc
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldRight[B](z: B)(f: (A, B) => B): B = this match {
+ case Nil => z
+ case x :: xs => f(x, xs.foldRight(z)(f))
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the list has elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ override def reduceLeft[B >: A](f: (B, A) => B): B = this match {
+ case Nil => throw new UnsupportedOperationException("Nil.reduceLeft")
+ case x :: Nil => x
+ case x0 :: x1 :: xs =>
+ var acc : B = f(x0, x1)
+ var these : List[A] = xs
+ while (!these.isEmpty) {
+ acc = f(acc, these.head)
+ these = these.tail
+ }
+ acc
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from right to left
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the list has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ *
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ override def reduceRight[B >: A](f: (A, B) => B): B = this match {
+ case Nil => throw new UnsupportedOperationException("Nil.reduceRight")
+ case x :: Nil => x
+ case x :: xs => f(x, xs reduceRight f)
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this list, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this list is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ final override def flatMap[B](f: A => Iterable[B]): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ var those = f(these.head).elements
+ while (those.hasNext) {
+ b += those.next
+ }
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** A list consisting of all elements of this list in reverse order.
+ */
+ override def reverse: List[A] = {
+ var result: List[A] = Nil
+ var these = this
+ while (!these.isEmpty) {
+ result = these.head :: result
+ these = these.tail
+ }
+ result
+ }
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two lists is longer than the other, its remaining elements are ignored.
+ *
+ * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>))</code> when
+ * <code>List(a<sub>0</sub>, ..., a<sub>m</sub>)
+ * zip List(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked.
+ */
+ def zip[B](that: List[B]): List[(A, B)] = {
+ val b = new ListBuffer[(A, B)]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += ((these.head, those.head))
+ these = these.tail
+ those = those.tail
+ }
+ b.toList
+ }
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param that list <code>that</code> may have a different length
+ * as the self list.
+ * @param thisElem element <code>thisElem</code> is used to fill up the
+ * resulting list if the self list is shorter than
+ * <code>that</code>
+ * @param thatElem element <code>thatElem</code> is used to fill up the
+ * resulting list if <code>that</code> is shorter than
+ * the self list
+ * @return <code>List((a<sub>0</sub>,b<sub>0</sub>), ...,
+ * (a<sub>n</sub>,b<sub>n</sub>), (elem,b<sub>n+1</sub>),
+ * ..., {elem,b<sub>m</sub>})</code>
+ * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
+ * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
+ * invoked where <code>m &gt; n</code>.
+ */
+ def zipAll[B, C >: A, D >: B](that: List[B], thisElem: C, thatElem: D): List[(C, D)] = {
+ val b = new ListBuffer[(C, D)]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += ((these.head, those.head))
+ these = these.tail
+ those = those.tail
+ }
+ while (!these.isEmpty) {
+ b += ((these.head, thatElem))
+ these = these.tail
+ }
+ while (!those.isEmpty) {
+ b += ((thisElem, those.head))
+ those = those.tail
+ }
+ b.toList
+ }
+
+ /** Computes the union of this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to add to the list.
+ * @return a list without doubles containing the elements of this
+ * list and those of the given list <code>that</code>.
+ */
+ def union[B >: A](that: List[B]): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ if (!that.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.prependToList(that)
+ }
+
+ /** Computes the difference between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to remove from this list.
+ * @return this list without the elements of the given list
+ * <code>that</code>.
+ * @deprecated use <code>--</code> instead
+ */
+ @deprecated
+ def diff[B >: A](that: List[B]): List[B] = this -- that
+
+ /** Computes the difference between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to remove from this list.
+ * @return this list without the elements of the given list
+ * <code>that</code>.
+ */
+ def -- [B >: A](that: List[B]): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ if (!that.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Computes the difference between this list and the given object
+ * <code>x</code>.
+ *
+ * @param x the object to remove from this list.
+ * @return this list without the elements of the given object
+ * <code>x</code>.
+ */
+ def - [B >: A](x: B): List[B] = {
+ val b = new ListBuffer[B]
+ var these = this
+ while (!these.isEmpty) {
+ if (these.head != x) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Concatenate the elements of this list. The elements of this list
+ * should be a <code>Iterables</code>.
+ *
+ * Note: The compiler might not be able to infer the type parameter.
+ *
+ * @param f An implicit conversion to an <code>Iterable</code> instance.
+ * @return The concatenation of all elements of iterables in this list.
+ */
+ def flatten[B](implicit f : A => Iterable[B]) : List[B] = {
+ val buf = new ListBuffer[B]
+ foreach(f(_).foreach(buf += _))
+ buf.toList
+ }
+
+ override def stringPrefix = "List"
+
+ override def toStream : Stream[A] = null // !!!
+ /*new Stream.Definite[A] {
+ override def force : List[A] = List.this
+ override def isEmpty = List.this.isEmpty
+ override def head = List.this.head
+ override def tail = List.this.tail.toStream
+ protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = if (!isEmpty) {
+ var prefix0 = prefix
+ var buf1 = buf.append(prefix0).append(head)
+ prefix0 = ", "
+ var tail0 = tail
+ while (!tail0.isEmpty) {
+ buf1 = buf.append(prefix0).append(tail0.head)
+ tail0 = tail0.tail
+ }
+ buf1
+ } else buf
+ }*/
+
+}
+
+/** The empty list.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+@SerialVersionUID(0 - 8256821097970055419L)
+case object Nil extends List[Nothing] {
+ override def isEmpty = true
+ override def head: Nothing =
+ throw new NoSuchElementException("head of empty list")
+ override def tail: List[Nothing] =
+ throw new NoSuchElementException("tail of empty list")
+}
+
+/** A non empty list characterized by a head and a tail.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+@SerialVersionUID(0L - 8476791151983527571L)
+final case class ::[B](private var hd: B, private[scalax] var tl: List[B]) extends List[B] {
+ override def head : B = hd
+ override def tail : List[B] = tl
+ override def isEmpty: Boolean = false
+
+ import java.io._
+
+ private def writeObject(out: ObjectOutputStream) {
+ var xs: List[B] = this
+ while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail }
+ out.writeObject(ListSerializeEnd)
+ }
+
+ private def readObject(in: ObjectInputStream) {
+ hd = in.readObject.asInstanceOf[B]
+ assert(hd != ListSerializeEnd)
+ var current: ::[B] = this
+ while (true) in.readObject match {
+ case ListSerializeEnd =>
+ current.tl = Nil
+ return
+ case a : Any =>
+ val list : ::[B] = new ::(a.asInstanceOf[B], Nil)
+ current.tl = list
+ current = list
+ }
+ }
+}
+
+/** Only used for list serialization */
+@SerialVersionUID(0L - 8476791151975527571L)
+private[scalax] case object ListSerializeEnd
+/** This object provides methods for creating specialized lists, and for
+ * transforming special kinds of lists (e.g. lists of lists).
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 15/07/2003
+ */
+object List {
+
+ /** Create a list with given elements.
+ *
+ * @param xs the elements to put in the list
+ * @return the list containing elements xs.
+ */
+ def apply[A](xs: A*): List[A] = (xs.asInstanceOf[Iterable[A]]).toList // !!!
+
+ /** for unapply matching
+ */
+ def unapplySeq[A](x: List[A]): Some[List[A]] = Some(x)
+
+ /** Create a sorted list of all integers in a range.
+ *
+ * @param from the start value of the list
+ * @param end the end value of the list
+ * @return the sorted list of all integers in range [from;end).
+ */
+ def range(start: Int, end: Int): List[Int] =
+ range(start, end, 1)
+
+ /** Create a list with element values
+ * <code>v<sub>n+1</sub> = v<sub>n</sub> + step</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and elements are in the range between <code>start</code> (inclusive)
+ * and <code>end</code> (exclusive)
+ *
+ * @param start the start value of the list
+ * @param end the end value of the list
+ * @param step the increment value of the list
+ * @return the sorted list of all integers in range [start;end).
+ */
+ def range(start: Int, end: Int, step: Int): List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = start
+ while ((step <= 0 || i < end) && (step >= 0 || i > end)) {
+ b += i
+ i += step
+ }
+ b.toList
+ }
+
+ /** Create a sorted list with element values
+ * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and elements are in the range between <code>start</code> (inclusive)
+ * and <code>end</code> (exclusive)
+ *
+ * @param start the start value of the list
+ * @param end the end value of the list
+ * @param step the increment function of the list, must be monotonically increasing or decreasing
+ * @return the sorted list of all integers in range [start;end).
+ */
+ def range(start: Int, end: Int, step: Int => Int): List[Int] = {
+ val up = step(start) > start
+ val down = step(start) < start
+ val b = new ListBuffer[Int]
+ var i = start
+ while ((!up || i < end) && (!down || i > end)) {
+ b += i
+ i += step(i)
+ }
+ b.toList
+ }
+
+ /** Create a list containing several copies of an element.
+ *
+ * @param n the length of the resulting list
+ * @param elem the element composing the resulting list
+ * @return a list composed of n elements all equal to elem
+ */
+ def make[A](n: Int, elem: A): List[A] = {
+ val b = new ListBuffer[A]
+ var i = 0
+ while (i < n) {
+ b += elem
+ i += 1
+ }
+ b.toList
+ }
+
+ /** Create a list by applying a function to successive integers.
+ *
+ * @param n the length of the resulting list
+ * @param maker the procedure which, given an integer <code>n</code>,
+ * returns the nth element of the resulting list, where
+ * <code>n</code> is in interval <code>[0;n)</code>.
+ * @return the list obtained by applying the maker function to
+ * successive integers from 0 to n (exclusive).
+ */
+ def tabulate[A](n: Int, maker: Int => A): List[A] = {
+ val b = new ListBuffer[A]
+ var i = 0
+ while (i < n) {
+ b += maker(i)
+ i += 1
+ }
+ b.toList
+ }
+
+ /** Concatenate all the elements of a given list of lists.
+ *
+ * @param xss the list of lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def flatten[A](xss: List[List[A]]): List[A] = {
+ val b = new ListBuffer[A]
+ for (xs <- xss) {
+ var xc = xs
+ while (!xc.isEmpty) {
+ b += xc.head
+ xc = xc.tail
+ }
+ }
+ b.toList
+ }
+
+ /** Concatenate all the argument lists into a single list.
+ *
+ * @param xss the lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def concat[A](xss: List[A]*): List[A] = {
+ val b = new ListBuffer[A]
+ for (xs <- xss) {
+ var xc = xs
+ while (!xc.isEmpty) {
+ b += xc.head
+ xc = xc.tail
+ }
+ }
+ b.toList
+ }
+
+ /** Transforms a list of pairs into a pair of lists.
+ *
+ * @param xs the list of pairs to unzip
+ * @return a pair of lists.
+ */
+ def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = {
+ val b1 = new ListBuffer[A]
+ val b2 = new ListBuffer[B]
+ var xc = xs
+ while (!xc.isEmpty) {
+ b1 += xc.head._1
+ b2 += xc.head._2
+ xc = xc.tail
+ }
+ (b1.toList, b2.toList)
+ }
+
+ /** Transforms an iterable of pairs into a pair of lists.
+ *
+ * @param xs the iterable of pairs to unzip
+ * @return a pair of lists.
+ */
+ def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) =
+ xs.foldRight[(List[A], List[B])]((Nil, Nil)) {
+ case ((x, y), (xs, ys)) => (x :: xs, y :: ys)
+ }
+
+ /**
+ * Returns the <code>Left</code> values in the given <code>Iterable</code> of <code>Either</code>s.
+ */
+ def lefts[A, B](es: Iterable[Either[A, B]]) =
+ es.foldRight[List[A]](Nil)((e, as) => e match {
+ case Left(a) => a :: as
+ case Right(_) => as
+ })
+
+ /**
+ * Returns the <code>Right</code> values in the given<code>Iterable</code> of <code>Either</code>s.
+ */
+ def rights[A, B](es: Iterable[Either[A, B]]) =
+ es.foldRight[List[B]](Nil)((e, bs) => e match {
+ case Left(_) => bs
+ case Right(b) => b :: bs
+ })
+
+ /** Transforms an Iterable of Eithers into a pair of lists.
+ *
+ * @param xs the iterable of Eithers to separate
+ * @return a pair of lists.
+ */
+ def separate[A,B](es: Iterable[Either[A,B]]): (List[A], List[B]) =
+ es.foldRight[(List[A], List[B])]((Nil, Nil)) {
+ case (Left(a), (lefts, rights)) => (a :: lefts, rights)
+ case (Right(b), (lefts, rights)) => (lefts, b :: rights)
+ }
+
+ /** Converts an iterator to a list.
+ *
+ * @param it the iterator to convert
+ * @return a list that contains the elements returned by successive
+ * calls to <code>it.next</code>
+ */
+ def fromIterator[A](it: Iterator[A]): List[A] = it.toList
+
+ /** Converts an array into a list.
+ *
+ * @param arr the array to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length)
+
+ /** Converts a range of an array into a list.
+ *
+ * @param arr the array to convert
+ * @param start the first index to consider
+ * @param len the lenght of the range to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = {
+ var res: List[A] = Nil
+ var i = start + len
+ while (i > start) {
+ i -= 1
+ res = arr(i) :: res
+ }
+ res
+ }
+
+ /** Parses a string which contains substrings separated by a
+ * separator character and returns a list of all substrings.
+ *
+ * @param str the string to parse
+ * @param separator the separator character
+ * @return the list of substrings
+ */
+ def fromString(str: String, separator: Char): List[String] = {
+ var words: List[String] = Nil
+ var pos = str.length()
+ while (pos > 0) {
+ val pos1 = str.lastIndexOf(separator, pos - 1)
+ if (pos1 + 1 < pos)
+ words = str.substring(pos1 + 1, pos) :: words
+ pos = pos1
+ }
+ words
+ }
+
+ /** Returns the given string as a list of characters.
+ *
+ * @param str the string to convert.
+ * @return the string as a list of characters.
+ * @deprecated use <code>str.toList</code> instead
+ */
+ @deprecated def fromString(str: String): List[Char] =
+ str.toList.asInstanceOf[List[Char]] // !!!
+
+ /** Returns the given list of characters as a string.
+ *
+ * @param xs the list to convert.
+ * @return the list in form of a string.
+ */
+ def toString(xs: List[Char]): String = {
+ val sb = new StringBuilder()
+ var xc = xs
+ while (!xc.isEmpty) {
+ sb.append(xc.head)
+ xc = xc.tail
+ }
+ sb.toString()
+ }
+
+ /** Like xs map f, but returns <code>xs</code> unchanged if function
+ * <code>f</code> maps all elements to themselves.
+ *
+ * @param xs ...
+ * @param f ...
+ * @return ...
+ */
+ def mapConserve[A <: AnyRef](xs: List[A])(f: A => A): List[A] = {
+ def loop(ys: List[A]): List[A] =
+ if (ys.isEmpty) xs
+ else {
+ val head0 = ys.head
+ val head1 = f(head0)
+ if (head1 eq head0) {
+ loop(ys.tail)
+ } else {
+ val ys1 = head1 :: mapConserve(ys.tail)(f)
+ if (xs eq ys) ys1
+ else {
+ val b = new ListBuffer[A]
+ var xc = xs
+ while (xc ne ys) {
+ b += xc.head
+ xc = xc.tail
+ }
+ b.prependToList(ys1)
+ }
+ }
+ }
+ loop(xs)
+ }
+
+ /** Returns the list resulting from applying the given function <code>f</code>
+ * to corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a0,b0), ..., f(an,bn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>n = min(k,l)</code>
+ */
+ def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = {
+ val b = new ListBuffer[C]
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ b += f(xc.head, yc.head)
+ xc = xc.tail
+ yc = yc.tail
+ }
+ b.toList
+ }
+
+ /** Returns the list resulting from applying the given function
+ * <code>f</code> to corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a<sub>0</sub>,b<sub>0</sub>,c<sub>0</sub>),
+ * ..., f(a<sub>n</sub>,b<sub>n</sub>,c<sub>n</sub>)]</code>
+ * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>,
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>,
+ * <code>[c<sub>0</sub>, ..., c<sub>m</sub>]</code> and
+ * <code>n = min(k,l,m)</code>
+ */
+ def map3[A,B,C,D](xs: List[A], ys: List[B], zs: List[C])(f: (A, B, C) => D): List[D] = {
+ val b = new ListBuffer[D]
+ var xc = xs
+ var yc = ys
+ var zc = zs
+ while (!xc.isEmpty && !yc.isEmpty && !zc.isEmpty) {
+ b += f(xc.head, yc.head, zc.head)
+ xc = xc.tail
+ yc = yc.tail
+ zc = zc.tail
+ }
+ b.toList
+ }
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for all corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>(p(a<sub>0</sub>,b<sub>0</sub>) &amp;&amp;
+ * ... &amp;&amp; p(a<sub>n</sub>,b<sub>n</sub>))]</code>
+ * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>;
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>
+ * and <code>n = min(k,l)</code>
+ */
+ def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = {
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ if (!f(xc.head, yc.head)) return false
+ xc = xc.tail
+ yc = yc.tail
+ }
+ true
+ }
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for some corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n != 0 &amp;&amp; (p(a<sub>0</sub>,b<sub>0</sub>) ||
+ * ... || p(a<sub>n</sub>,b<sub>n</sub>))]</code> if the lists are
+ * <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>,
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code> and
+ * <code>n = min(k,l)</code>
+ */
+ def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = {
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ if (f(xc.head, yc.head)) return true
+ xc = xc.tail
+ yc = yc.tail
+ }
+ false
+ }
+
+ /** Transposes a list of lists.
+ * pre: All element lists have the same length.
+ *
+ * @param xss the list of lists
+ * @return the transposed list of lists
+ */
+ def transpose[A](xss: List[List[A]]): List[List[A]] = {
+ val buf = new ListBuffer[List[A]]
+ var yss = xss
+ while (!yss.head.isEmpty) {
+ buf += (yss map (_.head))
+ yss = (yss map (_.tail))
+ }
+ buf.toList
+ }
+
+ /** Lists with ordered elements are ordered
+ implicit def list2ordered[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = new Ordered[List[a]] {
+ def compare [b >: List[a] <% Ordered[b]](y: b): Int = y match {
+ case y1: List[a] => compareLists(x, y1);
+ case _ => -(y compare x)
+ }
+ private def compareLists(xs: List[a], ys: List[a]): Int = {
+ if (xs.isEmpty && ys.isEmpty) 0
+ else if (xs.isEmpty) -1
+ else if (ys.isEmpty) 1
+ else {
+ val s = xs.head compare ys.head;
+ if (s != 0) s
+ else compareLists(xs.tail, ys.tail)
+ }
+ }
+ }
+ */
+}
+
diff --git a/src/library/scalax/collection/mutable/Appendable.scala b/src/library/scalax/collection/mutable/Appendable.scala
new file mode 100644
index 0000000000..b8e8569a14
--- /dev/null
+++ b/src/library/scalax/collection/mutable/Appendable.scala
@@ -0,0 +1,94 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $
+
+package scalax.collection.mutable
+
+/** This class represents collections that can be augmented using a += operator.
+ *
+ * @autor Martin Odersky
+ * @owner Martin Odersky
+ * @version 2.8
+ */
+trait Appendable[A] {
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A): Unit
+
+ /** Append a two or more elements to this buffer.
+ *
+ * @param elem1 the first element to append.
+ * @param elem2 the second element to append.
+ * @param elems the remaining elements to append.
+ */
+ def +=(elem1: A, elem2: A, elems: A*) {
+ this += elem1
+ this += elem2
+ this ++= elems.asInstanceOf[Iterable[A]] // !!!
+ }
+
+ /** Appends a number of elements provided by an iterator
+ *
+ * @param iter the iterator.
+ */
+ def ++=(iter: collection.Iterator[A]) { iter foreach += }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def ++=(iter: collection.Iterable[A]) { iter foreach += }
+
+ /** Append a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +(elem: A): this.type = { this += elem; this }
+
+ /** Append two or more elements to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem1 the first element to append.
+ * @param elem2 the second element to append.
+ * @param elems the remaining elements to append.
+ */
+ def +(elem1: A, elem2: A, elems: A*): this.type =
+ this + elem1 + elem2 ++ elems.asInstanceOf[Iterable[A]] // !!!
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ def ++(iter: Iterable[A]): this.type = { this ++= iter; this }
+
+ /** Appends a number of elements provided by an iterator
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterator
+ * @return the updated buffer.
+ */
+ def ++(iter: Iterator[A]): this.type = { this ++= iter; this }
+
+ /** Clears the buffer contents.
+ */
+ def clear()
+}
+
+
+
+
diff --git a/src/library/scalax/collection/mutable/ArrayBuffer.scala b/src/library/scalax/collection/mutable/ArrayBuffer.scala
new file mode 100644
index 0000000000..3e4877cef7
--- /dev/null
+++ b/src/library/scalax/collection/mutable/ArrayBuffer.scala
@@ -0,0 +1,118 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ArrayBuffer.scala 15407 2008-06-20 09:26:36Z stepancheg $
+
+
+package scalax.collection.mutable
+
+/** An implementation of the <code>Buffer</code> class using an array to
+ * represent the assembled sequence internally. Append, update and random
+ * access take constant time (amortized time). Prepends and removes are
+ * linear in the buffer size.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+@serializable
+class ArrayBuffer[A] extends Buffer[A] with Builder[ArrayBuffer, A] with ResizableArray[A] {
+
+ def clear() {
+ size0 = 0
+ }
+
+ /** Appends a single element to this buffer and returns
+ * the identity of the buffer. It takes constant time.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A) {
+ ensureSize(size0 + 1)
+ array(size0) = elem.asInstanceOf[AnyRef]
+ size0 += 1
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ override def ++=(iter: Iterable[A]) { iter copyToBuffer this }
+
+ /** Prepends a single element to this buffer and return
+ * the identity of the buffer. It takes time linear in
+ * the buffer size.
+ *
+ * @param elem the element to append.
+ * @return the updated buffer.
+ */
+ def +:(elem: A): this.type = {
+ ensureSize(size0 + 1)
+ copy(0, 1, size0)
+ array(0) = elem.asInstanceOf[AnyRef]
+ size0 += 1
+ this
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ override def ++:(iter: Iterable[A]): this.type = { insertAll(0, iter); this }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def insertAll(n: Int, iter: Iterable[A]) {
+ if ((n < 0) || (n > size0))
+ throw new IndexOutOfBoundsException(n.toString)
+ val xs = iter.elements.toList
+ val len = xs.length
+ ensureSize(size0 + len)
+ copy(n, n + len, size0 - n)
+ xs.copyToArray(array.asInstanceOf[Array[Any]], n)
+ size0 += len
+ }
+
+ /** Removes the element on a given index position. It takes time linear in
+ * the buffer size.
+ *
+ * @param n the index which refers to the element to delete.
+ * @return the updated array buffer.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def remove(n: Int, count: Int) {
+ if ((n < 0) || (n >= size0))
+ throw new IndexOutOfBoundsException(n.toString)
+ copy(n + count, n, size0 - (n + count))
+ size0 -= count
+ }
+
+ /** Return a clone of this buffer.
+ *
+ * @return an <code>ArrayBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = new ArrayBuffer[A] ++ this
+
+ def result: ArrayBuffer[A] = this
+
+ /** Defines the prefix of the string representation.
+ */
+ override def stringPrefix: String = "ArrayBuffer"
+}
diff --git a/src/library/scalax/collection/mutable/Buffer.scala b/src/library/scalax/collection/mutable/Buffer.scala
new file mode 100644
index 0000000000..c11fa37409
--- /dev/null
+++ b/src/library/scalax/collection/mutable/Buffer.scala
@@ -0,0 +1,264 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Buffer.scala 15799 2008-08-15 18:23:54Z odersky $
+
+
+package scalax.collection.mutable
+
+import generic.mutable.VectorTemplate
+
+/** Buffers are used to create sequences of elements incrementally by
+ * appending, prepending, or inserting new elements. It is also
+ * possible to access and modify elements in a random access fashion
+ * via the index of the element in the current sequence.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+@cloneable
+trait Buffer[A] extends Vector[A] with VectorTemplate[Buffer, A] with Appendable[A]
+// with Scriptable[Message[(Location, A)]]
+ with CloneableCollection
+{
+
+// Abstract methods from Vector:
+
+ /** Return element at index `n`
+ * @throws IndexOutofBoundsException if the index is not valid
+ */
+ def apply(n: Int): A
+
+ /** Return number of elements in the buffer
+ */
+ def length: Int
+
+ /** Create a new buffer of the same kind as this one */
+ def newBuilder[B]: Builder[Buffer, B] = new ArrayBuffer[B]
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ * @throws IndexOutofBoundsException if the index is not valid
+ */
+ def update(n: Int, newelem: A): Unit
+
+// Abstract methods from Appendable
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A): Unit
+
+ /** Clears the buffer contents.
+ */
+ def clear()
+
+// Abstract methods new in this class
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ * @param elem the element to prepend.
+ */
+ def +:(elem: A): this.type
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ * @throws IndexOutofBoundsException if the index is not valid
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit
+
+ /** Removes a number of elements from a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ * @param count the number of elements to delete
+ * @throws IndexOutofBoundsException if the index is not valid
+ */
+ def remove(n: Int, count: Int): Unit
+
+// Concrete methods
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ def remove(n: Int): A = {
+ val elem = this(n)
+ remove(n, 1)
+ elem
+ }
+
+ /** Removes a single element from this buffer, at its first occurrence.
+ * If the list does not contain that element, it is unchanged
+ *
+ * @param x the element to remove.
+ */
+ def -= (x: A) {
+ val i = indexOf(x)
+ if (i != -1) remove(i)
+ }
+
+ /** Removes a single element from this buffer, at its first occurrence,
+ * and returns the identity of the buffer.
+ * If the buffer does not contain that element, it is unchanged
+ *
+ * @param x the element to remove.
+ */
+ def - (x: A): this.type = { -=(x); this }
+
+ /** Prepend two ore more elements to this buffer and return
+ * the identity of the buffer.
+ * @param elem the element to prepend.
+ */
+ def +:(elem1: A, elem2: A, elems: A*): this.type =
+ elem1 +: elem2 +: (elems.asInstanceOf[Iterable[A]]) ++: this // !!!
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def ++:(iter: Iterable[A]): this.type = { for (x <- iter) x +: this; this }
+
+ /** Prepends a number of elements provided by an iterator
+ * The identity of the buffer is returned.
+ *
+ * @param iter the iterator
+ * @return the updated buffer.
+ */
+ def ++:(iter: Iterator[A]): this.type = { for (x <- iter) x +: this; this }
+
+ /** Appends a elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ def append(elems: A*) { this ++= elems.asInstanceOf[Iterable[A]] } // !!!
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def appendAll(iter: Iterable[A]) { this ++= iter }
+
+ /** Prepend given elements to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ def prepend(elems: A*) { elems.asInstanceOf[Iterable[A]] ++: this } // !!!
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def prependAll(iter: Iterable[A]) { iter ++: this }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def prependAll(iter: Iterator[A]) { iter ++: this }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ def insert(n: Int, elems: A*) { insertAll(n, elems.asInstanceOf[Iterable[A]]) } // !!!
+
+ /** Removes the first <code>n</code> elements.
+ *
+ * @param n the number of elements to remove from the beginning
+ * of this buffer.
+ */
+ def trimStart(n: Int) { remove(0, n) }
+
+ /** Removes the last <code>n</code> elements.
+ *
+ * @param n the number of elements to remove from the end
+ * of this buffer.
+ */
+ def trimEnd(n: Int) { remove(length - n max 0, n) }
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ * !!!! todo: rewrite location, msg etc with enumerations or else pack in a subpackage
+ def <<(cmd: Message[(Location, A)]) {
+ cmd match {
+ case Include((l, elem)) => l match {
+ case Start => prepend(elem)
+ case End => append(elem)
+ case Index(n) => insert(n, elem)
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ case Update((l, elem)) => l match {
+ case Start => update(0, elem)
+ case End => update(length - 1, elem)
+ case Index(n) => update(n, elem)
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ case Remove((l, _)) => l match {
+ case Start => remove(0)
+ case End => remove(length - 1)
+ case Index(n) => remove(n)
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ case Reset() => clear
+ case s: Script[_] => s.elements foreach <<
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ }
+ */
+
+ /** Return a clone of this buffer.
+ *
+ * @return a buffer with the same elements.
+ */
+ override def clone(): Buffer[A] = super.clone().asInstanceOf[Buffer[A]]
+
+ /** Defines the prefix of the string representation.
+ */
+ override def stringPrefix: String = "Buffer"
+
+ /** Adds a number of elements in an array
+ *
+ * @param src the array
+ * @param start the first element to append
+ * @param len the number of elements to append
+ * @deprecated replace by: <code>buf ++= src.view(start, end)</code>
+ */
+ @deprecated def ++=(src: Array[A], start: Int, len: Int) {
+ var i = start
+ val end = i + len
+ while (i < end) {
+ this += src(i)
+ i += 1
+ }
+ }
+
+}
+
+
+
+
diff --git a/src/library/scalax/collection/mutable/CloneableCollection.scala b/src/library/scalax/collection/mutable/CloneableCollection.scala
new file mode 100644
index 0000000000..ab2c210134
--- /dev/null
+++ b/src/library/scalax/collection/mutable/CloneableCollection.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: CloneableCollection.scala 12003 2007-06-13 12:14:15Z mihaylov $
+
+
+package scalax.collection.mutable
+
+/** The J2ME version of the library defined this trait with a clone method
+ * to substitute for the lack of Object.clone there
+ */
+trait CloneableCollection {
+ override def clone(): AnyRef = super.clone()
+}
diff --git a/src/library/scalax/collection/mutable/ListBuffer.scala b/src/library/scalax/collection/mutable/ListBuffer.scala
new file mode 100644
index 0000000000..adc8cbdb26
--- /dev/null
+++ b/src/library/scalax/collection/mutable/ListBuffer.scala
@@ -0,0 +1,288 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $
+
+
+package scalax.collection.mutable
+
+import generic.SequenceForwarder
+import immutable.List
+import collection.immutable.{List, Nil, ::}
+
+/** A Buffer implementation back up by a list. It provides constant time
+ * prepend and append. Most other operations are linear.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.8
+ */
+@serializable
+final class ListBuffer[A]
+ extends Buffer[A]
+ with Builder[List, A]
+ with SequenceForwarder[A]
+{
+ private var start: List[A] = Nil
+ private var last0: ::[A] = _
+ private var exported: Boolean = false
+
+ protected def underlying: Sequence[A] = start
+
+ // Implementations of abstract methods in Buffer
+
+ /** Replaces element at index <code>n</code> with the new element
+ * <code>newelem</code>. Takes time linear in the buffer size. (except the first
+ * element, which is updated in constant time).
+ *
+ * @param n the index of the element to replace.
+ * @param x the new element.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def update(n: Int, x: A) {
+ try {
+ if (exported) copy()
+ if (n == 0) {
+ val newElem = new :: (x, start.tail);
+ if (last0 eq start) last0 = newElem
+ start = newElem
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i += 1
+ }
+ val newElem = new :: (x, cursor.tail.tail)
+ if (last0 eq cursor.tail) last0 = newElem
+ cursor.asInstanceOf[::[A]].tl = newElem
+ }
+ } catch {
+ case ex: Exception => throw new IndexOutOfBoundsException(n.toString())
+ }
+ }
+
+ /** Appends a single element to this buffer. This operation takes constant time.
+ *
+ * @param x the element to append.
+ */
+ def += (x: A) {
+ if (exported) copy()
+ if (start.isEmpty) {
+ last0 = new :: (x, Nil)
+ start = last0
+ } else {
+ val last1 = last0
+ last0 = new :: (x, Nil)
+ last1.tl = last0
+ }
+ }
+
+ /** Clears the buffer contents.
+ */
+ def clear() {
+ start = Nil
+ exported = false
+ }
+
+ /** Prepends a single element to this buffer. This operation takes constant
+ * time.
+ *
+ * @param x the element to prepend.
+ * @return this buffer.
+ */
+ def +: (x: A): this.type = {
+ if (exported) copy()
+ val newElem = new :: (x, start)
+ if (start.isEmpty) last0 = newElem
+ start = newElem
+ this
+ }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a new
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def insertAll(n: Int, iter: Iterable[A]) {
+ try {
+ if (exported) copy()
+ var elems = iter.elements.toList.reverse
+ if (n == 0) {
+ while (!elems.isEmpty) {
+ val newElem = new :: (elems.head, start)
+ if (start.isEmpty) last0 = newElem
+ start = newElem
+ elems = elems.tail
+ }
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i += 1
+ }
+ while (!elems.isEmpty) {
+ val newElem = new :: (elems.head, cursor.tail)
+ if (cursor.tail.isEmpty) last0 = newElem
+ cursor.asInstanceOf[::[A]].tl = newElem
+ elems = elems.tail
+ }
+ }
+ } catch {
+ case ex: Exception =>
+ throw new IndexOutOfBoundsException(n.toString())
+ }
+ }
+
+ /** Removes the element on a given index position. This operation takes time linear in
+ * the buffer size.
+ *
+ * @param n the index which refers to the element to delete.
+ * @return the updated array buffer.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def remove(n: Int, count: Int) {
+ try {
+ if (exported) copy()
+ var old = start.head;
+ if (n == 0) {
+ var c = count
+ while (c > 0) {
+ start = start.tail
+ c -= 1
+ }
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i += 1
+ }
+ var c = count
+ while (c > 0) {
+ if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]]
+ cursor.asInstanceOf[::[A]].tl = cursor.tail.tail
+ c -= 1
+ }
+ }
+ old
+ } catch {
+ case ex: Exception =>
+ throw new IndexOutOfBoundsException(n.toString())
+ }
+ }
+
+// Implementation of abstract method in Builder
+
+ def result = toList
+
+ /** Converts this buffer to a list. Takes constant time. The buffer is
+ * copied lazily, the first time it is mutated.
+ */
+ override def toList: List[A] = {
+ exported = !start.isEmpty
+ start
+ }
+
+// New methods in ListBuffer
+
+ /** Prepends the elements of this buffer to a given list
+ *
+ * @param xs the list to which elements are prepended
+ */
+ def prependToList(xs: List[A]): List[A] =
+ if (start.isEmpty) xs
+ else { last0.tl = xs; toList }
+
+// Overrides of methods in Buffer
+
+ /** Removes the element on a given index position. Takes time linear in
+ * the buffer size (except for the first element, which is removed in constant
+ * time).
+ *
+ * @param n the index which refers to the element to delete.
+ * @return n the element that was formerly at position <code>n</code>.
+ * @pre an element exists at position <code>n</code>
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ override def remove(n: Int): A = try {
+ if (exported) copy()
+ var old = start.head;
+ if (n == 0) {
+ start = start.tail
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i += 1
+ }
+ old = cursor.tail.head
+ if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]]
+ cursor.asInstanceOf[::[A]].tl = cursor.tail.tail
+ }
+ old
+ } catch {
+ case ex: Exception =>
+ throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** Remove a single element from this buffer. This operation takes linear time
+ * (except removing the first element, which is done in constant time).
+ *
+ * @param x the element to remove.
+ */
+ override def -= (x: A) {
+ if (exported) copy()
+ if (start.isEmpty) {}
+ else if (start.head == x) start = start.tail
+ else {
+ var cursor = start
+ while (!cursor.tail.isEmpty && cursor.tail.head != x) { cursor = cursor.tail }
+ if (!cursor.tail.isEmpty) {
+ val z = cursor.asInstanceOf[::[A]]
+ if (z.tl == last0)
+ last0 = z
+ z.tl = cursor.tail.tail
+ }
+ }
+ }
+
+ /** expose the underlying list but do not mark it as exported */
+ override def readOnly : List[A] = start
+
+ // Private methods
+
+ /** Copy contents of this buffer */
+ private def copy() {
+ var cursor = start
+ val limit = last0.tail
+ clear
+ while (cursor ne limit) {
+ this += cursor.head
+ cursor = cursor.tail
+ }
+ }
+
+ /** Returns a clone of this buffer.
+ *
+ * @return a <code>ListBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this
+
+ /** Defines the prefix of the string representation.
+ *
+ * @return the string representation of this buffer.
+ */
+ override def stringPrefix: String = "ListBuffer"
+}
+
diff --git a/src/library/scalax/collection/mutable/ResizableArray.scala b/src/library/scalax/collection/mutable/ResizableArray.scala
new file mode 100644
index 0000000000..e4dd8bd47d
--- /dev/null
+++ b/src/library/scalax/collection/mutable/ResizableArray.scala
@@ -0,0 +1,103 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ResizableArray.scala 15407 2008-06-20 09:26:36Z stepancheg $
+
+
+package scalax.collection.mutable
+
+/** This class is used internally to implement data structures that
+ * are based on resizable arrays.
+ *
+ * @author Matthias Zenger, Burak Emir
+ * @version 1.0, 03/05/2004
+ */
+trait ResizableArray[A] extends Vector[A] {
+
+ protected def initialSize: Int = 16
+ protected var array: Array[AnyRef] = new Array[AnyRef](initialSize min 1)
+
+ protected var size0: Int = 0
+
+ //##########################################################################
+ // implement/override methods of Vector[A]
+
+ /** Returns the length of this resizable array.
+ */
+ def length: Int = size0
+
+ def apply(idx: Int) = {
+ if (idx >= size0) throw new IndexOutOfBoundsException(idx.toString)
+ array(idx).asInstanceOf[A]
+ }
+
+ def update(idx: Int, elem: A) {
+ if (idx >= size0) throw new IndexOutOfBoundsException(idx.toString)
+ array(idx) = elem.asInstanceOf[AnyRef]
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ */
+ override def copyToArray[B >: A](xs: Array[B], start: Int) {
+ Array.copy(array, 0, xs, start, size0)
+ }
+
+ /** Copy all elements to a buffer
+ * @param The buffer to which elements are copied
+ */
+ override def copyToBuffer[B >: A](dest: Buffer[B]) {
+ dest ++= array.asInstanceOf[Iterable[A]] // !!!
+ }
+
+ override def foreach(f: A => Unit) {
+ var i = 0
+ while (i < size) {
+ f(array(i).asInstanceOf[A])
+ i += 1
+ }
+ }
+
+ //##########################################################################
+
+ /** remove elements of this array at indices after <code>sz</code>
+ */
+ def reduceToSize(sz: Int) {
+ require(sz <= size0)
+ size0 = sz
+ }
+
+ /** ensure that the internal array has at n cells */
+ protected def ensureSize(n: Int) {
+ if (n > array.length) {
+ var newsize = array.length * 2
+ while (n > newsize)
+ newsize = newsize * 2
+ val newar: Array[AnyRef] = new Array(newsize)
+ Array.copy(array, 0, newar, 0, size0)
+ array = newar
+ }
+ }
+
+ /** Swap two elements of this array.
+ */
+ protected def swap(a: Int, b: Int) {
+ val h = array(a)
+ array(a) = array(b)
+ array(b) = h
+ }
+
+ /** Move parts of the array.
+ */
+ protected def copy(m: Int, n: Int, len: Int) {
+ Array.copy(array, m, array, n, len)
+ }
+}
diff --git a/src/library/scalax/collection/mutable/Vector.scala b/src/library/scalax/collection/mutable/Vector.scala
new file mode 100644
index 0000000000..b181e93303
--- /dev/null
+++ b/src/library/scalax/collection/mutable/Vector.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Vector.scala 15437 2008-06-25 16:22:45Z stepancheg $
+
+package scalax.collection.mutable
+
+trait Vector[A] extends collection.Vector[A] with generic.mutable.VectorTemplate[Vector, A]
+
+object Vector extends generic.nonvariant.SequenceFactory[Vector] {
+
+ /** The empty iterable */
+ def apply[A](args: A*): Vector[A] = null // !!!
+
+}
diff --git a/src/library/scalax/util/control/Break.scala b/src/library/scalax/util/control/Break.scala
new file mode 100755
index 0000000000..173188d2e9
--- /dev/null
+++ b/src/library/scalax/util/control/Break.scala
@@ -0,0 +1,15 @@
+package scalax.util.control
+
+object Break {
+ private class BreakException extends RuntimeException
+ private val breakException = new BreakException
+ def break { throw breakException }
+ def breakable(op: => Unit) {
+ try {
+ op
+ } catch {
+ case ex: BreakException =>
+ }
+ }
+}
+
diff --git a/test/files/neg/accesses.check b/test/files/neg/accesses.check
index 627c17dd90..94fcd615bc 100644
--- a/test/files/neg/accesses.check
+++ b/test/files/neg/accesses.check
@@ -1,16 +1,16 @@
-accesses.scala:23: error: error overriding method f2 in class A of type => Unit;
+accesses.scala:23: error: overriding method f2 in class A of type => Unit;
method f2 has weaker access privileges; it should not be private
private def f2: Unit = ()
^
-accesses.scala:24: error: error overriding method f3 in class A of type => Unit;
+accesses.scala:24: error: overriding method f3 in class A of type => Unit;
method f3 has weaker access privileges; it should be at least protected
private[p2] def f3: Unit = ()
^
-accesses.scala:25: error: error overriding method f4 in class A of type => Unit;
+accesses.scala:25: error: overriding method f4 in class A of type => Unit;
method f4 has weaker access privileges; it should be at least private[p1]
private[p2] def f4: Unit
^
-accesses.scala:26: error: error overriding method f5 in class A of type => Unit;
+accesses.scala:26: error: overriding method f5 in class A of type => Unit;
method f5 has weaker access privileges; it should be at least protected[p1]
protected[p2] def f5: Unit
^
diff --git a/test/files/neg/bug521.check b/test/files/neg/bug521.check
index b85e26677b..eda06ff9f6 100644
--- a/test/files/neg/bug521.check
+++ b/test/files/neg/bug521.check
@@ -1,14 +1,14 @@
bug521.scala:10: error: class PlainFile needs to be abstract, since method path in class AbstractFile of type => String is not defined
class PlainFile(val file : File) extends AbstractFile {}
^
-bug521.scala:13: error: error overriding value file in class PlainFile of type java.io.File;
+bug521.scala:13: error: overriding value file in class PlainFile of type java.io.File;
value file needs `override' modifier
final class ZipArchive(val file : File, archive : ZipFile) extends PlainFile(file) {
^
bug521.scala:13: error: class ZipArchive needs to be abstract, since method path in class AbstractFile of type => String is not defined
final class ZipArchive(val file : File, archive : ZipFile) extends PlainFile(file) {
^
-bug521.scala:15: error: error overriding value path in class VirtualFile of type String;
+bug521.scala:15: error: overriding value path in class VirtualFile of type String;
method path is not stable
override def path = "";
^
diff --git a/test/files/neg/bug630.check b/test/files/neg/bug630.check
index 03113be7da..739d214fe5 100644
--- a/test/files/neg/bug630.check
+++ b/test/files/neg/bug630.check
@@ -1,5 +1,5 @@
-bug630.scala:20: error: error overriding value foo in trait Bar of type Req2;
- object foo has incompatible type object Test.foo
+bug630.scala:20: error: overriding value foo in trait Bar of type Req2;
+ object foo has incompatible type
object foo extends Req1
^
one error found
diff --git a/test/files/neg/bug708.check b/test/files/neg/bug708.check
index 513709f2a0..cfeb01c87f 100644
--- a/test/files/neg/bug708.check
+++ b/test/files/neg/bug708.check
@@ -1,5 +1,5 @@
-bug708.scala:8: error: error overriding type S in trait X with bounds >: Nothing <: A.this.T;
- type S has incompatible type Any
+bug708.scala:8: error: overriding type S in trait X with bounds >: Nothing <: A.this.T;
+ type S has incompatible type
override private[A] type S = Any;
^
one error found
diff --git a/test/files/neg/lazy-override.check b/test/files/neg/lazy-override.check
index d1c9d305f0..793e6b2020 100644
--- a/test/files/neg/lazy-override.check
+++ b/test/files/neg/lazy-override.check
@@ -1,8 +1,8 @@
-lazy-override.scala:11: error: error overriding value x in class A of type Int;
+lazy-override.scala:11: error: overriding value x in class A of type Int;
lazy value x cannot override a concrete non-lazy value
override lazy val x: Int = { print("/*B.x*/"); 3 }
^
-lazy-override.scala:13: error: error overriding lazy value y in class A of type Int;
+lazy-override.scala:13: error: overriding lazy value y in class A of type Int;
value y must be declared lazy to override a concrete lazy value
override val y: Int = { print("/*B.y*/"); 3 }
^
diff --git a/test/files/neg/t1163.check b/test/files/neg/t1163.check
index c96ec732a5..69e6b7ac4a 100644
--- a/test/files/neg/t1163.check
+++ b/test/files/neg/t1163.check
@@ -1,5 +1,5 @@
-t1163.scala:2: error: error overriding method foo in trait Sub of type => Sub;
- method foo in trait Super of type => Super has incompatible type => Super;
+t1163.scala:2: error: overriding method foo in trait Sub of type => Sub;
+ method foo in trait Super of type => Super has incompatible type;
(Note that method foo in trait Sub of type => Sub is abstract,
and is therefore overridden by concrete method foo in trait Super of type => Super)
trait Sub extends Super { override def foo: Sub }
diff --git a/test/files/neg/tcpoly_variance.check b/test/files/neg/tcpoly_variance.check
index 146240ac9b..2df4b4d429 100644
--- a/test/files/neg/tcpoly_variance.check
+++ b/test/files/neg/tcpoly_variance.check
@@ -1,5 +1,5 @@
-tcpoly_variance.scala:6: error: error overriding method str in class A of type => m[java.lang.Object];
- method str has incompatible type => m[String]
+tcpoly_variance.scala:6: error: overriding method str in class A of type => m[java.lang.Object];
+ method str has incompatible type
override def str: m[String] = error("foo") // since x in m[x] is invariant, ! m[String] <: m[Object]
^
one error found
diff --git a/test/files/run/t1524.check b/test/files/run/t1524.check
new file mode 100644
index 0000000000..e79c5e8f96
--- /dev/null
+++ b/test/files/run/t1524.check
@@ -0,0 +1 @@
+initial
diff --git a/test/files/run/t1524.scala b/test/files/run/t1524.scala
new file mode 100644
index 0000000000..4520028dda
--- /dev/null
+++ b/test/files/run/t1524.scala
@@ -0,0 +1,7 @@
+object Test extends Application {
+
+ val buf = new scala.collection.mutable.ArrayBuffer[String] { override val initialSize = 0 }
+ buf += "initial"
+ buf += "second"
+ println(buf.first)
+} \ No newline at end of file