summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Checkers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala8
-rw-r--r--src/library/scala/Array.scala48
-rw-r--r--test/files/run/multi-array.check3
-rw-r--r--test/files/run/multi-array.scala12
13 files changed, 120 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
index cf8e14819f..0c467f1279 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
@@ -451,9 +451,9 @@ abstract class Checkers {
error("NEW call to non-reference type: " + kind)
}
- case CREATE_ARRAY(elem) =>
- checkStack(1)
- checkType(stack.pop, INT)
+ case CREATE_ARRAY(elem, dims) =>
+ checkStack(dims)
+ stack.pop(dims) foreach (checkType(_, INT))
stack.push(ARRAY(elem))
case IS_INSTANCE(tpe) =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 91832c0346..6a21b00f86 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -653,16 +653,20 @@ abstract class GenICode extends SubComponent {
assert(ctor.isClassConstructor,
"'new' call to non-constructor: " + ctor.name)
- generatedType = toTypeKind(tpt.tpe)
+ generatedType = toTypeKind(fun.tpe.resultType)
assert(generatedType.isReferenceType || generatedType.isArrayType,
"Non reference type cannot be instantiated: " + generatedType)
var ctx1 = ctx
generatedType match {
- case ARRAY(elem) =>
+ case arr @ ARRAY(elem) =>
ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)
- ctx1.bb.emit(CREATE_ARRAY(elem), tree.pos)
+ val dims = arr.dimensions
+ var elemKind = arr.elementKind
+ if (args.length != dims)
+ for (i <- args.length until dims) elemKind = ARRAY(elemKind)
+ ctx1.bb.emit(CREATE_ARRAY(elemKind, args.length), tree.pos)
case rt @ REFERENCE(cls) =>
assert(ctor.owner == cls,
@@ -958,7 +962,7 @@ abstract class GenICode extends SubComponent {
generatedType = ARRAY(elmKind)
ctx1.bb.emit(CONSTANT(new Constant(elems.length)), tree.pos)
- ctx1.bb.emit(CREATE_ARRAY(elmKind))
+ ctx1.bb.emit(CREATE_ARRAY(elmKind, 1))
// inline array literals
var i = 0
while (i < elems.length) {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index 93941f653a..7590dea711 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -26,7 +26,7 @@ import scala.tools.nsc.util.{Position,NoPosition}
case CALL_PRIMITIVE(primitive) =>
case CALL_METHOD(method, style) =>
case NEW(kind) =>
- case CREATE_ARRAY(elem) =>
+ case CREATE_ARRAY(elem, dims) =>
case IS_INSTANCE(tpe) =>
case CHECK_CAST(tpe) =>
case SWITCH(tags, labels) =>
@@ -361,15 +361,15 @@ trait Opcodes { self: ICodes =>
/** This class represents a CREATE_ARRAY instruction
- * Stack: ...:size(int)
+ * Stack: ...:size_1:size_2:..:size_n
* ->: ...:arrayref
*/
- case class CREATE_ARRAY(elem: TypeKind) extends Instruction {
+ case class CREATE_ARRAY(elem: TypeKind, dims: Int) extends Instruction {
/** Returns a string representation of this instruction */
- override def toString(): String ="CREATE_ARRAY "+elem.toString();
+ override def toString(): String ="CREATE_ARRAY "+elem.toString() + " x " + dims;
- override def consumed = 1;
- override def consumedTypes = INT :: Nil
+ override def consumed = dims;
+ override def consumedTypes = List.make(dims, INT)
override def produced = 1;
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index 1bf5455a13..233fb09e0c 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -82,6 +82,9 @@ trait TypeKinds { self: ICodes =>
case DOUBLE | LONG => true
case _ => false
}
+
+ /** The number of dimensions for array types. */
+ def dimensions: Int = 0
}
/**
@@ -272,12 +275,28 @@ trait TypeKinds { self: ICodes =>
// "VALUE(" + cls.fullNameString + ")";
// }
+ def ArrayN(elem: TypeKind, dims: Int): ARRAY = {
+ assert(dims > 0)
+ if (dims == 1)
+ ARRAY(elem)
+ else
+ ARRAY(ArrayN(elem, dims - 1))
+ }
+
final case class ARRAY(val elem: TypeKind) extends TypeKind {
override def toString(): String =
"ARRAY[" + elem + "]"
override def isArrayType = true
+ override def dimensions: Int = 1 + elem.dimensions
+
+ /** The ultimate element type of this array. */
+ def elementKind: TypeKind = elem match {
+ case a @ ARRAY(e1) => a.elementKind
+ case k => k
+ }
+
/**
* Approximate `lub'. The common type of two references is
* always AnyRef. For 'real' least upper bound wrt to subclassing
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala
index 53a1c13dc8..0fe5f852f2 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala
@@ -60,12 +60,16 @@ trait TypeStacks { self: ICodes =>
def pop3: (TypeKind, TypeKind, TypeKind) = (pop, pop, pop)
/** Drop the first n elements of the stack. */
- def pop(n: Int): Unit = types = types.drop(n)
+ def pop(n: Int): List[TypeKind] = {
+ val prefix = types.take(n)
+ types = types.drop(n)
+ prefix
+ }
/**
* A TypeStack aggress with another one if they have the same
* length and each type kind agrees position-wise. Two
- * types agree if they are subtypes of one another.
+ * types agree if one is a subtype of the other.
*/
def agreesWith(other: TypeStack): Boolean =
(types.length == other.types.length) &&
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index 4ab2883126..aca103aecf 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -341,8 +341,8 @@ abstract class CopyPropagation {
}
out.stack = v1 :: out.stack
- case CREATE_ARRAY(elem) =>
- out.stack = Unknown :: out.stack.drop(1)
+ case CREATE_ARRAY(elem, dims) =>
+ out.stack = Unknown :: out.stack.drop(dims)
case IS_INSTANCE(tpe) =>
out.stack = Unknown :: out.stack.drop(1)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
index 4a69746c71..eacd40d42a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -274,8 +274,8 @@ abstract class TypeFlowAnalysis {
case NEW(kind) =>
stack.push(kind)
- case CREATE_ARRAY(elem) =>
- stack.pop
+ case CREATE_ARRAY(elem, dims) =>
+ stack.pop(dims)
stack.push(ARRAY(elem))
case IS_INSTANCE(tpe) =>
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 809ff80eb3..88f635f79d 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -811,12 +811,14 @@ abstract class GenJVM extends SubComponent {
val className = javaName(cls)
jcode.emitNEW(className)
- case CREATE_ARRAY(elem) => elem match {
+ case CREATE_ARRAY(elem, 1) => elem match {
case REFERENCE(_) | ARRAY(_) =>
jcode.emitANEWARRAY(javaType(elem).asInstanceOf[JReferenceType])
case _ =>
jcode.emitNEWARRAY(javaType(elem))
}
+ case CREATE_ARRAY(elem, dims) =>
+ jcode.emitMULTIANEWARRAY(javaType(ArrayN(elem, dims)).asInstanceOf[JReferenceType], dims)
case IS_INSTANCE(tpe) =>
tpe match {
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 39c128d847..4111f2ec84 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -1473,7 +1473,10 @@ abstract class GenMSIL extends SubComponent {
ignoreNextDup = true
// works also for arrays and reference-types
- case CREATE_ARRAY(elem) => mcode.Emit(OpCodes.Newarr, msilType(elem))
+ case CREATE_ARRAY(elem, dims) =>
+ // TODO: handle multi dimensional arrays
+ assert(dims == 1, "Can't handle multi dimensional arrays")
+ mcode.Emit(OpCodes.Newarr, msilType(elem))
// works for arrays and reference-types
case IS_INSTANCE(tpe) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index d9a6740b1e..3a3f67e549 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -490,11 +490,11 @@ abstract class ICodeReader extends ClassfileParser {
case T_LONG => LONG
}
size += 1
- code.emit(CREATE_ARRAY(kind))
+ code.emit(CREATE_ARRAY(kind, 1))
case JVM.anewarray =>
val tpe = pool.getClassOrArrayType(in.nextChar); size += 2
- code.emit(CREATE_ARRAY(toTypeKind(tpe)))
+ code.emit(CREATE_ARRAY(toTypeKind(tpe), 1))
case JVM.arraylength => code.emit(CALL_PRIMITIVE(ArrayLength(OBJECT))); // the kind does not matter
case JVM.athrow => code.emit(THROW());
@@ -531,8 +531,8 @@ abstract class ICodeReader extends ClassfileParser {
size += 3
val tpe = toTypeKind(pool.getClassOrArrayType(in.nextChar))
val dim = in.nextByte
- assert(dim == 1, "Cannot handle multidimensional arrays yet.")
- code.emit(CREATE_ARRAY(tpe))
+// assert(dim == 1, "Cannot handle multidimensional arrays yet.")
+ code.emit(CREATE_ARRAY(tpe, dim))
case JVM.ifnull => code.emit(LCZJUMP(parseJumpTarget, pc + size, EQ, OBJECT))
case JVM.ifnonnull => code.emit(LCZJUMP(parseJumpTarget, pc + size, NE, OBJECT))
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala
index aaf72f1c92..b9e58afbed 100644
--- a/src/library/scala/Array.scala
+++ b/src/library/scala/Array.scala
@@ -189,6 +189,54 @@ object Array {
*/
final class Array[A](_length: Int) extends RandomAccessSeq.Mutable[A] {
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
+ /** Multidimensional array creation */
+ def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = {
+ this(dim1);
+ throw new Error()
+ }
+
/** The length of the array */
def length: Int = throw new Error()
diff --git a/test/files/run/multi-array.check b/test/files/run/multi-array.check
new file mode 100644
index 0000000000..c43d9c6172
--- /dev/null
+++ b/test/files/run/multi-array.check
@@ -0,0 +1,3 @@
+Array(1,2,3)
+null
+Array(Array(0,1,2),Array(1,2,3),Array(2,3,4))
diff --git a/test/files/run/multi-array.scala b/test/files/run/multi-array.scala
new file mode 100644
index 0000000000..1dbbad32a8
--- /dev/null
+++ b/test/files/run/multi-array.scala
@@ -0,0 +1,12 @@
+object Test extends Application {
+ val a = Array(1, 2, 3)
+ println(a.deepToString)
+
+ val aaiIncomplete = new Array[Array[Array[Int]]](3)
+ println(aaiIncomplete(0))
+
+ val aaiComplete: Array[Array[Int]] = new Array[Array[Int]](3, 3)
+ for (i <- 0 until 3; j <- 0 until 3)
+ aaiComplete(i)(j) = i + j
+ println(aaiComplete.deepToString)
+}