From 9e4dfe26684b3f824e608a30bfba0d0cf1cf0ae2 Mon Sep 17 00:00:00 2001 From: schinz Date: Sun, 17 Apr 2005 18:27:30 +0000 Subject: - improved the interaction between arrays and r... - improved the interaction between arrays and run time types --- sources/scala/Type.java | 5 ++ sources/scala/runtime/types/ClassType.java | 10 +++- sources/scala/runtime/types/CompoundType.java | 2 +- sources/scala/runtime/types/JavaClassType.java | 11 ++++ sources/scala/runtime/types/JavaRefArrayType.java | 38 ++++++++------ sources/scala/runtime/types/SingleType.java | 2 +- sources/scala/runtime/types/SpecialType.java | 2 +- sources/scala/runtime/types/TypeBoolean.java | 6 +-- sources/scala/runtime/types/TypeByte.java | 6 +-- sources/scala/runtime/types/TypeChar.java | 6 +-- sources/scala/runtime/types/TypeDouble.java | 6 +-- sources/scala/runtime/types/TypeFloat.java | 6 +-- sources/scala/runtime/types/TypeInt.java | 6 +-- sources/scala/runtime/types/TypeLong.java | 6 +-- sources/scala/runtime/types/TypeShort.java | 6 +-- sources/scala/runtime/types/TypeUnit.java | 6 +-- sources/scala/runtime/types/ValueType.java | 4 ++ sources/scalac/symtab/Definitions.java | 18 +++++++ sources/scalac/transformer/TypesAsValuesPhase.java | 59 ++++++++++++++++++---- sources/scalac/util/Names.java | 2 + 20 files changed, 150 insertions(+), 57 deletions(-) diff --git a/sources/scala/Type.java b/sources/scala/Type.java index cc9a2b524e..df07f7e8fd 100644 --- a/sources/scala/Type.java +++ b/sources/scala/Type.java @@ -58,6 +58,11 @@ abstract public class Type implements java.io.Serializable { abstract public boolean isSameType(Type that); abstract public boolean isSubType(Type that); + public boolean isSameAsJavaType(Class that) { + throw new Error("cannot compare Scala type " + this + + " with Java type " + that); + } + public boolean equals(Object that) { return (that instanceof Type) && this.isSameType((Type)that); } diff --git a/sources/scala/runtime/types/ClassType.java b/sources/scala/runtime/types/ClassType.java index 6a0e682852..79d964712f 100644 --- a/sources/scala/runtime/types/ClassType.java +++ b/sources/scala/runtime/types/ClassType.java @@ -24,7 +24,6 @@ public abstract class ClassType extends Type { } public Array newArray(int size) { - // TODO is that correct if we have type arguments? Object[] array = (Object[])java.lang.reflect.Array.newInstance(clazz, size); return RunTime.box_oarray(array); @@ -66,6 +65,15 @@ public abstract class ClassType extends Type { && (((ClassType)that).clazz == this.clazz); } + public boolean isSameAsJavaType(Class that) { + if (this.isTrivial) + return clazz == that; + else if (clazz != that) + return false; + else + throw new Error("uncomparable types"); + } + public int hashCode() { return clazz.hashCode(); } diff --git a/sources/scala/runtime/types/CompoundType.java b/sources/scala/runtime/types/CompoundType.java index 18b8f8deb6..716b00cfe2 100644 --- a/sources/scala/runtime/types/CompoundType.java +++ b/sources/scala/runtime/types/CompoundType.java @@ -32,7 +32,7 @@ public class CompoundType extends Type { } public Array newArray(int size) { - throw new Error(); // TODO + throw new Error("cannot create arrays of compound types"); } public Object defaultValue() { diff --git a/sources/scala/runtime/types/JavaClassType.java b/sources/scala/runtime/types/JavaClassType.java index 96aed1a7e2..5a73641e51 100644 --- a/sources/scala/runtime/types/JavaClassType.java +++ b/sources/scala/runtime/types/JavaClassType.java @@ -36,6 +36,17 @@ public class JavaClassType extends ClassType { return jct; } + public static JavaClassType javaArrayType(String elemFullName, int dimen) { + StringBuffer fullName = new StringBuffer(); + for (int i = 0; i < dimen; ++i) + fullName.append('['); + if (elemFullName.length() == 1 && "ZBCDFIJS".indexOf(elemFullName) >= 0) + fullName.append(elemFullName); + else + fullName.append('L').append(elemFullName).append(';'); + return javaClassType(fullName.toString()); + } + public JavaClassType(String fullName) throws ClassNotFoundException { super(Class.forName(fullName, false, loader), true); } diff --git a/sources/scala/runtime/types/JavaRefArrayType.java b/sources/scala/runtime/types/JavaRefArrayType.java index 0d679c256c..2b25592f7a 100644 --- a/sources/scala/runtime/types/JavaRefArrayType.java +++ b/sources/scala/runtime/types/JavaRefArrayType.java @@ -21,10 +21,22 @@ import scala.Array; */ public class JavaRefArrayType extends Type { + public final int dimensions; public final Type elemType; - public JavaRefArrayType(Type elemType) { + public static JavaRefArrayType javaRefArrayType(Type elemType, + int dimensions) { + if (elemType instanceof JavaRefArrayType) { + JavaRefArrayType other = (JavaRefArrayType)elemType; + return new JavaRefArrayType(other.elemType, + dimensions + other.dimensions); + } else + return new JavaRefArrayType(elemType, dimensions); + } + + private JavaRefArrayType(Type elemType, int dimensions) { this.elemType = elemType; + this.dimensions = dimensions; } public Array newArray(int size) { @@ -37,20 +49,7 @@ public class JavaRefArrayType extends Type { public boolean isInstance(Object o) { assert Statistics.incInstanceOf(); - if (o instanceof Object[]) { - if (elemType instanceof ClassType) { - ClassType elemTypeClass = (ClassType)elemType; - if (o.getClass().getComponentType() == elemTypeClass.clazz) { - if (elemTypeClass.isTrivial) - return true; - else - throw new Error("not able to compute isInstance"); - } else - return false; - } else - throw new Error("not able to compute isInstance"); - } else - return false; + return this.isSameAsJavaType(o.getClass()); } public boolean isSameType(Type that) { @@ -58,6 +57,15 @@ public class JavaRefArrayType extends Type { && (elemType.isSameType(((JavaRefArrayType)that).elemType)); } + public boolean isSameAsJavaType(Class that) { + Class thatElemType = that; + for (int i = 0; i < dimensions && thatElemType != null; ++i) + thatElemType = thatElemType.getComponentType(); + + return (thatElemType != null) + && (elemType.isSameAsJavaType(thatElemType)); + } + public boolean isSubType(Type that) { return isSameType(that); } diff --git a/sources/scala/runtime/types/SingleType.java b/sources/scala/runtime/types/SingleType.java index ea1c10c2ae..635ced6be2 100644 --- a/sources/scala/runtime/types/SingleType.java +++ b/sources/scala/runtime/types/SingleType.java @@ -21,7 +21,7 @@ public class SingleType extends Type { } public Array newArray(int size) { - throw new Error(); // TODO + throw new Error("cannot create array of single types"); } public Object defaultValue() { diff --git a/sources/scala/runtime/types/SpecialType.java b/sources/scala/runtime/types/SpecialType.java index ad80a4feae..5916182fd7 100644 --- a/sources/scala/runtime/types/SpecialType.java +++ b/sources/scala/runtime/types/SpecialType.java @@ -24,7 +24,7 @@ import scala.runtime.RunTime; abstract public class SpecialType extends Type { public Array newArray(int size) { - return RunTime.box_oarray(new Object[size]); + throw new Error("cannot create arrays of special types"); } public Object defaultValue() { diff --git a/sources/scala/runtime/types/TypeBoolean.java b/sources/scala/runtime/types/TypeBoolean.java index 520cb7e60c..dab68955db 100644 --- a/sources/scala/runtime/types/TypeBoolean.java +++ b/sources/scala/runtime/types/TypeBoolean.java @@ -17,9 +17,6 @@ import scala.Boolean; public class TypeBoolean extends ValueType { private final Boolean ZERO = RunTime.box_zvalue(false); - public Array newArray(int size) { - return RunTime.box_zarray(new boolean[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Boolean)) @@ -27,6 +24,9 @@ public class TypeBoolean extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Boolean.TYPE; + } public String toString() { return "scala.Boolean"; } public int hashCode() { return 0x88888888; } }; diff --git a/sources/scala/runtime/types/TypeByte.java b/sources/scala/runtime/types/TypeByte.java index 7767a89cde..bb87a1ff1e 100644 --- a/sources/scala/runtime/types/TypeByte.java +++ b/sources/scala/runtime/types/TypeByte.java @@ -17,9 +17,6 @@ import scala.Byte; public class TypeByte extends ValueType { private final Byte ZERO = RunTime.box_bvalue((byte)0); - public Array newArray(int size) { - return RunTime.box_barray(new byte[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Byte)) @@ -27,6 +24,9 @@ public class TypeByte extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Byte.TYPE; + } public String toString() { return "scala.Byte"; } public int hashCode() { return 0x77777777; } }; diff --git a/sources/scala/runtime/types/TypeChar.java b/sources/scala/runtime/types/TypeChar.java index c1cf021b99..2f26ffb866 100644 --- a/sources/scala/runtime/types/TypeChar.java +++ b/sources/scala/runtime/types/TypeChar.java @@ -17,9 +17,6 @@ import scala.Char; public class TypeChar extends ValueType { private final Char ZERO = RunTime.box_cvalue((char)0); - public Array newArray(int size) { - return RunTime.box_carray(new char[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Char)) @@ -27,6 +24,9 @@ public class TypeChar extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == char.class; + } public String toString() { return "scala.Char"; } public int hashCode() { return 0x66666666; } }; diff --git a/sources/scala/runtime/types/TypeDouble.java b/sources/scala/runtime/types/TypeDouble.java index b4066dda26..79e6a19178 100644 --- a/sources/scala/runtime/types/TypeDouble.java +++ b/sources/scala/runtime/types/TypeDouble.java @@ -16,9 +16,6 @@ import scala.Array; public public class TypeDouble extends ValueType { private final scala.Double ZERO = RunTime.box_dvalue(0.0); - public Array newArray(int size) { - return RunTime.box_darray(new double[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Double)) @@ -26,6 +23,9 @@ public public class TypeDouble extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Double.TYPE; + } public String toString() { return "scala.Double"; } public int hashCode() { return 0x11111111; } }; diff --git a/sources/scala/runtime/types/TypeFloat.java b/sources/scala/runtime/types/TypeFloat.java index cdedfd6c69..ae66212991 100644 --- a/sources/scala/runtime/types/TypeFloat.java +++ b/sources/scala/runtime/types/TypeFloat.java @@ -16,9 +16,6 @@ import scala.Array; public class TypeFloat extends ValueType { private final scala.Float ZERO = RunTime.box_fvalue(0.0f); - public Array newArray(int size) { - return RunTime.box_farray(new float[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Float)) @@ -26,6 +23,9 @@ public class TypeFloat extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Float.TYPE; + } public String toString() { return "scala.Float"; } public int hashCode() { return 0x22222222; } }; diff --git a/sources/scala/runtime/types/TypeInt.java b/sources/scala/runtime/types/TypeInt.java index 1e359e73c6..0109f3e1b3 100644 --- a/sources/scala/runtime/types/TypeInt.java +++ b/sources/scala/runtime/types/TypeInt.java @@ -17,9 +17,6 @@ import scala.Int; public class TypeInt extends ValueType { private final Int ZERO = RunTime.box_ivalue(0); - public Array newArray(int size) { - return RunTime.box_iarray(new int[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Int)) @@ -27,6 +24,9 @@ public class TypeInt extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Integer.TYPE; + } public String toString() { return "scala.Int"; } public int hashCode() { return 0x44444444; } }; diff --git a/sources/scala/runtime/types/TypeLong.java b/sources/scala/runtime/types/TypeLong.java index ab2c10ec95..4258224191 100644 --- a/sources/scala/runtime/types/TypeLong.java +++ b/sources/scala/runtime/types/TypeLong.java @@ -16,9 +16,6 @@ import scala.Array; public class TypeLong extends ValueType { private final scala.Long ZERO = RunTime.box_lvalue(0l); - public Array newArray(int size) { - return RunTime.box_larray(new long[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Long)) @@ -26,6 +23,9 @@ public class TypeLong extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Long.TYPE; + } public String toString() { return "scala.Long"; } public int hashCode() { return 0x33333333; } }; diff --git a/sources/scala/runtime/types/TypeShort.java b/sources/scala/runtime/types/TypeShort.java index 6597e2a70e..ce4af21e18 100644 --- a/sources/scala/runtime/types/TypeShort.java +++ b/sources/scala/runtime/types/TypeShort.java @@ -16,9 +16,6 @@ import scala.Array; public class TypeShort extends ValueType { private final scala.Short ZERO = RunTime.box_svalue((short)0); - public Array newArray(int size) { - return RunTime.box_sarray(new short[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Short)) @@ -26,6 +23,9 @@ public class TypeShort extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Short.TYPE; + } public String toString() { return "scala.Short"; } public int hashCode() { return 0x55555555; } }; diff --git a/sources/scala/runtime/types/TypeUnit.java b/sources/scala/runtime/types/TypeUnit.java index 0628af9e7f..d42a994f89 100644 --- a/sources/scala/runtime/types/TypeUnit.java +++ b/sources/scala/runtime/types/TypeUnit.java @@ -17,9 +17,6 @@ import scala.Unit; public class TypeUnit extends ValueType { private final Unit ZERO = RunTime.box_uvalue(); - public Array newArray(int size) { - return RunTime.box_oarray(new Object[size]); - } public Object cast(Object o) { assert scala.runtime.types.Statistics.incTypeCast(); if (! (o == null || o instanceof scala.Unit)) @@ -27,6 +24,9 @@ public class TypeUnit extends ValueType { return o; } public Object defaultValue() { return ZERO; } + public boolean isSameAsJavaType(Class that) { + return that == java.lang.Void.TYPE; + } public String toString() { return "scala.Unit"; } public int hashCode() { return 0x99999999; } }; diff --git a/sources/scala/runtime/types/ValueType.java b/sources/scala/runtime/types/ValueType.java index 77baacf56a..0cffb9c854 100644 --- a/sources/scala/runtime/types/ValueType.java +++ b/sources/scala/runtime/types/ValueType.java @@ -11,6 +11,7 @@ package scala.runtime.types; import scala.Type; +import scala.Array; /** * Abstract superclass for all value types. @@ -31,4 +32,7 @@ abstract public class ValueType extends Type { public boolean isSameType(Type that) { return this == that; } + public Array newArray(int size) { + throw new Error("internal error (Scala runtime)"); + } } diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java index a6286853da..cb647954ec 100644 --- a/sources/scalac/symtab/Definitions.java +++ b/sources/scalac/symtab/Definitions.java @@ -714,6 +714,24 @@ public class Definitions { return JAVACLASSTYPE_JAVACLASSTYPE; } + private Symbol JAVACLASSTYPE_JAVAARRAYTYPE; + public Symbol JAVACLASSTYPE_JAVAARRAYTYPE() { + if (JAVACLASSTYPE_JAVAARRAYTYPE == null) + JAVACLASSTYPE_JAVAARRAYTYPE = + loadTerm(JAVACLASSTYPE_CLASS.linkedModule().moduleClass(), + Names.javaArrayType); + return JAVACLASSTYPE_JAVAARRAYTYPE; + } + + private Symbol JAVAREFARRAYTYPE_JAVAREFARRAYTYPE; + public Symbol JAVAREFARRAYTYPE_JAVAREFARRAYTYPE() { + if (JAVAREFARRAYTYPE_JAVAREFARRAYTYPE == null) + JAVAREFARRAYTYPE_JAVAREFARRAYTYPE = + loadTerm(JAVAREFARRAYTYPE_CLASS.linkedModule().moduleClass(), + Names.javaRefArrayType); + return JAVAREFARRAYTYPE_JAVAREFARRAYTYPE; + } + //######################################################################## // Public Fields - Global values diff --git a/sources/scalac/transformer/TypesAsValuesPhase.java b/sources/scalac/transformer/TypesAsValuesPhase.java index 3ac714b103..c56e577df1 100644 --- a/sources/scalac/transformer/TypesAsValuesPhase.java +++ b/sources/scalac/transformer/TypesAsValuesPhase.java @@ -103,6 +103,7 @@ public class TypesAsValuesPhase extends Phase { private final TEnv EENV = new TEnv(); private final Map/**/ predefTypes; + private final Map/**/ basicTypes; private HashMap/**/ ancestorCache = new HashMap(); @@ -129,6 +130,16 @@ public class TypesAsValuesPhase extends Phase { predefTypes.put(defs.ALLREF_CLASS, defs.RTT_ALLREF()); predefTypes.put(defs.ALL_CLASS, defs.RTT_ALL()); + basicTypes = new HashMap(); + basicTypes.put(defs.BOOLEAN_TYPE(), "Z"); + basicTypes.put(defs.BYTE_TYPE(), "B"); + basicTypes.put(defs.CHAR_TYPE(), "C"); + basicTypes.put(defs.DOUBLE_TYPE(), "D"); + basicTypes.put(defs.FLOAT_TYPE(), "F"); + basicTypes.put(defs.INT_TYPE(), "I"); + basicTypes.put(defs.LONG_TYPE(), "J"); + basicTypes.put(defs.SHORT_TYPE(), "S"); + membersToAdd.put(defs.ARRAY_CLASS, new Symbol[0]); paramsToAdd.put(ARRAY_CONSTRUCTOR, new Symbol[0]); @@ -136,7 +147,7 @@ public class TypesAsValuesPhase extends Phase { } else { transformer = new TV_MiniTransformer(global); typeAccessorType = null; - predefTypes = null; + predefTypes = basicTypes = null; } } @@ -401,8 +412,8 @@ public class TypesAsValuesPhase extends Phase { return gen.ValDef(symbol, transform(rhs, symbol)); case New(Apply(TypeApply(Tree fun, Tree[] targs), Tree[] vargs)): - // TODO still needed? - if (fun.symbol() == ARRAY_CONSTRUCTOR && false) { + if (fun.symbol() == ARRAY_CONSTRUCTOR + && targs[0].type().symbol().isParameter()) { // Transform array creations: // new Array[T](size) // becomes @@ -411,7 +422,7 @@ public class TypesAsValuesPhase extends Phase { assert vargs.length == 1; Tree newArrayfun = gen.mkRef(tree.pos, typeAsValue(targs[0].pos, - targs[0].type, + targs[0].type(), currentOwner, EENV), defs.TYPE_NEWARRAY()); @@ -855,7 +866,7 @@ public class TypesAsValuesPhase extends Phase { return env.treeForVar(sym); } else if (sym == defs.ARRAY_CLASS) { assert args.length == 1; - return arrayType(pos, sym, args[0], owner, env); + return arrayType(pos, args[0], owner, env); } else if (predefTypes.containsKey(sym)) { return gen.mkGlobalRef(pos, (Symbol)predefTypes.get(sym)); } else if (sym.isJava()) { @@ -885,15 +896,41 @@ public class TypesAsValuesPhase extends Phase { } private Tree arrayType(int pos, - Symbol sym, Type elemType, Symbol owner, TEnv env) { - Tree constr = - gen.mkPrimaryConstructorGlobalRef(pos, - defs.JAVAREFARRAYTYPE_CLASS); - Tree[] args = new Tree[]{ typeAsValue(pos, elemType, owner, env) }; - return gen.New(pos, gen.mkApply_V(constr, args)); + Type realElemType = elemType; + int dimensions = 1; + while (realElemType.symbol() == defs.ARRAY_CLASS) { + realElemType = realElemType.typeArgs()[0]; + ++dimensions; + } + + if (isTrivial(elemType)) { + Tree nameLit; + if (basicTypes.containsKey(elemType)) + nameLit = + gen.mkStringLit(pos, (String)basicTypes.get(elemType)); + else + nameLit = gen.mkSymbolNameLit(pos, realElemType.symbol()); + + Tree constr = + gen.mkGlobalRef(pos, defs.JAVACLASSTYPE_JAVAARRAYTYPE()); + Tree[] args = new Tree[]{ + nameLit, + gen.mkIntLit(pos, dimensions) + }; + return gen.mkApply_V(constr, args); + } else { + Tree constr = + gen.mkGlobalRef(pos, + defs.JAVAREFARRAYTYPE_JAVAREFARRAYTYPE()); + Tree[] args = new Tree[]{ + typeAsValue(pos, elemType, owner, env), + gen.mkIntLit(pos, dimensions) + }; + return gen.mkApply_V(constr, args); + } } private Tree javaType(int pos, Symbol sym) { diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index 7bfc3d17f0..16557bbaab 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -191,6 +191,8 @@ public class Names { public static final Name isEmpty = Name.fromString("isEmpty"); public static final Name instantiate = Name.fromString("instantiate"); public static final Name java = Name.fromString("java"); + public static final Name javaRefArrayType = Name.fromString("javaRefArrayType"); + public static final Name javaArrayType = Name.fromString("javaArrayType"); public static final Name javaClassType = Name.fromString("javaClassType"); public static final Name lang = Name.fromString("lang"); public static final Name length = Name.fromString("length"); -- cgit v1.2.3