diff options
author | Paul Phillips <paulp@improving.org> | 2009-09-22 06:24:34 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-09-22 06:24:34 +0000 |
commit | efc9abd507efc4a1847459a3523dbd95d1e0acb3 (patch) | |
tree | 965a24814c8546972cddf718988e7ab41cce1cb4 /src/library | |
parent | d094b4ac4dfc3822129562921d801a2ae7616605 (diff) | |
download | scala-efc9abd507efc4a1847459a3523dbd95d1e0acb3.tar.gz scala-efc9abd507efc4a1847459a3523dbd95d1e0acb3.tar.bz2 scala-efc9abd507efc4a1847459a3523dbd95d1e0acb3.zip |
Attempting to widen the field of possibilities ...
Attempting to widen the field of possibilities for equality, a proof
by construction that a large codebase doesn't need to perform equality
checks between different primitives types if it is not so inclined.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/collection/generic/BitSetTemplate.scala | 6 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/LongMap.scala | 2 | ||||
-rw-r--r-- | src/library/scala/io/BytePickle.scala | 2 | ||||
-rw-r--r-- | src/library/scala/io/UTF8Codec.scala | 2 | ||||
-rw-r--r-- | src/library/scala/runtime/BoxesRunTime.java | 75 | ||||
-rw-r--r-- | src/library/scala/xml/Utility.scala | 59 | ||||
-rw-r--r-- | src/library/scala/xml/parsing/TokenTests.scala | 2 |
7 files changed, 97 insertions, 51 deletions
diff --git a/src/library/scala/collection/generic/BitSetTemplate.scala b/src/library/scala/collection/generic/BitSetTemplate.scala index 501a388b4d..670109a874 100644 --- a/src/library/scala/collection/generic/BitSetTemplate.scala +++ b/src/library/scala/collection/generic/BitSetTemplate.scala @@ -61,7 +61,7 @@ trait BitSetTemplate[+This <: BitSetTemplate[This] with Set[Int]] extends SetTem for (i <- 0 until nwords) { val w = word(i) for (j <- i * WordLength until (i + 1) * WordLength) { - if ((w & (1L << j)) != 0) f(j) + if ((w & (1L << j)) != 0L) f(j) } } } @@ -109,7 +109,7 @@ trait BitSetTemplate[+This <: BitSetTemplate[This] with Set[Int]] extends SetTem /** Does the set contain the given element? */ def contains(elem: Int): Boolean = - 0 <= elem && (word(elem >> LogWL) & (1L << elem)) != 0 + 0 <= elem && (word(elem >> LogWL) & (1L << elem)) != 0L /** Is the set a subset of the given bitset */ @@ -154,6 +154,6 @@ object BitSetTemplate { private def popCount(w: Long): Int = { def pc2(w: Int) = if (w == 0) 0 else pc1(w & 0xff) + pc1(w >>> 8) def pc4(w: Int) = if (w == 0) 0 else pc2(w & 0xffff) + pc2(w >>> 16) - if (w == 0) 0 else pc4(w.toInt) + pc4((w >>> 32).toInt) + if (w == 0L) 0 else pc4(w.toInt) + pc4((w >>> 32).toInt) } } diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index 2be51e7577..d553329114 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -4,7 +4,7 @@ package scala.collection.immutable; * @author David MacIver */ private[immutable] object LongMapUtils{ - def zero(i : Long, mask : Long) = (i & mask) == 0; + def zero(i : Long, mask : Long) = (i & mask) == 0L; def mask(i : Long, mask : Long) = i & (complement(mask - 1) ^ mask) def hasMatch(key : Long, prefix : Long, m : Long) = mask(key, m) == prefix; def unsignedCompare(i : Long, j : Long) = (i < j) ^ (i < 0) ^ (j < 0) diff --git a/src/library/scala/io/BytePickle.scala b/src/library/scala/io/BytePickle.scala index 558a299399..7e5628e207 100644 --- a/src/library/scala/io/BytePickle.scala +++ b/src/library/scala/io/BytePickle.scala @@ -69,7 +69,7 @@ object BytePickle { case Def() => Array.concat(s, Array[Byte](1)) }; def appU(s: Array[Byte]): (RefDef, Array[Byte]) = - if (s(0) == 0) (Ref(), s.slice(1, s.length)) + if (s(0) == (0: Byte)) (Ref(), s.slice(1, s.length)) else (Def(), s.slice(1, s.length)); } diff --git a/src/library/scala/io/UTF8Codec.scala b/src/library/scala/io/UTF8Codec.scala index 21d3b3bb31..6bbe6263ee 100644 --- a/src/library/scala/io/UTF8Codec.scala +++ b/src/library/scala/io/UTF8Codec.scala @@ -33,7 +33,7 @@ object UTF8Codec @deprecated("""Use new String(Array(ch), 0, 1).getBytes("UTF-8") instead""") def encode(ch: Int): Array[Byte] = - if ((Character getType ch) == Character.SURROGATE) UNI_REPLACEMENT_BYTES + if ((Character getType ch) == Character.SURROGATE.toInt) UNI_REPLACEMENT_BYTES else try new String(Array(ch), 0, 1) getBytes "UTF-8" catch { case _: IllegalArgumentException => UNI_REPLACEMENT_BYTES } diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index 3f71bb9409..885022c01c 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -11,6 +11,8 @@ package scala.runtime; +import java.io.*; + /** An object (static class) that defines methods used for creating, * reverting, and calculating with, boxed values. There are four classes * of methods in this object: @@ -25,7 +27,44 @@ package scala.runtime; * @author Martin Odersky * @contributor Stepan Koltsov * @version 2.0 */ -public class BoxesRunTime { +public class BoxesRunTime +{ + /**** Temporary code to support logging all equality comparisons. ****/ + private static boolean eqeqLogging = false; + private static String eqeqLogName = "/tmp/trunk-eqeq.log"; + private static FileWriter eqeqLog; + public static void setEqEqLogging(boolean state) { + eqeqLogging = state; + if (state) { + try { eqeqLog = new FileWriter(eqeqLogName, true); } + catch (IOException e) { eqeqLog = null; } + + log("Started eqeq log at " + (new java.util.Date())); + } + } + private static String obToString(Object o) { + String s = o.toString() + " (" + o.getClass().getSimpleName() + ")"; + return s.replaceAll("\\n", " "); + } + private static void logInternal(String msg, Object a, Object b, String where) { + log(msg + obToString(a) + " == " + obToString(b) + " " + where); + } + + public static String whereAreWe() { + StackTraceElement e = Thread.currentThread().getStackTrace()[3]; + return"(" + e.getClassName() + "." + e.getMethodName() + e.getFileName() + ":" + e.getLineNumber() + ")"; + } + public static void log(String msg) { + if (eqeqLogging && eqeqLog != null) { + try { + eqeqLog.write(msg + "\n"); + eqeqLog.flush(); + } + catch (IOException e) { } + } + } + + /**** End temporary logging section. ****/ private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7; @@ -121,16 +160,15 @@ public class BoxesRunTime { return d == null ? 0.0d : ((Double)d).doubleValue(); } -/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */ + /**************************************/ - /** A rich implementation of the <code>equals</code> method that overrides the - * default equals because Java's boxed primitives are utterly broken. This equals - * is inserted instead of a normal equals by the Scala compiler (in the - * ICode phase, method <code>genEqEqPrimitive</code>) only when either - * side of the comparison is a subclass of <code>AnyVal</code>, of - * <code>java.lang.Number</code>, of <code>java.lang.Character</code> or - * is exactly <code>Any</code> or <code>AnyRef</code>. */ public static boolean equals(Object a, Object b) { + if ((a instanceof Number || a instanceof Character) && (b instanceof Number || b instanceof Character)) { + if (a.getClass() != b.getClass()) { + logInternal("[ BOXED ] Comparing: ", a, b, whereAreWe()); + } + } + if (a == null || b == null) return a == b; if (a.equals(b)) @@ -139,32 +177,41 @@ public class BoxesRunTime { int acode = typeCode(a); int bcode = typeCode(b); int maxcode = (acode < bcode) ? bcode : acode; + boolean res = false; if (maxcode <= INT) { int aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).intValue(); int bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).intValue(); - return aa == bb; + res = (aa == bb); } if (maxcode <= LONG) { long aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).longValue(); long bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).longValue(); - return aa == bb; + res = (aa == bb); } if (maxcode <= FLOAT) { float aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).floatValue(); float bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).floatValue(); - return aa == bb; + res = (aa == bb); } if (maxcode <= DOUBLE) { double aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).doubleValue(); double bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).doubleValue(); - return aa == bb; + res = (aa == bb); } - return b.equals(a); + if (res || b.equals(a)) { + String msg; + if (res) msg = "[ BOXED ] Overriding equals between different types: "; + else msg = "[ BOXED ] Overriding equals because b.equals(a): "; + logInternal(msg, a, b, whereAreWe()); + return true; + } + return false; } return false; } + /* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */ /** arg1 + arg2 */ diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 39e594eb05..302f77d07c 100644 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -331,44 +331,43 @@ object Utility extends AnyRef with parsing.TokenTests * @return ... */ def parseAttributeValue(value: String): Seq[Node] = { - val zs: Seq[Char] = value val sb = new StringBuilder var rfb: StringBuilder = null val nb = new NodeBuffer() - val it = zs.iterator + + val it = value.iterator while (it.hasNext) { var c = it.next - c match { - case '&' => // entity! flush buffer into text node - it.next match { - case '#' => - c = it.next - val theChar = parseCharRef ({ ()=> c },{ () => c = it.next },{s => throw new RuntimeException(s)}) - sb.append(theChar) - - case x => - if (rfb eq null) rfb = new StringBuilder() - rfb.append(x) - c = it.next - while (c != ';') { - rfb.append(c) - c = it.next - } - val ref = rfb.toString() - rfb.setLength(0) - unescape(ref,sb) match { - case null => - if (sb.length > 0) { // flush buffer - nb += Text(sb.toString()) - sb.setLength(0) - } - nb += EntityRef(sb.toString()) // add entityref - case _ => + // entity! flush buffer into text node + if (c == '&') { + c = it.next + if (c == '#') { + c = it.next + val theChar = parseCharRef ({ ()=> c },{ () => c = it.next },{s => throw new RuntimeException(s)}) + sb.append(theChar) + } + else { + if (rfb eq null) rfb = new StringBuilder() + rfb append c + c = it.next + while (c != ';') { + rfb.append(c) + c = it.next + } + val ref = rfb.toString() + rfb.setLength(0) + unescape(ref,sb) match { + case null => + if (sb.length > 0) { // flush buffer + nb += Text(sb.toString()) + sb.setLength(0) } + nb += EntityRef(sb.toString()) // add entityref + case _ => } - case x => - sb.append(x) + } } + else sb append c } if (sb.length > 0) { // flush buffer val x = Text(sb.toString()) diff --git a/src/library/scala/xml/parsing/TokenTests.scala b/src/library/scala/xml/parsing/TokenTests.scala index e4d9b371f8..608a715d15 100644 --- a/src/library/scala/xml/parsing/TokenTests.scala +++ b/src/library/scala/xml/parsing/TokenTests.scala @@ -37,7 +37,7 @@ trait TokenTests { */ def isNameChar(ch: Char) = isNameStart(ch) || (ch match { case '.' | '-' | ':' => true; - case _ => java.lang.Character.getType( ch ).asInstanceOf[Byte] match { + case _ => java.lang.Character.getType( ch ).toByte match { case java.lang.Character.COMBINING_SPACING_MARK => true; // Mc case java.lang.Character.ENCLOSING_MARK => true; // Me case java.lang.Character.NON_SPACING_MARK => true; // Mn |