diff options
-rw-r--r-- | src/compiler/scala/reflect/internal/Definitions.scala | 26 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/JavaPlatform.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 12 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala | 19 | ||||
-rw-r--r-- | test/files/pos/t5644/BoxesRunTime.java | 836 | ||||
-rw-r--r-- | test/files/pos/t5644/other.scala | 3 |
9 files changed, 898 insertions, 22 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 0224f9158e..e1740b621e 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -863,7 +863,8 @@ trait Definitions extends reflect.api.StandardDefinitions { // boxed classes lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef") lazy val VolatileObjectRefClass = getRequiredClass("scala.runtime.VolatileObjectRef") - lazy val BoxesRunTimeClass = getRequiredModule("scala.runtime.BoxesRunTime") + lazy val BoxesRunTimeModule = getRequiredModule("scala.runtime.BoxesRunTime") + lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass lazy val BoxedNumberClass = getClass(sn.BoxedNumber) lazy val BoxedCharacterClass = getClass(sn.BoxedCharacter) lazy val BoxedBooleanClass = getClass(sn.BoxedBoolean) @@ -874,6 +875,9 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val BoxedFloatClass = getRequiredClass("java.lang.Float") lazy val BoxedDoubleClass = getRequiredClass("java.lang.Double") + lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean) + lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber) + lazy val BoxedUnitClass = getRequiredClass("scala.runtime.BoxedUnit") lazy val BoxedUnitModule = getRequiredModule("scala.runtime.BoxedUnit") def BoxedUnit_UNIT = getMember(BoxedUnitModule, nme.UNIT) @@ -990,12 +994,24 @@ trait Definitions extends reflect.api.StandardDefinitions { else findNamedMember(segs.tail, root.info member segs.head) def getMember(owner: Symbol, name: Name): Symbol = { - if (owner == NoSymbol) NoSymbol - else owner.info.nonPrivateMember(name) match { - case NoSymbol => throw new FatalError(owner + " does not have a member " + name) - case result => result + getMemberIfDefined(owner, name) orElse { + throw new FatalError(owner + " does not have a member " + name) + } + } + def getMemberIfDefined(owner: Symbol, name: Name): Symbol = + owner.info.nonPrivateMember(name) + + /** Using getDecl rather than getMember may avoid issues with + * OverloadedTypes turning up when you don't want them, if you + * know the method in question is uniquely declared in the given owner. + */ + def getDecl(owner: Symbol, name: Name): Symbol = { + getDeclIfDefined(owner, name) orElse { + throw new FatalError(owner + " does not have a decl " + name) } } + def getDeclIfDefined(owner: Symbol, name: Name): Symbol = + owner.info.nonPrivateDecl(name) def packageExists(packageName: String): Boolean = getModuleIfDefined(packageName).isPackage diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 8df687eca9..5e0c24d304 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1002,7 +1002,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Set phase to a newly created syntaxAnalyzer and call definitions.init. */ val parserPhase: Phase = syntaxAnalyzer.newPhase(NoPhase) phase = parserPhase - definitions.init + definitions.init() // Flush the cache in the terminal phase: the chain could have been built // before without being used. (This happens in the interpreter.) diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala index 27df45b563..314a3b45a0 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -38,10 +38,10 @@ trait JavaPlatform extends Platform { genJVM // generate .class files ) ++ depAnalysisPhase - lazy val externalEquals = getMember(BoxesRunTimeClass, nme.equals_) - lazy val externalEqualsNumNum = getMember(BoxesRunTimeClass, nme.equalsNumNum) - lazy val externalEqualsNumChar = getMember(BoxesRunTimeClass, nme.equalsNumChar) - lazy val externalEqualsNumObject = getMember(BoxesRunTimeClass, nme.equalsNumObject) + lazy val externalEquals = getDecl(BoxesRunTimeClass, nme.equals_) + lazy val externalEqualsNumNum = getDecl(BoxesRunTimeClass, nme.equalsNumNum) + lazy val externalEqualsNumChar = getDecl(BoxesRunTimeClass, nme.equalsNumChar) + lazy val externalEqualsNumObject = getDecl(BoxesRunTimeClass, nme.equalsNumObject) /** We could get away with excluding BoxedBooleanClass for the * purpose of equality testing since it need not compare equal diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 7b7135d180..18dc4aa56c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -1281,7 +1281,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val jname = javaName(method) val jtype = javaType(method).asInstanceOf[JMethodType] - def debugMsg(invoke: String) { + def dbg(invoke: String) { debuglog("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype)) } @@ -1299,14 +1299,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } style match { - case Static(true) => jcode.emitINVOKESPECIAL (jowner, jname, jtype) ; debugMsg("invokespecial") - case Static(false) => jcode.emitINVOKESTATIC (jowner, jname, jtype) ; debugMsg("invokestatic") - case Dynamic if isInterfaceCall(receiver) => jcode.emitINVOKEINTERFACE(jowner, jname, jtype) ; debugMsg("invokinterface") - case Dynamic => jcode.emitINVOKEVIRTUAL (jowner, jname, jtype) ; debugMsg("invokevirtual") + case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype) + case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype) + case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.emitINVOKEINTERFACE(jowner, jname, jtype) + case Dynamic => dbg("invokevirtual"); jcode.emitINVOKEVIRTUAL(jowner, jname, jtype) case SuperCall(_) => + dbg("invokespecial") jcode.emitINVOKESPECIAL(jowner, jname, jtype) initModule() - debugMsg("invokespecial") } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 68af518d3a..775a7a9d38 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -625,11 +625,11 @@ abstract class ICodeReader extends ClassfileParser { * such as Int.box(5). */ def isBox(m: Symbol): Boolean = - (m.owner == definitions.BoxesRunTimeClass.moduleClass + (m.owner == definitions.BoxesRunTimeClass && m.name.startsWith("boxTo")) def isUnbox(m: Symbol): Boolean = - (m.owner == definitions.BoxesRunTimeClass.moduleClass + (m.owner == definitions.BoxesRunTimeClass && m.name.startsWith("unboxTo")) /** Return the icode class that should include members with the given flags. diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index b21fa4bc83..e6f5dc5b5f 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -299,11 +299,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL { def testForName(name: Name): Tree => Tree = t => ( if (nme.CommonOpNames(name)) - gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean), t :: Nil) + gen.mkMethodCall(definitions.Boxes_isNumberOrBool, t :: Nil) else if (nme.BooleanOpNames(name)) t IS_OBJ BoxedBooleanClass.tpe else - gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumber), t :: Nil) + gen.mkMethodCall(definitions.Boxes_isNumber, t :: Nil) ) /** The Tree => Tree function in the return is necessary to prevent the original qual @@ -318,8 +318,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL { else if (params.tail.isEmpty) nme.primitiveInfixMethodName(name) else nme.NO_NAME ) - if (methodName == nme.NO_NAME) None - else Some((getMember(BoxesRunTimeClass, methodName), testForName(name))) + definitions.getDeclIfDefined(BoxesRunTimeClass, methodName) match { + case NoSymbol => None + case sym => assert(!sym.isOverloaded, sym) ; Some((sym, testForName(name))) + } } /* ### BOXING PARAMS & UNBOXING RESULTS ### */ diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 105c2c0b98..8895905ca7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -14,6 +14,20 @@ import util.returning abstract class TreeCheckers extends Analyzer { import global._ + private val everything = ListBuffer[(Phase, Map[Tree, (Symbol, Type)])]() + private val currentTrees = mutable.Map[Tree, (Symbol, Type)]() + + if (settings.debug.value) { + sys addShutdownHook { + for ((ph, map) <- everything.toList) { + println("\n>>>> " + ph + "\n") + for ((tree, (sym, tpe)) <- map.toList.sortBy(_._1.summaryString)) { + println("%20s %20s %s".format(sym, tpe, ("" + tree) take 50)) + } + } + } + } + private def classstr(x: AnyRef) = x.getClass.getName split """\\.|\\$""" last; private def typestr(x: Type) = " (tpe = " + x + ")" private def treestr(t: Tree) = t + " [" + classstr(t) + "]" + typestr(t.tpe) @@ -92,11 +106,16 @@ abstract class TreeCheckers extends Analyzer { if (maps.isEmpty || maps.last._1 != ph) maps += ((ph, new PhaseMap)) + currentTrees.clear() traverse(unit.body) + everything += ((ph, currentTrees.toMap)) + reportChanges() } override def traverse(tree: Tree): Unit = { val sym = tree.symbol + currentTrees(tree) = ((sym, tree.tpe)) + if (sym != null && sym != NoSymbol) { record(sym, tree) tree match { diff --git a/test/files/pos/t5644/BoxesRunTime.java b/test/files/pos/t5644/BoxesRunTime.java new file mode 100644 index 0000000000..241bf79ac8 --- /dev/null +++ b/test/files/pos/t5644/BoxesRunTime.java @@ -0,0 +1,836 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + + +package scala.runtime; + +import java.io.*; +import scala.math.ScalaNumber; + +/** 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: + * - Convenience boxing methods which call the static valueOf method + * on the boxed class, thus utilizing the JVM boxing cache. + * - Convenience unboxing methods returning default value on null. + * - The generalised comparison method to be used when an object may + * be a boxed value. + * - Standard value operators for boxed number and quasi-number values. + * + * @author Gilles Dubochet + * @author Martin Odersky + * @contributor Stepan Koltsov + * @version 2.0 */ +public final class BoxesRunTime +{ + private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7; + + /** We don't need to return BYTE and SHORT, as everything which might + * care widens to INT. + */ + private static int typeCode(Object a) { + if (a instanceof java.lang.Integer) return INT; + if (a instanceof java.lang.Double) return DOUBLE; + if (a instanceof java.lang.Long) return LONG; + if (a instanceof java.lang.Character) return CHAR; + if (a instanceof java.lang.Float) return FLOAT; + if ((a instanceof java.lang.Byte) || (a instanceof java.lang.Short)) return INT; + return OTHER; + } + + private static int eqTypeCode(Number a) { + int code = typeCode(a); + if (code == CHAR) + return OTHER; + else + return code; + } + + private static String boxDescription(Object a) { + return "" + a.getClass().getSimpleName() + "(" + a + ")"; + } + +/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */ + + public static java.lang.Boolean boxToBoolean(boolean b) { + return java.lang.Boolean.valueOf(b); + } + + public static java.lang.Character boxToCharacter(char c) { + return java.lang.Character.valueOf(c); + } + + public static java.lang.Byte boxToByte(byte b) { + return java.lang.Byte.valueOf(b); + } + + public static java.lang.Short boxToShort(short s) { + return java.lang.Short.valueOf(s); + } + + public static java.lang.Integer boxToInteger(int i) { + return java.lang.Integer.valueOf(i); + } + + public static java.lang.Long boxToLong(long l) { + return java.lang.Long.valueOf(l); + } + + public static java.lang.Float boxToFloat(float f) { + return java.lang.Float.valueOf(f); + } + + public static java.lang.Double boxToDouble(double d) { + // System.out.println("box " + d); + // (new Throwable()).printStackTrace(); + return java.lang.Double.valueOf(d); + } + +/* UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING */ + + public static boolean unboxToBoolean(Object b) { + return b == null ? false : ((java.lang.Boolean)b).booleanValue(); + } + + public static char unboxToChar(Object c) { + return c == null ? 0 : ((java.lang.Character)c).charValue(); + } + + public static byte unboxToByte(Object b) { + return b == null ? 0 : ((java.lang.Byte)b).byteValue(); + } + + public static short unboxToShort(Object s) { + return s == null ? 0 : ((java.lang.Short)s).shortValue(); + } + + public static int unboxToInt(Object i) { + return i == null ? 0 : ((java.lang.Integer)i).intValue(); + } + + public static long unboxToLong(Object l) { + return l == null ? 0 : ((java.lang.Long)l).longValue(); + } + + public static float unboxToFloat(Object f) { + return f == null ? 0.0f : ((java.lang.Float)f).floatValue(); + } + + public static double unboxToDouble(Object d) { + // System.out.println("unbox " + d); + return d == null ? 0.0d : ((java.lang.Double)d).doubleValue(); + } + + /* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */ + + public static boolean equals(Object x, Object y) { + if (x == y) return true; + return equals2(x, y); + } + + /** Since all applicable logic has to be present in the equals method of a ScalaNumber + * in any case, we dispatch to it as soon as we spot one on either side. + */ + public static boolean equals2(Object x, Object y) { + if (x instanceof java.lang.Number) + return equalsNumObject((java.lang.Number)x, y); + if (x instanceof java.lang.Character) + return equalsCharObject((java.lang.Character)x, y); + if (x == null) + return y == null; + + return x.equals(y); + } + + public static boolean equalsNumObject(java.lang.Number xn, Object y) { + if (y instanceof java.lang.Number) + return equalsNumNum(xn, (java.lang.Number)y); + if (y instanceof java.lang.Character) + return equalsNumChar(xn, (java.lang.Character)y); + if (xn == null) + return y == null; + + return xn.equals(y); + } + + public static boolean equalsNumNum(java.lang.Number xn, java.lang.Number yn) { + int xcode = eqTypeCode(xn); + int ycode = eqTypeCode(yn); + switch (ycode > xcode ? ycode : xcode) { + case INT: + return xn.intValue() == yn.intValue(); + case LONG: + return xn.longValue() == yn.longValue(); + case FLOAT: + return xn.floatValue() == yn.floatValue(); + case DOUBLE: + return xn.doubleValue() == yn.doubleValue(); + default: + if ((yn instanceof ScalaNumber) && !(xn instanceof ScalaNumber)) + return yn.equals(xn); + } + if (xn == null) + return yn == null; + + return xn.equals(yn); + } + + public static boolean equalsCharObject(java.lang.Character xc, Object y) { + if (y instanceof java.lang.Character) + return xc.charValue() == ((java.lang.Character)y).charValue(); + if (y instanceof java.lang.Number) + return equalsNumChar((java.lang.Number)y, xc); + if (xc == null) + return y == null; + + return xc.equals(y); + } + + private static boolean equalsNumChar(java.lang.Number xn, java.lang.Character yc) { + if (yc == null) + return xn == null; + + char ch = yc.charValue(); + switch (eqTypeCode(xn)) { + case INT: + return xn.intValue() == ch; + case LONG: + return xn.longValue() == ch; + case FLOAT: + return xn.floatValue() == ch; + case DOUBLE: + return xn.doubleValue() == ch; + default: + return xn.equals(yc); + } + } + + /** Hashcode algorithm is driven by the requirements imposed + * by primitive equality semantics, namely that equal objects + * have equal hashCodes. The first priority are the integral/char + * types, which already have the same hashCodes for the same + * values except for Long. So Long's hashCode is altered to + * conform to Int's for all values in Int's range. + * + * Float is problematic because it's far too small to hold + * all the Ints, so for instance Int.MaxValue.toFloat claims + * to be == to each of the largest 64 Ints. There is no way + * to preserve equals/hashCode alignment without compromising + * the hashCode distribution, so Floats are only guaranteed + * to have the same hashCode for whole Floats in the range + * Short.MinValue to Short.MaxValue (2^16 total.) + * + * Double has its hashCode altered to match the entire Int range, + * but is not guaranteed beyond that. (But could/should it be? + * The hashCode is only 32 bits so this is a more tractable + * issue than Float's, but it might be better simply to exclude it.) + * + * Note: BigInt and BigDecimal, being arbitrary precision, could + * be made consistent with all other types for the Int range, but + * as yet have not. + * + * Note: Among primitives, Float.NaN != Float.NaN, but the boxed + * verisons are equal. This still needs reconciliation. + */ + public static int hashFromLong(java.lang.Long n) { + int iv = n.intValue(); + if (iv == n.longValue()) return iv; + else return n.hashCode(); + } + public static int hashFromDouble(java.lang.Double n) { + int iv = n.intValue(); + double dv = n.doubleValue(); + if (iv == dv) return iv; + + long lv = n.longValue(); + if (lv == dv) return java.lang.Long.valueOf(lv).hashCode(); + else return n.hashCode(); + } + public static int hashFromFloat(java.lang.Float n) { + int iv = n.intValue(); + float fv = n.floatValue(); + if (iv == fv) return iv; + + long lv = n.longValue(); + if (lv == fv) return java.lang.Long.valueOf(lv).hashCode(); + else return n.hashCode(); + } + public static int hashFromNumber(java.lang.Number n) { + if (n instanceof java.lang.Long) return hashFromLong((java.lang.Long)n); + else if (n instanceof java.lang.Double) return hashFromDouble((java.lang.Double)n); + else if (n instanceof java.lang.Float) return hashFromFloat((java.lang.Float)n); + else return n.hashCode(); + } + public static int hashFromObject(Object a) { + if (a instanceof Number) return hashFromNumber((Number)a); + else return a.hashCode(); + } + + private static int unboxCharOrInt(Object arg1, int code) { + if (code == CHAR) + return ((java.lang.Character) arg1).charValue(); + else + return ((java.lang.Number) arg1).intValue(); + } + private static long unboxCharOrLong(Object arg1, int code) { + if (code == CHAR) + return ((java.lang.Character) arg1).charValue(); + else + return ((java.lang.Number) arg1).longValue(); + } + private static float unboxCharOrFloat(Object arg1, int code) { + if (code == CHAR) + return ((java.lang.Character) arg1).charValue(); + else + return ((java.lang.Number) arg1).floatValue(); + } + private static double unboxCharOrDouble(Object arg1, int code) { + if (code == CHAR) + return ((java.lang.Character) arg1).charValue(); + else + return ((java.lang.Number) arg1).doubleValue(); + } + +/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */ + + /** arg1 + arg2 */ + public static Object add(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + return boxToInteger(unboxCharOrInt(arg1, code1) + unboxCharOrInt(arg2, code2)); + } + if (maxcode <= LONG) { + return boxToLong(unboxCharOrLong(arg1, code1) + unboxCharOrLong(arg2, code2)); + } + if (maxcode <= FLOAT) { + return boxToFloat(unboxCharOrFloat(arg1, code1) + unboxCharOrFloat(arg2, code2)); + } + if (maxcode <= DOUBLE) { + return boxToDouble(unboxCharOrDouble(arg1, code1) + unboxCharOrDouble(arg2, code2)); + } + throw new NoSuchMethodException(); + } + + /** arg1 - arg2 */ + public static Object subtract(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + return boxToInteger(unboxCharOrInt(arg1, code1) - unboxCharOrInt(arg2, code2)); + } + if (maxcode <= LONG) { + return boxToLong(unboxCharOrLong(arg1, code1) - unboxCharOrLong(arg2, code2)); + } + if (maxcode <= FLOAT) { + return boxToFloat(unboxCharOrFloat(arg1, code1) - unboxCharOrFloat(arg2, code2)); + } + if (maxcode <= DOUBLE) { + return boxToDouble(unboxCharOrDouble(arg1, code1) - unboxCharOrDouble(arg2, code2)); + } + throw new NoSuchMethodException(); + } + + /** arg1 * arg2 */ + public static Object multiply(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + return boxToInteger(unboxCharOrInt(arg1, code1) * unboxCharOrInt(arg2, code2)); + } + if (maxcode <= LONG) { + return boxToLong(unboxCharOrLong(arg1, code1) * unboxCharOrLong(arg2, code2)); + } + if (maxcode <= FLOAT) { + return boxToFloat(unboxCharOrFloat(arg1, code1) * unboxCharOrFloat(arg2, code2)); + } + if (maxcode <= DOUBLE) { + return boxToDouble(unboxCharOrDouble(arg1, code1) * unboxCharOrDouble(arg2, code2)); + } + throw new NoSuchMethodException(); + } + + /** arg1 / arg2 */ + public static Object divide(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + + if (maxcode <= INT) + return boxToInteger(unboxCharOrInt(arg1, code1) / unboxCharOrInt(arg2, code2)); + if (maxcode <= LONG) + return boxToLong(unboxCharOrLong(arg1, code1) / unboxCharOrLong(arg2, code2)); + if (maxcode <= FLOAT) + return boxToFloat(unboxCharOrFloat(arg1, code1) / unboxCharOrFloat(arg2, code2)); + if (maxcode <= DOUBLE) + return boxToDouble(unboxCharOrDouble(arg1, code1) / unboxCharOrDouble(arg2, code2)); + + throw new NoSuchMethodException(); + } + + /** arg1 % arg2 */ + public static Object takeModulo(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + + if (maxcode <= INT) + return boxToInteger(unboxCharOrInt(arg1, code1) % unboxCharOrInt(arg2, code2)); + if (maxcode <= LONG) + return boxToLong(unboxCharOrLong(arg1, code1) % unboxCharOrLong(arg2, code2)); + if (maxcode <= FLOAT) + return boxToFloat(unboxCharOrFloat(arg1, code1) % unboxCharOrFloat(arg2, code2)); + if (maxcode <= DOUBLE) + return boxToDouble(unboxCharOrDouble(arg1, code1) % unboxCharOrDouble(arg2, code2)); + + throw new NoSuchMethodException(); + } + + /** arg1 >> arg2 */ + public static Object shiftSignedRight(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + if (code1 <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + if (code2 <= INT) { + int val2 = unboxCharOrInt(arg2, code2); + return boxToInteger(val1 >> val2); + } + if (code2 <= LONG) { + long val2 = unboxCharOrLong(arg2, code2); + return boxToInteger(val1 >> val2); + } + } + if (code1 <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + if (code2 <= INT) { + int val2 = unboxCharOrInt(arg2, code2); + return boxToLong(val1 >> val2); + } + if (code2 <= LONG) { + long val2 = unboxCharOrLong(arg2, code2); + return boxToLong(val1 >> val2); + } + } + throw new NoSuchMethodException(); + } + + /** arg1 << arg2 */ + public static Object shiftSignedLeft(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + if (code1 <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + if (code2 <= INT) { + int val2 = unboxCharOrInt(arg2, code2); + return boxToInteger(val1 << val2); + } + if (code2 <= LONG) { + long val2 = unboxCharOrLong(arg2, code2); + return boxToInteger(val1 << val2); + } + } + if (code1 <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + if (code2 <= INT) { + int val2 = unboxCharOrInt(arg2, code2); + return boxToLong(val1 << val2); + } + if (code2 <= LONG) { + long val2 = unboxCharOrLong(arg2, code2); + return boxToLong(val1 << val2); + } + } + throw new NoSuchMethodException(); + } + + /** arg1 >>> arg2 */ + public static Object shiftLogicalRight(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + if (code1 <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + if (code2 <= INT) { + int val2 = unboxCharOrInt(arg2, code2); + return boxToInteger(val1 >>> val2); + } + if (code2 <= LONG) { + long val2 = unboxCharOrLong(arg2, code2); + return boxToInteger(val1 >>> val2); + } + } + if (code1 <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + if (code2 <= INT) { + int val2 = unboxCharOrInt(arg2, code2); + return boxToLong(val1 >>> val2); + } + if (code2 <= LONG) { + long val2 = unboxCharOrLong(arg2, code2); + return boxToLong(val1 >>> val2); + } + } + throw new NoSuchMethodException(); + } + + /** -arg */ + public static Object negate(Object arg) throws NoSuchMethodException { + int code = typeCode(arg); + if (code <= INT) { + int val = unboxCharOrInt(arg, code); + return boxToInteger(-val); + } + if (code <= LONG) { + long val = unboxCharOrLong(arg, code); + return boxToLong(-val); + } + if (code <= FLOAT) { + float val = unboxCharOrFloat(arg, code); + return boxToFloat(-val); + } + if (code <= DOUBLE) { + double val = unboxCharOrDouble(arg, code); + return boxToDouble(-val); + } + throw new NoSuchMethodException(); + } + + /** +arg */ + public static Object positive(Object arg) throws NoSuchMethodException { + int code = typeCode(arg); + if (code <= INT) { + return boxToInteger(+unboxCharOrInt(arg, code)); + } + if (code <= LONG) { + return boxToLong(+unboxCharOrLong(arg, code)); + } + if (code <= FLOAT) { + return boxToFloat(+unboxCharOrFloat(arg, code)); + } + if (code <= DOUBLE) { + return boxToDouble(+unboxCharOrDouble(arg, code)); + } + throw new NoSuchMethodException(); + } + + /** arg1 & arg2 */ + public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) + return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue()); + else + throw new NoSuchMethodException(); + } + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + + if (maxcode <= INT) + return boxToInteger(unboxCharOrInt(arg1, code1) & unboxCharOrInt(arg2, code2)); + if (maxcode <= LONG) + return boxToLong(unboxCharOrLong(arg1, code1) & unboxCharOrLong(arg2, code2)); + + throw new NoSuchMethodException(); + } + + /** arg1 | arg2 */ + public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) + return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue()); + else + throw new NoSuchMethodException(); + } + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + + if (maxcode <= INT) + return boxToInteger(unboxCharOrInt(arg1, code1) | unboxCharOrInt(arg2, code2)); + if (maxcode <= LONG) + return boxToLong(unboxCharOrLong(arg1, code1) | unboxCharOrLong(arg2, code2)); + + throw new NoSuchMethodException(); + } + + /** arg1 ^ arg2 */ + public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) + return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue()); + else + throw new NoSuchMethodException(); + } + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + + if (maxcode <= INT) + return boxToInteger(unboxCharOrInt(arg1, code1) ^ unboxCharOrInt(arg2, code2)); + if (maxcode <= LONG) + return boxToLong(unboxCharOrLong(arg1, code1) ^ unboxCharOrLong(arg2, code2)); + + throw new NoSuchMethodException(); + } + + /** arg1 && arg2 */ + public static Object takeConditionalAnd(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { + return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() && ((java.lang.Boolean) arg2).booleanValue()); + } + throw new NoSuchMethodException(); + } + + /** arg1 || arg2 */ + public static Object takeConditionalOr(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { + return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() || ((java.lang.Boolean) arg2).booleanValue()); + } + throw new NoSuchMethodException(); + } + + /** ~arg */ + public static Object complement(Object arg) throws NoSuchMethodException { + int code = typeCode(arg); + if (code <= INT) { + return boxToInteger(~unboxCharOrInt(arg, code)); + } + if (code <= LONG) { + return boxToLong(~unboxCharOrLong(arg, code)); + } + throw new NoSuchMethodException(); + } + + /** !arg */ + public static Object takeNot(Object arg) throws NoSuchMethodException { + if (arg instanceof Boolean) { + return boxToBoolean(!((java.lang.Boolean) arg).booleanValue()); + } + throw new NoSuchMethodException(); + } + + public static Object testEqual(Object arg1, Object arg2) throws NoSuchMethodException { + return boxToBoolean(arg1 == arg2); + } + + public static Object testNotEqual(Object arg1, Object arg2) throws NoSuchMethodException { + return boxToBoolean(arg1 != arg2); + } + + public static Object testLessThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + int val2 = unboxCharOrInt(arg2, code2); + return boxToBoolean(val1 < val2); + } + if (maxcode <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + long val2 = unboxCharOrLong(arg2, code2); + return boxToBoolean(val1 < val2); + } + if (maxcode <= FLOAT) { + float val1 = unboxCharOrFloat(arg1, code1); + float val2 = unboxCharOrFloat(arg2, code2); + return boxToBoolean(val1 < val2); + } + if (maxcode <= DOUBLE) { + double val1 = unboxCharOrDouble(arg1, code1); + double val2 = unboxCharOrDouble(arg2, code2); + return boxToBoolean(val1 < val2); + } + throw new NoSuchMethodException(); + } + + public static Object testLessOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + int val2 = unboxCharOrInt(arg2, code2); + return boxToBoolean(val1 <= val2); + } + if (maxcode <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + long val2 = unboxCharOrLong(arg2, code2); + return boxToBoolean(val1 <= val2); + } + if (maxcode <= FLOAT) { + float val1 = unboxCharOrFloat(arg1, code1); + float val2 = unboxCharOrFloat(arg2, code2); + return boxToBoolean(val1 <= val2); + } + if (maxcode <= DOUBLE) { + double val1 = unboxCharOrDouble(arg1, code1); + double val2 = unboxCharOrDouble(arg2, code2); + return boxToBoolean(val1 <= val2); + } + throw new NoSuchMethodException(); + } + + public static Object testGreaterOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + int val2 = unboxCharOrInt(arg2, code2); + return boxToBoolean(val1 >= val2); + } + if (maxcode <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + long val2 = unboxCharOrLong(arg2, code2); + return boxToBoolean(val1 >= val2); + } + if (maxcode <= FLOAT) { + float val1 = unboxCharOrFloat(arg1, code1); + float val2 = unboxCharOrFloat(arg2, code2); + return boxToBoolean(val1 >= val2); + } + if (maxcode <= DOUBLE) { + double val1 = unboxCharOrDouble(arg1, code1); + double val2 = unboxCharOrDouble(arg2, code2); + return boxToBoolean(val1 >= val2); + } + throw new NoSuchMethodException(); + } + + public static Object testGreaterThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = unboxCharOrInt(arg1, code1); + int val2 = unboxCharOrInt(arg2, code2); + return boxToBoolean(val1 > val2); + } + if (maxcode <= LONG) { + long val1 = unboxCharOrLong(arg1, code1); + long val2 = unboxCharOrLong(arg2, code2); + return boxToBoolean(val1 > val2); + } + if (maxcode <= FLOAT) { + float val1 = unboxCharOrFloat(arg1, code1); + float val2 = unboxCharOrFloat(arg2, code2); + return boxToBoolean(val1 > val2); + } + if (maxcode <= DOUBLE) { + double val1 = unboxCharOrDouble(arg1, code1); + double val2 = unboxCharOrDouble(arg2, code2); + return boxToBoolean(val1 > val2); + } + throw new NoSuchMethodException(); + } + + public static boolean isBoxedNumberOrBoolean(Object arg) { + return (arg instanceof java.lang.Boolean) || isBoxedNumber(arg); + } + public static boolean isBoxedNumber(Object arg) { + return ( + (arg instanceof java.lang.Integer) + || (arg instanceof java.lang.Long) + || (arg instanceof java.lang.Double) + || (arg instanceof java.lang.Float) + || (arg instanceof java.lang.Short) + || (arg instanceof java.lang.Character) + || (arg instanceof java.lang.Byte) + ); + } + + /** arg.toChar */ + public static java.lang.Character toCharacter(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return boxToCharacter((char)unboxToInt(arg)); + if (arg instanceof java.lang.Short) return boxToCharacter((char)unboxToShort(arg)); + if (arg instanceof java.lang.Character) return (java.lang.Character)arg; + if (arg instanceof java.lang.Long) return boxToCharacter((char)unboxToLong(arg)); + if (arg instanceof java.lang.Byte) return boxToCharacter((char)unboxToByte(arg)); + if (arg instanceof java.lang.Float) return boxToCharacter((char)unboxToFloat(arg)); + if (arg instanceof java.lang.Double) return boxToCharacter((char)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toByte */ + public static java.lang.Byte toByte(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return boxToByte((byte)unboxToInt(arg)); + if (arg instanceof java.lang.Character) return boxToByte((byte)unboxToChar(arg)); + if (arg instanceof java.lang.Byte) return (java.lang.Byte)arg; + if (arg instanceof java.lang.Long) return boxToByte((byte)unboxToLong(arg)); + if (arg instanceof java.lang.Short) return boxToByte((byte)unboxToShort(arg)); + if (arg instanceof java.lang.Float) return boxToByte((byte)unboxToFloat(arg)); + if (arg instanceof java.lang.Double) return boxToByte((byte)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toShort */ + public static java.lang.Short toShort(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return boxToShort((short)unboxToInt(arg)); + if (arg instanceof java.lang.Long) return boxToShort((short)unboxToLong(arg)); + if (arg instanceof java.lang.Character) return boxToShort((short)unboxToChar(arg)); + if (arg instanceof java.lang.Byte) return boxToShort((short)unboxToByte(arg)); + if (arg instanceof java.lang.Short) return (java.lang.Short)arg; + if (arg instanceof java.lang.Float) return boxToShort((short)unboxToFloat(arg)); + if (arg instanceof java.lang.Double) return boxToShort((short)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toInt */ + public static java.lang.Integer toInteger(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return (java.lang.Integer)arg; + if (arg instanceof java.lang.Long) return boxToInteger((int)unboxToLong(arg)); + if (arg instanceof java.lang.Double) return boxToInteger((int)unboxToDouble(arg)); + if (arg instanceof java.lang.Float) return boxToInteger((int)unboxToFloat(arg)); + if (arg instanceof java.lang.Character) return boxToInteger((int)unboxToChar(arg)); + if (arg instanceof java.lang.Byte) return boxToInteger((int)unboxToByte(arg)); + if (arg instanceof java.lang.Short) return boxToInteger((int)unboxToShort(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toLong */ + public static java.lang.Long toLong(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return boxToLong((long)unboxToInt(arg)); + if (arg instanceof java.lang.Double) return boxToLong((long)unboxToDouble(arg)); + if (arg instanceof java.lang.Float) return boxToLong((long)unboxToFloat(arg)); + if (arg instanceof java.lang.Long) return (java.lang.Long)arg; + if (arg instanceof java.lang.Character) return boxToLong((long)unboxToChar(arg)); + if (arg instanceof java.lang.Byte) return boxToLong((long)unboxToByte(arg)); + if (arg instanceof java.lang.Short) return boxToLong((long)unboxToShort(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toFloat */ + public static java.lang.Float toFloat(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return boxToFloat((float)unboxToInt(arg)); + if (arg instanceof java.lang.Long) return boxToFloat((float)unboxToLong(arg)); + if (arg instanceof java.lang.Float) return (java.lang.Float)arg; + if (arg instanceof java.lang.Double) return boxToFloat((float)unboxToDouble(arg)); + if (arg instanceof java.lang.Character) return boxToFloat((float)unboxToChar(arg)); + if (arg instanceof java.lang.Byte) return boxToFloat((float)unboxToByte(arg)); + if (arg instanceof java.lang.Short) return boxToFloat((float)unboxToShort(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toDouble */ + public static java.lang.Double toDouble(Object arg) throws NoSuchMethodException { + if (arg instanceof java.lang.Integer) return boxToDouble((double)unboxToInt(arg)); + if (arg instanceof java.lang.Float) return boxToDouble((double)unboxToFloat(arg)); + if (arg instanceof java.lang.Double) return (java.lang.Double)arg; + if (arg instanceof java.lang.Long) return boxToDouble((double)unboxToLong(arg)); + if (arg instanceof java.lang.Character) return boxToDouble((double)unboxToChar(arg)); + if (arg instanceof java.lang.Byte) return boxToDouble((double)unboxToByte(arg)); + if (arg instanceof java.lang.Short) return boxToDouble((double)unboxToShort(arg)); + throw new NoSuchMethodException(); + } + +} diff --git a/test/files/pos/t5644/other.scala b/test/files/pos/t5644/other.scala new file mode 100644 index 0000000000..50388fd9ec --- /dev/null +++ b/test/files/pos/t5644/other.scala @@ -0,0 +1,3 @@ +class Foo { + List(1) exists(_ == (null: Any)) +} |