summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-28 20:10:54 +0000
committerPaul Phillips <paulp@improving.org>2009-10-28 20:10:54 +0000
commitb7772a6535b1d3989ad350069568b124619f2877 (patch)
tree56726bf0a76929fc69bcf059e68e6e7fb2632ce1
parentcc934ee7bb181645d4436eb923f7eb843b7c259d (diff)
downloadscala-b7772a6535b1d3989ad350069568b124619f2877.tar.gz
scala-b7772a6535b1d3989ad350069568b124619f2877.tar.bz2
scala-b7772a6535b1d3989ad350069568b124619f2877.zip
Whole bunch of code for people interested in eq...
Whole bunch of code for people interested in equality. This includes four command line options you can use to alter equality semantics and the various levels of babbling and panicking which the runtime has to offer when confronted with a boxed primitive comparison.
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala44
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala6
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java311
-rw-r--r--src/library/scala/runtime/Equality.java58
5 files changed, 140 insertions, 291 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index e1429b1644..eb6017815a 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -825,8 +825,6 @@ trait ScalacSettings {
withHelpSyntax("-Ysqueeze:<enabled>")
val Ystatistics = BooleanSetting ("-Ystatistics", "Print compiler statistics")
val stop = PhasesSetting ("-Ystop", "Stop after phase")
- val logEquality = BooleanSetting ("-Ylog-equality", "Log all noteworthy equality tests (hardcoded to /tmp/scala-equality-log.txt)") .
- withPostSetHook(() => scala.runtime.Equality.logEverything = true)
val refinementMethodDispatch =
ChoiceSetting ("-Ystruct-dispatch", "Selects dispatch method for structural refinement method calls",
List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") .
@@ -838,6 +836,16 @@ trait ScalacSettings {
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
val Ytailrec = BooleanSetting ("-Ytailrecommend", "Alert methods which would be tail-recursive if private or final.")
+ // Equality specific
+ val logEqEq = BooleanSetting ("-Ylog-eqeq", "Log all noteworthy equality tests") .
+ withPostSetHook(() => scala.runtime.Equality.logEverything = true)
+ val YfutureEqEq = BooleanSetting ("-Yfuture-eqeq", "Use proposed overloading-based numeric equality semantics.") .
+ withPostSetHook(() => scala.runtime.Equality.use28Semantics = true)
+ val YwarnEqEq = BooleanSetting ("-Ywarn-eqeq", "Warn when boxed primitives of different types are compared.") .
+ withPostSetHook(() => scala.runtime.Equality.warnOnBoxedCompare = true)
+ val YdieEqEq = BooleanSetting ("-Ydie-changed-eqeq", "Throw an exception if a comparison would have come back differently in scala 2.7.") .
+ withPostSetHook(() => scala.runtime.Equality.dieOnBoxedCompareIfValuesAreEqual = true)
+
// Warnings
val Xwarninit = BooleanSetting ("-Xwarninit", "Warn about possible changes in initialization semantics")
val Xchecknull = BooleanSetting ("-Xcheck-null", "Emit warning on selection of nullable reference")
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b3d7da8f06..99f0d4cf3c 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1291,7 +1291,7 @@ abstract class GenICode extends SubComponent {
elseCtx: Context): Unit =
{
def genComparisonOp(l: Tree, r: Tree, code: Int) {
- if (settings.logEquality.value && isUniversalEqualityOp(code))
+ if (settings.logEqEq.value && isUniversalEqualityOp(code))
logEqEq(tree, l, r, code)
val op: TestOp = code match {
@@ -1422,9 +1422,13 @@ abstract class GenICode extends SubComponent {
(rsym == ObjectClass) ||
(lsym != rsym) && (isBoxed(lsym) || isBoxed(rsym))
}
+ def cannotAvoidBoxesRuntime =
+ settings.logEqEq.value || settings.YwarnEqEq.value || settings.YdieEqEq.value
- if (mustUseAnyComparator) {
-
+ /** We can avoid generating calls to BoxesRuntime only if -Yfuture-eqeq
+ * is enabled AND none of the eqeq logging options are enabled.
+ */
+ if (mustUseAnyComparator && (!settings.YfutureEqEq.value || cannotAvoidBoxesRuntime)) {
val ctx1 = genLoad(l, ctx, ANY_REF_CLASS)
val ctx2 = genLoad(r, ctx1, ANY_REF_CLASS)
ctx2.bb.emitOnly(
@@ -1433,7 +1437,6 @@ abstract class GenICode extends SubComponent {
)
}
else {
-
if (isNull(l))
// null == expr -> expr eq null
genLoad(r, ctx, ANY_REF_CLASS).bb emitOnly CZJUMP(thenCtx.bb, elseCtx.bb, EQ, ANY_REF_CLASS)
@@ -2153,39 +2156,18 @@ abstract class GenICode extends SubComponent {
override def varsInScope: Buffer[Local] = new ListBuffer
}
- /** Log equality tests to file if they are playing with typefire */
+ /** Log equality tests between different primitives. */
def logEqEq(tree: Tree, l: Tree, r: Tree, code: Int) {
import definitions._
val op = if (code == scalaPrimitives.EQ) "==" else if (code == scalaPrimitives.NE) "!=" else "??"
-
- def mayBeNumericComparison: Boolean = {
- def isPossiblyBoxed(sym: Symbol): Boolean = {
- import definitions._
- // classes as which a boxed primitive may statically appear
- val possibleBoxes = List(BoxedNumberClass, BoxedCharacterClass, SerializableClass, ComparableClass)
-
- (sym == ObjectClass) || (possibleBoxes exists (sym isNonBottomSubClass _))
- }
-
- val lsym = l.tpe.typeSymbol
- val rsym = r.tpe.typeSymbol
-
- def isSameBox = {
- def isFinalBox(s: Symbol) = (s isNonBottomSubClass BoxedNumberClass) && s.isFinal
- isFinalBox(lsym) && isFinalBox(rsym) && lsym == rsym
- }
- isPossiblyBoxed(lsym) && isPossiblyBoxed(rsym) && !isSameBox
- }
-
val tkl = toTypeKind(l.tpe)
val tkr = toTypeKind(r.tpe)
- lazy val whereAreWe = tree.pos.source + ":" + tree.pos.line
- def logit(preface: String) =
- runtime.Equality.log("[%s] %s %s %s (%s)".format(preface, l.tpe, op, r.tpe, whereAreWe))
if (tkl.isNumericType && tkr.isNumericType && tkl != tkr)
- logit(" KNOWN ")
- else if (mayBeNumericComparison)
- logit("UNKNOWN")
+ runtime.Equality.logComparison(
+ "Comparing actual primitives",
+ "%s %s %s".format(l.tpe, op, r.tpe),
+ tree.pos.source + ":" + tree.pos.line
+ )
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
index a46a987bb8..12f6f4021b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
@@ -70,6 +70,12 @@ abstract class ConstantFolder {
}
private def foldBinop(op: Name, x: Constant, y: Constant): Constant = try {
+ // temporarily logging folded ==/!= so the log doesn't have unexplained absences
+ if ((op == nme.EQ || op == nme.NE) && x.tag != y.tag && settings.logEqEq.value) {
+ val opstr = if (op == nme.EQ) "==" else "!="
+ scala.runtime.Equality.log("Folding constant expression (%s %s %s)".format(x.value, opstr, y.value))
+ }
+
val optag = if (x.tag == y.tag) x.tag
else if (isNumeric(x.tag) && isNumeric(y.tag))
if (x.tag > y.tag) x.tag else y.tag
diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java
index 010e2738c9..3e75cb213e 100644
--- a/src/library/scala/runtime/BoxesRunTime.java
+++ b/src/library/scala/runtime/BoxesRunTime.java
@@ -33,15 +33,19 @@ public class BoxesRunTime
private static int typeCode(Object a) {
if (a instanceof Integer) return INT;
+ if (a instanceof Byte) return BYTE;
if (a instanceof Character) return CHAR;
if (a instanceof Long) return LONG;
if (a instanceof Double) return DOUBLE;
- if (a instanceof Float) return FLOAT;
- if (a instanceof Byte) return BYTE;
if (a instanceof Short) return SHORT;
+ if (a instanceof Float) return FLOAT;
return OTHER;
}
+ private static String boxDescription(Object a) {
+ return "" + a.getClass().getSimpleName() + "(" + a + ")";
+ }
+
/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */
public static Boolean boxToBoolean(boolean b) {
@@ -135,221 +139,7 @@ public class BoxesRunTime
/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
- /** These methods manually implement "overloading" among boxed primitives.
- * The compiler is capable of inserting (but does not presently) the specific
- * equals method based on the statically known types of the boxes.
- */
-
- public static boolean equalsCharacterCharacter(Character a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.charValue();
- }
- public static boolean equalsCharacterByte(Character a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.byteValue();
- }
- public static boolean equalsCharacterShort(Character a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.shortValue();
- }
- public static boolean equalsCharacterInteger(Character a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.intValue();
- }
- public static boolean equalsCharacterLong(Character a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.longValue();
- }
- public static boolean equalsCharacterFloat(Character a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.floatValue();
- }
- public static boolean equalsCharacterDouble(Character a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.charValue() == b.doubleValue();
- }
- public static boolean equalsByteCharacter(Byte a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.charValue();
- }
- public static boolean equalsByteByte(Byte a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.byteValue();
- }
- public static boolean equalsByteShort(Byte a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.shortValue();
- }
- public static boolean equalsByteInteger(Byte a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.intValue();
- }
- public static boolean equalsByteLong(Byte a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.longValue();
- }
- public static boolean equalsByteFloat(Byte a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.floatValue();
- }
- public static boolean equalsByteDouble(Byte a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.byteValue() == b.doubleValue();
- }
- public static boolean equalsShortCharacter(Short a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.charValue();
- }
- public static boolean equalsShortByte(Short a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.byteValue();
- }
- public static boolean equalsShortShort(Short a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.shortValue();
- }
- public static boolean equalsShortInteger(Short a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.intValue();
- }
- public static boolean equalsShortLong(Short a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.longValue();
- }
- public static boolean equalsShortFloat(Short a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.floatValue();
- }
- public static boolean equalsShortDouble(Short a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.shortValue() == b.doubleValue();
- }
- public static boolean equalsIntegerCharacter(Integer a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.charValue();
- }
- public static boolean equalsIntegerByte(Integer a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.byteValue();
- }
- public static boolean equalsIntegerShort(Integer a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.shortValue();
- }
- public static boolean equalsIntegerInteger(Integer a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.intValue();
- }
- public static boolean equalsIntegerLong(Integer a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.longValue();
- }
- public static boolean equalsIntegerFloat(Integer a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.floatValue();
- }
- public static boolean equalsIntegerDouble(Integer a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.intValue() == b.doubleValue();
- }
- public static boolean equalsLongCharacter(Long a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.charValue();
- }
- public static boolean equalsLongByte(Long a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.byteValue();
- }
- public static boolean equalsLongShort(Long a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.shortValue();
- }
- public static boolean equalsLongInteger(Long a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.intValue();
- }
- public static boolean equalsLongLong(Long a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.longValue();
- }
- public static boolean equalsLongFloat(Long a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.floatValue();
- }
- public static boolean equalsLongDouble(Long a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.longValue() == b.doubleValue();
- }
- public static boolean equalsFloatCharacter(Float a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.charValue();
- }
- public static boolean equalsFloatByte(Float a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.byteValue();
- }
- public static boolean equalsFloatShort(Float a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.shortValue();
- }
- public static boolean equalsFloatInteger(Float a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.intValue();
- }
- public static boolean equalsFloatLong(Float a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.longValue();
- }
- public static boolean equalsFloatFloat(Float a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.floatValue();
- }
- public static boolean equalsFloatDouble(Float a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.floatValue() == b.doubleValue();
- }
- public static boolean equalsDoubleCharacter(Double a, Character b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.charValue();
- }
- public static boolean equalsDoubleByte(Double a, Byte b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.byteValue();
- }
- public static boolean equalsDoubleShort(Double a, Short b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.shortValue();
- }
- public static boolean equalsDoubleInteger(Double a, Integer b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.intValue();
- }
- public static boolean equalsDoubleLong(Double a, Long b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.longValue();
- }
- public static boolean equalsDoubleFloat(Double a, Float b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.floatValue();
- }
- public static boolean equalsDoubleDouble(Double a, Double b) {
- if (a == null || b == null) return (Object)a == (Object)b;
- else return a.doubleValue() == b.doubleValue();
- }
-
- /** The current equals method, whose logic is under review. **/
-
- 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()) {
- Equality.logInternal("[ BOXED ] Comparing: ", a, b, Equality.whereAreWe());
- }
- }
-
- if (a == null || b == null)
- return a == b;
- if (a.equals(b))
- return true;
+ private static boolean equalsBonusLogicFromScala27(Object a, Object b) {
if (a instanceof Number || a instanceof Character || b instanceof Number || b instanceof Character) {
int acode = typeCode(a);
int bcode = typeCode(b);
@@ -376,18 +166,45 @@ public class BoxesRunTime
res = (aa == bb);
}
- 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): ";
- Equality.logInternal(msg, a, b, Equality.whereAreWe());
- return true;
- }
- return false;
+ if (res || b.equals(a)) return true;
+ else return false;
}
return false;
}
+ private static String logMessage(Object a, Object b, String where) {
+ return "Compared boxed primitives (" + boxDescription(a) + " == " + boxDescription(b) + ") @ " + where;
+ }
+
+ private static void verifyEqEq(Object a, Object b, boolean isFatal, boolean onlyIfActuallyEqual) {
+ int code1 = typeCode(a);
+ int code2 = typeCode(b);
+
+ if (code1 < OTHER && code2 < OTHER && code1 != code2) {
+ if (!onlyIfActuallyEqual || equalsBonusLogicFromScala27(a, b)) {
+ String msg = logMessage(a, b, Equality.whereAreWe(5));
+ Equality.warnOrDie(msg, isFatal);
+ }
+ }
+ }
+
+ /** The current equals method. **/
+ public static boolean equals(Object a, Object b) {
+ if (a == null || b == null)
+ return a == b;
+
+ verifyEqEq(a, b,
+ (Equality.dieOnBoxedCompare || Equality.dieOnBoxedCompareIfValuesAreEqual),
+ (Equality.warnOnBoxedCompareIfValuesAreEqual || Equality.dieOnBoxedCompareIfValuesAreEqual)
+ );
+
+ if (a.equals(b))
+ return true;
+
+ if (Equality.use28Semantics) return false;
+ else return equalsBonusLogicFromScala27(a, b);
+ }
+
/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */
/** arg1 + arg2 */
@@ -889,11 +706,11 @@ public class BoxesRunTime
/** arg.toChar */
public static Character toCharacter(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return (Character)arg;
- if (arg instanceof Byte) return boxToCharacter((char)unboxToByte(arg));
- if (arg instanceof Short) return boxToCharacter((char)unboxToShort(arg));
if (arg instanceof Integer) return boxToCharacter((char)unboxToInt(arg));
+ if (arg instanceof Short) return boxToCharacter((char)unboxToShort(arg));
+ if (arg instanceof Character) return (Character)arg;
if (arg instanceof Long) return boxToCharacter((char)unboxToLong(arg));
+ if (arg instanceof Byte) return boxToCharacter((char)unboxToByte(arg));
if (arg instanceof Float) return boxToCharacter((char)unboxToFloat(arg));
if (arg instanceof Double) return boxToCharacter((char)unboxToDouble(arg));
throw new NoSuchMethodException();
@@ -901,11 +718,11 @@ public class BoxesRunTime
/** arg.toByte */
public static Byte toByte(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Integer) return boxToByte((byte)unboxToInt(arg));
if (arg instanceof Character) return boxToByte((byte)unboxToChar(arg));
if (arg instanceof Byte) return (Byte)arg;
- if (arg instanceof Short) return boxToByte((byte)unboxToShort(arg));
- if (arg instanceof Integer) return boxToByte((byte)unboxToInt(arg));
if (arg instanceof Long) return boxToByte((byte)unboxToLong(arg));
+ if (arg instanceof Short) return boxToByte((byte)unboxToShort(arg));
if (arg instanceof Float) return boxToByte((byte)unboxToFloat(arg));
if (arg instanceof Double) return boxToByte((byte)unboxToDouble(arg));
throw new NoSuchMethodException();
@@ -913,11 +730,11 @@ public class BoxesRunTime
/** arg.toShort */
public static Short toShort(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Integer) return boxToShort((short)unboxToInt(arg));
+ if (arg instanceof Long) return boxToShort((short)unboxToLong(arg));
if (arg instanceof Character) return boxToShort((short)unboxToChar(arg));
if (arg instanceof Byte) return boxToShort((short)unboxToByte(arg));
if (arg instanceof Short) return (Short)arg;
- if (arg instanceof Integer) return boxToShort((short)unboxToInt(arg));
- if (arg instanceof Long) return boxToShort((short)unboxToLong(arg));
if (arg instanceof Float) return boxToShort((short)unboxToFloat(arg));
if (arg instanceof Double) return boxToShort((short)unboxToDouble(arg));
throw new NoSuchMethodException();
@@ -925,49 +742,49 @@ public class BoxesRunTime
/** arg.toInt */
public static Integer toInteger(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return boxToInteger((int)unboxToChar(arg));
- if (arg instanceof Byte) return boxToInteger((int)unboxToByte(arg));
- if (arg instanceof Short) return boxToInteger((int)unboxToShort(arg));
if (arg instanceof Integer) return (Integer)arg;
if (arg instanceof Long) return boxToInteger((int)unboxToLong(arg));
- if (arg instanceof Float) return boxToInteger((int)unboxToFloat(arg));
if (arg instanceof Double) return boxToInteger((int)unboxToDouble(arg));
+ if (arg instanceof Float) return boxToInteger((int)unboxToFloat(arg));
+ if (arg instanceof Character) return boxToInteger((int)unboxToChar(arg));
+ if (arg instanceof Byte) return boxToInteger((int)unboxToByte(arg));
+ if (arg instanceof Short) return boxToInteger((int)unboxToShort(arg));
throw new NoSuchMethodException();
}
/** arg.toLong */
public static Long toLong(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Integer) return boxToLong((long)unboxToInt(arg));
+ if (arg instanceof Double) return boxToLong((long)unboxToDouble(arg));
+ if (arg instanceof Float) return boxToLong((long)unboxToFloat(arg));
+ if (arg instanceof Long) return (Long)arg;
if (arg instanceof Character) return boxToLong((long)unboxToChar(arg));
if (arg instanceof Byte) return boxToLong((long)unboxToByte(arg));
if (arg instanceof Short) return boxToLong((long)unboxToShort(arg));
- if (arg instanceof Integer) return boxToLong((long)unboxToInt(arg));
- if (arg instanceof Long) return (Long)arg;
- if (arg instanceof Float) return boxToLong((long)unboxToFloat(arg));
- if (arg instanceof Double) return boxToLong((long)unboxToDouble(arg));
throw new NoSuchMethodException();
}
/** arg.toFloat */
public static Float toFloat(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return boxToFloat((float)unboxToChar(arg));
- if (arg instanceof Byte) return boxToFloat((float)unboxToByte(arg));
- if (arg instanceof Short) return boxToFloat((float)unboxToShort(arg));
if (arg instanceof Integer) return boxToFloat((float)unboxToInt(arg));
if (arg instanceof Long) return boxToFloat((float)unboxToLong(arg));
if (arg instanceof Float) return (Float)arg;
if (arg instanceof Double) return boxToFloat((float)unboxToDouble(arg));
+ if (arg instanceof Character) return boxToFloat((float)unboxToChar(arg));
+ if (arg instanceof Byte) return boxToFloat((float)unboxToByte(arg));
+ if (arg instanceof Short) return boxToFloat((float)unboxToShort(arg));
throw new NoSuchMethodException();
}
/** arg.toDouble */
public static Double toDouble(Object arg) throws NoSuchMethodException {
- if (arg instanceof Character) return boxToDouble((double)unboxToChar(arg));
- if (arg instanceof Byte) return boxToDouble((double)unboxToByte(arg));
- if (arg instanceof Short) return boxToDouble((double)unboxToShort(arg));
if (arg instanceof Integer) return boxToDouble((double)unboxToInt(arg));
- if (arg instanceof Long) return boxToDouble((double)unboxToLong(arg));
if (arg instanceof Float) return boxToDouble((double)unboxToFloat(arg));
if (arg instanceof Double) return (Double)arg;
+ if (arg instanceof Long) return boxToDouble((double)unboxToLong(arg));
+ if (arg instanceof Character) return boxToDouble((double)unboxToChar(arg));
+ if (arg instanceof Byte) return boxToDouble((double)unboxToByte(arg));
+ if (arg instanceof Short) return boxToDouble((double)unboxToShort(arg));
throw new NoSuchMethodException();
}
diff --git a/src/library/scala/runtime/Equality.java b/src/library/scala/runtime/Equality.java
index 3ec89360b8..018b3b4c07 100644
--- a/src/library/scala/runtime/Equality.java
+++ b/src/library/scala/runtime/Equality.java
@@ -12,6 +12,11 @@
package scala.runtime;
import java.io.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.Handler;
+import java.util.logging.StreamHandler;
+import java.util.logging.SimpleFormatter;
/** An object (static class) encapsulating the variations on equality
* presently under consideration. It's written in java so it can easily
@@ -19,33 +24,64 @@ import java.io.*;
*/
public class Equality
{
- public static boolean disallowNullEquals = true;
- public static boolean disallowPrimitiveEquals = true;
- public static boolean warnOnEqualsAny = true;
- public static boolean callCanEqualIfAvailable = true;
public static boolean logEverything = false;
+ public static boolean use28Semantics = false;
+
+ public static boolean warnOnBoxedCompare = false;
+ public static boolean warnOnBoxedCompareIfValuesAreEqual = false;
+ public static boolean dieOnBoxedCompare = false;
+ public static boolean dieOnBoxedCompareIfValuesAreEqual = false;
+
+ private static Handler handler;
+ public static Logger logger;
+ public static final Logger defaultLogger;
+
+ static {
+ class EqualityLogger extends Logger {
+ EqualityLogger() {
+ super("EqualityLogger", null);
+ }
+ }
+ defaultLogger = new EqualityLogger();
+
+ handler = new StreamHandler(System.out, new SimpleFormatter());
+ handler.setLevel(Level.INFO);
+ defaultLogger.addHandler(handler);
+
+ logger = defaultLogger;
+ }
+
+ public static void warnOrDie(String msg, boolean isFatal) {
+ if (isFatal) throw new RuntimeException(msg);
+ else log(msg);
+ // else System.out.println(msg);
+ }
public static String obToString(Object o) {
String s = o.toString() + " (" + o.getClass().getSimpleName() + ")";
return s.replaceAll("\\n", " ");
}
- public static void logInternal(String msg, Object a, Object b, String where) {
- log(String.format("%s %s == %s at %s", msg, obToString(a), obToString(b), where));
+ public static void logComparison(String msg, String cmp, String where) {
+ log(String.format("%s (%s) at %s", msg, cmp, where));
}
- public static String whereAreWe() {
+ public static String whereAreWe() { return whereAreWe(4); }
+ public static String whereAreWe(int depth) {
StackTraceElement[] es = Thread.currentThread().getStackTrace();
- if (es.length < 4)
+ if (es.length < depth)
return "<unknown>";
- StackTraceElement e = es[3];
+ StackTraceElement e = es[depth - 1];
String clazz = e.getClassName().replaceAll("\\$.*$", "\\$...");
return String.format("%s.%s(%s.%d)", clazz, e.getMethodName(), e.getFileName(), e.getLineNumber());
}
public static void log(String msg) {
- if (logEverything)
- System.out.println(msg);
+ if (logger != null) {
+ logger.warning(msg);
+ handler.flush();
+ }
+ else System.out.println(msg);
}
}