diff options
author | Martin Odersky <odersky@gmail.com> | 2005-12-21 13:47:53 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-12-21 13:47:53 +0000 |
commit | 99b6474dabc8a4bcc9282f041d48fb9671c4f2b8 (patch) | |
tree | c701a1fac4866e0c7c0d41e49edd69c0c633f06f | |
parent | 7ccea812b72c15670fb3c5026acb7856a36e7fad (diff) | |
download | scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.gz scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.tar.bz2 scala-99b6474dabc8a4bcc9282f041d48fb9671c4f2b8.zip |
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 > 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(); |