summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-12-21 13:47:53 +0000
committerMartin Odersky <odersky@gmail.com>2005-12-21 13:47:53 +0000
commit99b6474dabc8a4bcc9282f041d48fb9671c4f2b8 (patch)
treec701a1fac4866e0c7c0d41e49edd69c0c633f06f /src
parent7ccea812b72c15670fb3c5026acb7856a36e7fad (diff)
downloadscala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.gz
scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.bz2
scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.zip
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala15
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala73
-rw-r--r--src/library/scala/Double.java72
-rw-r--r--src/library/scala/Float.java60
-rw-r--r--src/library/scala/Iterator.scala9
-rw-r--r--src/library/scala/List.scala557
-rw-r--r--src/library/scala/Long.java2
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala5
-rw-r--r--src/library/scala/collection/mutable/Buffer.scala2
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala318
-rw-r--r--src/library/scala/collection/mutable/Message.scala2
-rw-r--r--src/library/scala/runtime/compat/Platform.scala2
20 files changed, 828 insertions, 357 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index dedfc6b03a..910b6d0f2a 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -113,12 +113,23 @@ abstract class TreeInfo {
case _ => false
}
- /** The longest statement suffix that starts with a constructor */
+ /** The first constructor definitions in `stats' */
def firstConstructor(stats: List[Tree]): Tree = stats.head match {
case constr @ DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => constr
case _ => firstConstructor(stats.tail)
}
-
+/*
+ /** The super call that calls mixin `mix' in stats */
+ def superCall(stats: List[Tree], mix: Name): Tree = stats match {
+ case scall @ Apply(Select(Super(_, mix1), name), List()) :: _
+ if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && mix1 == mix) =>
+ scall
+ case _ :: stats1 =>
+ superCall(stats1, name)
+ case _ =>
+ assert(false, "no supercall to " + mix + " in " + stats);
+ }
+*/
/** Is name a left-associative operator? */
def isLeftAssoc(operator: Name): boolean =
operator.length > 0 && operator(operator.length - 1) != ':';
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 0634ace4d0..36f6d5890e 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1552,8 +1552,11 @@ import Tokens._;
/** ClassTemplate ::= [`extends' TemplateParents] [[NL] TemplateBody]
* TemplateParents ::= SimpleType {`(' [Exprs] `)'} {`with' SimpleType}
*/
- def classTemplate(mods: Modifiers, name: Name, vparamss: List[List[ValDef]]): Template = {
- val ret = atPos(in.currentPos) {
+ def classTemplate(mods: Modifiers, name: Name, vparamss: List[List[ValDef]]): Template =
+ atPos(in.currentPos) {
+ def acceptEmptyTemplateBody(msg: String): unit =
+ if (!(in.token == SEMI || in.token == NEWLINE || in.token == COMMA || in.token == RBRACE))
+ syntaxError(msg, true);
val parents = new ListBuffer[Tree];
val argss = new ListBuffer[List[Tree]];
if (in.token == EXTENDS) {
@@ -1568,25 +1571,21 @@ import Tokens._;
in.nextToken();
parents += simpleType()
}
- } else argss += List();
+ } else {
+ if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected");
+ argss += List()
+ }
if (name != nme.ScalaObject.toTypeName)
parents += scalaScalaObjectConstr;
if (mods.hasFlag(Flags.CASE)) parents += caseClassConstr;
val ps = parents.toList;
if (in.token == NEWLINE && in.next.token == LBRACE) in.nextToken();
var body =
- if (in.token == LBRACE) {
- templateBody()
- } else {
- if (!(in.token == SEMI || in.token == NEWLINE || in.token == COMMA || in.token == RBRACE))
- syntaxError("`extends' or `{' expected", true);
- List()
- }
+ if (in.token == LBRACE) templateBody()
+ else { acceptEmptyTemplateBody("`{' expected"); List() }
if (!mods.hasFlag(Flags.TRAIT)) Template(ps, vparamss, argss.toList, body)
else Template(ps, body)
}
- ret;
- }
////////// TEMPLATES ////////////////////////////////////////////////////////////
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 6903f2b504..b4f760220f 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -188,13 +188,13 @@ import Flags._;
var i = 0;
var j = fullname.pos('.', i);
while (j < fullname.length) {
- sym = sym.info.nonPrivateMember(fullname.subName(i, j));
+ sym = sym.info.member(fullname.subName(i, j));
i = j + 1;
j = fullname.pos('.', i)
}
val result =
- if (module) sym.info.nonPrivateMember(fullname.subName(i, j)).suchThat(.hasFlag(MODULE));
- else sym.info.nonPrivateMember(fullname.subName(i, j).toTypeName);
+ if (module) sym.info.member(fullname.subName(i, j)).suchThat(.hasFlag(MODULE));
+ else sym.info.member(fullname.subName(i, j).toTypeName);
if (result == NoSymbol)
throw new FatalError((if (module) "object " else "class ") + fullname + " not found.");
result
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 4eaac75fcf..58ef0187e1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1607,6 +1607,8 @@ import Flags._;
case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
(tparams1.length == tparams2.length &&
(res1 matches res2.substSym(tparams2, tparams1)))
+ case Pair(PolyType(List(), rtp1), MethodType(List(), rtp2)) => matchesType(rtp1, rtp2)
+ case Pair(MethodType(List(), rtp1), PolyType(List(), rtp2)) => matchesType(rtp1, rtp2)
case Pair(PolyType(List(), rtp1), _) => matchesType(rtp1, tp2)
case Pair(_, PolyType(List(), rtp2)) => matchesType(tp1, rtp2)
case Pair(MethodType(_, _), _) => false
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 0e56cf8824..6b633f389f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -289,7 +289,7 @@ abstract class ClassfileParser {
def parseMethod(): unit = {
val jflags = in.nextChar();
var sflags = transFlags(jflags);
- if ((sflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | PRIVATE;
+ if ((jflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | PRIVATE;
if ((sflags & PRIVATE) != 0) {
in.skip(4); skipAttributes();
} else {
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 95a500634b..466ed4674c 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -211,7 +211,8 @@ abstract class ExplicitOuter extends InfoTransform {
// as constructor arguments might be missing
}
val mixinConstructorCalls =
- for (val mixin <- clazz.info.parents.tail; !(mixin.symbol hasFlag INTERFACE)) yield
+ for (val mixin <- clazz.info.parents.tail;
+ !(mixin.symbol hasFlag INTERFACE) && mixin.symbol != ScalaObjectClass) yield
mixinConstructorCall(mixin.symbol);
tree match {
case Block(supercall :: stats, expr) =>
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 08935e7e16..bcdd9b09b8 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -282,7 +282,7 @@ abstract class Mixin extends InfoTransform {
true
}
if (newDefs.isEmpty) stats
- else stats.filter(isNotDuplicate) ::: newDefs
+ else newDefs ::: stats.filter(isNotDuplicate)//!!!
}
def completeSuperAccessor(stat: Tree) = stat match {
case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index e982ac1ba1..d80f573029 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -13,6 +13,7 @@ import symtab.Flags._;
import definitions._;
import posAssigner.atPos;
+ // statistics
var normM = 0;
var normP = 0;
var normO = 0;
@@ -152,17 +153,24 @@ import symtab.Flags._;
tp1
}
+ private val stdErrorClass = RootClass.newErrorClass(nme.ERROR.toTypeName);
+ private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR);
+
/** The context-dependent inferencer part */
class Inferencer(context: Context) {
/* -- Error Messages ----------------------------------------------------- */
def setError[T <: Tree](tree: T): T = {
- val name = newTermName("<error: " + tree + ">");
if (tree.hasSymbol)
- tree.setSymbol(
- if (tree.isType) context.owner.newErrorClass(name.toTypeName)
- else context.owner.newErrorValue(name));
+ if (context.reportGeneralErrors) {
+ val name = newTermName("<error: " + tree.symbol + ">");
+ tree.setSymbol(
+ if (tree.isType) context.owner.newErrorClass(name.toTypeName)
+ else context.owner.newErrorValue(name));
+ } else {
+ tree.setSymbol(if (tree.isType) stdErrorClass else stdErrorValue)
+ }
tree.setType(ErrorType)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index f60ffae9b5..f6552d9fc5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -96,7 +96,10 @@ abstract class RefChecks extends InfoTransform {
* 1.7. If O is an abstract type then
* either M is an abstract type, and M's bounds are sharper than O's bounds.
* or M is an unparameterized type alias or class which conforms to O's bounds.
- * 1.8. If O and M are values, then M's type is a subtype of O's type.
+ * 1.8. If O and M are values, then
+ * 1.8.1 M's type is a subtype of O's type, or
+ * 1.8.2 M is of type []S, O is of type ()T and S <: T, or
+ * 1.8.3 M is of type ()S, O is of type []T and S <: T, or
* 2. Check that only abstract classes have deferred members
* 3. Check that every member with an `override' modifier
* overrides some other member.
@@ -115,6 +118,12 @@ abstract class RefChecks extends InfoTransform {
else "")))
);
+ def overridesType(tp1: Type, tp2: Type): boolean = Pair(tp1, tp2) match {
+ case Pair(MethodType(List(), rtp1), PolyType(List(), rtp2)) => rtp1 <:< rtp2
+ case Pair(PolyType(List(), rtp1), MethodType(List(), rtp2)) => rtp1 <:< rtp2
+ case _ => tp1 <:< tp2
+ }
+
/* Check that all conditions for overriding `other' by `member' are met. */
def checkOverride(clazz: Symbol, member: Symbol, other: Symbol): unit = {
val pos = if (member.owner == clazz) member.pos else clazz.pos;
@@ -179,8 +188,9 @@ abstract class RefChecks extends InfoTransform {
if (!(self.memberInfo(other).bounds containsType self.memberType(member))) // (1.7)
overrideTypeError();
} else if (other.isTerm) {
- if (!(self.memberInfo(member) <:< (self.memberInfo(other)))) // 8
+ if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8
overrideTypeError();
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e6d2e0e8a3..3664e641bb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -279,8 +279,11 @@ import scala.collection.mutable.{HashMap, ListBuffer}
* unless followed by explicit type application.
* (4) Do the following to unapplied methods used as values:
* (4.1) If the method has only implicit parameters pass implicit arguments
- * (4.2) otherwise, convert to function by eta-expansion,
- * except if the method is a constructor, in which case we issue an error.
+ * (4.2) otherwise, if `pt' is a function type and method is not a constructor,
+ * convert to function by eta-expansion,
+ * (4.3) otherwise, if the method is nullary with a result type compatible to `pt'
+ * and it is not a constructor, apply it to ()
+ * otherwise issue an error
* (5) Convert a class type that serves as a constructor in a pattern as follows:
* (5.1) If this type refers to a case class, set tree's type to the unique
* instance of its primary constructor that is a subtype of the expected type.
@@ -326,15 +329,21 @@ import scala.collection.mutable.{HashMap, ListBuffer}
adapt(tree, mode, pt)
} else tree;
typed(applyImplicitArgs(tree1), mode, pt)
- case mt: MethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
- isCompatible(tree.tpe, pt)) => // (4.2)
- if (tree.symbol.isConstructor || pt == WildcardType ||
- !(pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType))) {
- errorTree(tree, "missing arguments for " + tree.symbol) //debug
- } else {
- if (settings.debug.value) log("eta-expanding " + tree + ":" + tree.tpe + " to " + pt);//debug
+ case mt: MethodType
+ if (((mode & (EXPRmode | FUNmode)) == EXPRmode) &&
+ (context.undetparams.isEmpty || (mode & POLYmode) != 0)) =>
+ if (!tree.symbol.isConstructor && pt != WildcardType && isCompatible(mt, pt) &&
+ (pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType))) { // (4.2)
+ if (settings.debug.value) log("eta-expanding " + tree + ":" + tree.tpe + " to " + pt);
typed(etaExpand(tree), mode, pt)
- }
+ } else if (!tree.symbol.isConstructor &&
+ mt.paramTypes.isEmpty && isCompatible(mt.resultType, pt)) { // (4.3)
+ typed(Apply(tree, List()) setPos tree.pos)
+ } else {
+ if (context.reportGeneralErrors)
+ error(tree.pos, "missing arguments for " + tree.symbol);
+ setError(tree)
+ }
case _ =>
if (tree.isType) {
val clazz = tree.tpe.symbol;
@@ -409,7 +418,7 @@ import scala.collection.mutable.{HashMap, ListBuffer}
}
}
if (settings.debug.value) log("error tree = " + tree);
- typeErrorTree(tree, tree.tpe, pt)
+ typeErrorTree(tree, tree.tpe, pt)
}
}
}
@@ -426,16 +435,35 @@ import scala.collection.mutable.{HashMap, ListBuffer}
else qual
} else qual;
- private def completeSuperType(supertpt: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = {
+ private def completeParentType(tpt: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = {
enclTparams foreach context.scope.enter;
namer.enterValueParams(context.owner, vparamss);
- val newTree = New(supertpt)
- .setType(PolyType(tparams, appliedType(supertpt.tpe, tparams map (.tpe))));
- val tree = typed(atPos(supertpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)));
+ val newTree = New(tpt)
+ .setType(PolyType(tparams, appliedType(tpt.tpe, tparams map (.tpe))));
+ val tree = typed(atPos(tpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)));
if (settings.debug.value) log("superconstr " + tree + " co = " + context.owner);//debug
tree.tpe
}
+/*
+ def completeParentType(tpt: Tree, templ: Template): Tree =
+ if (tpt.hasSymbol) {
+ val tparams = tpt.symbol.typeParams;
+ if (!tparams.isEmpty) {
+ val constr @ DefDef(_, _, _, vparamss, _, rhs) = treeInfo.firstConstructor(templ.body);
+ val Apply(_, superargs) = treeInfo.superCall(rhs, tpt.symbol.name);
+ val outercontext = context.outer;
+ TypeTree(
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ .completeParentType(
+ tpt,
+ tparams,
+ context.owner.unsafeTypeParams,
+ vparamss map (.map(.duplicate.asInstanceOf[ValDef])),
+ superargs map (.duplicate))) setPos tpt.pos;
+ } else tpt
+ } else tpt
+*/
def parentTypes(templ: Template): List[Tree] = try {
if (templ.parents.isEmpty) List()
else {
@@ -453,8 +481,8 @@ import scala.collection.mutable.{HashMap, ListBuffer}
treeInfo.firstConstructor(templ.body);
val outercontext = context.outer;
supertpt = TypeTree(
- newTyper(outercontext.makeNewScope(constr, outercontext.owner/*.newValue(templ.pos, newTermName("<dummy>"))*/))
- .completeSuperType(
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ .completeParentType(
supertpt,
tparams,
context.owner.unsafeTypeParams,
@@ -1467,9 +1495,10 @@ import scala.collection.mutable.{HashMap, ListBuffer}
private def typedImplicit(pos: int, info: ImplicitInfo, pt: Type, local: boolean): Tree =
if (isCompatible(depoly(info.tpe), pt)) {
var tree: Tree = EmptyTree;
- def fail(reason: String): Tree = {
+ def fail(reason: String, sym1: Symbol, sym2: Symbol): Tree = {
if (settings.debug.value)
- log(tree.toString() + " is not a valid implicit value because:\n" + reason);
+ log(tree.toString() + " is not a valid implicit value because:\n" + reason +
+ sym1 + " " + sym2);
EmptyTree
}
try {
@@ -1481,10 +1510,10 @@ import scala.collection.mutable.{HashMap, ListBuffer}
val tree1 = adapt(tree, EXPRmode, pt);
if (settings.debug.value)
log("adapted implicit " + tree.symbol + ":" + tree1.tpe + " to " + pt);//debug
- if (info.sym == tree.symbol) tree1
- else fail("syms differ: " + tree.symbol + " " + info.sym)
+ if (tree1.tpe != ErrorType && info.sym == tree.symbol) tree1
+ else fail("syms differ: ", tree.symbol, info.sym)
} catch {
- case ex: TypeError => fail(ex.getMessage())
+ case ex: TypeError => fail(ex.getMessage(), NoSymbol, NoSymbol)
}
} else EmptyTree;
diff --git a/src/library/scala/Double.java b/src/library/scala/Double.java
index 77f44fd10e..677366b6fb 100644
--- a/src/library/scala/Double.java
+++ b/src/library/scala/Double.java
@@ -75,4 +75,76 @@ public abstract class Double extends AnyVal implements java.io.Serializable {
public double $div (double that) { return value / that; }
public double $percent (double that) { return value % that; }
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public double $plus (float that) { return value + that; }
+ public double $minus (float that) { return value - that; }
+ public double $times (float that) { return value * that; }
+ public double $div (float that) { return value / that; }
+ public double $percent (float that) { return value % that; }
+
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public double $plus (long that) { return value + that; }
+ public double $minus (long that) { return value - that; }
+ public double $times (long that) { return value * that; }
+ public double $div (long that) { return value / that; }
+ public double $percent (long that) { return value % that; }
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public double $plus (int that) { return value + that; }
+ public double $minus (int that) { return value - that; }
+ public double $times (int that) { return value * that; }
+ public double $div (int that) { return value / that; }
+ public double $percent (int that) { return value % that; }
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public double $plus (char that) { return value + that; }
+ public double $minus (char that) { return value - that; }
+ public double $times (char that) { return value * that; }
+ public double $div (char that) { return value / that; }
+ public double $percent (char that) { return value % that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public double $plus (short that) { return value + that; }
+ public double $minus (short that) { return value - that; }
+ public double $times (short that) { return value * that; }
+ public double $div (short that) { return value / that; }
+ public double $percent (short that) { return value % that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public double $plus (byte that) { return value + that; }
+ public double $minus (byte that) { return value - that; }
+ public double $times (byte that) { return value * that; }
+ public double $div (byte that) { return value / that; }
+ public double $percent (byte that) { return value % that; }
+
}
diff --git a/src/library/scala/Float.java b/src/library/scala/Float.java
index a4a35f575e..6b3efb36ff 100644
--- a/src/library/scala/Float.java
+++ b/src/library/scala/Float.java
@@ -90,4 +90,64 @@ public abstract class Float extends AnyVal implements java.io.Serializable {
public float $div (float that) { return value / that; }
public float $percent (float that) { return value % that; }
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public float $plus (long that) { return value + that; }
+ public float $minus (long that) { return value - that; }
+ public float $times (long that) { return value * that; }
+ public float $div (long that) { return value / that; }
+ public float $percent (long that) { return value % that; }
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public float $plus (int that) { return value + that; }
+ public float $minus (int that) { return value - that; }
+ public float $times (int that) { return value * that; }
+ public float $div (int that) { return value / that; }
+ public float $percent (int that) { return value % that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public float $plus (short that) { return value + that; }
+ public float $minus (short that) { return value - that; }
+ public float $times (short that) { return value * that; }
+ public float $div (short that) { return value / that; }
+ public float $percent (short that) { return value % that; }
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public float $plus (char that) { return value + that; }
+ public float $minus (char that) { return value - that; }
+ public float $times (char that) { return value * that; }
+ public float $div (char that) { return value / that; }
+ public float $percent (char that) { return value % that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public float $plus (byte that) { return value + that; }
+ public float $minus (byte that) { return value - that; }
+ public float $times (byte that) { return value * that; }
+ public float $div (byte that) { return value / that; }
+ public float $percent (byte that) { return value % that; }
+
}
diff --git a/src/library/scala/Iterator.scala b/src/library/scala/Iterator.scala
index 1664eb2ffe..7a7194e47b 100644
--- a/src/library/scala/Iterator.scala
+++ b/src/library/scala/Iterator.scala
@@ -364,6 +364,15 @@ trait Iterator[+A] {
override def buffered: BufferedIterator[A] = this;
}
+ /** Returns a counted iterator from this iterator.
+ */
+ def counted = new CountedIterator[A] {
+ private var cnt = -1;
+ def count = cnt;
+ def hasNext: Boolean = Iterator.this.hasNext;
+ def next: A = { cnt = cnt + 1; Iterator.this.next }
+ }
+
/** Creates two new iterators that both iterate over the same elements
* than this iterator (in the same order).
*/
diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala
index 4da2611640..19f4bf789d 100644
--- a/src/library/scala/List.scala
+++ b/src/library/scala/List.scala
@@ -4,12 +4,13 @@
** __\ \/ /__/ __ |/ /__/ __ | **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
-** $Id:List.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+** $Id$
\* */
package scala;
import Predef._;
+import scala.collection.mutable.ListBuffer;
/** This object provides methods for creating specialized lists, and for
* transforming special kinds of lists (e.g. lists of lists).
@@ -47,9 +48,15 @@ object List {
* @param step the increment value of the list
* @return the sorted list of all integers in range [from;end).
*/
- def range(from: Int, end: Int, step: Int): List[Int] =
- if (from >= end) Nil
- else from :: range(from + step, end, step);
+ def range(from: Int, end: Int, step: Int): List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = from
+ while (i < end) {
+ b += i
+ i = i + step
+ }
+ b.toList
+ }
/** Create a sorted list of all integers in a range.
*
@@ -58,9 +65,15 @@ object List {
* @param step the increment function of the list
* @return the sorted list of all integers in range [from;end).
*/
- def range(from: Int, end: Int, step: Int => Int): List[Int] =
- if (from >= end) Nil
- else from :: range(step(from), end, step);
+ def range(from: Int, end: Int, step: Int => Int): List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = from
+ while (i < end) {
+ b += i
+ i = i + step(i)
+ }
+ b.toList
+ }
/** Create a list containing several copies of an element.
*
@@ -68,9 +81,15 @@ object 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] =
- if (n == 0) Nil
- else elem :: make(n - 1, elem);
+ def make[a](n: int, elem: a): List[a] = {
+ val b = new ListBuffer[a]
+ var i = 0
+ while (i < n) {
+ b += elem
+ i = i + 1
+ }
+ b.toList
+ }
/** Create a list by applying a function to successive integers.
*
@@ -81,19 +100,31 @@ object List {
* integers from 0 to n (exclusive).
*/
def tabulate[a](n: int, maker: int => a): List[a] = {
- def loop(i: int): List[a] =
- if (i == n) Nil
- else maker(i) :: loop(i + 1);
- loop(0)
+ val b = new ListBuffer[a]
+ var i = 0
+ while (i < n) {
+ b += maker(i)
+ i = i + 1
+ }
+ b.toList
}
/** Concatenate all the elements of a given list of lists.
* @param l the list of lists that are to be concatenated
* @return the concatenation of all the lists
*/
- def flatten[a](l: List[List[a]]): List[a] = l match {
- case Nil => Nil
- case head :: tail => head ::: flatten(tail)
+ def flatten[a](l: List[List[a]]): List[a] = {
+ val b = new ListBuffer[a]
+ var xsc = l
+ while (!xsc.isEmpty) {
+ var xc = xsc.head
+ while (!xc.isEmpty) {
+ b += xc.head
+ xc = xc.tail
+ }
+ xsc = xsc.tail
+ }
+ b.toList
}
/** Transforms a list of pair into a pair of lists.
@@ -101,11 +132,16 @@ object List {
* @param l the list of pairs to unzip
* @return a pair of lists: the first list in the pair contains the list
*/
- def unzip[a,b](l: List[Pair[a,b]]): Pair[List[a], List[b]] = l match {
- case Nil => new Pair(Nil, Nil)
- case Pair(f, s) :: tail =>
- val Pair(fs, ss) = unzip(tail);
- Pair(f :: fs, s :: ss)
+ def unzip[a,b](l: List[Pair[a,b]]): Pair[List[a], List[b]] = {
+ val b1 = new ListBuffer[a]
+ val b2 = new ListBuffer[b]
+ var xc = l
+ while (!xc.isEmpty) {
+ b1 += xc.head._1
+ b2 += xc.head._2
+ xc = xc.tail
+ }
+ Pair(b1.toList, b2.toList)
}
/** Converts an iterator to a list
@@ -114,9 +150,11 @@ object List {
* @return a list that contains the elements returned by successive
* calls to <code>it.next</code>
*/
- def fromIterator[a](it: Iterator[a]): List[a] =
- if (it.hasNext) it.next :: fromIterator(it);
- else Nil;
+ def fromIterator[a](it: Iterator[a]): List[a] = {
+ val b = new ListBuffer[a]
+ while (it.hasNext) b += it.next
+ b.toList
+ }
/** Converts an array into a list.
*
@@ -162,20 +200,7 @@ object List {
}
words
}
-/*
- var res: List[String] = Nil;
- var start = 0;
- var end = str.indexOf(separator);
- while (end >= 0) {
- if (end > start)
- res = str.substring(start, end) :: res;
- end = end + 1;
- start = end;
- end = str.indexOf(separator, end);
- }
- res.reverse
- }
-*/
+
/** Returns the given string as a list of characters.
*
* @param str the string to convert.
@@ -198,14 +223,41 @@ object List {
*/
def toString(xs: List[Char]): String = {
val sb = new StringBuffer();
- var ys = xs;
- while (!ys.isEmpty) {
- sb.append(ys.head);
- ys = ys.tail;
+ var xc = xs;
+ while (!xc.isEmpty) {
+ sb.append(xc.head);
+ xc = xc.tail;
}
sb.toString()
}
+ /** Like xs map f, but returns xs unchanged if function `f' maps all elements to themselves
+ */
+ 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.
*
@@ -214,21 +266,16 @@ object List {
* <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] =
- if (xs.isEmpty || ys.isEmpty) Nil
- else f(xs.head, ys.head) :: map2(xs.tail, ys.tail)(f);
-
- /** Like xs map f, but returns xs unchanged if function `f' maps all elements to themselves
- */
- def mapConserve[a <: AnyRef](xs: List[a])(f: a => a): List[a] = {
- if (xs.isEmpty) xs
- else {
- val head = xs.head;
- val head1 = f(head);
- val tail = xs.tail;
- val tail1 = mapConserve(tail)(f);
- if ((head1 eq head) && (tail1 eq tail)) xs else head1 :: tail1
+ 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
@@ -239,9 +286,19 @@ object List {
* <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code>, <code>[c0, ..., cm]</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] =
- if (xs.isEmpty || ys.isEmpty || zs.isEmpty) Nil
- else f(xs.head, ys.head, zs.head) :: map3(xs.tail, ys.tail, zs.tail)(f);
+ 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.
@@ -251,9 +308,16 @@ object List {
* <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
* <code>m = min(k,l)</code>
*/
- def forall2[a,b](xs: List[a], ys: List[b])(f: (a, b) => boolean): boolean =
- if (xs.isEmpty || ys.isEmpty) true
- else f(xs.head, ys.head) && forall2(xs.tail, ys.tail)(f);
+ 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.
@@ -263,9 +327,16 @@ object List {
* <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
* <code>m = min(k,l)</code>
*/
- def exists2[a,b](xs: List[a], ys: List[b])(f: (a, b) => boolean): boolean =
- if (xs.isEmpty || ys.isEmpty) false
- else f(xs.head, ys.head) || exists2(xs.tail, ys.tail)(f);
+ 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.
@@ -330,7 +401,7 @@ sealed abstract class List[+a] extends Seq[a] {
* @param x the element to append.
* @return the list with <code>x</code> appended at the beginning.
*/
- def ::[b >: a](x: b): List[b] =
+ def ::[b >: a] (x: b): List[b] =
new scala.::(x, this);
/** Returns a list resulting from the concatenation of the given
@@ -341,10 +412,17 @@ sealed abstract class List[+a] extends Seq[a] {
* @param prefix the list to concatenate at the beginning of this list.
* @return the concatenation of the two lists.
*/
- def :::[b >: a](prefix: List[b]): List[b] = prefix match {
- case Nil => this
- case head :: tail => head :: (tail ::: this);
- }
+ def :::[b >: a](prefix: List[b]): List[b] =
+ if (isEmpty) prefix
+ else {
+ val b = new ListBuffer[b]
+ var those = prefix
+ while (!those.isEmpty) {
+ b += those.head
+ those = those.tail
+ }
+ b.prependToList(this)
+ }
/** Reverse the given prefix and append the current list to that.
* This function is equivalent to an application of <code>reverse</code>
@@ -355,7 +433,7 @@ sealed abstract class List[+a] extends Seq[a] {
*/
def reverse_:::[b >: a](prefix: List[b]): List[b] = prefix match {
case Nil => this
- case head :: tail => tail.reverse_:::(head :: this)//todo: remove type annotation
+ case head :: tail => tail.reverse_:::(head :: this)
}
/** Returns the number of elements in the list.
@@ -363,11 +441,11 @@ sealed abstract class List[+a] extends Seq[a] {
* @return the number of elements in the list.
*/
def length: Int = {
- var xs = this;
+ var these = this;
var len = 0;
- while (!xs.isEmpty) {
+ while (!these.isEmpty) {
len = len + 1;
- xs = xs.tail
+ these = these.tail
}
len
}
@@ -377,12 +455,16 @@ sealed abstract class List[+a] extends Seq[a] {
*
* @return a list of all indices in the list.
*/
- def indices: List[Int] = {
- def loop(i: Int, xs: List[a]): List[Int] = xs match {
- case Nil => Nil
- case _ :: ys => i :: loop(i + 1, ys)
+ def indices: List[int] = {
+ val b = new ListBuffer[int]
+ var i = 0
+ var these = this
+ while (!these.isEmpty) {
+ b += i
+ i = i + 1
+ these = these.tail
}
- loop(0, this)
+ b.toList
}
/** Returns the elements in the list as an iterator
@@ -390,13 +472,13 @@ sealed abstract class List[+a] extends Seq[a] {
* @return an iterator on the list elements.
*/
def elements: Iterator[a] = new Iterator[a] {
- var current = List.this;
- def hasNext: Boolean = !current.isEmpty;
+ var these = List.this;
+ def hasNext: Boolean = !these.isEmpty;
def next: a =
if (!hasNext)
error("next on empty Iterator")
else {
- val result = current.head; current = current.tail; result
+ val result = these.head; these = these.tail; result
}
}
@@ -404,38 +486,53 @@ sealed abstract class List[+a] extends Seq[a] {
*
* @return a list which enumerates all elements of this sequence.
*/
- override def toList: List[a] = this;
+ //override def toList: List[a] = this; //!!!
/** Returns the list without its last element.
*
* @return the list without its last element.
* @throws <code>java.lang.RuntimeException</code> if the list is empty.
*/
- def init: List[a] = this match {
- case Nil => error("Nil.init")
- case _ :: Nil => Nil
- case head :: tail => head :: tail.init
- }
+ def init: List[a] =
+ if (isEmpty) error("Nil.init")
+ else {
+ val b = new ListBuffer[a]
+ var elem = head
+ var next = tail
+ while (!next.isEmpty) {
+ b += elem
+ elem = next.head
+ next = next.tail
+ }
+ b.toList
+ }
/** Returns the last element of this list.
*
* @return the last element of the list.
* @throws <code>java.lang.RuntimeException</code> if the list is empty.
*/
- def last: a = this match {
- case Nil => error("Nil.last")
- case last :: Nil => last
- case _ :: tail => tail.last
- }
+ def last: a =
+ if (isEmpty) error("Nil.last")
+ else if (tail.isEmpty) head
+ else tail.last;
/** Returns the <code>n</code> first elements of this list.
*
* @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] =
- if (n == 0 || isEmpty) Nil
- else head :: (tail take (n-1));
+ override def take(n: Int): List[a] = {
+ val b = new ListBuffer[a]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i = i + 1
+ b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
/** Returns the list without its <code>n</code> first elements.
*
@@ -481,12 +578,17 @@ sealed abstract class List[+a] extends Seq[a] {
* @return a pair of lists composed of the first <code>n</code>
* elements, and the other elements.
*/
- def splitAt(n: Int): Pair[List[a], List[a]] =
- if (n == 0) Pair(Nil, this)
- else {
- val Pair(tail1, tail2) = tail splitAt (n-1);
- Pair(head :: tail1, tail2)
+ def splitAt(n: Int): Pair[List[a], List[a]] = {
+ val b = new ListBuffer[a]
+ var i = 0
+ var these = this;
+ while (!these.isEmpty && i < n) {
+ i = i + 1
+ b += these.head
+ these = these.tail
}
+ Pair(b.toList, these)
+ }
/** Returns the longest prefix of this list whose elements satisfy
* the predicate <code>p</code>.
@@ -495,9 +597,15 @@ sealed abstract class List[+a] extends Seq[a] {
* @return the longest prefix of this list whose elements satisfy
* the predicate <code>p</code>.
*/
- def takeWhile(p: a => Boolean): List[a] =
- if (isEmpty || !p(head)) Nil
- else head :: (tail takeWhile p);
+ 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>.
@@ -517,14 +625,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @return a pair consisting of the longest prefix of the list whose
* elements all satisfy <code>p</code>, and the rest of the list.
*/
- def span(p: a => Boolean): Pair[List[a], List[a]] = this match {
- case Nil => Pair(Nil, Nil)
- case head :: tail =>
- if (p(head)) {
- val Pair(tail1, tail2) = tail span p;
- Pair(head :: tail1, tail2)
- } else
- Pair(Nil, this)
+ def span(p: a => Boolean): Pair[List[a], List[a]] = {
+ val b = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ Pair(b.toList, these)
}
/** Like <code>span</code> but with the predicate inverted.
@@ -546,9 +654,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @param f function to apply to each element.
* @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>.
*/
- def map[b](f: a => b): List[b] = this match {
- case Nil => Nil
- case head :: tail => f(head) :: (tail map f)
+ 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
@@ -572,11 +685,11 @@ sealed abstract class List[+a] extends Seq[a] {
* @param f the treatment to apply to each element.
*/
override def foreach(f: a => Unit): Unit = {
- def loop(xs: List[a]): Unit = xs match {
- case Nil => ()
- case head :: tail => f(head); loop(tail)
+ var these = this;
+ while (!these.isEmpty) {
+ f(these.head)
+ these = these.tail
}
- loop(this)
}
/** Returns all the elements of this list that satisfy the
@@ -585,13 +698,26 @@ sealed abstract class List[+a] extends Seq[a] {
* @param p the redicate used to filter the list.
* @return the elements of this list satisfying <code>p</code>.
*/
- def filter(p: a => Boolean): List[a] = this match {
- case Nil => this
- case head :: tail =>
- if (p(head)) {
- val tail1 = tail filter p;
- if (tail eq tail1) this else head :: tail1
- } else tail filter p
+ 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
+ }
+ while (!these.isEmpty) {
+ if (p(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
}
/** Removes all elements of the list which satisfy the predicate
@@ -601,11 +727,7 @@ sealed abstract class List[+a] extends Seq[a] {
* @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): List[a] = this match {
- case Nil => this
- case head :: tail =>
- if (p(head)) tail remove p else head :: (tail remove p)
- }
+ def remove(p: a => Boolean): List[a] = filter (x => !p(x));
/** Partition the list in two sub-lists according to a predicate.
*
@@ -615,12 +737,15 @@ sealed abstract class List[+a] extends Seq[a] {
* relative order of the elements in the sub-lists is the same as in
* the original list.
*/
- def partition(p: a => Boolean): Pair[List[a], List[a]] = this match {
- case Nil => Pair(Nil, Nil)
- case head :: tail =>
- val Pair(taily, tailn) = tail partition p;
- if (p(head)) Pair(head :: taily, tailn)
- else Pair(taily, head :: tailn)
+ def partition(p: a => Boolean): Pair[List[a], List[a]] = {
+ val btrue = new ListBuffer[a]
+ val bfalse = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty) {
+ (if (p(these.head)) btrue else bfalse) += these.head
+ these = these.tail
+ }
+ Pair(btrue.toList, bfalse.toList)
}
/** Sort the list according to the comparison function
@@ -685,9 +810,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @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 = this match {
- case Nil => 0
- case head :: tail => if (p(head)) 1 + (tail count p) else (tail count p)
+ def count(p: a => Boolean): Int = {
+ var cnt = 0
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) cnt = cnt + 1
+ these = these.tail
+ }
+ cnt
}
/** Tests if the predicate <code>p</code> is satisfied by all elements
@@ -696,8 +826,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @param p the test predicate.
* @return True iff all elements of this list satisfy the predicate <code>p</code>.
*/
- override def forall(p: a => Boolean): Boolean =
- isEmpty || (p(head) && (tail forall p));
+ 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>.
@@ -706,8 +842,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @return true iff there exists an element in this list that satisfies
* the predicate <code>p</code>.
*/
- override def exists(p: a => Boolean): Boolean =
- !isEmpty && (p(head) || (tail exists p));
+ override def exists(p: a => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return true
+ these = these.tail
+ }
+ false
+ }
/** Tests if the given value <code>elem</code> is a member of this
* iterable object.
@@ -716,7 +858,7 @@ sealed abstract class List[+a] extends Seq[a] {
* @return True iff there is an element of this list which is
* equal (w.r.t. <code>==</code>) to <code>elem</code>.
*/
- def contains(elem: Any): boolean = exists { x => x == elem }
+ def contains(elem: Any): boolean = exists (.==(elem))
/** Find and return the first element of the list satisfying a
* predicate, if any.
@@ -725,9 +867,13 @@ sealed abstract class List[+a] extends Seq[a] {
* @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] = this match {
- case Nil => None
- case head :: tail => if (p(head)) Some(head) else tail find p
+ 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
@@ -737,9 +883,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @return <code>op(... (op(op(z,a0),a1) ...), an)</code> if the list
* is <code>[a0, a1, ..., an]</code>.
*/
- override def foldLeft[b](z: b)(f: (b, a) => b): b = this match {
- case Nil => z
- case x :: xs => xs.foldLeft[b](f(z, x))(f)
+ 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
@@ -772,9 +923,18 @@ sealed abstract class List[+a] extends Seq[a] {
* @return <code>f(a0) ::: ... ::: f(an)</code> if this list is
* <code>[a0, ..., an]</code>.
*/
- def flatMap[b](f: a => List[b]): List[b] = this match {
- case Nil => Nil
- case head :: tail => f(head) ::: (tail flatMap f)
+ def flatMap[b](f: a => List[b]): List[b] = {
+ val b = new ListBuffer[b]
+ var these = this
+ while (!these.isEmpty) {
+ var those = f(these.head)
+ while (!those.isEmpty) {
+ b += those.head
+ those = those.tail
+ }
+ these = these.tail
+ }
+ b.toList
}
/** Reverses the elements of this list.
@@ -817,9 +977,17 @@ sealed abstract class List[+a] extends Seq[a] {
* @return <code>[(a0,b0), ..., (an,bn)]</code> when
* <code>[a0, ..., an] zip [b0, ..., bn]</code> is invoked.
*/
- def zip[b](that: List[b]): List[Pair[a,b]] =
- if (this.isEmpty || that.isEmpty) Nil
- else Pair(this.head, that.head) :: this.tail.zip(that.tail);
+ def zip[b](that: List[b]): List[Pair[a,b]] = {
+ val b = new ListBuffer[Pair[a, b]]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += Pair(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
@@ -834,15 +1002,25 @@ sealed abstract class List[+a] extends Seq[a] {
* when <code>[a0, ..., an] zip [b0, ..., bm]</code> is invoked where
* <code>m &gt; n</code>.
*/
- def zipAll[c >: a, b](that: List[b], thisElem: c, thatElem: b): List[Pair[c,b]] =
- if (this.isEmpty && that.isEmpty)
- Nil
- else if (this.isEmpty)
- List.make(that.length, thisElem) zip that
- else if (that.isEmpty)
- this zip List.make(this.length, thatElem)
- else
- Pair(this.head, that.head) :: this.tail.zipAll(that.tail, thisElem, thatElem);
+ def zipAll[b, c >: a, d >: b](that: List[b], thisElem: c, thatElem: d): List[Pair[c,d]] = {
+ val b = new ListBuffer[Pair[c, d]]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += Pair(these.head, those.head)
+ these = these.tail
+ those = those.tail
+ }
+ while (!these.isEmpty) {
+ b += Pair(these.head, thatElem)
+ these = these.tail
+ }
+ while (!those.isEmpty) {
+ b += Pair(thisElem, those.head)
+ those = those.tail
+ }
+ b.toList
+ }
/** Computes the union of this list and the given list
* <code>that</code>.
@@ -851,11 +1029,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @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] = this match {
- case Nil => that
- case head :: tail =>
- if (that contains head) tail union that
- else head :: (tail union that)
+ 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
@@ -864,11 +1045,14 @@ sealed abstract class List[+a] extends Seq[a] {
* @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 diff[b >: a](that: List[b]): List[b] = this match {
- case Nil => Nil
- case head :: tail =>
- if (that contains head) tail diff that
- else head :: (tail diff that)
+ def diff[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 intersection between this list and the given list
@@ -885,11 +1069,14 @@ sealed abstract class List[+a] extends Seq[a] {
*
* @return the list without doubles.
*/
- def removeDuplicates: List[a] = this match {
- case Nil => this
- case head :: tail =>
- if (tail contains head) tail.removeDuplicates
- else head :: tail.removeDuplicates
+ def removeDuplicates: List[a] = {
+ val b = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty) {
+ if (!these.tail.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
}
}
@@ -911,9 +1098,9 @@ case object Nil extends List[All] {
* @version 1.0, 15/07/2003
*/
[SerialVersionUID(0L - 8476791151983527571L)]
-final case class ::[+b](hd: b, tl: List[b]) extends List[b] {
+final case class ::[b](hd: b, var tl: List[b]) extends List[b] {
+ def head = hd;
+ def tail = tl;
def isEmpty: boolean = false;
- def head: b = hd;
- def tail: List[b] = tl;
}
diff --git a/src/library/scala/Long.java b/src/library/scala/Long.java
index bcaf38eb36..a3a9b2c73e 100644
--- a/src/library/scala/Long.java
+++ b/src/library/scala/Long.java
@@ -116,7 +116,6 @@ public abstract class Long extends AnyVal implements java.io.Serializable {
public long $bar (long that) { return value | that; }
public long $amp (long that) { return value & that; }
public long $up (long that) { return value ^ that; }
-/*
public boolean $eq$eq (int that) { return value == that; }
public boolean $bang$eq (int that) { return value != that; }
@@ -177,5 +176,4 @@ public abstract class Long extends AnyVal implements java.io.Serializable {
public long $bar (byte that) { return value | that; }
public long $amp (byte that) { return value & that; }
public long $up (byte that) { return value ^ that; }
-*/
}
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index e89e1a9c81..d2e25e5932 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -9,6 +9,8 @@
package scala.collection.mutable;
+import Predef._;
+
/** An implementation of the Buffer trait using an array to
* represent the assembled sequence internally.
@@ -136,9 +138,10 @@ class ArrayBuffer[A] extends Buffer[A] with ResizableArray[A] {
*/
override def equals(obj: Any): Boolean = obj match {
case that: ArrayBuffer[A] =>
+ ( this.length == that.length &&
elements.zip(that.elements).forall {
case Pair(thiselem, thatelem) => thiselem == thatelem;
- }
+ } )
case _ => false
}
diff --git a/src/library/scala/collection/mutable/Buffer.scala b/src/library/scala/collection/mutable/Buffer.scala
index f1e8d0fe9b..8dc0482c5c 100644
--- a/src/library/scala/collection/mutable/Buffer.scala
+++ b/src/library/scala/collection/mutable/Buffer.scala
@@ -9,6 +9,8 @@
package scala.collection.mutable;
+import Predef._;
+
/** 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
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index 527741bbc9..ce9061bcfa 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -9,135 +9,213 @@
package scala.collection.mutable;
+import Predef._;
-/** A list buffer uses a list internally to assemble sequences of elements
- * incrementally by appending or prepending new elements. It is also
- * possible to access and modify elements in a random access fashion
- * via the index of the element in the sequence.
- *
- * @author Matthias Zenger
- * @version 1.0, 15/03/2004
- */
-class ListBuffer[A] extends Buffer[A] with MutableList[A] {
-
- /** Append a single element to this buffer and return
- * the identity of the buffer.
- *
- * @param elem the element to append.
- */
- def +(elem: A): Buffer[A] = { appendElem(elem); this }
-
- /** Prepend a single element to this buffer and return
- * the identity of the buffer.
- *
- * @param elem the element to append.
- */
- def +:(elem: A): Buffer[A] = { prependElem(elem); 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.
- */
- def insertAll(n: Int, iter: Iterable[A]): Unit = {
- val it = iter.elements;
- while (it.hasNext) {
- val newelem = it.next;
- if (n == 0)
- prepend(newelem);
- else if (n >= len)
- append(newelem);
- else {
- var elem = first;
- var i = n;
- while (i > 1) {
- elem = elem.next;
- if (elem == null)
- error("cannot insert element " + n + " in ListBuffer");
- i = i - 1;
- }
- val old = elem.next;
- elem.next = new LinkedList[A](newelem, old);
- }
- }
+final class ListBuffer[A] extends Buffer[A] {
+ private var start: List[A] = Nil;
+ private var last: ::[A] = _;
+ private var exported: boolean = false;
+
+ /** Append a single element to this buffer and return
+ * the identity of the buffer. Same as ``this += x; this''
+ *
+ * @param x the element to append.
+ */
+ def + (x: A): Buffer[A] = { this += x; this }
+
+ /** Prepend a single element to this buffer.
+ *
+ * @param x the element to prepend.
+ */
+ def +: (x: A): Buffer[A] = {
+ if (exported) copy()
+ val newElem = new scala.:: (x, start)
+ if (start.isEmpty) last = newElem
+ start = newElem
+ this
+ }
+
+ /** Append a single element to this buffer.
+ *
+ * @param x the element to append.
+ */
+ override def += (x: A): unit = {
+ if (exported) copy()
+ if (start.isEmpty) {
+ last = new scala.:: (x, Nil)
+ start = last
+ } else {
+ val last1 = last
+ last = new scala.:: (x, Nil)
+ last1.tl = last
}
+ }
+
+ /** Converts this buffer to a list
+ */
+ override def toList: List[A] = {
+ exported = !start.isEmpty
+ start
+ }
- /** 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.
- */
- def update(n: Int, newelem: A): Unit = {
- var elem = first;
- var i = n;
- while (i > 0) {
- elem = elem.next;
- if (elem == null)
- error("cannot update element " + n + " in Buffer");
- i = i - 1;
- }
- elem.elem = newelem;
+ /** 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 { last.tl = xs; toList }
+
+ /** Clears the buffer contents.
+ */
+ def clear: unit = {
+ start = Nil
+ exported = false
+ }
+
+ /** Copy contents of this buffer */
+ private def copy() = {
+ var cursor = start
+ val limit = last.tail
+ clear
+ while (cursor ne limit) {
+ this += cursor.head
+ cursor = cursor.tail
}
+ }
+
+ /** Returns the length of this buffer.
+ */
+ def length: int = start.length
- /** 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 old = apply(n);
- if (n >= len)
- error("cannot remove element " + n + " in Buffer");
- if ((n == 0) && (len == 1)) {
- first = null;
- last = null;
- } else if (n == 0) {
- first = first.next;
- } else {
- var elem = first;
- var i = n;
- while (i > 1) {
- elem = elem.next;
- i = i - 1;
- }
- elem.next = elem.next.next;
- if (n == (len - 1)) {
- last = elem.next;
- }
- }
- len = len - 1;
- old;
+ private def noElem(n: int): All = error("element " + n + " does not exist in buffer");
+
+ /** Returns the <code>n</code>th element of this list. This method
+ * yields an error if the element does not exist.
+ */
+ def apply(n: Int): A = try {
+ start(n)
+ } catch {
+ case ex: Error => noElem(n)
+ }
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param x the new element.
+ */
+ def update(n: Int, x: A): unit = try {
+ if (exported) copy()
+ if (n == 0) {
+ val newElem = new scala.:: (x, start.tail);
+ if (last eq start) last = newElem
+ start = newElem
+ } else {
+ var cursor = start;
+ var i = 1;
+ while (i < n) {
+ cursor = cursor.tail
+ i = i + 1
+ }
+ val newElem = new scala.:: (x, cursor.tail.tail)
+ if (last eq cursor.tail) last = newElem
+ cursor.asInstanceOf[scala.::[A]].tl = newElem
}
+ } catch {
+ case ex: Error => noElem(n)
+ }
- /** Clears the buffer contents.
- */
- def clear: Unit = reset;
-
- /** Return a clone of this buffer.
- *
- * @return an <code>ArrayBuffer</code> with the same elements.
- */
- override def clone(): Buffer[A] = {
- val res = new ListBuffer[A];
- res ++= this;
- res
+ /** 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.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): unit = try {
+ if (exported) copy()
+ var elems = iter.elements.toList.reverse;
+ if (n == 0) {
+ while (!elems.isEmpty) {
+ val newElem = new scala.:: (elems.head, start);
+ if (start.isEmpty) last = newElem
+ start = newElem
+ elems = elems.tail
+ }
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i = i + 1
+ }
+ while (!elems.isEmpty) {
+ val newElem = new scala.:: (elems.head, cursor.tail);
+ if (cursor.tail.isEmpty) last = newElem
+ cursor.asInstanceOf[scala.::[A]].tl = newElem
+ elems = elems.tail
+ }
}
+ } catch {
+ case ex: Error => noElem(n)
+ }
- /** Checks if two buffers are structurally identical.
- *
- * @return true, iff both buffers contain the same sequence of elements.
- */
- override def equals(obj: Any): Boolean = obj match {
- case that: ListBuffer[A] =>
- elements.zip(that.elements).forall {
- case Pair(thiselem, thatelem) => thiselem == thatelem;
- }
- case _ => false
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ * @return n the element that was formerly at posiition `n'
+ * @pre an element exists at position `n'
+ */
+ 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 = i + 1
+ }
+ old = cursor.tail.head
+ if (last eq cursor.tail) last = cursor.asInstanceOf[scala.::[A]]
+ cursor.asInstanceOf[scala.::[A]].tl = cursor.tail.tail
}
+ old
+ } catch {
+ case ex: Error => noElem(n)
+ }
+
+ /** Returns an iterator over all elements of this list.
+ * Note: the iterator can be affected by insertions, updates and deletions
+ * that are performed afterwards on the buffer. To get iterator an over the current
+ * buffer snapshot, use toList.elements
+ */
+ override def elements: Iterator[A] = start.elements
- /** Defines the prefix of the string representation.
- */
- override protected def stringPrefix: String = "ListBuffer";
+ /** Return a clone of this buffer.
+ *
+ * @return a <code>ListBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this
+
+ /** Checks if two buffers are structurally identical.
+ *
+ * @return true, iff both buffers contain the same sequence of elements.
+ */
+ override def equals(obj: Any): Boolean = obj match {
+ case that: ListBuffer[A] =>
+ (this.length == that.length &&
+ elements.zip(that.elements).forall {
+ case Pair(thiselem, thatelem) => thiselem == thatelem;
+ })
+ case _ => false
+ }
+
+ /** Defines the prefix of the string representation.
+ */
+ override protected def stringPrefix: String = "ListBuffer";
}
+
diff --git a/src/library/scala/collection/mutable/Message.scala b/src/library/scala/collection/mutable/Message.scala
index bd805c5d6e..effd2c2114 100644
--- a/src/library/scala/collection/mutable/Message.scala
+++ b/src/library/scala/collection/mutable/Message.scala
@@ -9,6 +9,8 @@
package scala.collection.mutable;
+import Predef._;
+
/** Class <code>Message</code> represents messages that are issued by observable
* collection classes whenever a data structure is changed. Class <code>Message</code>
diff --git a/src/library/scala/runtime/compat/Platform.scala b/src/library/scala/runtime/compat/Platform.scala
index 282421a981..7aa3870669 100644
--- a/src/library/scala/runtime/compat/Platform.scala
+++ b/src/library/scala/runtime/compat/Platform.scala
@@ -12,7 +12,7 @@
package scala.runtime.compat;
object Platform {
- def arraycopy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: int): Unit =
+ def arraycopy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int): Unit =
System.arraycopy(src, srcPos, dest, destPos, length);
def getClass(obj: AnyRef) = obj.getClass();
def getClassName(obj: AnyRef) = obj.getClass().getName();